Skip to content

Instantly share code, notes, and snippets.

@ericswpark
Created March 5, 2025 02:17
Show Gist options
  • Save ericswpark/4e41c8af1d01e59d1726711dd0814fce to your computer and use it in GitHub Desktop.
Save ericswpark/4e41c8af1d01e59d1726711dd0814fce to your computer and use it in GitHub Desktop.
XINU x86_32 (i386) and grub ISO generation patch
From 96775ccde72c4f53a87431073d6585671a1fd3e6 Mon Sep 17 00:00:00 2001
From: Eric Park <[email protected]>
Date: Tue, 4 Mar 2025 19:57:48 -0500
Subject: [PATCH 1/4] Import normal x86 code
This overwrites Quark support with the normal x86 (i386) version found
on the official XINU website:
https://www.cs.purdue.edu/homes/comer/downloads/Xinu_Book_And_Code/VirtualBox/Xinu-VirtualBox.tar.gz
Leading whitespaces and all.
---
COPYRIGHT | 24 ++
DESCRIPTION | 35 ++-
compile/Makefile | 31 ++-
compile/bin/buildxbin | 38 ---
compile/ld.script | 1 +
config/.yyleng | 1 +
config/Configuration | 49 +++-
config/Makefile | 6 +-
config/conf.c | 83 +++++-
config/conf.h | 19 +-
config/config | Bin 41312 -> 41312 bytes
config/config.y | 18 +-
config/y.tab.c | 120 ++++-----
device/eth/82545EMInit.c | 525 ++++++++++++++++++++++++++++++++++++
device/eth/ethcontrol.c | 70 +++--
device/eth/ethhandler.c | 171 ++++++------
device/eth/ethinit.c | 329 +++-------------------
device/eth/ethmcast.c | 79 ------
device/eth/ethread.c | 139 ++++------
device/eth/ethwrite.c | 104 +++----
device/lfs/lfdballoc.c | 4 +-
device/lfs/lflcontrol.c | 2 +-
device/lfs/lfscheck.c | 3 +-
device/lfs/lfsckfmt.c | 10 +-
device/lfs/lfscreate.c | 15 ++
device/lfs/lfsinit.c | 6 +-
device/lfs/lfsopen.c | 6 +
device/nam/mount.c | 13 +-
device/nam/naminit.c | 19 +-
device/nam/nammap.c | 8 +-
device/pipe/pipe_close.c | 57 ++++
device/pipe/pipe_getc.c | 68 +++++
device/pipe/pipe_init.c | 22 ++
device/pipe/pipe_open.c | 37 +++
device/pipe/pipe_putc.c | 46 ++++
device/pipe/pipe_read.c | 43 +++
device/pipe/pipe_write.c | 40 +++
device/rds/Design_Notes | 143 ++++++++++
device/rds/rdsars.c | 35 +++
device/rds/rdsbufalloc.c | 50 ----
device/rds/rdsclose.c | 60 -----
device/rds/rdscomm.c | 14 +-
device/rds/rdscontrol.c | 162 ++++++-----
device/rds/rdsinit.c | 82 +-----
device/rds/rdsopen.c | 114 ++++++--
device/rds/rdsprocess.c | 268 +++++++++---------
device/rds/rdsqfcns.c | 288 ++++++++++++++++++++
device/rds/rdsread.c | 123 ++-------
device/rds/rdswrite.c | 90 ++-----
device/rfs/rflclose.c | 46 ++++
device/rfs/rflgetc.c | 8 +-
device/rfs/rflread.c | 3 +
device/rfs/rfscomm.c | 23 +-
device/rfs/rfscontrol.c | 10 +-
device/rfs/rfsinit.c | 16 +-
device/rfs/rfsopen.c | 2 +-
device/sdmc/sdmcclose.c | 15 ++
device/sdmc/sdmccmd.c | 288 ++++++++++++++++++++
device/sdmc/sdmcdispatch.S | 20 ++
device/sdmc/sdmcinit.c | 56 ++++
device/sdmc/sdmcinterrupt.c | 72 +++++
device/sdmc/sdmcopen.c | 204 ++++++++++++++
device/sdmc/sdmcread.c | 211 +++++++++++++++
device/sdmc/sdmcwrite.c | 19 ++
device/tty/ttycontrol.c | 2 +-
device/tty/ttygetc.c | 2 +-
device/tty/ttyhandle_in.c | 3 +-
device/tty/ttyhandle_out.c | 11 +-
device/tty/ttyhandler.c | 7 +-
device/tty/ttyinit.c | 14 +-
device/tty/ttykickout.c | 4 +-
device/tty/ttyread.c | 2 +-
device/tty/ttywrite.c | 2 +-
include/bufpool.h | 7 +-
include/clock.h | 11 +-
include/conf.h | 19 +-
include/date.h | 38 +--
include/device.h | 2 +-
include/dhcp.h | 1 +
include/e1000e.h | 415 ++++++++++++++++++++++++++++
include/ether.h | 19 +-
include/file.h | 4 +-
include/i386.h | 57 ++++
include/icmp.h | 30 +--
include/icu.h | 2 +-
include/icu.s | 2 +-
include/io.h | 37 +++
include/kernel.h | 57 ++--
include/lfilesys.h | 11 +-
include/mark.h | 7 -
include/memory.h | 2 +
include/name.h | 2 +-
include/net.h | 2 +-
include/pci.h | 132 ++++-----
include/pipe.h | 29 ++
include/process.h | 2 +-
include/prototypes.h | 156 ++++++-----
include/quark_eth.h | 146 ----------
include/quark_irq.h | 4 +-
include/quark_pdat.h | 2 +-
include/ramdisk.h | 4 +-
include/rdisksys.h | 133 ++++-----
include/rfilesys.h | 28 +-
include/sdmc.h | 83 ++----
include/shell.h | 12 +-
include/shprototypes.h | 9 +
include/testsuite.h | 6 +-
include/tftp.h | 11 +-
include/uart.h | 20 +-
include/xinu.h | 5 +-
lib/memchr.c | 0
net/arp.c | 6 +-
net/dhcp.c | 5 +-
net/dhcp_dump.c | 4 +-
net/dns.c | 100 +++++--
net/dot2ip.c | 9 +-
net/hexdump.c | 10 +-
net/icmp.c | 24 +-
net/ip.c | 6 +-
net/pxe.c | 48 ++--
net/tftp.c | 205 ++++++++------
net/udp.c | 12 +-
shell/Notes_On_Pipes | 74 +++++
shell/addargs.c | 20 +-
shell/lexan.c | 33 +--
shell/shell.c | 454 ++++++++++++++++++++-----------
shell/xsh_arp.c | 4 +-
shell/xsh_cat.c | 8 +-
shell/xsh_date.c | 6 +-
shell/xsh_devdump.c | 8 +-
shell/xsh_echo.c | 2 +-
shell/xsh_help.c | 20 +-
shell/xsh_kill.c | 8 +-
shell/xsh_ls.c | 121 +++++++++
shell/xsh_memdump.c | 36 +--
shell/xsh_ns.c | 136 ++++++++++
shell/xsh_ping.c | 46 +---
shell/xsh_ps.c | 8 +-
shell/xsh_rdstest.c | 42 +--
shell/xsh_tee.c | 47 ++++
shell/xsh_udpdump.c | 15 +-
shell/xsh_udpecho.c | 58 ++--
shell/xsh_udpserver.c | 18 +-
shell/xsh_uptime.c | 16 +-
system/chprio.c | 6 +-
system/conf.c | 83 +++++-
system/create.c | 6 +-
system/ctxsw.S | 2 +-
system/early_imr.c | 223 ---------------
system/evec.c | 164 ++++-------
system/getutime.c | 2 +-
system/i386.c | 139 ++++++++++
system/initialize.c | 55 ++--
system/kprintf.c | 35 +--
system/main.c | 23 +-
system/mark.c | 31 ++-
system/meminit.c | 190 ++-----------
system/mkbufpool.c | 9 +-
system/pci.c | 513 +++++++++++++++++++++--------------
system/platinit.c | 80 ------
system/quark_irq.c | 43 ---
system/quark_pdat.c | 67 -----
system/queue.c | 2 +-
system/resume.c | 8 +-
system/sleep.c | 3 +-
system/stacktrace.c | 10 +-
system/start.S | 273 ++++++++-----------
167 files changed, 6181 insertions(+), 3612 deletions(-)
create mode 100644 COPYRIGHT
delete mode 100755 compile/bin/buildxbin
create mode 100644 config/.yyleng
create mode 100644 device/eth/82545EMInit.c
delete mode 100644 device/eth/ethmcast.c
create mode 100644 device/pipe/pipe_close.c
create mode 100644 device/pipe/pipe_getc.c
create mode 100644 device/pipe/pipe_init.c
create mode 100644 device/pipe/pipe_open.c
create mode 100644 device/pipe/pipe_putc.c
create mode 100644 device/pipe/pipe_read.c
create mode 100644 device/pipe/pipe_write.c
create mode 100644 device/rds/Design_Notes
create mode 100644 device/rds/rdsars.c
delete mode 100644 device/rds/rdsbufalloc.c
delete mode 100644 device/rds/rdsclose.c
create mode 100644 device/rds/rdsqfcns.c
create mode 100644 device/sdmc/sdmcclose.c
create mode 100644 device/sdmc/sdmccmd.c
create mode 100644 device/sdmc/sdmcdispatch.S
create mode 100644 device/sdmc/sdmcinit.c
create mode 100644 device/sdmc/sdmcinterrupt.c
create mode 100644 device/sdmc/sdmcopen.c
create mode 100644 device/sdmc/sdmcread.c
create mode 100644 device/sdmc/sdmcwrite.c
create mode 100644 include/e1000e.h
create mode 100644 include/i386.h
create mode 100644 include/io.h
create mode 100644 include/pipe.h
delete mode 100644 include/quark_eth.h
delete mode 100644 lib/memchr.c
create mode 100644 shell/Notes_On_Pipes
create mode 100644 shell/xsh_ls.c
create mode 100644 shell/xsh_ns.c
create mode 100644 shell/xsh_tee.c
delete mode 100644 system/early_imr.c
create mode 100644 system/i386.c
delete mode 100755 system/platinit.c
delete mode 100644 system/quark_irq.c
delete mode 100644 system/quark_pdat.c
diff --git a/COPYRIGHT b/COPYRIGHT
new file mode 100644
index 0000000..451d591
--- /dev/null
+++ b/COPYRIGHT
@@ -0,0 +1,24 @@
+<<<<begin COPYRIGHT>>>
+
+Portions of this software are covered by the following copyright:
+
+ Copyright (c) 2012, 2015 Douglas E. Comer and CRC Press, Inc.
+ All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that this notice is preserved and that due credit is given
+to the copyright holders. The names of the copyright holders
+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 express or implied warranty. The author
+assumes no liability for damages incidental or consequential, nor is the
+software warranted for correctness or suitability for any purpose.
+ Portions of this software are documented in the book:
+
+ Operating System Design -- The Xinu Approach, CRC Press,
+ Boca Raton, FL, Linksys version 2012, Second Edition 2015.
+
+This software may not be published in a textbook without written
+permission from the copyright holders.
+
+<<<<end COPYRIGHT>>>
diff --git a/DESCRIPTION b/DESCRIPTION
index 9354181..5726161 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1 +1,34 @@
-This directory holds Xinu sources for the Galileo.
+This directory holds Xinu sources for Virtual Box. They are derived from
+the Galileo version described in:
+
+ Douglas Comer, Operating System Design -- The Xinu Approach,
+ Second edition, CRC Press, 2015.
+
+The changes are:
+
+ 1) The tty driver uses port-mapped I/O in place of the memory-mapped I/O
+ used on the Galileo. The include file io.h contains macros that
+ handle both. Also, in uart.h, the Control and Status Registers are
+ sing;e bytes instead of the word-oriented approach used on the Galileo.
+
+ 2) The Ethernet driver is for an Intel 82545EM chip, which is a form of
+ Intel's E1000E Ethernet design. The internals of the driver differ
+ completely from the driver used with the Ethernet on the Galileo SoC.
+
+ 3) The startup sequence (file start.S) differs from the Galileo startup
+ sequence. It may be possible to move toward a more common form; we
+ adopted an older startup sequence that works, and haven't tried to
+ blend them.
+
+ 4) The platform initialization used with the Galileo (platinit.c) has
+ been removed, and basic PC functions have been substituted (in file
+ i386.c).
+
+ 5) The Galileo version uses the memory map left by grub to construct a
+ free list. We deleted the code that depends on grub and substituted
+ simpler free list code from an earlier version of Xinu because we
+ had trouble reading the grub free list. Additional work may be
+ needed to ensure the free list is correct.
+
+ 6) The code includes a pipe device, and the shell has pipes.
+
diff --git a/compile/Makefile b/compile/Makefile
index 637ba9f..4929de0 100644
--- a/compile/Makefile
+++ b/compile/Makefile
@@ -1,7 +1,8 @@
#########################################################################
# #
# #
-# Makefile for the Intel Galileo version of the Xinu operating system #
+# Makefile for the VBOX version of Xinu, using as much as possible #
+# from the Galileo code #
# #
# includes: .deps and .defs #
# #
@@ -9,16 +10,16 @@
#########################################################################
COMPILER_ROOT = /usr/bin/
-PNAME = galileo
+PNAME = Vbox
PLAT = Platform_$(PNAME)
TOPDIR = ..
CC = ${COMPILER_ROOT}gcc-4.8
LD = ${COMPILER_ROOT}ld
OBJCOPY = ${COMPILER_ROOT}objcopy
-XINU = $(TOPDIR)/compile/xinu
+XINU = $(TOPDIR)/compile/xinu.elf
XINUBIN = $(TOPDIR)/compile/xinu.bin
-XINUXBIN = $(TOPDIR)/compile/xinu.xbin
+XINUXBIN = $(TOPDIR)/compile/xinu
MAKEXBIN = $(TOPDIR)/compile/bin/buildxbin
BUILDMAKE = $(TOPDIR)/compile/bin/build-make
@@ -29,7 +30,7 @@ DEFSFILE = .defs
VERSIONFILE = version
LDSCRIPT = ld.script
MKVERS = $(TOPDIR)/compile/bin/mkvers
-REBUILDFLAGS = -s $(TOPDIR)/system debug.c \
+REBUILDFLAGS = -s $(TOPDIR)/system debug.c \
-s $(TOPDIR)/lib \
-s $(TOPDIR)/device/tty \
-s $(TOPDIR)/device/nam \
@@ -38,12 +39,19 @@ REBUILDFLAGS = -s $(TOPDIR)/system debug.c \
-s $(TOPDIR)/device/ram \
-s $(TOPDIR)/device/lfs \
-s $(TOPDIR)/device/rfs \
+ -s $(TOPDIR)/device/pipe \
-s $(TOPDIR)/net 'arp_dump*' \
'dhcp_dump*' pxe.c \
-s $(TOPDIR)/shell 'xsh_rdstest*'
INCLUDE = -I$(TOPDIR)/include
-DEFS = -DBSDURG -DVERSION=\""`cat $(VERSIONFILE)`"\"
+
+# Amount to move loaded image down in memory
+
+BRELOC = 0x150000
+BOOTPLOC= 0x150000
+
+DEFS = -DBRELOC=${BRELOC} -DBOOTPLOC=${BOOTPLOC} -DBSDURG -DVERSION=\""`cat $(VERSIONFILE)`"\"
# Compiler flags
CFLAGS = -march=i586 -m32 -fno-builtin -fno-stack-protector -nostdlib -c -Wall -O0 ${DEFS} ${INCLUDE}
@@ -97,15 +105,16 @@ export
# Specific additional rules and exceptions
#--------------------------------------------------------------------------------
+# The following inserts 'echo' when run on xinu00
+ECHO$(MACHINE) = echo; echo "On Vbox, the following command would be run: "
+
xinu: Makefile rebuild $(BLDDIRS) $(DEFSFILE) $(DEPSFILE) $(CONFH) $(CONFC) $(LD_LIST)
@echo;echo 'Loading object files to produce GRUB bootable xinu'
@$(LD) $(LDFLAGS) $(LD_LIST) -o $(XINU)
- @echo;echo 'Building $(XINUBIN)'
- @objcopy -O binary $(XINU) $(XINUBIN)
- @echo;echo 'Building $(XINUXBIN)'
- @$(MAKEXBIN) $(XINUBIN) $(XINUXBIN)
- @rm -f $(XINUBIN)
+ @echo Copying xinu.elf to xinu.boot in the TFTP directory.
+ @$(ECHOxinu00) cp xinu.elf /srv/tftp/xinu.boot
@echo
+
$(BLDDIRS):
@mkdir -p $(BLDDIRS)
diff --git a/compile/bin/buildxbin b/compile/bin/buildxbin
deleted file mode 100755
index 41d4026..0000000
--- a/compile/bin/buildxbin
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/perl
-#########################################################################
-#
-# buildxbin - Creates an xboot Xinu image from a binary Xinu image
-# Adds the xboot header to the Xinu image
-#
-#########################################################################
-
-use strict;
-
-my $header_version = 0; # xboot header version
-my $header_size = 512; # xboot header size
-my $load_address = 0x100000; # Load Xinu at 1 MB
-my @xboot_header = (0x58, 0x69, 0x6E, 0x75); # xboot signature - the 4 characters 'X', 'i', 'n', 'u'
-
-my $xinu_img_in = shift or die "Usage: buildxbin xinu.bin xinu.xbin\n";
-my $xinu_img_out = shift or die "Usage: buildxbin xinu.bin xinu.xbin\n";
-
-# Determine image size
-my $xinu_img_size = -s $xinu_img_in;
-
-# Determine the image checksum
-my $checksum = `/usr/bin/crc32 $xinu_img_in`;
-chomp $checksum;
-my $checksum_int = hex $checksum;
-
-# Create the xboot header
-my $header_string = pack("C4LLLLLC4", (@xboot_header, $header_version, $load_address, $load_address, $xinu_img_size, $checksum_int, @xboot_header));
-my $pad_size = $header_size - length($header_string) - 1; # pack will output header string as null terminated so reduce the padding by 1
-
-# Output the xboot header
-open(my $xinu_out, '>:raw', $xinu_img_out) or die "Unable to open $xinu_img_out: $!\n";
-print $xinu_out pack("Z*", $header_string);
-print $xinu_out pack("x$pad_size");
-close($xinu_out);
-
-# Add the Xinu image
-system("cat $xinu_img_in >> $xinu_img_out");
\ No newline at end of file
diff --git a/compile/ld.script b/compile/ld.script
index 73a89eb..5957e16 100644
--- a/compile/ld.script
+++ b/compile/ld.script
@@ -17,6 +17,7 @@ SECTIONS
data = ABSOLUTE(.); /* data: beginning of data segment */
*(.data .data.*)
edata = ABSOLUTE(.) ; /* edata: end of data */
+ _edata = ABSOLUTE(.) ; /* _edata: end of data section */
. = ALIGN(4096);
}
.bss :
diff --git a/config/.yyleng b/config/.yyleng
new file mode 100644
index 0000000..0fd4972
--- /dev/null
+++ b/config/.yyleng
@@ -0,0 +1 @@
+extern int yyleng;
diff --git a/config/Configuration b/config/Configuration
index 1f976f3..5fa09dd 100644
--- a/config/Configuration
+++ b/config/Configuration
@@ -34,7 +34,7 @@ tty:
/* type of a ethernet device */
eth:
- on quark_eth
+ on e1000e
-i ethinit -o ioerr -c ioerr
-r ethread -g ioerr -p ioerr
-w ethwrite -s ioerr -n ethcontrol
@@ -43,7 +43,7 @@ eth:
/* type of a remote disk system device */
rds:
on udp
- -i rdsinit -o rdsopen -c rdsclose
+ -i rdsinit -o rdsopen -c ioerr
-r rdsread -g ioerr -p ioerr
-w rdswrite -s ioerr -n rdscontrol
-intr ionull
@@ -72,7 +72,7 @@ rfl:
-w rflwrite -s rflseek -n ioerr
-intr ionull
-/* type of a local file system master device */
+/* type of a local file system primary device */
lfs:
on ram
-i lfsinit -o lfsopen -c ioerr
@@ -96,19 +96,34 @@ nam:
-w ioerr -s ioerr -n ioerr
-intr ioerr
+/* type of the main pipe device */
+pipem:
+ on none
+ -i ionull -o pipe_open -c ioerr
+ -r ioerr -g ioerr -p ioerr
+ -w ioerr -s ioerr -n ioerr
+ -intr ionull
+
+/* type of a pipe pseudo-device */
+pip:
+ on none
+ -i pipe_init -o ioerr -c pipe_close
+ -r pipe_read -g pipe_getc -p pipe_putc
+ -w pipe_write -s ioerr -n ioerr
+ -intr ionull
%%
/* Actual device declarations that each give the name of a device that */
/* will be present in the system */
/* Define the console device to be a tty and specify CSR*/
- CONSOLE is tty on uart csr 0001770 -irq 0052
+ CONSOLE is tty on uart csr 0001770 -irq 0044
/* Define a null device */
NULLDEV is null on nothing
/* Physical Ethernet (raw packet transfer) */
- ETHER0 is eth on quark_eth csr 0 -irq 0053
+ ETHER0 is eth on e1000e csr 0 -irq 0 */
/* Define a namespace device */
NAMESPACE is nam on top
@@ -136,7 +151,7 @@ nam:
RFILE8 is rfl on rfs
RFILE9 is rfl on rfs
- /* Define the local file system master device (one per system) */
+ /* Define the local file system primary device (one per system) */
LFILESYS is lfs on ram
@@ -148,7 +163,23 @@ nam:
LFILE3 is lfl on lfs
LFILE4 is lfl on lfs
LFILE5 is lfl on lfs
-
+
+ /* Main pipe device */
+
+ PIPE is pipem on none
+
+ /* Definitions of actual pipe pseudo devices */
+
+ PIPE0 is pip on none
+ PIPE1 is pip on none
+ PIPE2 is pip on none
+ PIPE3 is pip on none
+ PIPE4 is pip on none
+ PIPE5 is pip on none
+ PIPE6 is pip on none
+ PIPE7 is pip on none
+ PIPE8 is pip on none
+ PIPE9 is pip on none
%%
/* Configuration and Size Constants */
@@ -160,4 +191,6 @@ nam:
#define IRQ_ATH_MISC IRQ_HW4 /* Misc. IRQ is wired to hardware 4 */
#define CLKFREQ 200000000 /* 200 MHz clock */
-#define LF_DISK_DEV RAM0
+#ifndef ETHER0
+#define ETHER0 0
+#endif
diff --git a/config/Makefile b/config/Makefile
index 68a6a47..a5118b1 100644
--- a/config/Makefile
+++ b/config/Makefile
@@ -10,6 +10,7 @@ YACC = ${COMPILER_ROOT}bison -y # Flag enables yacc-compatible filenames
CFLAGS =
LFLAGS = -lfl
+
#
# Name of the configuration program
#
@@ -25,8 +26,11 @@ lex.yy.c: config.l
$(LEX) config.l
y.tab.c: config.y
+ @(if test "x$$LOGNAME" = "xxinu"; then \
+ echo "extern size_t yyleng;"; \
+ else echo "extern int yyleng;"; fi) > .yyleng
$(YACC) config.y
-
+
clean:
rm -f config lex.yy.c y.tab.c
diff --git a/config/conf.c b/config/conf.c
index 4b2724f..be47c97 100644
--- a/config/conf.c
+++ b/config/conf.c
@@ -24,7 +24,7 @@ struct dentry devtab[NDEVS] =
(void *)ttyinit, (void *)ionull, (void *)ionull,
(void *)ttyread, (void *)ttywrite, (void *)ioerr,
(void *)ttygetc, (void *)ttyputc, (void *)ttycontrol,
- (void *)0x3f8, (void *)ttydispatch, 42 },
+ (void *)0x3f8, (void *)ttydispatch, 36 },
/* NULLDEV is null */
{ 1, 0, "NULLDEV",
@@ -38,7 +38,7 @@ struct dentry devtab[NDEVS] =
(void *)ethinit, (void *)ioerr, (void *)ioerr,
(void *)ethread, (void *)ethwrite, (void *)ioerr,
(void *)ioerr, (void *)ioerr, (void *)ethcontrol,
- (void *)0x0, (void *)ethdispatch, 43 },
+ (void *)0x0, (void *)ethdispatch, 0 },
/* NAMESPACE is nam */
{ 3, 0, "NAMESPACE",
@@ -49,7 +49,7 @@ struct dentry devtab[NDEVS] =
/* RDISK is rds */
{ 4, 0, "RDISK",
- (void *)rdsinit, (void *)rdsopen, (void *)rdsclose,
+ (void *)rdsinit, (void *)rdsopen, (void *)ioerr,
(void *)rdsread, (void *)rdswrite, (void *)ioerr,
(void *)ioerr, (void *)ioerr, (void *)rdscontrol,
(void *)0x0, (void *)ionull, 0 },
@@ -185,5 +185,82 @@ struct dentry devtab[NDEVS] =
(void *)lflinit, (void *)ioerr, (void *)lflclose,
(void *)lflread, (void *)lflwrite, (void *)lflseek,
(void *)lflgetc, (void *)lflputc, (void *)lflcontrol,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE is pipem */
+ { 24, 0, "PIPE",
+ (void *)ionull, (void *)pipe_open, (void *)ioerr,
+ (void *)ioerr, (void *)ioerr, (void *)ioerr,
+ (void *)ioerr, (void *)ioerr, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE0 is pip */
+ { 25, 0, "PIPE0",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE1 is pip */
+ { 26, 1, "PIPE1",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE2 is pip */
+ { 27, 2, "PIPE2",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE3 is pip */
+ { 28, 3, "PIPE3",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE4 is pip */
+ { 29, 4, "PIPE4",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE5 is pip */
+ { 30, 5, "PIPE5",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE6 is pip */
+ { 31, 6, "PIPE6",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE7 is pip */
+ { 32, 7, "PIPE7",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE8 is pip */
+ { 33, 8, "PIPE8",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE9 is pip */
+ { 34, 9, "PIPE9",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
(void *)0x0, (void *)ionull, 0 }
};
diff --git a/config/conf.h b/config/conf.h
index cb64009..c9312b6 100644
--- a/config/conf.h
+++ b/config/conf.h
@@ -49,6 +49,17 @@ extern struct dentry devtab[]; /* one entry per device */
#define LFILE3 21 /* type lfl */
#define LFILE4 22 /* type lfl */
#define LFILE5 23 /* type lfl */
+#define PIPE 24 /* type pipem */
+#define PIPE0 25 /* type pip */
+#define PIPE1 26 /* type pip */
+#define PIPE2 27 /* type pip */
+#define PIPE3 28 /* type pip */
+#define PIPE4 29 /* type pip */
+#define PIPE5 30 /* type pip */
+#define PIPE6 31 /* type pip */
+#define PIPE7 32 /* type pip */
+#define PIPE8 33 /* type pip */
+#define PIPE9 34 /* type pip */
/* Control block sizes */
@@ -62,8 +73,10 @@ extern struct dentry devtab[]; /* one entry per device */
#define Nlfs 1
#define Nlfl 6
#define Nnam 1
+#define Npipem 1
+#define Npip 10
-#define NDEVS 24
+#define NDEVS 35
/* Configuration and Size Constants */
@@ -75,4 +88,6 @@ extern struct dentry devtab[]; /* one entry per device */
#define IRQ_ATH_MISC IRQ_HW4 /* Misc. IRQ is wired to hardware 4 */
#define CLKFREQ 200000000 /* 200 MHz clock */
-#define LF_DISK_DEV RAM0
+#ifndef ETHER0
+#define ETHER0 0
+#endif
diff --git a/config/config b/config/config
index 7c4a6f8a923bd69714466ab95172880552045775..0f12e243c181e0510da1c38ba4b2d966b5375668 100755
GIT binary patch
delta 12617
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
delta 12379
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
JbK`9P{|ENAUGo3{
diff --git a/config/config.y b/config/config.y
index f7290b0..33dbfd1 100644
--- a/config/config.y
+++ b/config/config.y
@@ -17,20 +17,12 @@
#include <string.h>
#include <ctype.h>
+/* Avoid warnings for undeclared items */
+
extern char *yytext;
-/*
- Work-around for the type conflict that results from unmatched versions
- of flex and bison (lex and yacc). The idea is to force the new flex
- style so the output file (lex.yy.c) treats yyleng as an int (as was
- done by oldest lex versions) instead of a size_t. We override the
- new flex typedef of yy_size_t.
-*/
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef int yy_size_t;
-#endif
-/* End work-around */
-extern int yyleng;
+#include ".yyleng"
+extern int yylex(void);
+
/********************************************************************************/
diff --git a/config/y.tab.c b/config/y.tab.c
index e37e6ea..8de3cb9 100644
--- a/config/y.tab.c
+++ b/config/y.tab.c
@@ -74,20 +74,12 @@
#include <string.h>
#include <ctype.h>
+/* Avoid warnings for undeclared items */
+
extern char *yytext;
-/*
- Work-around for the type conflict that results from unmatched versions
- of flex and bison (lex and yacc). The idea is to force the new flex
- style so the output file (lex.yy.c) treats yyleng as an int (as was
- done by oldest lex versions) instead of a size_t. We override the
- new flex typedef of yy_size_t.
-*/
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef int yy_size_t;
-#endif
-/* End work-around */
-extern int yyleng;
+#include ".yyleng"
+extern int yylex(void);
+
/********************************************************************************/
@@ -187,7 +179,7 @@ void yyerror(char *);
-#line 191 "y.tab.c"
+#line 183 "y.tab.c"
# ifndef YY_CAST
# ifdef __cplusplus
@@ -726,10 +718,10 @@ static const yytype_int8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 141, 141, 150, 151, 154, 157, 160, 161, 164,
- 167, 170, 171, 174, 175, 176, 177, 178, 179, 180,
- 181, 182, 183, 184, 185, 188, 191, 201, 202, 205,
- 208, 211, 214, 217, 220, 223
+ 0, 133, 133, 142, 143, 146, 149, 152, 153, 156,
+ 159, 162, 163, 166, 167, 168, 169, 170, 171, 172,
+ 173, 174, 175, 176, 177, 180, 183, 193, 194, 197,
+ 200, 203, 206, 209, 212, 215
};
#endif
@@ -1320,139 +1312,139 @@ yyreduce:
switch (yyn)
{
case 3: /* devtypes: %empty */
-#line 150 "config.y"
+#line 142 "config.y"
{ doing = "device definitions"; }
-#line 1326 "y.tab.c"
+#line 1318 "y.tab.c"
break;
case 6: /* tname: IDENT */
-#line 157 "config.y"
+#line 149 "config.y"
{ yyval = newtype(yytext); }
-#line 1332 "y.tab.c"
+#line 1324 "y.tab.c"
break;
case 9: /* theader: ON tonid */
-#line 164 "config.y"
+#line 156 "config.y"
{ yyval = yyvsp[0]; }
-#line 1338 "y.tab.c"
+#line 1330 "y.tab.c"
break;
case 10: /* tonid: IDENT */
-#line 167 "config.y"
+#line 159 "config.y"
{ yyval = addton(yytext); }
-#line 1344 "y.tab.c"
+#line 1336 "y.tab.c"
break;
case 13: /* attr: CSR number */
-#line 174 "config.y"
+#line 166 "config.y"
{ addattr(CSR, yyvsp[0]); }
-#line 1350 "y.tab.c"
+#line 1342 "y.tab.c"
break;
case 14: /* attr: IRQ number */
-#line 175 "config.y"
+#line 167 "config.y"
{ addattr(IRQ, yyvsp[0]); }
-#line 1356 "y.tab.c"
+#line 1348 "y.tab.c"
break;
case 15: /* attr: INTR id */
-#line 176 "config.y"
+#line 168 "config.y"
{ addattr(INTR, 0); }
-#line 1362 "y.tab.c"
+#line 1354 "y.tab.c"
break;
case 16: /* attr: OPEN id */
-#line 177 "config.y"
+#line 169 "config.y"
{ addattr(OPEN, 0); }
-#line 1368 "y.tab.c"
+#line 1360 "y.tab.c"
break;
case 17: /* attr: CLOSE id */
-#line 178 "config.y"
+#line 170 "config.y"
{ addattr(CLOSE, 0); }
-#line 1374 "y.tab.c"
+#line 1366 "y.tab.c"
break;
case 18: /* attr: INIT id */
-#line 179 "config.y"
+#line 171 "config.y"
{ addattr(INIT, 0); }
-#line 1380 "y.tab.c"
+#line 1372 "y.tab.c"
break;
case 19: /* attr: GETC id */
-#line 180 "config.y"
+#line 172 "config.y"
{ addattr(GETC, 0); }
-#line 1386 "y.tab.c"
+#line 1378 "y.tab.c"
break;
case 20: /* attr: PUTC id */
-#line 181 "config.y"
+#line 173 "config.y"
{ addattr(PUTC, 0); }
-#line 1392 "y.tab.c"
+#line 1384 "y.tab.c"
break;
case 21: /* attr: READ id */
-#line 182 "config.y"
+#line 174 "config.y"
{ addattr(READ, 0); }
-#line 1398 "y.tab.c"
+#line 1390 "y.tab.c"
break;
case 22: /* attr: WRITE id */
-#line 183 "config.y"
+#line 175 "config.y"
{ addattr(WRITE, 0); }
-#line 1404 "y.tab.c"
+#line 1396 "y.tab.c"
break;
case 23: /* attr: SEEK id */
-#line 184 "config.y"
+#line 176 "config.y"
{ addattr(SEEK, 0); }
-#line 1410 "y.tab.c"
+#line 1402 "y.tab.c"
break;
case 24: /* attr: CONTROL id */
-#line 185 "config.y"
+#line 177 "config.y"
{ addattr(CONTROL, 0); }
-#line 1416 "y.tab.c"
+#line 1408 "y.tab.c"
break;
case 25: /* id: IDENT */
-#line 188 "config.y"
+#line 180 "config.y"
{ yyval = 0; getattrid(yytext); }
-#line 1422 "y.tab.c"
+#line 1414 "y.tab.c"
break;
case 26: /* number: INTEGER */
-#line 191 "config.y"
+#line 183 "config.y"
{ yyval = config_atoi(yytext, yyleng); }
-#line 1428 "y.tab.c"
+#line 1420 "y.tab.c"
break;
case 27: /* devices: %empty */
-#line 201 "config.y"
+#line 193 "config.y"
{ doing = "interface types"; }
-#line 1434 "y.tab.c"
+#line 1426 "y.tab.c"
break;
case 31: /* dname: IDENT */
-#line 211 "config.y"
+#line 203 "config.y"
{ newdev(yytext); }
-#line 1440 "y.tab.c"
+#line 1432 "y.tab.c"
break;
case 33: /* devisid: IDENT */
-#line 217 "config.y"
+#line 209 "config.y"
{ devisid(yytext); }
-#line 1446 "y.tab.c"
+#line 1438 "y.tab.c"
break;
case 35: /* devonid: IDENT */
-#line 223 "config.y"
+#line 215 "config.y"
{ devonid(yytext); }
-#line 1452 "y.tab.c"
+#line 1444 "y.tab.c"
break;
-#line 1456 "y.tab.c"
+#line 1448 "y.tab.c"
default: break;
}
@@ -1645,7 +1637,7 @@ yyreturnlab:
return yyresult;
}
-#line 226 "config.y"
+#line 218 "config.y"
#include "lex.yy.c"
diff --git a/device/eth/82545EMInit.c b/device/eth/82545EMInit.c
new file mode 100644
index 0000000..8fa48c9
--- /dev/null
+++ b/device/eth/82545EMInit.c
@@ -0,0 +1,525 @@
+/* 82545EMInit.c - _82545EMInit */
+
+#include <xinu.h>
+
+local status _82545EM_init_hw(struct ethcblk *);
+local void _82545EM_reset_hw(struct ethcblk *);
+local void _82545EM_configure_rx(struct ethcblk *);
+local void _82545EM_configure_tx(struct ethcblk *);
+status _82545EM_read_phy_reg(struct ethcblk *, uint32, uint16 *);
+status _82545EM_write_phy_reg(struct ethcblk *, uint32, uint16);
+
+
+/*------------------------------------------------------------------------
+ * _82545EMInit - initialize Intel 82545EM Ethernet NIC
+ *------------------------------------------------------------------------
+ */
+status _82545EMInit(
+ struct ethcblk *ethptr
+ )
+{
+ struct eth_tx_desc* txRingPtr;
+ struct eth_rx_desc* rxRingPtr;
+ uint16 command;
+ int32 i;
+ uint32 rar_low, rar_high, bufptr;
+
+ /* Read PCI configuration information */
+ /* Read I/O base address */
+
+ pci_bios_read_config_dword(ethptr->pcidev, E1000_PCI_IOBASE,
+ (uint32 *)&ethptr->iobase);
+ ethptr->iobase &= ~1;
+ ethptr->iobase &= 0xffff; /* the low bit is set to indicate I/O */
+
+ /* Read interrupt line number */
+
+ pci_bios_read_config_byte (ethptr->pcidev, E1000_PCI_IRQ,
+ (byte *)&(ethptr->dev->dvirq));
+
+ /* Enable PCI bus master, I/O port access */
+
+ pci_bios_read_config_word(ethptr->pcidev, E1000_PCI_COMMAND,
+ &command);
+ command |= E1000_PCI_CMD_MASK;
+ pci_bios_write_config_word(ethptr->pcidev, E1000_PCI_COMMAND,
+ command);
+
+ /* Read the MAC address */
+
+ rar_low = eth_io_readl(ethptr->iobase, E1000_RAL(0));
+ rar_high = eth_io_readl(ethptr->iobase, E1000_RAH(0));
+
+ for (i = 0; i < ETH_ADDR_LEN; i++)
+ ethptr->devAddress[i] = (byte)(rar_low >> (i*8));
+ for (i = 0; i < ETH_ADDR_LEN; i++)
+ ethptr->devAddress[i + 4] = (byte)(rar_high >> (i*8));
+
+ kprintf("MAC address is %02x:%02x:%02x:%02x:%02x:%02x\n",
+ 0xff&ethptr->devAddress[0],
+ 0xff&ethptr->devAddress[1],
+ 0xff&ethptr->devAddress[2],
+ 0xff&ethptr->devAddress[3],
+ 0xff&ethptr->devAddress[4],
+ 0xff&ethptr->devAddress[5]);
+
+ /* Initialize structure pointers */
+
+ ethptr->rxRingSize = E1000_RX_RING_SIZE;
+ ethptr->txRingSize = E1000_TX_RING_SIZE;
+ ethptr->isem = semcreate(0);
+ ethptr->osem = semcreate(ethptr->txRingSize);
+
+ /* Rings must be aligned on a 16-byte boundary */
+
+ ethptr->rxRing = (void *)getmem((ethptr->rxRingSize + 1)
+ * E1000_RDSIZE);
+ ethptr->txRing = (void *)getmem((ethptr->txRingSize + 1)
+ * E1000_TDSIZE);
+ ethptr->rxRing = (void *)(((uint32)ethptr->rxRing + 0xf) & ~0xf);
+ ethptr->txRing = (void *)(((uint32)ethptr->txRing + 0xf) & ~0xf);
+
+ /* Buffers are highly recommended to be allocated on cache-line */
+ /* size (64-byte for E8400) */
+
+ ethptr->rxBufs = (void *)getmem((ethptr->rxRingSize + 1)
+ * ETH_BUF_SIZE);
+ ethptr->txBufs = (void *)getmem((ethptr->txRingSize + 1)
+ * ETH_BUF_SIZE);
+ ethptr->rxBufs = (void *)(((uint32)ethptr->rxBufs + 0x3f)
+ & ~0x3f);
+ ethptr->txBufs = (void *)(((uint32)ethptr->txBufs + 0x3f)
+ & ~0x3f);
+
+ if ( (SYSERR == (uint32)ethptr->rxBufs) ||
+ (SYSERR == (uint32)ethptr->txBufs) ) {
+ return SYSERR;
+ }
+
+ /* Set buffer pointers and rings to zero */
+
+ memset(ethptr->rxBufs, '\0', ethptr->rxRingSize * ETH_BUF_SIZE);
+ memset(ethptr->txBufs, '\0', ethptr->txRingSize * ETH_BUF_SIZE);
+ memset(ethptr->rxRing, '\0', E1000_RDSIZE * ethptr->rxRingSize);
+ memset(ethptr->txRing, '\0', E1000_TDSIZE * ethptr->txRingSize);
+
+ /* Insert the buffer into descriptor ring */
+
+ rxRingPtr = (struct eth_rx_desc *)ethptr->rxRing;
+ bufptr = (uint32)ethptr->rxBufs;
+ for (i = 0; i < ethptr->rxRingSize; i++) {
+ rxRingPtr->buffer_addr = (uint64)bufptr;
+ rxRingPtr++;
+ bufptr += ETH_BUF_SIZE;
+ }
+
+ txRingPtr = (struct eth_tx_desc *)ethptr->txRing;
+ bufptr = (uint32)ethptr->txBufs;
+ for (i = 0; i < ethptr->txRingSize; i++) {
+ txRingPtr->buffer_addr = (uint64)bufptr;
+ txRingPtr++;
+ bufptr += ETH_BUF_SIZE;
+ }
+
+ /* Reset packet buffer allocation to default */
+
+ eth_io_writel(ethptr->iobase, E1000_PBA, E1000_PBA_48K);
+
+ /* Reset the NIC to bring it into a known state and initialize it */
+
+ _82545EM_reset_hw(ethptr);
+
+ /* Initialize the hardware */
+
+ if (_82545EM_init_hw(ethptr) != OK)
+ return SYSERR;
+
+ /* Configure the NIC */
+
+ eth_io_writel(ethptr->iobase, E1000_AIT, 0);
+
+ /* Configure the RX */
+
+ _82545EM_configure_rx(ethptr);
+
+ /* Configure the TX */
+
+ _82545EM_configure_tx(ethptr);
+
+ /* Register the interrupt and enable interrupt */
+
+ set_evec(ethptr->dev->dvirq + IRQBASE, (uint32)ethdispatch);
+ ethIrqEnable(ethptr);
+
+ return OK;
+}
+
+/*------------------------------------------------------------------------
+ * _82545EM_reset_hw - Reset the hardware
+ *------------------------------------------------------------------------
+ */
+local void _82545EM_reset_hw(
+ struct ethcblk *ethptr
+ )
+{
+ uint32 ctrl;
+
+ /* Masking off all interrupts */
+
+ eth_io_writel(ethptr->iobase, E1000_IMC, 0xffffffff);
+
+ /* Disable the Transmit and Receive units. */
+
+ eth_io_writel(ethptr->iobase, E1000_RCTL, 0);
+ eth_io_writel(ethptr->iobase, E1000_TCTL, E1000_TCTL_PSP);
+ eth_io_flush(ethptr->iobase);
+ MDELAY(10);
+
+ ctrl = eth_io_readl(ethptr->iobase, E1000_CTRL);
+
+ /* Issuing a global reset */
+
+ eth_io_writel(ethptr->iobase, E1000_CTRL, ctrl | E1000_CTRL_RST);
+ MDELAY(5);
+
+ eth_io_writel(ethptr->iobase, E1000_IMC, 0xffffffff);
+ eth_io_readl(ethptr->iobase, E1000_ICR);
+}
+
+/*------------------------------------------------------------------------
+ * _82545EM_init_hw - Initialize the hardware
+ *------------------------------------------------------------------------
+ */
+local status _82545EM_init_hw(
+ struct ethcblk *ethptr
+ )
+{
+ uint16 i;
+ uint32 ctrl;
+ uint16 mii_autoneg_adv_reg, mii_1000t_ctrl_reg;
+ uint16 phy_data, phy_ctrl, phy_status;
+
+ /* Setup the receive address */
+ /* Zero out the other receive addresses */
+
+ for (i = 1; i < E1000_82545EM_RAR_ENTRIES; i++) {
+ eth_io_writel(ethptr->iobase, E1000_RAL(i), 0);
+ eth_io_flush(ethptr->iobase);
+ eth_io_writel(ethptr->iobase, E1000_RAH(i), 0);
+ eth_io_flush(ethptr->iobase);
+ }
+
+ /* Zero out the Multicast HASH table */
+
+ for (i = 0; i < E1000_82545EM_MTA_ENTRIES; i++) {
+ eth_io_writel(ethptr->iobase, E1000_MTA + (i << 2), 0);
+ eth_io_flush(ethptr->iobase);
+ }
+
+ /* Configure copper link settings */
+
+ ctrl = eth_io_readl(ethptr->iobase, E1000_CTRL);
+ ctrl |= E1000_CTRL_SLU;
+ ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+ eth_io_writel(ethptr->iobase, E1000_CTRL, ctrl);
+
+ if (_82545EM_read_phy_reg(ethptr, M88E1000_PHY_SPEC_CTRL,
+ &phy_data) != OK)
+ return SYSERR;
+
+ phy_data |= M88E1000_PSCR_AUTO_X_MODE;
+ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
+
+ if (_82545EM_write_phy_reg(ethptr, M88E1000_PHY_SPEC_CTRL,
+ phy_data) != OK)
+ return SYSERR;
+
+ /* Commit the changes. */
+
+ if (_82545EM_read_phy_reg(ethptr, E1000_PHY_CONTROL,
+ &phy_ctrl) != OK)
+ return SYSERR;
+
+ phy_ctrl |= E1000_MII_CR_RESET;
+
+ if (_82545EM_write_phy_reg(ethptr, E1000_PHY_CONTROL,
+ phy_ctrl) != OK)
+ return SYSERR;
+
+ DELAY(1);
+
+ /* Setup autoneg and flow control advertisement and perform */
+ /* autonegotiation. */
+
+ if (_82545EM_read_phy_reg(ethptr, E1000_PHY_AUTONEG_ADV,
+ &mii_autoneg_adv_reg) != OK)
+ return SYSERR;
+
+ if (_82545EM_read_phy_reg(ethptr, E1000_PHY_1000T_CTRL,
+ &mii_1000t_ctrl_reg) != OK)
+ return SYSERR;
+
+ mii_autoneg_adv_reg |= (E1000_NWAY_AR_100TX_FD_CAPS |
+ E1000_NWAY_AR_100TX_HD_CAPS |
+ E1000_NWAY_AR_10T_FD_CAPS |
+ E1000_NWAY_AR_10T_HD_CAPS);
+ mii_1000t_ctrl_reg &= ~E1000_CR_1000T_HD_CAPS;
+ mii_1000t_ctrl_reg |= E1000_CR_1000T_FD_CAPS;
+
+ mii_autoneg_adv_reg &= ~(E1000_NWAY_AR_ASM_DIR |
+ E1000_NWAY_AR_PAUSE);
+
+ if (_82545EM_write_phy_reg(ethptr, E1000_PHY_AUTONEG_ADV,
+ mii_autoneg_adv_reg) != OK)
+ return SYSERR;
+
+ if (_82545EM_write_phy_reg(ethptr, E1000_PHY_1000T_CTRL,
+ mii_1000t_ctrl_reg) != OK)
+ return SYSERR;
+
+ /* Restart auto-negotiation. */
+
+ if (_82545EM_read_phy_reg(ethptr, E1000_PHY_CONTROL,
+ &phy_ctrl) != OK)
+ return SYSERR;
+
+ phy_ctrl |= (E1000_MII_CR_AUTO_NEG_EN |
+ E1000_MII_CR_RESTART_AUTO_NEG);
+
+ if (_82545EM_write_phy_reg(ethptr, E1000_PHY_CONTROL,
+ phy_ctrl) != OK)
+ return SYSERR;
+
+ /* Wait for auto-negotiation to complete */
+
+ for (;;) {
+ if (_82545EM_read_phy_reg(ethptr, E1000_PHY_STATUS,
+ &phy_status) != OK)
+ DELAY(10);
+
+ if (_82545EM_read_phy_reg(ethptr, E1000_PHY_STATUS,
+ &phy_status) != OK)
+ return SYSERR;
+
+ if ((phy_status & E1000_MII_SR_LINK_STATUS) &&
+ (phy_status & E1000_MII_SR_AUTONEG_COMPLETE)) {
+ break;
+ }
+
+ MDELAY(100);
+ }
+
+ ctrl = eth_io_readl(ethptr->iobase, E1000_CTRL);
+ ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
+ eth_io_writel(ethptr->iobase, E1000_CTRL, ctrl);
+
+ return OK;
+}
+
+/*------------------------------------------------------------------------
+ * _82545EM_configure_rx - Configure Receive Unit after Reset
+ *------------------------------------------------------------------------
+ */
+local void _82545EM_configure_rx(
+ struct ethcblk *ethptr
+ )
+{
+ uint32 rctl, rxcsum;
+
+ rctl = eth_io_readl(ethptr->iobase, E1000_RCTL);
+
+ /* Disable receiver while configuring. */
+
+ eth_io_writel(ethptr->iobase, E1000_RCTL, rctl & ~E1000_RCTL_EN);
+
+ /* Enable receiver, accept broadcast packets, no loopback, and */
+ /* free buffer threshold is set to 1/2 RDLEN. */
+
+ rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
+ rctl |= E1000_RCTL_EN |
+ E1000_RCTL_BAM |
+ E1000_RCTL_LBM_NO |
+ E1000_RCTL_RDMTS_HALF;
+
+ /* Do not store bad packets, do not pass MAC control frame, */
+ /* disable long packet receive and CRC strip */
+
+ rctl &= ~(E1000_RCTL_SBP |
+ E1000_RCTL_LPE |
+ E1000_RCTL_SECRC |
+ E1000_RCTL_PMCF);
+
+ /* Setup buffer sizes */
+
+ rctl &= ~(E1000_RCTL_BSEX |
+ E1000_RCTL_SZ_4096);
+ rctl |= E1000_RCTL_SZ_2048;
+
+ /* Set the Receive Delay Timer Register, let driver be notified */
+ /* immediately each time a new packet has been stored in */
+ /* memory */
+
+ eth_io_writel(ethptr->iobase, E1000_RDTR, E1000_RDTR_DEFAULT);
+ eth_io_writel(ethptr->iobase, E1000_RADV, E1000_RADV_DEFAULT);
+
+ /* IRQ moderation */
+
+ eth_io_writel(ethptr->iobase, E1000_ITR,
+ 1000000000 / (E1000_ITR_DEFAULT * 256));
+
+ /* Setup the HW Rx Head and Tail Descriptor Pointers, the Base */
+ /* and Length of the Rx Descriptor Ring */
+
+ eth_io_writel(ethptr->iobase, E1000_RDBAL(0),
+ (uint32)ethptr->rxRing);
+ eth_io_writel(ethptr->iobase, E1000_RDBAH(0), 0);
+ eth_io_writel(ethptr->iobase, E1000_RDLEN(0),
+ E1000_RDSIZE * ethptr->rxRingSize);
+ eth_io_writel(ethptr->iobase, E1000_RDH(0), 0);
+ eth_io_writel(ethptr->iobase, E1000_RDT(0),
+ ethptr->rxRingSize - E1000_RING_BOUNDARY);
+
+ /* Disable Receive Checksum Offload for IPv4, TCP and UDP. */
+
+ rxcsum = eth_io_readl(ethptr->iobase, E1000_RXCSUM);
+ rxcsum &= ~(E1000_RXCSUM_TUOFL | E1000_RXCSUM_IPOFL);
+ eth_io_writel(ethptr->iobase, E1000_RXCSUM, rxcsum);
+
+ /* Enable receiver. */
+
+ eth_io_writel(ethptr->iobase, E1000_RCTL, rctl);
+}
+
+/*------------------------------------------------------------------------
+ * _82545EM_configure_tx - Configure Transmit Unit after Reset
+ *------------------------------------------------------------------------
+ */
+local void _82545EM_configure_tx(
+ struct ethcblk *ethptr
+ )
+{
+ uint32 tctl, tipg, txdctl;
+ uint32 ipgr1, ipgr2;
+
+ /* Set the transmit descriptor write-back policy for both queues */
+
+ txdctl = eth_io_readl(ethptr->iobase, E1000_TXDCTL(0));
+ txdctl &= ~E1000_TXDCTL_WTHRESH;
+ txdctl |= E1000_TXDCTL_GRAN;
+ eth_io_writel(ethptr->iobase, E1000_TXDCTL(0), txdctl);
+
+ /* Program the Transmit Control Register */
+
+ tctl = eth_io_readl(ethptr->iobase, E1000_TCTL);
+ tctl &= ~E1000_TCTL_CT;
+ tctl |= E1000_TCTL_RTLC |
+ E1000_TCTL_EN |
+ E1000_TCTL_PSP |
+ (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT);
+ tctl &= ~E1000_TCTL_COLD;
+ tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT;
+
+ /* Set the default values for the Tx Inter Packet Gap timer */
+
+ tipg = E1000_TIPG_IPGT_COPPER_DEFAULT;
+ ipgr1 = E1000_TIPG_IPGR1_DEFAULT;
+ ipgr2 = E1000_TIPG_IPGR2_DEFAULT;
+ tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT;
+ tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT;
+ eth_io_writel(ethptr->iobase, E1000_TIPG, tipg);
+
+ /* Set the Tx Interrupt Delay register */
+
+ eth_io_writel(ethptr->iobase, E1000_TIDV, E1000_TIDV_DEFAULT);
+ eth_io_writel(ethptr->iobase, E1000_TADV, E1000_TADV_DEFAULT);
+
+ /* Setup the HW Tx Head and Tail descriptor pointers */
+
+ eth_io_writel(ethptr->iobase, E1000_TDBAL(0),
+ (uint32)ethptr->txRing);
+ eth_io_writel(ethptr->iobase, E1000_TDBAH(0), 0);
+ eth_io_writel(ethptr->iobase, E1000_TDLEN(0),
+ E1000_TDSIZE * ethptr->txRingSize);
+ eth_io_writel(ethptr->iobase, E1000_TDH(0), 0);
+ eth_io_writel(ethptr->iobase, E1000_TDT(0), 0);
+
+ eth_io_writel(ethptr->iobase, E1000_TCTL, tctl);
+}
+
+/*------------------------------------------------------------------------
+ * _82545EM_read_phy_reg - Read MDI control register
+ *------------------------------------------------------------------------
+ */
+status _82545EM_read_phy_reg(
+ struct ethcblk *ethptr,
+ uint32 offset,
+ uint16 *data
+ )
+{
+ uint32 i, mdic = 0;
+
+ if (offset > E1000_MAX_PHY_REG_ADDRESS) {
+ return SYSERR;
+ }
+
+ mdic = ((offset << E1000_MDIC_REG_SHIFT) |
+ (E1000_82545EM_MDIC_PHY_ADDR << E1000_MDIC_PHY_SHIFT) |
+ (E1000_MDIC_OP_READ));
+
+ eth_io_writel(ethptr->iobase, E1000_MDIC, mdic);
+
+ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
+ DELAY(50);
+ mdic = eth_io_readl(ethptr->iobase, E1000_MDIC);
+ if (mdic & E1000_MDIC_READY)
+ break;
+ }
+ if (!(mdic & E1000_MDIC_READY)) {
+ return SYSERR;
+ }
+ if (mdic & E1000_MDIC_ERROR) {
+ return SYSERR;
+ }
+ *data = (uint16) mdic;
+
+ return OK;
+}
+
+/*------------------------------------------------------------------------
+ * _82545EM_write_phy_reg - Write MDI control register
+ *------------------------------------------------------------------------
+ */
+status _82545EM_write_phy_reg(
+ struct ethcblk *ethptr,
+ uint32 offset,
+ uint16 data
+ )
+{
+ uint32 i, mdic = 0;
+
+ if (offset > E1000_MAX_PHY_REG_ADDRESS) {
+ return SYSERR;
+ }
+
+ mdic = ( ((uint32)data) |
+ (offset << E1000_MDIC_REG_SHIFT) |
+ (E1000_82545EM_MDIC_PHY_ADDR << E1000_MDIC_PHY_SHIFT) |
+ (E1000_MDIC_OP_WRITE) );
+
+ eth_io_writel(ethptr->iobase, E1000_MDIC, mdic);
+
+ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
+ DELAY(50);
+ mdic = eth_io_readl(ethptr->iobase, E1000_MDIC);
+ if (mdic & E1000_MDIC_READY)
+ break;
+ }
+ if (!(mdic & E1000_MDIC_READY)) {
+ return SYSERR;
+ }
+ if (mdic & E1000_MDIC_ERROR) {
+ return SYSERR;
+ }
+
+ return OK;
+}
diff --git a/device/eth/ethcontrol.c b/device/eth/ethcontrol.c
index ec0e795..e365923 100644
--- a/device/eth/ethcontrol.c
+++ b/device/eth/ethcontrol.c
@@ -1,20 +1,22 @@
-/* ethcontrol.c - ethcontrol */
+/* ethcontrol.c - ethcontrol, ethIrqEnable, ethIrqDisable */
#include <xinu.h>
/*------------------------------------------------------------------------
- * ethcontrol - implement control function for a quark ethernet device
+ * ethcontrol - implement control function for an eth device
*------------------------------------------------------------------------
*/
-devcall ethcontrol (
- struct dentry *devptr, /* entry in device switch table */
+devcall ethcontrol(
+ struct dentry *devptr, /* entry in device switch table */
int32 func, /* control function */
- int32 arg1, /* argument 1, if needed */
+ int32 arg1, /* argument 1, if needed */
int32 arg2 /* argument 2, if needed */
)
{
- struct ethcblk *ethptr; /* Ethertab entry pointer */
- int32 retval = OK; /* Return value of cntl function*/
+ struct ethcblk *ethptr; /* pointer to control block */
+ uint32 rar_low, rar_high;
+ uint8 *addr;
+
ethptr = &ethertab[devptr->dvminor];
@@ -23,25 +25,61 @@ devcall ethcontrol (
/* Get MAC address */
case ETH_CTRL_GET_MAC:
- memcpy((byte *)arg1, ethptr->devAddress,
+ memcpy((byte *)arg1, ethptr->devAddress,
ETH_ADDR_LEN);
break;
- /* Add a multicast address */
+ case ETH_CTRL_SET_MAC:
+ addr = (uint8 *)arg1;
+ rar_low = ((uint32) addr[0] |
+ ((uint32) addr[1] << 8) |
+ ((uint32) addr[2] << 16) |
+ ((uint32) addr[3] << 24));
- case ETH_CTRL_ADD_MCAST:
- retval = ethmcast_add(ethptr, (byte *)arg1);
- break;
+ rar_high = ((uint32) addr[4] |
+ ((uint32) addr[5] << 8));
- /* Remove a multicast address */
+ if (rar_low || rar_high)
+ rar_high |= E1000_RAH_AV;
- case ETH_CTRL_REMOVE_MCAST:
- retval = ethmcast_remove(ethptr, (byte *)arg1);
+ eth_io_writel(ethptr->iobase, E1000_RAL(arg2),
+ rar_low);
+ eth_io_flush(ethptr->iobase);
+ eth_io_writel(ethptr->iobase, E1000_RAH(arg2),
+ rar_high);
+ eth_io_flush(ethptr->iobase);
+
break;
default:
return SYSERR;
}
- return retval;
+ return OK;
+}
+
+/*------------------------------------------------------------------------
+ * ethIrqDisable - Mask off interrupt generation on the NIC
+ *------------------------------------------------------------------------
+ */
+void ethIrqDisable(
+ struct ethcblk *ethptr
+ )
+{
+ eth_io_writel(ethptr->iobase, E1000_IMC, ~0);
+
+ eth_io_flush(ethptr->iobase);
+}
+
+/*------------------------------------------------------------------------
+ * eth_irq_enable - Enable default interrupt generation settings
+ *------------------------------------------------------------------------
+ */
+void ethIrqEnable(
+ struct ethcblk *ethptr
+ )
+{
+ eth_io_writel(ethptr->iobase, E1000_IMS, E1000_IMS_ENABLE_MASK);
+
+ eth_io_flush(ethptr->iobase);
}
diff --git a/device/eth/ethhandler.c b/device/eth/ethhandler.c
index 415f7aa..29ac94a 100644
--- a/device/eth/ethhandler.c
+++ b/device/eth/ethhandler.c
@@ -3,125 +3,132 @@
#include <xinu.h>
/*------------------------------------------------------------------------
- * ethhandler - Interrupt handler for Intel Quark Ethernet
+ * eth_rxPackets - handler for receiver interrupts
*------------------------------------------------------------------------
*/
-interrupt ethhandler(void)
+local void eth_rxPackets(
+ struct ethcblk *ethptr /* ptr to control block */
+ )
{
- struct ethcblk *ethptr; /* Ethertab entry pointer */
- struct eth_q_csreg *csrptr; /* Pointer to Ethernet CRSs */
- struct eth_q_tx_desc *tdescptr;/* Pointer to tx descriptor */
- struct eth_q_rx_desc *rdescptr;/* Pointer to rx descriptor */
- volatile uint32 sr; /* Copy of status register */
- uint32 count; /* Variable used to count pkts */
+ struct eth_rx_desc *descptr;/* ptr to ring descriptor */
+ uint32 tail; /* pos to insert next packet */
+ uint32 status; /* status of ring descriptor */
+ int numdesc; /* num. of descriptor reclaimed */
- ethptr = &ethertab[devtab[ETHER0].dvminor];
+ for (numdesc = 0; numdesc < ethptr->rxRingSize; numdesc++) {
- csrptr = (struct eth_q_csreg *)ethptr->csr;
+ /* Insert new arrived packet to the tail */
- /* Copy the status register into a local variable */
+ tail = ethptr->rxTail;
+ descptr = (struct eth_rx_desc *)ethptr->rxRing + tail;
+ status = descptr->status;
- sr = csrptr->sr;
-
- /* If there is no interrupt pending, return */
+ if (status == 0) {
+ break;
+ }
- if((csrptr->sr & ETH_QUARK_SR_NIS) == 0) {
- return;
+ ethptr->rxTail
+ = (ethptr->rxTail + 1) % ethptr->rxRingSize;
}
- /* Acknowledge the interrupt */
-
- csrptr->sr = sr;
-
- /* Check status register to figure out the source of interrupt */
-
- if (sr & ETH_QUARK_SR_TI) { /* Transmit interrupt */
-
- /* Pointer to the head of transmit desc ring */
-
- tdescptr = (struct eth_q_tx_desc *)ethptr->txRing +
- ethptr->txHead;
+ signaln(ethptr->isem, numdesc);
- /* Start packet count at zero */
-
- count = 0;
-
- /* Repeat until we process all the descriptor slots */
+ return;
+}
- while(ethptr->txHead != ethptr->txTail) {
+/*------------------------------------------------------------------------
+ * eth_txPackets - handler for transmitter interrupts
+ *------------------------------------------------------------------------
+ */
+local void eth_txPackets(
+ struct ethcblk *ethptr /* ptr to control block */
+ )
+{
+ struct eth_tx_desc *descptr;/* ptr to ring descriptor */
+ uint32 head; /* pos to reclaim descriptor */
+ char *pktptr; /* ptr used during packet copy */
+ int numdesc; /* num. of descriptor reclaimed */
- /* If the descriptor is owned by DMA, stop here */
+ for (numdesc = 0; numdesc < ethptr->txRingSize; numdesc++) {
+ head = ethptr->txHead;
+ descptr = (struct eth_tx_desc *)ethptr->txRing + head;
- if(tdescptr->ctrlstat & ETH_QUARK_TDCS_OWN) {
- break;
- }
+ if (!(descptr->upper.data & E1000_TXD_STAT_DD))
+ break;
- /* Descriptor was processed; increment count */
+ /* Clear the write-back descriptor and buffer */
- count++;
+ descptr->lower.data = 0;
+ descptr->upper.data = 0;
+ pktptr = (char *)((uint32)(descptr->buffer_addr &
+ ADDR_BIT_MASK));
+ memset(pktptr, '\0', ETH_BUF_SIZE);
- /* Go to the next descriptor */
+ ethptr->txHead
+ = (ethptr->txHead + 1) % ethptr->txRingSize;
+ }
- tdescptr += 1;
+ signaln(ethptr->osem, numdesc);
- /* Increment the head of the transmit desc ring */
+ return;
+}
- ethptr->txHead += 1;
- if(ethptr->txHead >= ethptr->txRingSize) {
- ethptr->txHead = 0;
- tdescptr = (struct eth_q_tx_desc *)
- ethptr->txRing;
- }
- }
- /* 'count' packets were processed by DMA, and slots are */
- /* now free; signal the semaphore accordingly */
+/*------------------------------------------------------------------------
+ * ethhandler - decode and handle interrupt from an E1000 device
+ *------------------------------------------------------------------------
+ */
+interrupt ethhandler(void)
+{
+ uint32 status;
+ struct dentry *devptr; /* address of device control blk*/
+ struct ethcblk *ethptr; /* ptr to control block */
- signaln(ethptr->osem, count);
+ /* Initialize structure pointers */
- }
- if(sr & ETH_QUARK_SR_RI) { /* Receive interrupt */
+ devptr = (struct dentry *) &devtab[ETHER0];
+
+ /* Obtain a pointer to the tty control block */
- /* Get the pointer to the tail of the receive desc list */
+ ethptr = &ethertab[devptr->dvminor];
- rdescptr = (struct eth_q_rx_desc *)ethptr->rxRing +
- ethptr->rxTail;
+ /* Invoke the device-specific interrupt handler */
- count = 0; /* Start packet count at zero */
+ /* Disable device interrupt */
- /* Repeat until we have received */
- /* maximum no. packets that can fit in queue */
+ ethIrqDisable(ethptr);
- while(count <= ethptr->rxRingSize) {
+ /* Obtain status bits from device */
- /* If the descriptor is owned by the DMA, stop */
+ status = eth_io_readl(ethptr->iobase, E1000_ICR);
- if(rdescptr->status & ETH_QUARK_RDST_OWN) {
- break;
- }
+ /* Not our interrupt */
- /* Descriptor was processed; increment count */
- count++;
+ if (status == 0) {
+ ethIrqEnable(ethptr);
+ return;
+ }
- /* Go to the next descriptor */
+ resched_cntl(DEFER_START);
- rdescptr += 1;
+ if (status & E1000_ICR_LSC) {
+ }
- /* Increment the tail index of the rx desc ring */
+ if (status & E1000_ICR_RXT0) {
+ ethptr->rxIrq++;
+ eth_rxPackets(ethptr);
+ }
- ethptr->rxTail += 1;
- if(ethptr->rxTail >= ethptr->rxRingSize) {
- ethptr->rxTail = 0;
- rdescptr = (struct eth_q_rx_desc *)
- ethptr->rxRing;
- }
- }
+ if (status & E1000_ICR_TXDW) {
+ ethptr->txIrq++;
+ eth_txPackets(ethptr);
+ }
- /* 'count' packets were received and are available, */
- /* so signal the semaphore accordingly */
+ /* Enable device interrupt */
- signaln(ethptr->isem, count);
- }
+ ethIrqEnable(ethptr);
+
+ resched_cntl(DEFER_STOP);
return;
}
diff --git a/device/eth/ethinit.c b/device/eth/ethinit.c
index 0abd63f..59b18cd 100644
--- a/device/eth/ethinit.c
+++ b/device/eth/ethinit.c
@@ -1,320 +1,55 @@
-/* ethinit.c - ethinit, eth_phy_read, eth_phy_write */
+/* ethinit.c - ethinit */
#include <xinu.h>
-struct ethcblk ethertab[1];
+#ifndef Neth
+#define Neth 1
+#endif
+struct ethcblk ethertab[Neth]; /* Ethernet control blocks */
/*------------------------------------------------------------------------
- * eth_phy_read - Read a PHY register
+ * ethinit - Initialize Ethernet device structures
*------------------------------------------------------------------------
*/
-uint16 eth_phy_read (
- volatile struct eth_q_csreg *csrptr, /* CSR address */
- uint32 regnum /* Register */
+devcall ethinit (
+ struct dentry *devptr
)
{
- uint32 retries; /* No. of retries for read */
+ struct ethcblk *ethptr;
+ int32 dinfo; /* device information */
- /* Wait for the MII to be ready */
-
- while(csrptr->gmiiar & ETH_QUARK_GMIIAR_GB);
-
- /* Prepare the GMII address register for read transaction */
-
- csrptr->gmiiar =
- (1 << 11) | /* Physical Layer Address = 1 */
- (regnum << 6) | /* PHY Register Number */
- (ETH_QUARK_GMIIAR_CR) | /* GMII Clock Range 100-150MHz*/
- (ETH_QUARK_GMIIAR_GB); /* Start the transaction */
-
- /* Wait for the transaction to complete */
-
- retries = 0;
- while(csrptr->gmiiar & ETH_QUARK_GMIIAR_GB) {
- DELAY(ETH_QUARK_INIT_DELAY);
- if((++retries) > ETH_QUARK_MAX_RETRIES)
- return 0;
- }
-
- /* Transaction is complete, read the PHY register value from */
- /* the GMII data register */
- return (uint16)csrptr->gmiidr;
-}
-
-/*------------------------------------------------------------------------
- * eth_phy_write - Write a PHY register
- *------------------------------------------------------------------------
- */
-void eth_phy_write (
- volatile struct eth_q_csreg *csrptr, /* CSR address */
- uint32 regnum, /* Register */
- uint16 value /* Value to write */
- )
-{
- uint32 retries; /* No. of retries for write */
-
- /* Wait for the MII to be ready */
-
- while(csrptr->gmiiar & ETH_QUARK_GMIIAR_GB);
-
- /* Write the value to GMII data register */
-
- csrptr->gmiidr = (uint32)value;
-
- /* Prepare the GMII address register for write transaction */
-
- csrptr->gmiiar =
- (1 << 11) | /* Physical Layer Address = 1 */
- (regnum << 6) | /* PHY Register Number */
- (ETH_QUARK_GMIIAR_CR) | /* GMII Clock Range 100-150MHz*/
- (ETH_QUARK_GMIIAR_GW) | /* Write transaction */
- (ETH_QUARK_GMIIAR_GB); /* Start the transaction */
-
- /* Wait till the transaction is complete */
-
- retries = 0;
- while(csrptr->gmiiar & ETH_QUARK_GMIIAR_GB) {
- DELAY(ETH_QUARK_INIT_DELAY);
- if((++retries) > ETH_QUARK_MAX_RETRIES)
- return;
- }
-}
-
-/*------------------------------------------------------------------------
- * eth_phy_reset - Reset an Ethernet PHY
- *------------------------------------------------------------------------
- */
-int32 eth_phy_reset (
- volatile struct eth_q_csreg *csrptr /* CSR address */
- )
-{
- uint16 value; /* Variable to read in PHY registers */
- uint32 retries; /* No. of retries for reset */
-
- /* Read the PHY control register (register 0) */
-
- value = eth_phy_read(csrptr, 0);
-
- /* Set bit 15 in control register to reset the PHY */
-
- eth_phy_write(csrptr, 0, (value | 0x8000));
-
- /* Wait for PHY reset process to complete */
-
- retries = 0;
- while(eth_phy_read(csrptr, 0) & 0x8000) {
- DELAY(ETH_QUARK_INIT_DELAY);
- if((++retries) > ETH_QUARK_MAX_RETRIES)
- return SYSERR;
- }
-
- /* See if the PHY has auto-negotiation capability */
-
- value = eth_phy_read(csrptr, 1); /* PHY Status register */
- if(value & 0x0008) { /* Auto-negotiation capable */
-
- /* Wait for the auto-negotiation process to complete */
-
- retries = 0;
- while((eth_phy_read(csrptr, 1) & 0x0020) == 0) {
- DELAY(ETH_QUARK_INIT_DELAY);
- if((++retries) > ETH_QUARK_MAX_RETRIES)
- return SYSERR;
- }
- }
-
- /* Wait for the Link to be Up */
-
- retries = 0;
- while((eth_phy_read(csrptr, 1) & 0x0004) == 0) {
- DELAY(ETH_QUARK_INIT_DELAY);
- if((++retries) > ETH_QUARK_MAX_RETRIES)
- return SYSERR;
- }
-
- DELAY(100000);
-
- kprintf("Ethernet Link is Up\n");
-
- return OK;
-}
-
-/*------------------------------------------------------------------------
- * ethinit - Initialize the Intel Quark Ethernet device
- *------------------------------------------------------------------------
- */
-int32 ethinit (
- struct dentry *devptr /* Entry in device switch table */
- )
-{
- struct ethcblk *ethptr; /* Ptr to control block */
- volatile struct eth_q_csreg *csrptr; /* Ptr to CSR */
- struct eth_q_tx_desc *tx_descs; /* Array of tx descs */
- struct eth_q_rx_desc *rx_descs; /* Array of rx descs */
- struct netpacket *pktptr; /* Pointer to a packet */
- void *temptr; /* Temp. pointer */
- uint32 retries; /* Retry count for reset*/
- int32 retval;
- int32 i;
+ /* Initialize structure pointers */
ethptr = &ethertab[devptr->dvminor];
-
- ethptr->csr = (struct eth_q_csreg *)devptr->dvcsr;
- csrptr = (struct eth_q_csreg *)ethptr->csr;
-
- /* Enable CSR Memory Space, Enable Bus Master */
- pci_write_config_word(ethptr->pcidev, 0x4, 0x0006);
-
- /* Reset the PHY */
- retval = eth_phy_reset(csrptr);
- if(retval == SYSERR) {
- return SYSERR;
- }
-
- /* Reset the Ethernet MAC */
- csrptr->bmr |= ETH_QUARK_BMR_SWR;
-
- /* Wait for the MAC Reset process to complete */
- retries = 0;
- while(csrptr->bmr & ETH_QUARK_BMR_SWR) {
- DELAY(ETH_QUARK_INIT_DELAY);
- if((++retries) > ETH_QUARK_MAX_RETRIES)
- return SYSERR;
- }
-
- /* Transmit Store and Forward */
- csrptr->omr |= ETH_QUARK_OMR_TSF;
-
- /* Set the interrupt handler */
- set_evec(devptr->dvirq, (uint32)devptr->dvintr);
-
- /* Set the MAC Speed = 100Mbps, Full Duplex mode */
- csrptr->maccr |= (ETH_QUARK_MACCR_RMIISPD100 |
- ETH_QUARK_MACCR_DM);
- /* Reset the MMC Counters */
- csrptr->mmccr |= ETH_QUARK_MMC_CNTFREEZ | ETH_QUARK_MMC_CNTRST;
-
- /* Retrieve the MAC address from SPI flash */
- get_quark_pdat_entry_data_by_id(QUARK_MAC1_ID,
- (char*)(ethptr->devAddress), ETH_ADDR_LEN);
-
- kprintf("MAC address is %02x:%02x:%02x:%02x:%02x:%02x\n",
- 0xff&ethptr->devAddress[0],
- 0xff&ethptr->devAddress[1],
- 0xff&ethptr->devAddress[2],
- 0xff&ethptr->devAddress[3],
- 0xff&ethptr->devAddress[4],
- 0xff&ethptr->devAddress[5]);
-
- /* Add the MAC address read from SPI flash into the */
- /* macaddr registers for address filtering */
- csrptr->macaddr0l = (uint32)(*((uint32 *)ethptr->devAddress));
- csrptr->macaddr0h = ((uint32)
- (*((uint16 *)(ethptr->devAddress + 4))) | 0x80000000);
-
- ethptr->txRingSize = ETH_QUARK_TX_RING_SIZE;
-
- /* Allocate memory for the transmit ring */
- temptr = (void *)getmem(sizeof(struct eth_q_tx_desc) *
- (ethptr->txRingSize+1));
- if((int)temptr == SYSERR) {
- return SYSERR;
- }
- memset(temptr, 0, sizeof(struct eth_q_tx_desc) *
- (ethptr->txRingSize+1));
-
- /* The transmit descriptors need to be 4-byte aligned */
- ethptr->txRing = (void *)(((uint32)temptr + 3) & (~3));
-
- /* Allocate memory for transmit buffers */
- ethptr->txBufs = (void *)getmem(sizeof(struct netpacket) *
- (ethptr->txRingSize+1));
- if((int)ethptr->txBufs == SYSERR) {
+ memset(ethptr, '\0', sizeof(struct ethcblk));
+ ethptr->dev = devptr;
+ ethptr->csr = devptr->dvcsr;
+ ethptr->state = ETH_STATE_DOWN;
+ ethptr->mtu = ETH_MTU;
+ ethptr->errors = 0;
+ ethptr->addrLen = ETH_ADDR_LEN;
+ ethptr->rxHead = ethptr->rxTail = 0;
+ ethptr->txHead = ethptr->txTail = 0;
+
+ dinfo = find_pci_device(INTEL_82545EM_DEVICE_ID,
+ INTEL_VENDOR_ID, 0);
+ if (dinfo == SYSERR) {
+ kprintf("Could not find an Intel 82545EM Ethernet\n");
return SYSERR;
}
- ethptr->txBufs = (void *)(((uint32)ethptr->txBufs + 3) & (~3));
+ kprintf("Found Intel 82545EM Ethernet NIC\n");
- /* Pointers to initialize transmit descriptors */
- tx_descs = (struct eth_q_tx_desc *)ethptr->txRing;
- pktptr = (struct netpacket *)ethptr->txBufs;
-
- /* Initialize the transmit descriptors */
- for(i = 0; i < ethptr->txRingSize; i++) {
- tx_descs[i].buffer1 = (uint32)(pktptr + i);
- }
-
- /* Create the output synchronization semaphore */
- ethptr->osem = semcreate(ethptr->txRingSize);
- if((int)ethptr->osem == SYSERR) {
- return SYSERR;
- }
-
- ethptr->rxRingSize = ETH_QUARK_RX_RING_SIZE;
-
- /* Allocate memory for the receive descriptors */
- temptr = (void *)getmem(sizeof(struct eth_q_rx_desc) *
- (ethptr->rxRingSize+1));
- if((int)temptr == SYSERR) {
+ ethptr->type = NIC_TYPE_82545EM;
+ ethptr->pcidev = dinfo;
+ if (_82545EMInit(ethptr) == SYSERR) {
+ kprintf("Could not initialize Intel 82545EM NIC\n");
return SYSERR;
}
- memset(temptr, 0, sizeof(struct eth_q_rx_desc) *
- (ethptr->rxRingSize+1));
-
- /* Receive descriptors must be 4-byte aligned */
- ethptr->rxRing = (struct eth_q_rx_desc *)
- (((uint32)temptr + 3) & (~3));
-
- /* Allocate memory for the receive buffers */
- ethptr->rxBufs = (void *)getmem(sizeof(struct netpacket) *
- (ethptr->rxRingSize+1));
- if((int)ethptr->rxBufs == SYSERR) {
- return SYSERR;
- }
-
- /* Receive buffers must be 4-byte aligned */
- ethptr->rxBufs = (void *)(((uint32)ethptr->rxBufs + 3) & (~3));
-
- /* Pointer to initialize receive descriptors */
- rx_descs = (struct eth_q_rx_desc *)ethptr->rxRing;
- /* Pointer to data buffers */
- pktptr = (struct netpacket *)ethptr->rxBufs;
+ /* Mark Ethernet interface active */
- /* Initialize the receive descriptors */
- for(i = 0; i < ethptr->rxRingSize; i++) {
-
- rx_descs[i].status = ETH_QUARK_RDST_OWN;
- rx_descs[i].buf1size = (uint32)sizeof(struct netpacket);
- rx_descs[i].buffer1 = (uint32)(pktptr + i);
- }
-
- /* Indicate end of ring on last descriptor */
- rx_descs[ethptr->rxRingSize-1].buf1size |= (ETH_QUARK_RDCTL1_RER);
-
- /* Create the input synchronization semaphore */
- ethptr->isem = semcreate(0);
- if((int)ethptr->isem == SYSERR) {
- return SYSERR;
- }
-
- /* Enable the Transmit and Receive Interrupts */
- csrptr->ier = ( ETH_QUARK_IER_NIE |
- ETH_QUARK_IER_TIE |
- ETH_QUARK_IER_RIE );
-
- /* Initialize the transmit descriptor base address */
- csrptr->tdla = (uint32)ethptr->txRing;
-
- /* Initialize the receive descriptor base address */
- csrptr->rdla = (uint32)ethptr->rxRing;
-
- /* Enable the MAC Receiver and Transmitter */
- csrptr->maccr |= (ETH_QUARK_MACCR_TE | ETH_QUARK_MACCR_RE);
-
- /* Start the Transmit and Receive Processes in the DMA */
- csrptr->omr |= (ETH_QUARK_OMR_ST | ETH_QUARK_OMR_SR);
+ ethptr->state = ETH_STATE_UP;
return OK;
-
}
diff --git a/device/eth/ethmcast.c b/device/eth/ethmcast.c
deleted file mode 100644
index ca9bda6..0000000
--- a/device/eth/ethmcast.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* ethmcast.c - ethmcast_add, ethmcast_remove */
-
-#include <xinu.h>
-
-/*------------------------------------------------------------------------
- * ethmcast_add - Add multicast address to Intel Quark Ethernet
- *------------------------------------------------------------------------
- */
-int32 ethmcast_add (
- struct ethcblk *ethptr, /* Ptr to control block */
- byte addr[ETH_ADDR_LEN] /* Mcast addr to add */
- )
-{
- int16 mcast_count;
-
- struct eth_q_csreg *csrptr = (struct eth_q_csreg *)ethptr->csr;
-
- /*Set the Pass all multicast bit in MAC Frame Filter Register */
-
- csrptr->macff |= 0x00000010;
-
- /* Get number of multicast addresses in array */
-
- mcast_count = ethptr->ed_mcc;
-
- /* Add address to array, provided limit is not exceeded */
-
- if(mcast_count < ETH_NUM_MCAST){
- memcpy(ethptr->ed_mca[mcast_count],addr,ETH_ADDR_LEN);
- mcast_count++;
- ethptr->ed_mcc = mcast_count;
- return OK;
- } else {
- return SYSERR;
- }
-}
-
-/*------------------------------------------------------------------------
- * ethmcast_remove - Remove multicast addr. from Intel Quark Ethernet
- *------------------------------------------------------------------------
- */
-int32 ethmcast_remove (
- struct ethcblk *ethptr, /* Pointer to control block */
- byte addr[ETH_ADDR_LEN] /* Mcast address to remove */
- )
-{
- int16 mcast_count;
- int32 i, j;
-
- mcast_count = ethptr->ed_mcc;
-
- /* Find multicast address in the array */
-
- for (i = 0; i < mcast_count; i++) {
- if (memcmp(addr, ethptr->ed_mca[i], ETH_ADDR_LEN) ==0) {
-
- /* Shift values to fill in the hole */
-
- for(j = i; j < mcast_count; j++) {
- memcpy(ethptr->ed_mca[j],
- ethptr->ed_mca[j+1],ETH_ADDR_LEN);
- memset(ethptr->ed_mca[j+1],'0',
- ETH_ADDR_LEN);
- }
- break;
- }
- }
-
- if(i < mcast_count) { /* Mcast address was removed */
-
- /* Decrement the number of multicast addresses */
-
- mcast_count--;
- ethptr->ed_mcc = mcast_count;
- return OK;
- } else { /* Mcast address was not found */
- return SYSERR;
- }
-}
diff --git a/device/eth/ethread.c b/device/eth/ethread.c
index 573f040..0a2ff13 100644
--- a/device/eth/ethread.c
+++ b/device/eth/ethread.c
@@ -3,105 +3,72 @@
#include <xinu.h>
/*------------------------------------------------------------------------
- * ethread - Read an incoming packet on Intel Quark Ethernet
+ * ethread - read a packet from an E1000E device
*------------------------------------------------------------------------
*/
-devcall ethread (
- struct dentry *devptr, /* Entry in device switch table */
- char *buf, /* Buffer for the packet */
- int32 len /* Size of the buffer */
+devcall ethread(
+ struct dentry *devptr, /* entry in device switch table */
+ char *buf, /* buffer to hold packet */
+ int32 len /* length of buffer */
)
{
- struct ethcblk *ethptr; /* Ethertab entry pointer */
- struct eth_q_rx_desc *rdescptr;/* Pointer to the descriptor */
- struct netpacket *pktptr; /* Pointer to packet */
- uint32 framelen = 0; /* Length of the incoming frame */
- bool8 valid_addr;
- int32 i;
+ struct ethcblk *ethptr; /* ptr to entry in ethertab */
+ struct eth_rx_desc *descptr; /* ptr to ring descriptor */
+ char *pktptr; /* ptr used during packet copy */
+ uint32 head; /* head of ring buffer */
+ uint32 status; /* status of entry */
+ uint32 length; /* packet length */
+ int32 retval;
+ uint32 rdt;
ethptr = &ethertab[devptr->dvminor];
- while(1) {
-
- /* Wait until there is a packet in the receive queue */
-
- wait(ethptr->isem);
-
- /* Point to the head of the descriptor list */
-
- rdescptr = (struct eth_q_rx_desc *)ethptr->rxRing +
- ethptr->rxHead;
- pktptr = (struct netpacket*)rdescptr->buffer1;
-
- /* See if destination address is our unicast address */
-
- if(!memcmp(pktptr->net_ethdst, ethptr->devAddress, 6)) {
- valid_addr = TRUE;
-
- /* See if destination address is the broadcast address */
-
- } else if(!memcmp(pktptr->net_ethdst,
- NetData.ethbcast,6)) {
- valid_addr = TRUE;
-
- /* For multicast addresses, see if we should accept */
-
- } else {
- valid_addr = FALSE;
- for(i = 0; i < (ethptr->ed_mcc); i++) {
- if(memcmp(pktptr->net_ethdst,
- ethptr->ed_mca[i], 6) == 0){
- valid_addr = TRUE;
- break;
- }
- }
- }
-
- if(valid_addr == TRUE){ /* Accept this packet */
-
- /* Get the length of the frame */
-
- framelen = (rdescptr->status >> 16) & 0x00003FFF;
-
- /* Only return len characters to caller */
-
- if(framelen > len) {
- framelen = len;
- }
-
- /* Copy the packet into the caller's buffer */
-
- memcpy(buf, (void*)rdescptr->buffer1, framelen);
- }
-
- /* Increment the head of the descriptor list */
-
- ethptr->rxHead += 1;
- if(ethptr->rxHead >= ETH_QUARK_RX_RING_SIZE) {
- ethptr->rxHead = 0;
- }
-
- /* Reset the descriptor to max possible frame len */
-
- rdescptr->buf1size = sizeof(struct netpacket);
+ if ((ETH_STATE_UP != ethptr->state)
+ || (len < ETH_HDR_LEN)) {
+ return SYSERR;
+ }
- /* If we reach the end of the ring, mark the descriptor */
+ /* Wait for a packet to arrive */
- if(ethptr->rxHead == 0) {
- rdescptr->rdctl1 |= (ETH_QUARK_RDCTL1_RER);
- }
+ wait(ethptr->isem);
- /* Indicate that the descriptor is ready for DMA input */
+ /* Find out where to pick up the packet */
- rdescptr->status = ETH_QUARK_RDST_OWN;
+ head = ethptr->rxHead;
+ descptr = (struct eth_rx_desc *)ethptr->rxRing + head;
+ status = descptr->status;
- if(valid_addr == TRUE) {
- break;
- }
+ if (!(status & E1000_RXD_STAT_DD)) { /* check for error */
+ kprintf("ethread: packet error!\n");
+ retval = SYSERR;
+ } else { /* pick up the packet */
+ pktptr = (char *)((uint32)(descptr->buffer_addr &
+ ADDR_BIT_MASK));
+ length = descptr->length;
+ memcpy(buf, pktptr, length);
+ retval = length;
+ }
+ /* Clear up the descriptor and the buffer */
+
+ descptr->length = 0;
+ descptr->csum = 0;
+ descptr->status = 0;
+ descptr->errors = 0;
+ descptr->special = 0;
+ memset((char *)((uint32)(descptr->buffer_addr & ADDR_BIT_MASK)),
+ '\0', ETH_BUF_SIZE);
+
+ /* Add newly reclaimed descriptor to the ring */
+
+ if (ethptr->rxHead % E1000_RING_BOUNDARY == 0) {
+ rdt = eth_io_readl(ethptr->iobase, E1000_RDT(0));
+ rdt = (rdt + E1000_RING_BOUNDARY) % ethptr->rxRingSize;
+ eth_io_writel(ethptr->iobase, E1000_RDT(0), rdt);
}
- /* Return the number of bytes returned from the packet */
-
- return framelen;
+ /* Advance the head pointing to the next ring descriptor which */
+ /* will be ready to be picked up */
+ ethptr->rxHead = (ethptr->rxHead + 1) % ethptr->rxRingSize;
+ return retval;
}
diff --git a/device/eth/ethwrite.c b/device/eth/ethwrite.c
index a5ca850..c1d907e 100644
--- a/device/eth/ethwrite.c
+++ b/device/eth/ethwrite.c
@@ -3,68 +3,72 @@
#include <xinu.h>
/*------------------------------------------------------------------------
- * ethwrite - enqueue packet for transmission on Intel Quark Ethernet
+ * ethwrite - write a packet to an E1000E device
*------------------------------------------------------------------------
*/
-devcall ethwrite (
- struct dentry *devptr, /* Entry in device switch table */
- char *buf, /* Buffer that hols a packet */
- int32 len /* Length of the packet */
+devcall ethwrite(
+ struct dentry *devptr, /* entry in device switch table */
+ void *buf, /* buffer that holds a packet */
+ int32 len /* length of buffer */
)
{
- struct ethcblk *ethptr; /* Pointer to control block */
- struct eth_q_csreg *csrptr; /* Address of device CSRs */
- volatile struct eth_q_tx_desc *descptr; /* Ptr to descriptor */
- uint32 i; /* Counts bytes during copy */
+ struct ethcblk *ethptr; /* ptr to entry in ethertab */
+ struct eth_tx_desc *descptr;/* ptr to ring descriptor */
+ char *pktptr; /* ptr used during packet copy */
+ uint32 tail; /* index of ring buffer for pkt */
+ uint32 tdt;
ethptr = &ethertab[devptr->dvminor];
- csrptr = (struct eth_q_csreg *)ethptr->csr;
+ /* Verify Ethernet interface is up and arguments are valid */
- /* Wait for an empty slot in the transmit descriptor ring */
-
- wait(ethptr->osem);
-
- /* Point to the tail of the descriptor ring */
-
- descptr = (struct eth_q_tx_desc *)ethptr->txRing + ethptr->txTail;
-
- /* Increment the tail index and wrap, if needed */
-
- ethptr->txTail += 1;
- if(ethptr->txTail >= ethptr->txRingSize) {
- ethptr->txTail = 0;
+ if ((ETH_STATE_UP != ethptr->state)
+ || (len < ETH_HDR_LEN)
+ || (len > ETH_MAX_PKT_LEN) ) {
+ return SYSERR;
}
- /* Add packet length to the descriptor */
+ /* If padding of short packet is enabled, the value in TX */
+ /* descriptor length feild should be not less than 17 */
+ /* bytes */
- descptr->buf1size = len;
+ if (len < 17)
+ return SYSERR;
- /* Copy packet into the buffer associated with the descriptor */
-
- for(i = 0; i < len; i++) {
- *((char *)descptr->buffer1 + i) = *((char *)buf + i);
- }
+ /* Wait for a free ring slot */
- /* Mark the descriptor if we are at the end of the ring */
-
- if(ethptr->txTail == 0) {
- descptr->ctrlstat = ETH_QUARK_TDCS_TER;
- } else {
- descptr->ctrlstat = 0;
- }
-
- /* Initialize the descriptor */
-
- descptr->ctrlstat |=
- (ETH_QUARK_TDCS_OWN | /* The desc is owned by DMA */
- ETH_QUARK_TDCS_IC | /* Interrupt after transfer */
- ETH_QUARK_TDCS_LS | /* Last segment of packet */
- ETH_QUARK_TDCS_FS); /* First segment of packet */
-
- /* Un-suspend DMA on the device */
-
- csrptr->tpdr = 1;
+ wait(ethptr->osem);
- return OK;
+ /* Find the tail of the ring to insert packet */
+
+ tail = ethptr->txTail;
+ descptr = (struct eth_tx_desc *)ethptr->txRing + tail;
+
+ /* Copy packet to transmit ring buffer */
+
+ pktptr = (char *)((uint32)descptr->buffer_addr & ADDR_BIT_MASK);
+ memcpy(pktptr, buf, len);
+
+ /* Insert transmitting command and length */
+
+ descptr->lower.data &= E1000_TXD_CMD_DEXT;
+ descptr->lower.data = E1000_TXD_CMD_IDE |
+ E1000_TXD_CMD_RS |
+ E1000_TXD_CMD_IFCS |
+ E1000_TXD_CMD_EOP |
+ len;
+ descptr->upper.data = 0;
+
+ /* Add descriptor by advancing the tail pointer */
+
+ tdt = eth_io_readl(ethptr->iobase, E1000_TDT(0));
+ tdt = (tdt + 1) % ethptr->txRingSize;
+ eth_io_writel(ethptr->iobase, E1000_TDT(0), tdt);
+
+ /* Advance the ring tail pointing to the next available ring */
+ /* descriptor */
+
+ ethptr->txTail = (ethptr->txTail + 1) % ethptr->txRingSize;
+
+ return len;
}
diff --git a/device/lfs/lfdballoc.c b/device/lfs/lfdballoc.c
index bafb418..b61b299 100644
--- a/device/lfs/lfdballoc.c
+++ b/device/lfs/lfdballoc.c
@@ -2,7 +2,7 @@
#include <xinu.h>
-#define DFILL '+' /* character used to fill a disk block */
+#define DFILL '+' /* Character used to fill an empty block*/
/*------------------------------------------------------------------------
* lfdballoc - Allocate a new data block from free list on disk
@@ -24,7 +24,7 @@ dbid32 lfdballoc (
}
retval = read(Lf_data.lf_dskdev, (char *)dbuff, dnum);
if (retval == SYSERR) {
- panic("lfdballoc cannot read disk block\n\r");
+ panic("lfdballoc cannot read disk block\n");
}
/* Unlink d-block from in-memory directory */
diff --git a/device/lfs/lflcontrol.c b/device/lfs/lflcontrol.c
index a023098..1010172 100644
--- a/device/lfs/lflcontrol.c
+++ b/device/lfs/lflcontrol.c
@@ -40,7 +40,7 @@ devcall lflcontrol (
return retval;
default:
- kprintf("lfcontrol: function %d not valid\n\r", func);
+ kprintf("lfcontrol: function %d not valid\n", func);
signal(lfptr->lfmutex);
return SYSERR;
}
diff --git a/device/lfs/lfscheck.c b/device/lfs/lfscheck.c
index 9f13dc9..7fc24f7 100644
--- a/device/lfs/lfscheck.c
+++ b/device/lfs/lfscheck.c
@@ -32,7 +32,8 @@ status lfscheck (
return SYSERR;
}
- /* Extra sanity check - verify file count is positive */
+ /* Extra sanity check - verify file count is non-negative */
+
if (dirptr->lfd_nfiles < 0){
return SYSERR;
}
diff --git a/device/lfs/lfsckfmt.c b/device/lfs/lfsckfmt.c
index f6e8da7..2251583 100644
--- a/device/lfs/lfsckfmt.c
+++ b/device/lfs/lfsckfmt.c
@@ -27,7 +27,7 @@ status lfsckfmt (
if (retval == SYSERR) {
panic("cannot read directory");
}
- kprintf("Have read directory from disk device %d\n\r",
+ kprintf("Have read directory from disk device %d\n",
disk);
/* Check to see if directory contains a Xinu file system */
@@ -41,25 +41,25 @@ status lfsckfmt (
lfiblks = 0;
nextib = dir.lfd_ifree;
- kprintf("initial index block is %d\n\r", nextib);
+ kprintf("initial index block is %d\n", nextib);
while (nextib != LF_INULL) {
lfiblks++;
lfibget(disk, nextib, &iblock);
nextib = iblock.ib_next;
}
ibsectors = (lfiblks + 6) /7;
- kprintf("Found %d index blocks (%d sectors)\n\r", lfiblks, ibsectors);
+ kprintf("Found %d index blocks (%d sectors)\n", lfiblks, ibsectors);
/* Follow data block list */
dblks = 0;
nextdb = dir.lfd_dfree;
- kprintf("initial data block is %d\n\r", nextdb);
+ kprintf("initial data block is %d\n", nextdb);
while (nextdb != LF_DNULL) {
dblks++;
read(disk, (char *)&dblock, nextdb);
nextdb = dblock.lf_nextdb;
}
- kprintf("Found %d data blocks\n\r", dblks);
+ kprintf("Found %d data blocks\n", dblks);
return OK;
}
diff --git a/device/lfs/lfscreate.c b/device/lfs/lfscreate.c
index 68ba943..cf243e9 100644
--- a/device/lfs/lfscreate.c
+++ b/device/lfs/lfscreate.c
@@ -24,6 +24,14 @@ status lfscreate (
int32 retval; /* Return value from func call */
int32 i; /* Loop index */
+ /* See if the disk device is valid or if a disk has already */
+ /* been formatted */
+
+ if ( isbaddev(disk) || (Lf_data.lf_dskdev >= 0) ) {
+ return SYSERR;
+ }
+ Lf_data.lf_dskdev = disk;
+
/* Compute total sectors on disk */
sectors = dsiz / LF_BLKSIZ; /* Truncate to full sector */
@@ -40,7 +48,14 @@ status lfscreate (
/* Create an initial directory */
memset((char *)&dir, NULLCH, sizeof(struct lfdir));
+ dir.lfd_fsysid = LFS_ID;
dir.lfd_nfiles = 0;
+ dir.lfd_allzeros = 0;
+ dir.lfd_allones = 0xffffffff;
+ dir.lfd_revid = ((LFS_ID>>24) & 0x000000ff) |
+ ((LFS_ID>> 8) & 0x0000ff00) |
+ ((LFS_ID<< 8) & 0x00ff0000) |
+ ((LFS_ID<<24) & 0xff000000) ;
dbindex= (dbid32)(ibsectors + 1);
dir.lfd_dfree = dbindex;
dblks = sectors - ibsectors - 1;
diff --git a/device/lfs/lfsinit.c b/device/lfs/lfsinit.c
index d9ab814..67581e5 100644
--- a/device/lfs/lfsinit.c
+++ b/device/lfs/lfsinit.c
@@ -5,16 +5,16 @@
struct lfdata Lf_data;
/*------------------------------------------------------------------------
- * lfsinit - Initialize the local file system master device
+ * lfsinit - Initialize the local file system primary device
*------------------------------------------------------------------------
*/
devcall lfsinit (
struct dentry *devptr /* Entry in device switch table */
)
{
- /* Assign ID of disk device that will be used */
+ /* Indicate that no disk device has been selected */
- Lf_data.lf_dskdev = LF_DISK_DEV;
+ Lf_data.lf_dskdev = -1;
/* Create a mutual exclusion semaphore */
diff --git a/device/lfs/lfsopen.c b/device/lfs/lfsopen.c
index 6ed5590..0c46936 100644
--- a/device/lfs/lfsopen.c
+++ b/device/lfs/lfsopen.c
@@ -24,6 +24,12 @@ devcall lfsopen (
int32 retval; /* Value returned from function */
int32 mbits; /* Mode bits */
+ if (Lf_data.lf_dskdev < 0) {
+ kprintf("error: no disk selected for local files ");
+ kprintf("use lfscreate)\n");
+ return SYSERR;
+ }
+
/* Check length of name file (leaving space for NULLCH */
from = name;
diff --git a/device/nam/mount.c b/device/nam/mount.c
index 90ac46f..b85c886 100644
--- a/device/nam/mount.c
+++ b/device/nam/mount.c
@@ -22,10 +22,17 @@ syscall mount(
psiz = namlen(prefix, NM_PRELEN);
rsiz = namlen(replace, NM_REPLLEN);
+ /* Check for table lverflow */
+
+ if (nnames >= NNAMES) {
+ kprintf("Namespace overflow\n");
+ restore(mask);
+ return SYSERR;
+ }
+
/* If arguments are invalid or table is full, return error */
- if ( (psiz == SYSERR) || (rsiz == SYSERR) ||
- (isbaddev(device)) || (nnames >= NNAMES) ) {
+ if ( (psiz == SYSERR) || (rsiz == SYSERR) || isbaddev(device) ) {
restore(mask);
return SYSERR;
}
@@ -34,7 +41,7 @@ syscall mount(
namptr = &nametab[nnames]; /* Next unused entry in table */
- /* copy prefix and replacement strings and record device ID */
+ /* Copy prefix and replacement strings and record device ID */
for (i=0; i<psiz; i++) { /* Copy prefix into table entry */
namptr->nprefix[i] = *prefix++;
diff --git a/device/nam/naminit.c b/device/nam/naminit.c
index df8641b..9ed6ebd 100644
--- a/device/nam/naminit.c
+++ b/device/nam/naminit.c
@@ -64,14 +64,14 @@ status naminit(void)
}
if (len > NM_MAXLEN) {
- kprintf("namespace: device name %s too long\r\n",
+ kprintf("namespace: device name %s too long\n",
devptr->dvname);
continue;
}
retval = mount(tmpstr, NULLSTR, devptr->dvnum);
if (retval == SYSERR) {
- kprintf("namespace: cannot mount device %d\r\n",
+ kprintf("namespace: cannot mount device %d\n",
devptr->dvname);
continue;
}
@@ -79,13 +79,14 @@ status naminit(void)
/* Add other prefixes (longest prefix first) */
- mount("/dev/null", "", NULLDEV);
- mount("/remote/", "remote:", RFILESYS);
- mount("/local/", NULLSTR, LFILESYS);
- mount("/dev/", NULLSTR, SYSERR);
- mount("~/", NULLSTR, LFILESYS);
- mount("/", "root:", RFILESYS);
- mount("", "", LFILESYS);
+ mount("/dev/null", "", NULLDEV);
+ mount("/remote/", NULLSTR, RFILESYS);
+ mount("/local/", NULLSTR, LFILESYS);
+ mount("/tmp/", "tmp-", LFILESYS);
+ mount("/dev/", NULLSTR, SYSERR);
+ mount("~/", NULLSTR, RFILESYS);
+ mount("/", "root:", RFILESYS);
+ mount("", NULLSTR, LFILESYS);
return OK;
}
diff --git a/device/nam/nammap.c b/device/nam/nammap.c
index be8b255..3019d75 100644
--- a/device/nam/nammap.c
+++ b/device/nam/nammap.c
@@ -31,9 +31,9 @@ devcall nammap(
for (iter=0; iter<nnames ; iter++) {
newdev = namrepl(tmpname, newname);
if (newdev != namdev) {
- namcpy(tmpname, newname, NM_MAXLEN);
return newdev; /* Either valid ID or SYSERR */
}
+ namcpy(tmpname, newname, NM_MAXLEN);
}
return SYSERR;
}
@@ -81,9 +81,9 @@ did32 namrepl(
}
/* Found a match - check that replacement string plus */
- /* bytes remaining at the end of the original name will */
- /* fit into new name buffer. Ignore null on replacement*/
- /* string, but keep null on remainder of name. */
+ /* bytes remaining at the end of the original name will*/
+ /* fit into new buffer. Ignore null on replacement */
+ /* string, but keep null on remainder of name. */
olen = namlen(name ,NM_MAXLEN);
rlen = namlen(namptr->nreplace,NM_MAXLEN) - 1;
diff --git a/device/pipe/pipe_close.c b/device/pipe/pipe_close.c
new file mode 100644
index 0000000..5bd8d8f
--- /dev/null
+++ b/device/pipe/pipe_close.c
@@ -0,0 +1,57 @@
+/* pipe_close.c - pipe_close */
+
+#include <xinu.h>
+
+/*------------------------------------------------------------------------
+ * pipe_close - Close a pipe
+ *------------------------------------------------------------------------
+*/
+
+devcall pipe_close (
+ struct dentry *devptr /* Entry in device switch table */
+ )
+{
+ struct pipecblk *piptr; /* Pointer to pipe control block*/
+
+ /* Note: because both a writing process and reading process use */
+ /* a given pipe, both will close the pipe. Conceptually, the */
+ /* first call moves the pipe to a read-only state and marks the*/
+ /* end-of-ile. The second call deallocates the pipe device, */
+ /* making it available for reuse. */
+
+ piptr = &pipetab[devptr->dvminor];
+
+ /* If pipe is completely closed, return SYSERR */
+
+ if (piptr->pstate == PIPE_FREE) {
+ return SYSERR;
+ }
+
+ /* First call to close -- move to EOF state */
+
+ if (piptr->pstate == PIPE_OPEN) {
+ piptr->pstate = PIPE_EOF;
+ resched_cntl(DEFER_START);
+ if (semcount(piptr->pcsem) < 0) {
+ /* Pipe is empty and consumer is blocked, so */
+ /* Allow the consumer to run */
+ semreset(piptr->pcsem, 0);
+ }
+
+ /* Allow a blocked producer to proceed, if any */
+
+ if (semcount(piptr->ppsem) < 0) {
+ semreset(piptr->ppsem, 0);
+ }
+ resched_cntl(DEFER_STOP);
+ return OK;
+ }
+
+ /* Second call to close - deallocate the pipe device */
+
+ piptr->pstate = PIPE_FREE;
+ semdelete(piptr->ppsem);
+ semdelete(piptr->pcsem);
+ piptr->pavail = 0;
+ return OK;
+}
diff --git a/device/pipe/pipe_getc.c b/device/pipe/pipe_getc.c
new file mode 100644
index 0000000..04488f9
--- /dev/null
+++ b/device/pipe/pipe_getc.c
@@ -0,0 +1,68 @@
+/* pipe_getc.c - pipe_getc */
+
+#include <xinu.h>
+
+/*------------------------------------------------------------------------
+ * pipe_getc - read one character from a pipe device
+ *------------------------------------------------------------------------
+ */
+devcall pipe_getc(
+ struct dentry *devptr /* Entry in device switch table */
+ )
+{
+ char ch; /* Byte of data from the buffer */
+ struct pipecblk *piptr; /* Pointer to pipe control block*/
+
+ /* Get a pointer to the control block for this pipe */
+
+ piptr = &pipetab[devptr->dvminor];
+
+ /* Check if pipe is not in use or at EOF */
+
+ if (piptr->pstate == PIPE_FREE) {
+ /* The pipe is not available */
+ return SYSERR;
+ }
+ if (piptr->pstate == PIPE_EOF) {
+
+ /* The writer closed the pipe, so return bytes while */
+ /* any remain in the buffer. */
+
+ if (piptr->pavail > 0) {
+ ch = piptr->pbuf[piptr->phead++];
+ if (piptr->phead >= PIPE_BUF_SIZE) {
+ piptr->phead = 0;
+ }
+ piptr->pavail--;
+ return 0xff & ch;
+ }
+ return EOF;
+ }
+
+ /* State is OPEN -- Wait for a byte to be available or a close */
+
+ wait(piptr->pcsem);
+
+ /* If the state changed while we were blocked, the producer must*/
+ /* have called close, possibly after writing bytes to the pipe.*/
+
+ if (piptr->pstate == PIPE_EOF) {
+ if (piptr->pavail <= 0) {
+ /* The buffer is empty */
+ return EOF;
+ }
+ }
+
+ /* A byte is available to be read -- pick up and return the byte*/
+
+ ch = piptr->pbuf[piptr->phead++];
+ if (piptr->phead >= PIPE_BUF_SIZE) {
+ piptr->phead = 0;
+ }
+ piptr->pavail--;
+
+ /* Signal the producer and return the byte */
+
+ signal(piptr->ppsem);
+ return 0xff & ch;
+}
diff --git a/device/pipe/pipe_init.c b/device/pipe/pipe_init.c
new file mode 100644
index 0000000..ae5f8fb
--- /dev/null
+++ b/device/pipe/pipe_init.c
@@ -0,0 +1,22 @@
+/* pipe_init.c - pipe_init */
+
+#include <xinu.h>
+
+struct pipecblk pipetab[Npip];
+
+/*------------------------------------------------------------------------
+ * pipe_init - initialize a pipe pseudo device
+ *------------------------------------------------------------------------
+ */
+devcall pipe_init (
+ struct dentry *devptr /* Entry in device switch table */
+ )
+{
+ struct pipecblk *piptr; /* Pointer to pipe control block*/
+
+ piptr = &pipetab[devptr->dvminor];
+
+ piptr->pstate = PIPE_FREE;
+ piptr->pdevid = devptr->dvnum;
+ return OK;
+}
diff --git a/device/pipe/pipe_open.c b/device/pipe/pipe_open.c
new file mode 100644
index 0000000..a4ede7d
--- /dev/null
+++ b/device/pipe/pipe_open.c
@@ -0,0 +1,37 @@
+/* pipeopen.c - pipeopen */
+
+#include <xinu.h>
+
+/*------------------------------------------------------------------------
+ * pipeopen - open one of the pipe pseudo devices
+ *------------------------------------------------------------------------
+ */
+devcall pipe_open(
+ struct dentry *devptr, /* Entry in device switch table */
+ char *buff, /* Not used */
+ int32 count /* Not used */
+ )
+{
+ struct pipecblk *piptr; /* Pointer to pipe control block*/
+ int i; /* Walks through control blocks */
+
+ /* Find a pipe pseudo device that is available */
+
+ for (i=0; i<Npip; i++) {
+ piptr = &pipetab[i];
+
+ if (piptr->pstate == PIPE_FREE) {
+ break;
+ }
+ }
+ if (i >= Npip) {
+ return SYSERR;
+ }
+
+ piptr->pstate = PIPE_OPEN;
+ piptr->pcsem = semcreate(0);
+ piptr->ppsem = semcreate(PIPE_BUF_SIZE);
+ piptr->phead = piptr->ptail = 0;
+ piptr->pavail= 0;
+ return piptr->pdevid;
+}
diff --git a/device/pipe/pipe_putc.c b/device/pipe/pipe_putc.c
new file mode 100644
index 0000000..83a772d
--- /dev/null
+++ b/device/pipe/pipe_putc.c
@@ -0,0 +1,46 @@
+/* pipeputc.c - pipeputc */
+
+#include <xinu.h>
+
+/*------------------------------------------------------------------------
+ * pipeputc - write one character to a pipe device
+ *------------------------------------------------------------------------
+ */
+devcall pipe_putc(
+ struct dentry *devptr, /* Entry in device switch table */
+ char ch /* Byte to write */
+ )
+{
+ struct pipecblk *piptr; /* Pointer to pipe control block*/
+
+ /* Get a pointer to the control block for this pipe */
+
+ piptr = &pipetab[devptr->dvminor];
+
+ /* Check that the pipe is available for writing */
+
+ if (piptr->pstate != PIPE_OPEN) {
+ return SYSERR;
+ }
+
+ wait(piptr->ppsem);
+
+ /* See if pipe was closed or set to EOF while we were blocked */
+
+ if (piptr->pstate != PIPE_OPEN) {
+ return SYSERR;
+ }
+
+ /* Deposit a byte in next buffer position */
+
+ piptr->pbuf[piptr->ptail++] = ch;
+ if (piptr->ptail >= PIPE_BUF_SIZE) {
+ piptr->ptail = 0;
+ }
+ piptr->pavail++;
+
+ /* Signal the consumer semaphore and return */
+
+ signal(piptr->pcsem);
+ return OK;
+}
diff --git a/device/pipe/pipe_read.c b/device/pipe/pipe_read.c
new file mode 100644
index 0000000..f941a87
--- /dev/null
+++ b/device/pipe/pipe_read.c
@@ -0,0 +1,43 @@
+/* pipe_read.c - pipe_read */
+
+#include <xinu.h>
+
+/*------------------------------------------------------------------------
+ * pipe_read - Read one or more bytes of data from a pipe device
+ *------------------------------------------------------------------------
+ */
+devcall pipe_read(
+ struct dentry *devptr, /* Entry in device switch table */
+ char *buff, /* Buffer for the bytes */
+ int32 count /* Maximum bytes to read */
+ )
+{
+ int32 retval; /* Return from pipegetc */
+ int32 nbytes; /* Number of bytes found */
+
+ if (count <= 0) {
+ return SYSERR;
+ }
+
+ nbytes = 0;
+ while (count > 0) {
+ retval = pipe_getc(devptr);
+ if ( (retval == SYSERR) || (retval == EOF) ) {
+ if (nbytes > 0) {
+ /* Some data already read -- return the */
+ /* data on this call; the next call */
+ /* will return EOF or SYSERR */
+ return nbytes;
+ } else {
+ return retval;
+ }
+ }
+
+ /* Normal case: a data byte has been found */
+
+ *buff++ = 0xff & retval;
+ count--;
+ nbytes++;
+ }
+ return nbytes;
+}
diff --git a/device/pipe/pipe_write.c b/device/pipe/pipe_write.c
new file mode 100644
index 0000000..8f0b654
--- /dev/null
+++ b/device/pipe/pipe_write.c
@@ -0,0 +1,40 @@
+/* pipe_write.c - pipe_write */
+
+#include <xinu.h>
+
+/*------------------------------------------------------------------------
+ * pipe_write - write one or more bytes of data to a pipe device
+ *------------------------------------------------------------------------
+ */
+devcall pipe_write(
+ struct dentry *devptr, /* Entry in device switch table */
+ char *buff, /* Buffer for the bytes */
+ int32 count /* Count of bytes to write */
+ )
+{
+ int32 nbytes; /* Count of bytes written */
+ int32 retval; /* Return value from pipe_putc */
+
+ /* Ensure count is valid */
+
+ if (count <= 0) {
+ return SYSERR;
+ }
+
+ nbytes = 0;
+ while(count > 0) {
+ retval = pipe_putc(devptr, *buff++);
+ if (retval == SYSERR) {
+ if (nbytes > 0) {
+ /* Report what has been written on this */
+ /* call and SYSERR on next call */
+ return nbytes;
+ } else {
+ return SYSERR;
+ }
+ }
+ nbytes++;
+ count--;
+ }
+ return nbytes;
+}
diff --git a/device/rds/Design_Notes b/device/rds/Design_Notes
new file mode 100644
index 0000000..3811e62
--- /dev/null
+++ b/device/rds/Design_Notes
@@ -0,0 +1,143 @@
+------------------------------------------------------------------------------------------
+
+ General ideas
+
+
+Cache:
+
+ If a block is in the cache, it is the latest version of the block.
+ However, a cached copy can be removed at any time if space in the
+ cache is needed for other blocks.
+
+ When searching the cache, start at the head. When inserting a block
+ or when a search finds a block, place the block at the head (assuming
+ temporal locality of reference). When stealing a cache node, take it
+ from the tail.
+
+A new copy of block B can enter the cache two ways:
+
+ When a write operation for block B enters the request queue for a block,
+ block B is cached. Note: there may be earlier read or write requests for
+ B in the request queue; they remain unchanged.
+
+ When a read completes for block B and no subsequent write requests for B
+ are in the request queue. Data from the read is cached.
+
+Actions:
+
+ When a write enters the request queue, add the block in the cache
+ (update an existing block or add a new block)
+
+ When a read enters the request queue
+
+ if the block is in the cache, satisfy the read request immediately
+ if the request queue contains a write for the block, satisfy the
+ request immediately (the cached copy has been stolen)
+ Otherwise, enqueue the request
+
+ When a read completes, check the request queue for a subsequent write to
+ the same block. If no write is found, add the block in the cache
+ (update an existing block or add a new block).
+
+------------------------------------------------------------------------------------------
+
+ More specifics
+
+request queue: A doubly-linked queue of requests to be handled, each containing
+ Block number
+ Operation (Read/Write/Sync)
+ Process ID (only needed for read & sync)
+ A pointer to caller's buffer (for read) or a block of data (for write)
+
+cache: A doubly-linked list of cached blocks with most recent at the head
+
+serial queue: A circular buffer of processes about to make requests, ordered by arrival
+ time, where each entry contains
+ Block number
+ Operation (Read/Write/Sync)
+ Process ID
+ Pointer to caller's buffer
+ The queue contains NPROC entries, which means a process can always add an
+ entry without blocking to wait for a slot.
+
+Operations: Read, Write, or Sync operations: (each runs with interrupts disabled
+ and uses the same algorithm)
+ Enqueue self on the serial queue
+ us rdsars to resume cproc and suspend the calling process atomically
+ return;
+
+Communication Process with PID cproc (runs with interrupts disabled)
+
+ while (TRUE) {
+ while (serialq is nonempty) {
+
+ if next item in serialq is read and block is in the cache {
+ satisfy the request, remove it from serialq, and resume
+ the process.
+ }
+ if no requestq nodes are available {
+ break out of the inner loop;
+
+ /* Move next request to the request queue */
+
+ Allocate request queue node from free list
+ copy pid and operation into request queue node
+ if a write {
+ copy data into the requestq node
+ Insert block into cache (either update or add a new node)
+ resume the process
+ add the node to the requestq
+ } else if a sync {
+ add the node to the requestq
+ } else if a read {
+ add the node to the requestq
+ }
+ }
+
+ /* All items that can be moved to the request queue have been moved */
+ /* If the request queue is empty, suspend the communication process; */
+ /* otherwise handle the next request. */
+
+ if requestq is empty {
+ suspend(getpid())
+ continue
+ }
+
+ /* Handle the next request, using the operation to select an action */
+
+ switch (operation) {
+ Sync:
+ resume the process
+ free the request node
+ continue;
+ Write:
+ Send 'write' message and receive response
+ free the request node
+ continue;
+
+ Read:
+ Send 'read' message and receive response
+ Scan requestq for a request with the same block
+ if a read is found {
+ copy data into the caller's buffer
+ resume the process
+ free the request node
+ }
+ if a write is found {
+ remember that subsequent write occurred
+ break out of the scan loop
+ }
+ if no subsequent write occurred, add the block to the cache
+ free the request node
+ continue;
+ }
+ }
+
+------------------------------------------------------------------------------------------
+
+Other functions
+
+rdcget: search the cache for block X
+rdcadd: add a block to the cache, replacing a previous entry
+rdqadd: add a node to the request queue
+rdqfree: unlink a request queue node and place it on the free list
diff --git a/device/rds/rdsars.c b/device/rds/rdsars.c
new file mode 100644
index 0000000..019f98d
--- /dev/null
+++ b/device/rds/rdsars.c
@@ -0,0 +1,35 @@
+/* rdsars.c - rdsars */
+
+#include <xinu.h>
+
+/*------------------------------------------------------------------------
+ * rdsars - atomically resume a high-priority server process and suspend
+ * the current process
+ *------------------------------------------------------------------------
+ */
+syscall rdsars(
+ pid32 pid /* ID of the process to resume */
+ )
+{
+ intmask mask; /* Saved interrupt mask */
+ struct procent *prptr; /* Ptr to process's table entry */
+
+ mask = disable();
+ if (isbadpid(pid)) {
+ restore(mask);
+ return SYSERR;
+ }
+ /* Set current process state to suspended */
+ proctab[currpid].prstate = PR_SUSP;
+
+ /* If target process is suspended, resume it */
+
+ prptr = &proctab[pid];
+ if (prptr->prstate == PR_SUSP) {
+ ready(pid);
+ } else {
+ resched();
+ }
+ restore(mask);
+ return OK;
+}
diff --git a/device/rds/rdsbufalloc.c b/device/rds/rdsbufalloc.c
deleted file mode 100644
index b872e07..0000000
--- a/device/rds/rdsbufalloc.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/* rdsbufalloc.c - rdsbufalloc */
-
-#include <xinu.h>
-
-/*------------------------------------------------------------------------
- * rdsbufalloc - Allocate a buffer from the free list or the cache
- *------------------------------------------------------------------------
- */
-struct rdbuff *rdsbufalloc (
- struct rdscblk *rdptr /* Ptr to device control block */
- )
-{
- struct rdbuff *bptr; /* Pointer to a buffer */
- struct rdbuff *pptr; /* Pointer to previous buffer */
- struct rdbuff *nptr; /* Pointer to next buffer */
-
- /* Wait for an available buffer */
-
- wait(rdptr->rd_availsem);
-
- /* If free list contains a buffer, extract it */
-
- bptr = rdptr->rd_free;
-
- if ( bptr != (struct rdbuff *)NULL ) {
- rdptr->rd_free = bptr->rd_next;
- return bptr;
- }
-
- /* Extract oldest item in cache that has ref count zero (at */
- /* least one such entry must exist because the semaphore */
- /* had a nonzero count) */
-
- bptr = rdptr->rd_ctprev;
- while (bptr != (struct rdbuff *) &rdptr->rd_chnext) {
- if (bptr->rd_refcnt <= 0) {
-
- /* Remove from cache and return to caller */
-
- pptr = bptr->rd_prev;
- nptr = bptr->rd_next;
- pptr->rd_next = nptr;
- nptr->rd_prev = pptr;
- return bptr;
- }
- bptr = bptr->rd_prev;
- }
- panic("Remote disk cannot find an available buffer");
- return (struct rdbuff *)SYSERR;
-}
diff --git a/device/rds/rdsclose.c b/device/rds/rdsclose.c
deleted file mode 100644
index eeac7e5..0000000
--- a/device/rds/rdsclose.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* rdsclose.c - rdsclose */
-
-#include <xinu.h>
-
-/*------------------------------------------------------------------------
- * rdsclose - Close a remote disk device
- *------------------------------------------------------------------------
- */
-devcall rdsclose (
- struct dentry *devptr /* Entry in device switch table */
- )
-{
- struct rdscblk *rdptr; /* Ptr to control block entry */
- struct rdbuff *bptr; /* Ptr to buffer on a list */
- struct rdbuff *nptr; /* Ptr to next buff on the list */
- int32 nmoved; /* Number of buffers moved */
-
- /* Device must be open */
-
- rdptr = &rdstab[devptr->dvminor];
- if (rdptr->rd_state != RD_OPEN) {
- return SYSERR;
- }
-
- /* Request queue must be empty */
-
- if (rdptr->rd_rhnext != (struct rdbuff *)&rdptr->rd_rtnext) {
- return SYSERR;
- }
-
- /* Move all buffers from the cache to the free list */
-
- bptr = rdptr->rd_chnext;
- nmoved = 0;
- while (bptr != (struct rdbuff *)&rdptr->rd_ctnext) {
- nmoved++;
-
- /* Unlink buffer from cache */
-
- nptr = bptr->rd_next;
- (bptr->rd_prev)->rd_next = nptr;
- nptr->rd_prev = bptr->rd_prev;
-
- /* Insert buffer into free list */
-
- bptr->rd_next = rdptr->rd_free;
-
- rdptr->rd_free = bptr;
- bptr->rd_status = RD_INVALID;
-
- /* Move to next buffer in the cache */
-
- bptr = nptr;
- }
-
- /* Set the state to indicate the device is closed */
-
- rdptr->rd_state = RD_FREE;
- return OK;
-}
diff --git a/device/rds/rdscomm.c b/device/rds/rdscomm.c
index d6d6484..3666a0d 100644
--- a/device/rds/rdscomm.c
+++ b/device/rds/rdscomm.c
@@ -3,9 +3,8 @@
#include <xinu.h>
/*------------------------------------------------------------------------
- * rdscomm - handle communication with a remote disk server (send a
- * request and receive a reply, including sequencing and
- * retries)
+ * rdscomm - send a request message to the remote disk server and
+ * a reply, handling sequence numbers and retries
*------------------------------------------------------------------------
*/
status rdscomm (
@@ -32,8 +31,8 @@ status rdscomm (
/* Register the server port, if not registered */
if ( ! rdptr->rd_registered ) {
- slot = udp_register(0, rdptr->rd_ser_port,
- rdptr->rd_loc_port);
+ slot = udp_register(rdptr->rd_ser_ip, rdptr->rd_ser_port,
+ rdptr->rd_loc_port);
if(slot == SYSERR) {
restore(mask);
return SYSERR;
@@ -70,8 +69,7 @@ status rdscomm (
/* Send a copy of the message */
- retval = udp_sendto(slot, rdptr->rd_ser_ip, rdptr->rd_ser_port,
- (char *)msg, mlen);
+ retval = udp_send(slot, (char *)msg, mlen);
if (retval == SYSERR) {
kprintf("Cannot send to remote disk server\n\r");
return SYSERR;
@@ -108,7 +106,7 @@ status rdscomm (
continue;
}
- /* Check the status */
+ /* Verify that the reply status is valid */
if (ntohs(reply->rd_status) != 0) {
return SYSERR;
diff --git a/device/rds/rdscontrol.c b/device/rds/rdscontrol.c
index 7482394..6784913 100644
--- a/device/rds/rdscontrol.c
+++ b/device/rds/rdscontrol.c
@@ -13,89 +13,81 @@ devcall rdscontrol (
int32 arg2 /* Argument #2 */
)
{
- struct rdscblk *rdptr; /* Pointer to control block */
- struct rdbuff *bptr; /* Ptr to buffer that will be */
- /* placed on the req. queue */
- struct rdbuff *pptr; /* Ptr to "previous" node on */
- /* a list */
- struct rd_msg_dreq msg; /* Buffer for delete request */
- struct rd_msg_dres resp; /* Buffer for delete response */
- char *to, *from; /* Used during name copy */
- int32 retval; /* Return value */
-
- /* Verify that device is currently open */
+ struct rdscblk *rdptr; /* Pointer to the control block */
+ /* for the disk device */
+ struct rdsent *sptr; /* Pointer tp serial queue entry*/
+ struct rd_msg_dreq msg; /* Delete message to be sent */
+ struct rd_msg_dres resp; /* Buffer to hold response */
+ char *to; /* Used to copy the disk ID */
+ char *from; /* " " " " " " */
+ int32 retval; /* Return value from rdscomm */
+
+
+ /* If the device not currently open, report an error */
rdptr = &rdstab[devptr->dvminor];
if (rdptr->rd_state != RD_OPEN) {
return SYSERR;
}
- /* Ensure rdsprocess is runnning */
-
- if ( ! rdptr->rd_comruns ) {
- rdptr->rd_comruns = TRUE;
- resume(rdptr->rd_comproc);
- }
-
switch (func) {
- /* Synchronize writes */
+ /* Synchronize writes */
- case RDS_CTL_SYNC:
+ case RDS_CTL_SYNC:
- /* Allocate a buffer to use for the request list */
+ /* If serial and request queues are empty, return */
- bptr = rdsbufalloc(rdptr);
- if (bptr == (struct rdbuff *)SYSERR) {
- return SYSERR;
+ if ( (rdptr->rdscount == 0) && (rdptr->rd_qhead ==
+ (struct rdqnode *)NULL)) {
+ return OK;
}
+ /* Obtain the next serial queue entry and fill it in */
- /* Form a sync request */
-
- bptr->rd_op = RD_OP_SYNC;
- bptr->rd_refcnt = 1;
- bptr->rd_blknum = 0; /* Unused */
- bptr->rd_status = RD_INVALID;
- bptr->rd_pid = getpid();
-
- /* Insert new request into list just before tail */
-
- pptr = rdptr->rd_rtprev;
- rdptr->rd_rtprev = bptr;
- bptr->rd_next = pptr->rd_next;
- bptr->rd_prev = pptr;
- pptr->rd_next = bptr;
+ sptr = &rdptr->rd_sq[rdptr->rdstail++];
+ if (rdptr->rdstail >= RD_SSIZE) {
+ rdptr->rdstail = 0; /* Wrap around, if needed */
+ }
+ rdptr->rdscount++; /* Increment the count of items */
+ sptr->rd_op = RD_OP_SYNC;
+ sptr->rd_blknum = 0; /* Not used */
+ sptr->rd_pid = getpid();
- /* Prepare to wait until item is processed */
+ /* Atomically resume the communication process and */
+ /* suspend the current process to wait until we */
+ /* recah the head of the request queue */
- recvclr();
+ rdsars(rdptr->rd_comproc);
+ return RD_BLKSIZ;
- /* Signal then semaphore to start communication */
+ /* Delete the remote disk (entirely remove it) */
- signal(rdptr->rd_reqsem);
+ case RDS_CTL_DEL:
- /* Block to wait for a message */
+ /* Change the state of the device to RD_DELETING to */
+ /* prevent further use */
+ rdptr->rd_state = RD_DELETING;
- bptr = (struct rdbuff *)receive();
- if (bptr == (struct rdbuff *)SYSERR) {
- return SYSERR;
- }
- break;
+ /* Call rds_sync to flush the request and serial queues */
+ rdscontrol(devptr, RDS_CTL_SYNC, NULL, NULL);
- /* Delete the remote disk (entirely remove it) */
+ /* Kill rdsprocess */
+ kill(rdptr->rd_comproc);
- case RDS_CTL_DEL:
+ /* Return the cache nodes in use to the free list */
+ rdptr->rd_ctail->rd_next = rdptr->rd_cfree;
+ rdptr->rd_cfree = rdptr->rd_chead;
/* Handcraft a message for the server that requests */
/* deleting the disk with the specified ID */
msg.rd_type = htons(RD_MSG_DREQ);/* Request deletion */
msg.rd_status = htons(0);
- msg.rd_seq = 0; /* rdscomm will insert sequence # later */
+ msg.rd_seq = 0; /* Rdscomm will insert sequence # later */
to = msg.rd_id;
memset(to, NULLCH, RD_IDLEN); /* Initialize to zeroes */
from = rdptr->rd_id;
- while ( (*to++ = *from++) != NULLCH ) { /* copy ID */
+ while ( (*to++ = *from++) != NULLCH ) { /* Copy ID */
;
}
@@ -107,25 +99,63 @@ devcall rdscontrol (
sizeof(struct rd_msg_dres),
rdptr);
- /* Check response */
+ /* Check the response */
- if (retval == SYSERR) {
- return SYSERR;
- } else if (retval == TIMEOUT) {
- kprintf("Timeout during remote file delete\n\r");
- return SYSERR;
- } else if (ntohs(resp.rd_status) != 0) {
+ if ( (retval == SYSERR) || (retval == TIMEOUT) ||
+ (ntohs(resp.rd_status) != 0) ) {
+ kprintf("Remote disk server error for delete.\n");
return SYSERR;
}
- /* Close local device */
+ rdptr->rd_state = RD_CLOSED;
- return rdsclose(devptr);
+ return OK;
- default:
- kprintf("rfsControl: function %d not valid\n\r", func);
- return SYSERR;
- }
+ /* Close a remote disk */
+
+ case RDS_CTL_CLOSE:
+
+ /* Change the state of the device to RD_CLOSING to */
+ /* prevent further use */
+ rdptr->rd_state = RD_CLOSED;
+
+ /* Call rds_sync to flush the request and serial queues */
+ rdscontrol(devptr, RDS_CTL_SYNC, NULL, NULL);
+
+ /* Handcraft a message for the server that requests */
+ /* closing the disk with the specified ID */
+
+ msg.rd_type = htons(RD_MSG_CREQ);/* Request closing */
+ msg.rd_status = htons(0);
+ msg.rd_seq = 0; /* Rdscomm will insert sequence # later */
+ to = msg.rd_id;
+ memset(to, NULLCH, RD_IDLEN); /* Initialize to zeroes */
+ from = rdptr->rd_id;
+ while ( (*to++ = *from++) != NULLCH ) { /* Copy ID */
+ ;
+ }
+
+ /* Send message and receive response */
+ retval = rdscomm((struct rd_msg_hdr *)&msg,
+ sizeof(struct rd_msg_creq),
+ (struct rd_msg_hdr *)&resp,
+ sizeof(struct rd_msg_cres),
+ rdptr);
+
+ /* Check the response */
+
+ if ( (retval == SYSERR) || (retval == TIMEOUT) ||
+ (ntohs(resp.rd_status) != 0) ) {
+ kprintf("Bad response from the remote disk server on the close request.\n");
+ return SYSERR;
+ }
+
+ return OK;
+
+ default:
+ kprintf("rsscontrol: invalid function %d\n");
+ return SYSERR;
+ }
return OK;
}
diff --git a/device/rds/rdsinit.c b/device/rds/rdsinit.c
index 8c39f7f..0d4d61e 100644
--- a/device/rds/rdsinit.c
+++ b/device/rds/rdsinit.c
@@ -13,94 +13,22 @@ devcall rdsinit (
)
{
struct rdscblk *rdptr; /* Ptr to device contol block */
- struct rdbuff *bptr; /* Ptr to buffer in memory */
- /* used to form linked list */
- struct rdbuff *pptr; /* Ptr to previous buff on list */
- struct rdbuff *buffend; /* Last address in buffer memory*/
- uint32 size; /* Total size of memory needed */
- /* buffers */
- /* Obtain address of control block */
+ /* Obtain the address of the control block */
rdptr = &rdstab[devptr->dvminor];
- /* Set control block to unused */
+ /* Set the device to the closed state */
- rdptr->rd_state = RD_FREE;
+ rdptr->rd_state = RD_CLOSED;
- /* Create the resprocess and leave it suspended. */
- /* Note: the process cannot be resumed because */
- /* device initialization occurs before interrupts */
- /* are enabled. */
-
- rdptr->rd_comproc = create(rdsprocess, RD_STACK, RD_PRIO,
- "rdsproc", 1, rdptr);
- if (rdptr->rd_comproc == SYSERR) {
- panic("Cannot create remote disk process");
- }
- rdptr->rd_comruns = FALSE;
-
- rdptr->rd_id[0] = NULLCH;
-
/* Set initial message sequence number */
rdptr->rd_seq = 1;
- /* Initialize request queue and cache to empty */
-
- rdptr->rd_rhnext = (struct rdbuff *) &rdptr->rd_rtnext;
- rdptr->rd_rhprev = (struct rdbuff *)NULL;
-
- rdptr->rd_rtnext = (struct rdbuff *)NULL;
- rdptr->rd_rtprev = (struct rdbuff *) &rdptr->rd_rhnext;
-
-
- rdptr->rd_chnext = (struct rdbuff *) &rdptr->rd_ctnext;
- rdptr->rd_chprev = (struct rdbuff *)NULL;
-
- rdptr->rd_ctnext = (struct rdbuff *)NULL;
- rdptr->rd_ctprev = (struct rdbuff *) &rdptr->rd_chnext;
-
- /* Allocate memory for a set of buffers (actually request */
- /* blocks and link them to form the initial free list */
-
- size = sizeof(struct rdbuff) * RD_BUFFS;
-
- bptr = (struct rdbuff *)getmem(size);
- rdptr->rd_free = bptr;
-
- if ((int32)bptr == SYSERR) {
- panic("Cannot allocate memory for remote disk buffers");
- }
-
- pptr = (struct rdbuff *) NULL; /* To avoid a compiler warning */
- buffend = (struct rdbuff *) ((char *)bptr + size);
- while (bptr < buffend) { /* walk through memory */
- pptr = bptr;
- bptr = (struct rdbuff *)
- (sizeof(struct rdbuff)+ (char *)bptr);
- pptr->rd_status = RD_INVALID; /* Buffer is empty */
- pptr->rd_next = bptr; /* Point to next buffer */
- }
- pptr->rd_next = (struct rdbuff *) NULL; /* Last buffer on list */
-
- /* Create the request list and available buffer semaphores */
-
- rdptr->rd_availsem = semcreate(RD_BUFFS);
- rdptr->rd_reqsem = semcreate(0);
-
- /* Set the server IP address, server port, and local port */
-
- if ( dot2ip(RD_SERVER_IP, &rdptr->rd_ser_ip) == SYSERR ) {
- panic("invalid IP address for remote disk server");
- }
-
- /* Set the port numbers */
-
- rdptr->rd_ser_port = RD_SERVER_PORT;
- rdptr->rd_loc_port = RD_LOC_PORT + devptr->dvminor;
+ rdptr->rd_id[0] = NULLCH;
- /* Specify that the server port is not yet registered */
+ /* Specify that the server UDP port is not yet registered */
rdptr->rd_registered = FALSE;
diff --git a/device/rds/rdsopen.c b/device/rds/rdsopen.c
index 67ee955..de4c2fa 100644
--- a/device/rds/rdsopen.c
+++ b/device/rds/rdsopen.c
@@ -20,17 +20,29 @@ devcall rdsopen (
int32 len; /* Counts chars in diskid */
char *idto; /* Ptr to ID string copy */
char *idfrom; /* Pointer into ID string */
+ uint32 size; /* Total size of memory needed */
+ /* for request or cache nodes */
+ char *p; /* Ptr walks memory and links */
+ /* nodes on a list */
+ char *pend; /* Address beyond the nodes */
+ char *pprev; /* Address of previous buffer */
+ /* when linking them */
+
+ /* Find the control block for this remote disk device */
rdptr = &rdstab[devptr->dvminor];
- /* Reject if device is already open */
+ /* Reject if the device is already open */
- if (rdptr->rd_state != RD_FREE) {
+ if (rdptr->rd_state != RD_CLOSED) {
return SYSERR;
}
+
+ /* Prevent concurrent open attempts */
+
rdptr->rd_state = RD_PEND;
- /* Copy disk ID into free table slot */
+ /* Copy the disk ID into the control block */
idto = rdptr->rd_id;
idfrom = diskid;
@@ -38,13 +50,15 @@ devcall rdsopen (
while ( (*idto++ = *idfrom++) != NULLCH) {
len++;
if (len >= RD_IDLEN) { /* ID string is too long */
+ rdptr->rd_state = RD_CLOSED;
return SYSERR;
}
}
- /* Verify that name is non-null */
+ /* Verify that the ID is non-null */
if (len == 0) {
+ rdptr->rd_state = RD_CLOSED;
return SYSERR;
}
@@ -54,40 +68,108 @@ devcall rdsopen (
msg.rd_status = htons(0);
msg.rd_seq = 0; /* Rdscomm fills in an entry */
idto = msg.rd_id;
- memset(idto, NULLCH, RD_IDLEN);/* initialize ID to zero bytes */
+ memset(idto, NULLCH, RD_IDLEN);/* Initialize ID to zero bytes */
idfrom = diskid;
while ( (*idto++ = *idfrom++) != NULLCH ) { /* Copy ID to req. */
;
}
- /* Send message and receive response */
+ /* Set the server port, local port, and the server IP address. */
+
+ if ( (int32)getlocalip() == SYSERR) {
+ kprintf("RDS cannot obtain an IP address\n");
+ return SYSERR;
+ }
+ rdptr->rd_ser_port = RD_SERVER_PORT;
+ rdptr->rd_loc_port = RD_LOC_PORT + devptr->dvminor;
+ if (dnslookup(RD_SERVER, &rdptr->rd_ser_ip) == SYSERR) {
+ kprintf("rdsopen: lookup of %s failed\n", RD_SERVER);
+ rdptr->rd_state = RD_CLOSED;
+ return SYSERR;
+ }
+ /* Send the open message and receive a response */
retval = rdscomm((struct rd_msg_hdr *)&msg,
sizeof(struct rd_msg_oreq),
(struct rd_msg_hdr *)&resp,
sizeof(struct rd_msg_ores),
rdptr );
- /* Check response */
+ /* Check the response */
- if (retval == SYSERR) {
- rdptr->rd_state = RD_FREE;
+ if ( (retval == SYSERR) || (retval == TIMEOUT) ||
+ (ntohs(resp.rd_status) != 0) ) {
+ rdptr->rd_state = RD_CLOSED;
return SYSERR;
- } else if (retval == TIMEOUT) {
- kprintf("Timeout during remote file open\n\r");
- rdptr->rd_state = RD_FREE;
+ }
+
+ /* Initialize the serial queue to empty */
+
+ rdptr->rdshead = rdptr->rdstail = rdptr->rdscount = 0;
+
+ /* Initialize the request queue to empty */
+
+ rdptr->rd_qhead = rdptr->rd_qtail = (struct rdqnode *) NULL;
+
+ /* Allocate request queue nodes and link them onto a free list */
+
+ size = sizeof(struct rdqnode) * RD_QNODES;
+
+ p = getmem(size);
+ if ((int32)p == SYSERR) {
+ kprintf("rdsopen: cannot allocted request queue\n");
+ rdptr->rd_state = RD_CLOSED;
return SYSERR;
- } else if (ntohs(resp.rd_status) != 0) {
- rdptr->rd_state = RD_FREE;
+ }
+ rdptr->rd_qfree = (struct rdqnode *)p;
+ pend = p + size;
+ pprev = p; /* To prevent a Compiler initialization" warning */
+ while (p < pend) { /* Walk through allocated memory */
+ pprev = p;
+ p = p + sizeof(struct rdqnode);
+ ((struct rdqnode *)pprev)->rd_next = (struct rdqnode *)p;
+ }
+ ((struct rdqnode *)pprev)->rd_next = NULL; /* End of the list */
+
+ /* Initialize the cache to empty */
+
+ rdptr->rd_chead = rdptr->rd_ctail = (struct rdcnode *) NULL;
+
+ /* Allocate cache nodes and link them onto a cache free list */
+
+ size = sizeof(struct rdcnode) * RD_CNODES;
+
+ p = getmem(size);
+ if ((int32)p == SYSERR) {
+ kprintf("rdsopen: cannot allocate cache nodes\n");
+ rdptr->rd_state = RD_CLOSED;
+ return SYSERR;
+ }
+ rdptr->rd_cfree = (struct rdcnode *)p;
+ pend = p + size;
+ while (p < pend) { /* Walk through allocated memory */
+ pprev = p;
+ p = p + sizeof(struct rdcnode);
+ ((struct rdcnode *)pprev)->rd_next = (struct rdcnode *)p;
+ }
+ ((struct rdcnode *)pprev)->rd_next = NULL; /* End of the list */
+
+ /* Create the communication process for this remote disk */
+
+ rdptr->rd_comproc = create(rdsprocess, RD_STACK, RD_PRIO,
+ "remdisk", 1, rdptr);
+ if (rdptr->rd_comproc == SYSERR) {
+ kprintf("rdsopen: cannot create remote disk process");
+ rdptr->rd_state = RD_CLOSED;
return SYSERR;
}
- /* Change state of device to indicate currently open */
+ /* Change state of device to open */
rdptr->rd_state = RD_OPEN;
- /* Return device descriptor */
+ /* Return the device ID of the remote disk device */
return devptr->dvnum;
}
diff --git a/device/rds/rdsprocess.c b/device/rds/rdsprocess.c
index a01ebab..39ab56b 100644
--- a/device/rds/rdsprocess.c
+++ b/device/rds/rdsprocess.c
@@ -1,14 +1,15 @@
/* rdsprocess.c - rdsprocess */
-
#include <xinu.h>
/*------------------------------------------------------------------------
* rdsprocess - High-priority background process that repeatedly
- * extracts an item from the request queue, sends the
- * request to the remote disk server, and handles the
- * response, including caching responses blocks
+ * moves items from the serial queue to the request queue
+ * extracts the next item on the request queue
+ * sends the request to the remote disk server, and
+ * caches new blocks
*------------------------------------------------------------------------
*/
+
void rdsprocess (
struct rdscblk *rdptr /* Ptr to device control block */
)
@@ -18,123 +19,103 @@ void rdsprocess (
struct rd_msg_rres resp; /* Buffer to hold response */
/* (includes data area) */
int32 retval; /* Return value from rdscomm */
- char *idto; /* Ptr to ID string copy */
- char *idfrom; /* Ptr into ID string */
- struct rdbuff *bptr; /* Ptr to buffer at the head of */
- /* the request queue */
- struct rdbuff *nptr; /* Ptr to next buffer on the */
- /* request queue */
- struct rdbuff *pptr; /* Ptr to previous buffer */
- struct rdbuff *qptr; /* Ptr that runs along the */
- /* request queue */
- int32 i; /* Loop index */
-
- while (TRUE) { /* Do forever */
-
- /* Wait until the request queue contains a node */
- wait(rdptr->rd_reqsem);
- bptr = rdptr->rd_rhnext;
+ char *idto; /* Ptr to ID string for copy */
+ char *idfrom; /* Ptr into ID string for copu */
+ struct rdqnode *rptr; /* Ptr to a node in the request */
+ /* queue */
+ struct rdsent *sptr; /* Ptr to item in serial queue */
+ bool8 wfound; /* Was a write found in the q? */
- /* Use operation in request to determine action */
-
- switch (bptr->rd_op) {
-
- case RD_OP_READ:
-
- /* Build a read request message for the server */
- msg.rd_type = htons(RD_MSG_RREQ); /* Read request */
- msg.rd_status = htons(0);
- msg.rd_seq = 0; /* Rdscomm fills in an entry */
- idto = msg.rd_id;
- memset(idto, NULLCH, RD_IDLEN);/* Initialize ID to zero */
- idfrom = rdptr->rd_id;
- while ( (*idto++ = *idfrom++) != NULLCH ) { /* Copy ID */
- ;
- }
+ while (TRUE) { /* Do forever */
- /* Send the message and receive a response */
+ /* Move entries from the serial queue to the request queue */
+ /* as long as request queue nodes are available */
- retval = rdscomm((struct rd_msg_hdr *)&msg,
- sizeof(struct rd_msg_rreq),
- (struct rd_msg_hdr *)&resp,
- sizeof(struct rd_msg_rres),
- rdptr );
+ while (rdptr->rdscount > 0) {
+ sptr = &rdptr->rd_sq[rdptr->rdshead];
- /* Check response */
+ /* If read can be satisfied from cache, satisfy it */
- if ( (retval == SYSERR) || (retval == TIMEOUT) ||
- (ntohs(resp.rd_status) != 0) ) {
- panic("Failed to contact remote disk server");
+ if ( (sptr->rd_op == RD_OP_READ) &&
+ (rdcget(rdptr, sptr->rd_blknum, sptr->rd_callbuf)
+ == OK)) {
+ rdptr->rdscount--;
+ rdptr->rdshead++;
+ if (rdptr->rdshead >= RD_SSIZE) {
+ rdptr->rdshead = 0;
+ }
+ resume(sptr->rd_pid);
+ continue;
}
- /* Copy data from the reply into the buffer */
+ /* If no request queue nodes available, stop moving */
+ /* items from the serial queue to the request queue */
- for (i=0; i<RD_BLKSIZ; i++) {
- bptr->rd_block[i] = resp.rd_data[i];
+ if ((rptr = rdptr->rd_qfree) == (struct rdqnode *)NULL) {
+ break;
}
- /* Unlink buffer from the request queue */
-
- nptr = bptr->rd_next;
- pptr = bptr->rd_prev;
- nptr->rd_prev = bptr->rd_prev;
- pptr->rd_next = bptr->rd_next;
+ /* Decrement count of nodes in the serial queue */
- /* Insert buffer in the cache */
+ rdptr->rdscount--;
- pptr = (struct rdbuff *) &rdptr->rd_chnext;
- nptr = pptr->rd_next;
- bptr->rd_next = nptr;
- bptr->rd_prev = pptr;
- pptr->rd_next = bptr;
- nptr->rd_prev = bptr;
+ /* Remove the next request queue node from the free list*/
- /* Initialize reference count */
+ rdptr->rd_qfree = rptr->rd_next;
- bptr->rd_refcnt = 1;
+ /* Fill in the blknum and pid from the serial node */
- /* Signal the available semaphore */
+ rptr->rd_blknum = sptr->rd_blknum;
+ rptr->rd_pid = sptr->rd_pid;
- signal(rdptr->rd_availsem);
+ /* Pass buffer pointer from serial to request queue node*/
+ rptr->rd_callbuf = sptr->rd_callbuf;
- /* Send a message to waiting process */
+ /* Use the operation to determine remaining actions */
- send(bptr->rd_pid, (uint32)bptr);
+ if ( (rptr->rd_op = sptr->rd_op) == RD_OP_WRITE) {
+ /* Copy data from the caller's buffer */
+ memcpy(rptr->rd_wbuf, sptr->rd_callbuf, RD_BLKSIZ);
+ /* Add the block to the cache */
+ rdcadd(rdptr, rptr->rd_blknum, rptr->rd_wbuf);
+ /* Resume the process */
+ resume(rptr->rd_pid);
+ }
+ /* Add the request node to the request queue */
+ rdqadd(rdptr, rptr);
- /* If other processes are waiting to read the */
- /* block, notify them and remove the request */
+ /* Increment the serial queue */
+ rdptr->rdshead++;
+ if (rdptr->rdshead >= RD_SSIZE) {
+ rdptr->rdshead = 0;
+ }
- qptr = rdptr->rd_rhnext;
- while (qptr != (struct rdbuff *)&rdptr->rd_rtnext) {
- if (qptr->rd_blknum == bptr->rd_blknum) {
- bptr->rd_refcnt++;
- send(qptr->rd_pid,(uint32)bptr);
+ }
- /* Unlink request from queue */
+ /* At this point, eligible items have been moved from the */
+ /* serial queue to the request queue -- either suspend the */
+ /* communication process, if the request queue is empty, */
+ /* or handle the next request. */
- pptr = qptr->rd_prev;
- nptr = qptr->rd_next;
- pptr->rd_next = bptr->rd_next;
- nptr->rd_prev = bptr->rd_prev;
+ if ( (rptr=rdptr->rd_qhead) == (struct rdqnode *)NULL ) {
+ suspend(getpid());
+ continue;
+ }
- /* Move buffer to the free list */
+ /* Handle a request -- use operation to determine action */
+ switch (rptr->rd_op) {
- qptr->rd_next = rdptr->rd_free;
- rdptr->rd_free = qptr;
- signal(rdptr->rd_availsem);
- break;
- }
- qptr = qptr->rd_next;
- }
- break;
+ case RD_OP_SYNC:
+ /* Resume the process and free the request queue node */
+ resume(rptr->rd_pid);
+ rptr = rdqfree(rdptr, rptr);
+ continue;
case RD_OP_WRITE:
-
/* Build a write request message for the server */
msg.rd_type = htons(RD_MSG_WREQ); /* Write request*/
- msg.rd_blk = bptr->rd_blknum;
msg.rd_status = htons(0);
msg.rd_seq = 0; /* Rdscomb fills in an entry */
idto = msg.rd_id;
@@ -143,70 +124,87 @@ void rdsprocess (
while ( (*idto++ = *idfrom++) != NULLCH ) { /* Copy ID */
;
}
- for (i=0; i<RD_BLKSIZ; i++) {
- msg.rd_data[i] = bptr->rd_block[i];
- }
-
- /* Unlink buffer from request queue */
-
- nptr = bptr->rd_next;
- pptr = bptr->rd_prev;
- pptr->rd_next = nptr;
- nptr->rd_prev = pptr;
-
- /* Insert buffer in the cache */
-
- pptr = (struct rdbuff *) &rdptr->rd_chnext;
- nptr = pptr->rd_next;
- bptr->rd_next = nptr;
- bptr->rd_prev = pptr;
- pptr->rd_next = bptr;
- nptr->rd_prev = bptr;
+ msg.rd_blk = htonl(rptr->rd_blknum);
+ memcpy(msg.rd_data, rptr->rd_callbuf, RD_BLKSIZ);
- /* Declare that buffer is eligible for reuse */
+ /* Free the node that was on the request queue */
- bptr->rd_refcnt = 0;
- signal(rdptr->rd_availsem);
+ rptr = rdqfree(rdptr, rptr);
/* Send the message and receive a response */
-
retval = rdscomm((struct rd_msg_hdr *)&msg,
sizeof(struct rd_msg_wreq),
(struct rd_msg_hdr *)&resp,
sizeof(struct rd_msg_wres),
rdptr );
- /* Check response */
+ /* Check the response */
if ( (retval == SYSERR) || (retval == TIMEOUT) ||
(ntohs(resp.rd_status) != 0) ) {
- panic("failed to contact remote disk server");
+ kprintf("remote disk write failed\n");
}
- break;
-
- case RD_OP_SYNC:
-
- /* Send a message to the waiting process */
+ continue;
- send(bptr->rd_pid, OK);
+ case RD_OP_READ:
+ /* Build a read request message for the server */
+ msg.rd_type = htons(RD_MSG_RREQ); /* Read request */
+ msg.rd_status = htons(0);
+ msg.rd_seq = 0; /* rdscomm fills in the value */
+ idto = msg.rd_id;
+ memset(idto, NULLCH, RD_IDLEN);/* Initialize ID to zero */
+ idfrom = rdptr->rd_id;
+ while ( (*idto++ = *idfrom++) != NULLCH ) { /* Copy ID */
+ ;
+ }
+ msg.rd_blk = htonl(rptr->rd_blknum);
- /* Unlink buffer from the request queue */
+ /* Send the message and receive a response */
- nptr = bptr->rd_next;
- pptr = bptr->rd_prev;
- nptr->rd_prev = bptr->rd_prev;
- pptr->rd_next = bptr->rd_next;
+ retval = rdscomm((struct rd_msg_hdr *)&msg,
+ sizeof(struct rd_msg_rreq),
+ (struct rd_msg_hdr *)&resp,
+ sizeof(struct rd_msg_rres),
+ rdptr );
- /* Insert buffer into the free list */
+ /* Check the response */
- bptr->rd_next = rdptr->rd_free;
- rdptr->rd_free = bptr;
- signal(rdptr->rd_availsem);
- break;
- }
- }
-}
+ if ( (retval == SYSERR) || (retval == TIMEOUT) ||
+ (ntohs(resp.rd_status) != 0) ) {
+ panic("remote disk error contacting server");
+ }
+ /* Walk through the request queue and satisfy all read */
+ /* requests for the block, including the first one */
+ wfound = FALSE;
+ rptr = rdptr->rd_qhead;
+ while (rptr != (struct rdqnode *)NULL) {
+ if (rptr->rd_blknum != rptr->rd_blknum) {
+ rptr = rptr->rd_next;
+ continue;
+ }
+ /* Block number matches; handle read or write */
+ if (rptr->rd_op == RD_OP_WRITE) {
+ wfound = TRUE;
+ break;
+ }
+ if ( rptr->rd_op == RD_OP_READ ) {
+ /* Satisfy the read for the block */
+ memcpy(rptr->rd_callbuf, resp.rd_data, RD_BLKSIZ);
+ resume(rptr->rd_pid);
+ rptr = rdqfree(rdptr, rptr);
+ }
+ }
+ /* Cache the block if no sucessive writes have appeared */
+ if (! wfound) {
+ rdcadd(rdptr, htonl(resp.rd_blk), resp.rd_data);
+ }
+ continue;
+ default:
+ continue; /* Should never happen */
+ }
+ }
+}
diff --git a/device/rds/rdsqfcns.c b/device/rds/rdsqfcns.c
new file mode 100644
index 0000000..7978daa
--- /dev/null
+++ b/device/rds/rdsqfcns.c
@@ -0,0 +1,288 @@
+/* rdsqfcns.c - rdqadd, rdqfree, rdcget, rdcadd, rdcdump, rdqdump */
+
+#include <xinu.h>
+
+/*------------------------------------------------------------------------
+ * rdqadd - Add a request node to the tail of the request queue
+ *------------------------------------------------------------------------
+ */
+void rdqadd (
+ struct rdscblk *rdptr, /* Control block pointer */
+ struct rdqnode *rptr /* Ptr to the request node */
+) {
+ struct rdqnode *tptr; /* Pointer to the tail */
+
+ tptr = rdptr->rd_qtail;
+ rptr->rd_next = (struct rdqnode *)NULL;
+ rptr->rd_prev = tptr;
+ if (tptr == (struct rdqnode *)NULL) {
+ /* Request queue was empty */
+ rdptr->rd_qhead = rdptr->rd_qtail = rptr;
+ } else {
+ tptr->rd_next = rdptr->rd_qtail = rptr;
+ }
+ return;
+}
+
+/*------------------------------------------------------------------------
+ * rdqfree - Unlink a node from the request queue, place the node on
+ * the free list, and return the address of the next node
+ * on the request queue (or NULL, if unlinking the tail)
+ *------------------------------------------------------------------------
+ */
+struct rdqnode * rdqfree(
+ struct rdscblk *rdptr, /* Control block pointer */
+ struct rdqnode *rptr /* Ptr to the request node */
+) {
+ struct rdqnode *nptr; /* Pointer to next node */
+ struct rdqnode *pptr; /* Pointer to previous node */
+
+ nptr = rptr->rd_next; /* Point to next node or NULL */
+ pptr = rptr->rd_prev; /* Point to prev. node or NULL */
+
+ /* Handle unlinking the head of the request queue */
+
+ if (rptr == rdptr->rd_qhead) {
+ /* See if queue contains multiple nodes */
+ if (rptr == rdptr->rd_qtail) {
+ /* This is the only node on the queue */
+ rdptr->rd_qhead = rdptr->rd_qtail =
+ (struct rdqnode *)NULL;
+ } else {
+ /* The queue contains other nodes */
+ rdptr->rd_qhead = nptr;
+ }
+
+ /* Handle unlinking the tail of the request queue */
+
+ } else if (rptr == rdptr->rd_qtail) {
+ rdptr->rd_qtail = pptr;
+ pptr->rd_next = (struct rdqnode *)NULL;
+
+ /* Handle unlinking a node in the middle of the queue */
+
+ } else {
+ pptr = rptr->rd_prev;
+ pptr->rd_next = nptr;
+ nptr->rd_prev = pptr;
+ }
+ /* Add the unlinked node to free list */
+ rptr->rd_next = rdptr->rd_qfree;
+ rdptr->rd_qfree = rptr;
+ return nptr;
+}
+
+/*------------------------------------------------------------------------
+ * rdsget - Search the cache for a block and, if found, copy the
+ * data into the caller's buffer
+ *------------------------------------------------------------------------
+ */
+int32 rdcget (
+ struct rdscblk *rdptr, /* Remote disk control block */
+ uint32 blknum, /* Block number to use */
+ char *buf /* Buffer to receive the data */
+) {
+ struct rdcnode *cptr; /* Pointer that walks the cache */
+
+ if (RD_CNODES == 0) {
+ /* No cache is being used */
+ return SYSERR;
+ }
+
+ for (cptr = rdptr->rd_chead; cptr != (struct rdcnode*)NULL;
+ cptr = cptr->rd_next) {
+ if (cptr->rd_blknum != blknum) {
+ continue;
+ }
+ /* Found the block in the cache -- copy the data */
+ memcpy(buf, cptr->rd_data, RD_BLKSIZ);
+ return OK;
+ }
+ return SYSERR;
+}
+
+/*------------------------------------------------------------------------
+ * rdcadd - Add a cache entry for a specified block and data,
+ * replacing an existing entry, allocting a free noode, or
+ * stealing the oldest node the cache
+ *------------------------------------------------------------------------
+ */
+void rdcadd (
+ struct rdscblk *rdptr, /* Remote disk control block */
+ uint32 blk, /* Block number to use */
+ char *buf /* Data for the block */
+) {
+ struct rdcnode *cptr; /* Pointer that walks the cache */
+ struct rdcnode *tptr; /* Temp. pointer to cache node */
+ /* used when unlinking */
+
+ if (RD_CNODES == 0) {
+ /* No cache is being used */
+ return;
+ }
+
+ /* Replace previous entry for the block, if one exists */
+
+ for (cptr = rdptr->rd_chead; cptr != (struct rdcnode*)NULL;
+ cptr = cptr->rd_next) {
+ if (cptr->rd_blknum != blk) {
+ continue;
+ }
+ /* Found the block in the cache -- replace the data */
+ /* witht he new data */
+ memcpy(cptr->rd_data, buf, RD_BLKSIZ);
+ return;
+ }
+
+ /* Allocate a free cache node, if any are available, or steal */
+ /* the oldest node in the cache */
+
+ cptr = rdptr->rd_cfree;
+ if (cptr != (struct rdcnode *)NULL) {
+ /* Unlink from the free list */
+ rdptr->rd_cfree = cptr->rd_next;
+ } else {
+ /* Steal the tail of the cache list */
+ cptr = rdptr->rd_ctail;
+ if (rdptr->rd_chead == rdptr->rd_ctail) {
+ /* Exactly one node in the cache, so unlink it */
+ rdptr->rd_chead = rdptr->rd_ctail =
+ (struct rdcnode *)NULL;
+ } else {
+ /* More than one node in the cache */
+ tptr = cptr->rd_prev;
+ tptr->rd_next = (struct rdcnode *)NULL;
+ rdptr->rd_ctail = tptr;
+ }
+ }
+ /* Fill in the block to be cached */
+ cptr->rd_blknum = blk;
+ memcpy(cptr->rd_data, buf, RD_BLKSIZ);
+
+ /* Add the node to head of the cache */
+
+ tptr = rdptr->rd_chead;
+ cptr->rd_next = tptr;
+ cptr->rd_prev = (struct rdcnode *)NULL;
+ rdptr->rd_chead = cptr;
+ if (tptr == (struct rdcnode *)NULL) {
+ /* Insert in an empty cache */
+ rdptr->rd_chead = rdptr->rd_ctail = cptr;
+ } else {
+ tptr->rd_prev = cptr;
+ }
+ return;
+}
+
+/*------------------------------------------------------------------------
+ * rdqdump - Dump the remote disk request queue
+ *------------------------------------------------------------------------
+ */
+void rdqdump (
+ did32 disk /* ID of disk to use */
+ )
+{
+ struct dentry *devptr; /* Entry in Device Switch Table */
+ struct rdscblk *rdptr; /* Pointer to the control block */
+ struct rdqnode *rptr; /* Ptr to item in request queue */
+ int32 n; /* Request number */
+ int32 i; /* Byte index in data */
+ byte ch; /* One byte of data */
+
+ devptr = (struct dentry *) &devtab[disk];
+ rdptr = &rdstab[devptr->dvminor];
+ rptr = rdptr->rd_qhead;
+
+ if (rptr == (struct rdqnode *)NULL) {
+ kprintf("****** request queue is empty ******\n");
+ return;
+ } else {
+ kprintf("****** request queue ******\n");
+ }
+
+ n = 0;
+ while (rptr != (struct rdqnode *)NULL) {
+ n++;
+ kprintf("Request Number %d ", n);
+ kprintf("OP=%d ", rptr->rd_op);
+ kprintf("Blk=%d ", rptr->rd_blknum);
+ kprintf("PID=%d\n", rptr->rd_pid);
+ if (rptr->rd_op == RD_OP_WRITE) {
+ for (i = 0; i < RD_BLKSIZ; i++) {
+ ch = rptr->rd_callbuf[i];
+ if ( (ch >= 'a' && ch <= 'z') ||
+ (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') ||
+ ch == ' ' || ch == '.' ||
+ ch == '-' || ch == '+' ||
+ ch == '*' || ch=='\n' ) {
+ kprintf("%c", ch);
+ } else {
+ kprintf("?");
+ }
+ if ( (i%512) == 0) {
+ kprintf("\n");
+ }
+ if ( (i%64) == 0) {
+ kprintf("\n");
+ }
+ }
+ kprintf("\n**** END OF DATA ****\n");
+ }
+ rptr = rptr->rd_next;
+ }
+}
+
+/*------------------------------------------------------------------------
+ * rdcdump - Dump the remote disk cache
+ *------------------------------------------------------------------------
+ */
+void rdcdump (
+ did32 disk /* ID of disk to use */
+ )
+{
+ struct dentry *devptr; /* Entry in Device Switch Table */
+ struct rdscblk *rdptr; /* Pointer to the control block */
+ struct rdcnode *cptr; /* Ptr to item in request queue */
+ int32 n; /* Node number */
+ int32 i; /* Byte index in data */
+ byte ch; /* One byte of data */
+
+ devptr = (struct dentry *) &devtab[disk];
+ rdptr = &rdstab[devptr->dvminor];
+ cptr = rdptr->rd_chead;
+
+ if (cptr == (struct rdcnode *)NULL) {
+ kprintf("****** disk cache is empty ******\n");
+ return;
+ } else {
+ kprintf("****** disk cache ******\n");
+ }
+ n = 0;
+ while (cptr != (struct rdcnode *)NULL) {
+ n++;
+ kprintf("\nNode %2d blk%4d\n", n, cptr->rd_blknum);
+ for (i = 0; i < RD_BLKSIZ; i++) {
+ ch = 0xff & cptr->rd_data[i];
+ if ( (ch >= 'a' && ch <= 'z') ||
+ (ch >= 'A' && ch <= 'Z') ||
+ (ch >= '0' && ch <= '9') ||
+ ch == ' ' || ch == '.' ||
+ ch == '-' || ch == '+' ||
+ ch == '*' || ch=='\n' ) {
+ kprintf("%c", ch);
+ } else {
+ kprintf("?");
+ }
+ if ( (i%512) == 0) {
+ kprintf("\n");
+ }
+ if ( (i%64) == 0) {
+ kprintf("\n");
+ }
+ }
+ kprintf("\n**** END OF DATA ****\n");
+ cptr = cptr->rd_next;
+ }
+ return;
+}
diff --git a/device/rds/rdsread.c b/device/rds/rdsread.c
index be99f01..6d09dbd 100644
--- a/device/rds/rdsread.c
+++ b/device/rds/rdsread.c
@@ -9,122 +9,35 @@
devcall rdsread (
struct dentry *devptr, /* Entry in device switch table */
char *buff, /* Buffer to hold disk block */
- int32 blk /* Block number of block to read*/
+ int32 blk /* Block num. of block to read */
)
{
- struct rdscblk *rdptr; /* Pointer to control block */
- struct rdbuff *bptr; /* Pointer to buffer possibly */
- /* in the request list */
- struct rdbuff *nptr; /* Pointer to "next" node on a */
- /* list */
- struct rdbuff *pptr; /* Pointer to "previous" node */
- /* on a list */
- struct rdbuff *cptr; /* Pointer that walks the cache */
+ struct rdscblk *rdptr; /* Pointer to the control block */
+ /* for the disk device */
+ struct rdsent *sptr; /* Pointer to serial queue entry*/
- /* If device not currently in use, report an error */
+ /* If the device not currently open, report an error */
rdptr = &rdstab[devptr->dvminor];
if (rdptr->rd_state != RD_OPEN) {
return SYSERR;
}
- /* Ensure rdsprocess is runnning */
+ /* Obtain the next serial queue entry and fill it in */
- if ( ! rdptr->rd_comruns ) {
- rdptr->rd_comruns = TRUE;
- resume(rdptr->rd_comproc);
+ sptr = &rdptr->rd_sq[rdptr->rdstail++];
+ if (rdptr->rdstail >= RD_SSIZE) { /* wrap around, if necessary */
+ rdptr->rdstail = 0;
}
+ rdptr->rdscount++; /* Increment the count of items */
+ sptr->rd_op = RD_OP_READ;
+ sptr->rd_blknum = blk;
+ sptr->rd_callbuf = buff;
+ sptr->rd_pid = getpid();
- /* Search the cache for specified block */
+ /* Atomically resume the communication process and suspend the */
+ /* the current process to wait for the read to complete */
- bptr = rdptr->rd_chnext;
- while (bptr != (struct rdbuff *)&rdptr->rd_ctnext) {
- if (bptr->rd_blknum == blk) {
- if (bptr->rd_status == RD_INVALID) {
- break;
- }
- memcpy(buff, bptr->rd_block, RD_BLKSIZ);
- return OK;
- }
- bptr = bptr->rd_next;
- }
-
- /* Search the request list for most recent occurrence of block */
-
- bptr = rdptr->rd_rtprev; /* Start at tail of list */
-
- while (bptr != (struct rdbuff *)&rdptr->rd_rhnext) {
- if (bptr->rd_blknum == blk) {
-
- /* If most recent request for block is write, copy data */
-
- if (bptr->rd_op == RD_OP_WRITE) {
- memcpy(buff, bptr->rd_block, RD_BLKSIZ);
- return OK;
- }
- break;
- }
- bptr = bptr->rd_prev;
- }
-
- /* Allocate a buffer and add read request to tail of req. queue */
-
- bptr = rdsbufalloc(rdptr);
- bptr->rd_op = RD_OP_READ;
- bptr->rd_refcnt = 1;
- bptr->rd_blknum = blk;
- bptr->rd_status = RD_INVALID;
- bptr->rd_pid = getpid();
-
- /* Insert new request into list just before tail */
-
- pptr = rdptr->rd_rtprev;
- rdptr->rd_rtprev = bptr;
- bptr->rd_next = pptr->rd_next;
- bptr->rd_prev = pptr;
- pptr->rd_next = bptr;
-
- /* Prepare to receive message when read completes */
-
- recvclr();
-
- /* Signal the semaphore to start communication */
-
- signal(rdptr->rd_reqsem);
-
- /* Block to wait for a message */
-
- bptr = (struct rdbuff *)receive();
- if (bptr == (struct rdbuff *)SYSERR) {
- return SYSERR;
- }
- memcpy(buff, bptr->rd_block, RD_BLKSIZ);
- bptr->rd_refcnt--;
- if (bptr->rd_refcnt <= 0) {
-
- /* Look for previous item in cache with the same block */
- /* number to see if this item was only being kept */
- /* until pending read completed */
-
- cptr = rdptr->rd_chnext;
- while (cptr != bptr) {
- if (cptr->rd_blknum == blk) {
-
- /* Unlink from cache */
-
- pptr = bptr->rd_prev;
- nptr = bptr->rd_next;
- pptr->rd_next = nptr;
- nptr->rd_prev = pptr;
-
- /* Add to the free list */
-
- bptr->rd_next = rdptr->rd_free;
- rdptr->rd_free = bptr;
- break;
- }
- cptr = cptr->rd_next;
- }
- }
- return OK;
+ rdsars(rdptr->rd_comproc);
+ return RD_BLKSIZ;
}
diff --git a/device/rds/rdswrite.c b/device/rds/rdswrite.c
index e9eed2a..7695b9d 100644
--- a/device/rds/rdswrite.c
+++ b/device/rds/rdswrite.c
@@ -9,89 +9,35 @@
devcall rdswrite (
struct dentry *devptr, /* Entry in device switch table */
char *buff, /* Buffer that holds a disk blk */
- int32 blk /* Block number to write */
+ int32 blk /* Block num. of block to write */
)
{
- struct rdscblk *rdptr; /* Pointer to control block */
- struct rdbuff *bptr; /* Pointer to buffer on a list */
- struct rdbuff *pptr; /* Ptr to previous buff on list */
- struct rdbuff *nptr; /* Ptr to next buffer on list */
- bool8 found; /* Was buff found during search?*/
+ struct rdscblk *rdptr; /* Pointer to the control block */
+ /* for the disk device */
+ struct rdsent *sptr; /* Pointer to serial queue entry*/
- /* If device not currently in use, report an error */
+ /* If the device not currently open, report an error */
rdptr = &rdstab[devptr->dvminor];
if (rdptr->rd_state != RD_OPEN) {
return SYSERR;
}
- /* Ensure rdsprocess is runnning */
+ /* Obtain the next serial queue entry and fill it in */
- if ( ! rdptr->rd_comruns ) {
- rdptr->rd_comruns = TRUE;
- resume(rdptr->rd_comproc);
+ sptr = &rdptr->rd_sq[rdptr->rdstail++];
+ if (rdptr->rdstail >= RD_SSIZE) { /* wrap around, if necessary */
+ rdptr->rdstail = 0;
}
+ rdptr->rdscount++; /* Increment the count of items */
+ sptr->rd_op = RD_OP_WRITE;
+ sptr->rd_blknum = blk;
+ sptr->rd_callbuf = buff;
+ sptr->rd_pid = getpid();
- /* If request queue already contains a write request */
- /* for the block, replace the contents */
+ /* Atomically resume the communication process and suspend the */
+ /* the current process to wait until the request is ebqueued */
- bptr = rdptr->rd_rhnext;
- while (bptr != (struct rdbuff *)&rdptr->rd_rtnext) {
- if ( (bptr->rd_blknum == blk) &&
- (bptr->rd_op == RD_OP_WRITE) ) {
- memcpy(bptr->rd_block, buff, RD_BLKSIZ);
- return OK;
- }
- bptr = bptr->rd_next;
- }
-
- /* Search cache for cached copy of block */
-
- bptr = rdptr->rd_chnext;
- found = FALSE;
- while (bptr != (struct rdbuff *)&rdptr->rd_ctnext) {
- if (bptr->rd_blknum == blk) {
- if (bptr->rd_refcnt <= 0) {
- pptr = bptr->rd_prev;
- nptr = bptr->rd_next;
-
- /* Unlink node from cache list and reset*/
- /* the available semaphore accordingly*/
-
- pptr->rd_next = bptr->rd_next;
- nptr->rd_prev = bptr->rd_prev;
- semreset(rdptr->rd_availsem,
- semcount(rdptr->rd_availsem) - 1);
- found = TRUE;
- }
- break;
- }
- bptr = bptr->rd_next;
- }
-
- if ( !found ) {
- bptr = rdsbufalloc(rdptr);
- }
-
- /* Create a write request */
-
- memcpy(bptr->rd_block, buff, RD_BLKSIZ);
- bptr->rd_op = RD_OP_WRITE;
- bptr->rd_refcnt = 0;
- bptr->rd_blknum = blk;
- bptr->rd_status = RD_VALID;
- bptr->rd_pid = getpid();
-
- /* Insert new request into list just before tail */
-
- pptr = rdptr->rd_rtprev;
- rdptr->rd_rtprev = bptr;
- bptr->rd_next = pptr->rd_next;
- bptr->rd_prev = pptr;
- pptr->rd_next = bptr;
-
- /* Signal semaphore to start communication process */
-
- signal(rdptr->rd_reqsem);
- return OK;
+ rdsars(rdptr->rd_comproc);
+ return RD_BLKSIZ;
}
diff --git a/device/rfs/rflclose.c b/device/rfs/rflclose.c
index f1f0d87..824447c 100644
--- a/device/rfs/rflclose.c
+++ b/device/rfs/rflclose.c
@@ -11,6 +11,11 @@ devcall rflclose (
)
{
struct rflcblk *rfptr; /* Pointer to control block */
+ int32 retval; /* Return value */
+ struct rf_msg_creq msg; /* Request message to send */
+ struct rf_msg_cres resp; /* Buffer for response */
+ char *from, *to; /* Used during name copy */
+ int32 len; /* Length of name */
/* Wait for exclusive access */
@@ -19,11 +24,52 @@ devcall rflclose (
/* Verify remote file device is open */
rfptr = &rfltab[devptr->dvminor];
+
+ /* If device not currently in use, report an error */
+
if (rfptr->rfstate == RF_FREE) {
signal(Rf_data.rf_mutex);
return SYSERR;
}
+ /* Form read request */
+
+ msg.rf_type = htons(RF_MSG_CREQ);
+ msg.rf_status = htons(0);
+ msg.rf_seq = 0; /* Rfscomm will set sequence */
+ from = rfptr->rfname;
+ to = msg.rf_name;
+ memset(to, NULLCH, RF_NAMLEN); /* Start name as all zero bytes */
+ len = 0;
+
+ while ( (*to++ = *from++) ) { /* Copy name to request */
+ if (++len >= RF_NAMLEN) {
+ signal(Rf_data.rf_mutex);
+ return SYSERR;
+ }
+ }
+
+ /* Send message and receive response */
+
+ retval = rfscomm((struct rf_msg_hdr *)&msg,
+ sizeof(struct rf_msg_creq),
+ (struct rf_msg_hdr *)&resp,
+ sizeof(struct rf_msg_cres) );
+
+ /* Check response */
+
+ if (retval == SYSERR) {
+ signal(Rf_data.rf_mutex);
+ return SYSERR;
+ } else if (retval == TIMEOUT) {
+ kprintf("Timeout during remote file close\n");
+ signal(Rf_data.rf_mutex);
+ return SYSERR;
+ } else if (ntohs(resp.rf_status) != 0) {
+ signal(Rf_data.rf_mutex);
+ return SYSERR;
+ }
+
/* Mark device closed */
rfptr->rfstate = RF_FREE;
diff --git a/device/rfs/rflgetc.c b/device/rfs/rflgetc.c
index 3db46c1..43bbb3e 100644
--- a/device/rfs/rflgetc.c
+++ b/device/rfs/rflgetc.c
@@ -15,9 +15,13 @@ devcall rflgetc(
retval = rflread(devptr, &ch, 1);
- if (retval != 1) {
+ if (retval == TIMEOUT) {
+ return TIMEOUT;
+ } else if ( (retval == EOF) || (retval == 0) ) {
+ return EOF;
+ } else if (retval != 1) {
return SYSERR;
}
- return (devcall)ch;
+ return (devcall)(ch&0xff);
}
diff --git a/device/rfs/rflread.c b/device/rfs/rflread.c
index 5d8979b..644d9e3 100644
--- a/device/rfs/rflread.c
+++ b/device/rfs/rflread.c
@@ -96,5 +96,8 @@ devcall rflread (
rfptr->rfpos += ntohl(resp.rf_len);
signal(Rf_data.rf_mutex);
+ if (ntohl(resp.rf_len) == 0) {
+ return EOF;
+ }
return ntohl(resp.rf_len);
}
diff --git a/device/rfs/rfscomm.c b/device/rfs/rfscomm.c
index cea00b8..1553804 100644
--- a/device/rfs/rfscomm.c
+++ b/device/rfs/rfscomm.c
@@ -19,17 +19,27 @@ int32 rfscomm (
int32 seq; /* Sequence for this exchange */
int16 rtype; /* Reply type in host byte order*/
int32 slot; /* UDP slot */
+ char err[128]; /* Error message buffer */
+
/* For the first time after reboot, register the server port */
if ( ! Rf_data.rf_registered ) {
- if ( (slot = udp_register(Rf_data.rf_ser_ip,
- Rf_data.rf_ser_port,
- Rf_data.rf_loc_port)) == SYSERR) {
+
+ /* Convert the server name to an IP address */
+
+ if (dnslookup(RF_SERVER, &Rf_data.rf_ser_ip) == SYSERR) {
+ sprintf(err, "rfs server %s is invalid", RF_SERVER);
+ panic("err");
+ }
+
+ if ( (slot = udp_register(Rf_data.rf_ser_ip,
+ Rf_data.rf_ser_port,
+ Rf_data.rf_loc_port)) == SYSERR) {
return SYSERR;
- }
- Rf_data.rf_udp_slot = slot;
- Rf_data.rf_registered = TRUE;
+ }
+ Rf_data.rf_udp_slot = slot;
+ Rf_data.rf_registered = TRUE;
}
/* Assign message next sequence number */
@@ -74,7 +84,6 @@ int32 rfscomm (
if (rtype != ( ntohs(msg->rf_type) | RF_MSG_RESPONSE) ) {
continue;
}
-
return retval; /* Return length to caller */
}
diff --git a/device/rfs/rfscontrol.c b/device/rfs/rfscontrol.c
index 052c5ea..f10cbb9 100644
--- a/device/rfs/rfscontrol.c
+++ b/device/rfs/rfscontrol.c
@@ -16,7 +16,6 @@ devcall rfscontrol (
int32 len; /* Length of name */
struct rf_msg_sreq msg; /* Buffer for size request */
struct rf_msg_sres resp; /* Buffer for size response */
- struct rflcblk *rfptr; /* Pointer to entry in rfltab */
char *to, *from; /* Used during name copy */
int32 retval; /* Return value */
@@ -24,10 +23,10 @@ devcall rfscontrol (
wait(Rf_data.rf_mutex);
- /* Check length and copy (needed for size) */
+ /* Check length of name (copy during the check even though the */
+ /* copy is only used for a size request) */
- rfptr = &rfltab[devptr->dvminor];
- from = rfptr->rfname;
+ from = (char *)arg1;
to = msg.rf_name;
len = 0;
memset(to, NULLCH, RF_NAMLEN); /* Start name as all zeroes */
@@ -79,7 +78,8 @@ devcall rfscontrol (
}
break;
- /* Obtain current file size (non-standard message size) */
+ /* Obtain current file size (cannot use rfsndmsg because a */
+ /* response contains a value in addition to the header) */
case RFS_CTL_SIZE:
diff --git a/device/rfs/rfsinit.c b/device/rfs/rfsinit.c
index 9eff0ad..66db58b 100644
--- a/device/rfs/rfsinit.c
+++ b/device/rfs/rfsinit.c
@@ -5,7 +5,7 @@
struct rfdata Rf_data;
/*------------------------------------------------------------------------
- * rfsinit - Initialize the remote file system master device
+ * rfsinit - Initialize the remote file system primary device
*------------------------------------------------------------------------
*/
devcall rfsinit(
@@ -13,15 +13,17 @@ devcall rfsinit(
)
{
- /* Choose an initial message sequence number */
+
+ /* Set an initial message sequence number */
Rf_data.rf_seq = 1;
- /* Set the server IP address, server port, and local port */
+ /* Set the server IP address to zero until rfscomm is called */
+
+ Rf_data.rf_ser_ip = 0;
+
+ /* Record the local and remote port numbers to use */
- if ( dot2ip(RF_SERVER_IP, &Rf_data.rf_ser_ip) == SYSERR ) {
- panic("invalid IP address for remote file server");
- }
Rf_data.rf_ser_port = RF_SERVER_PORT;
Rf_data.rf_loc_port = RF_LOC_PORT;
@@ -31,7 +33,7 @@ devcall rfsinit(
panic("Cannot create remote file system semaphore");
}
- /* Specify that the server port is not yet registered */
+ /* Specify that the UDP slot is not yet registered */
Rf_data.rf_registered = FALSE;
diff --git a/device/rfs/rfsopen.c b/device/rfs/rfsopen.c
index bee91a0..ad3ac03 100644
--- a/device/rfs/rfsopen.c
+++ b/device/rfs/rfsopen.c
@@ -91,7 +91,7 @@ devcall rfsopen (
signal(Rf_data.rf_mutex);
return SYSERR;
} else if (retval == TIMEOUT) {
- kprintf("Timeout during remote file open\n\r");
+ kprintf("Timeout during remote file open\n");
signal(Rf_data.rf_mutex);
return SYSERR;
} else if (ntohs(resp.rf_status) != 0) {
diff --git a/device/sdmc/sdmcclose.c b/device/sdmc/sdmcclose.c
new file mode 100644
index 0000000..80a0bb6
--- /dev/null
+++ b/device/sdmc/sdmcclose.c
@@ -0,0 +1,15 @@
+/* sdmcclose.c - sdmcclose */
+
+#include <xinu.h>
+#include <sdmc.h>
+
+/*------------------------------------------------------------------------
+ * sdmcclose - Close a SD memory card device
+ *------------------------------------------------------------------------
+ */
+devcall sdmcclose (
+ struct dentry *devptr /* entry in device switch table */
+ )
+{
+ return OK;
+}
diff --git a/device/sdmc/sdmccmd.c b/device/sdmc/sdmccmd.c
new file mode 100644
index 0000000..2c3d34a
--- /dev/null
+++ b/device/sdmc/sdmccmd.c
@@ -0,0 +1,288 @@
+/* sdmccmd.c - sdmc_cmd_err_rcvy, sdmc_issue_cmd_async, */
+/* sdmc_finalize_cmd_async, sdmc_issue_cmd_sync */
+
+#include <xinu.h>
+#include <sdmc.h>
+
+devcall sdmc_cmd_err_rcvy (
+ volatile struct sdmc_csreg *csrptr, /* SD controlelr CSR */
+ uint16* error_sts /* command error status */
+ )
+{
+ uint16 cmd12_err_sts = 0; /* CMD12 error status */
+
+ kprintf("[SDMC] Error recovery %04X\n", csrptr->err_int_status);
+
+ /* Set software reset bit for error type */
+
+ /* Command Error - Command software reset */
+ if(csrptr->err_int_status &
+ (SDMC_ERR_INT_CMD_TIMEOUT_ERR |
+ SDMC_ERR_INT_CMD_CRC_ERR |
+ SDMC_ERR_INT_CMD_END_BIT_ERR |
+ SDMC_ERR_INT_CMD_INDEX_ERR)) {
+
+ csrptr->sw_rst |= SDMC_SW_RST_CMD_LN;
+ while(csrptr->sw_rst & SDMC_SW_RST_CMD_LN) {
+ DELAY(SDMC_CMD_DELAY);
+ }
+ }
+
+ /* Data error - Data software reset */
+ if(csrptr->err_int_status &
+ (SDMC_ERR_INT_DATA_TIMEOUT_ERR |
+ SDMC_ERR_INT_DATA_CRC_ERR |
+ SDMC_ERR_INT_DATA_END_BIT_ERR)) {
+
+ csrptr->sw_rst |= SDMC_SW_RST_DAT_LN;
+ while(csrptr->sw_rst & SDMC_SW_RST_DAT_LN) {
+ DELAY(SDMC_CMD_DELAY);
+ }
+ }
+
+ kprintf("After software reset\n");
+
+ /* Save and clear the error status */
+ (*error_sts) = csrptr->err_int_status;
+ csrptr->err_int_status |= (*error_sts);
+
+ /* Issue the abort command (CMD12) */
+ /* Do not perform error recovery */
+ sdmc_issue_cmd_sync(csrptr, SDMC_ABT, 0x00000000, &cmd12_err_sts,
+ SDMC_CMD_NO_ERR_RCVY);
+
+ /* Wait for command and DAT inhibit signals to be cleared */
+ while(csrptr->pre_state & SDMC_PRE_STATE_CMD_INHIBIT_CMD) {
+ DELAY(SDMC_CMD_DELAY);
+ }
+ while(csrptr->pre_state & SDMC_PRE_STATE_CMD_INHIBIT_DAT) {
+ DELAY(SDMC_CMD_DELAY);
+ }
+
+ /* Clear the command complete interrupt */
+ if(csrptr->nml_int_status & SDMC_NML_INT_CMD_COMP) {
+ csrptr->nml_int_status |= SDMC_NML_INT_CMD_COMP;
+ }
+
+ /* Check status of abort command */
+ if(csrptr->err_int_status &
+ (SDMC_ERR_INT_CMD_TIMEOUT_ERR |
+ SDMC_ERR_INT_CMD_CRC_ERR |
+ SDMC_ERR_INT_CMD_END_BIT_ERR |
+ SDMC_ERR_INT_CMD_INDEX_ERR)) {
+
+ /* Clear the error status */
+ csrptr->err_int_status |= csrptr->err_int_status;
+
+ /* Error in abort, error is non recoverable */
+ return SDMC_RC_NON_RECOVERABLE_ERROR;
+ }
+
+ /* Check for data timeout */
+ if(csrptr->err_int_status & SDMC_ERR_INT_DATA_TIMEOUT_ERR) {
+
+ /* Clear the error status */
+ csrptr->err_int_status |= csrptr->err_int_status;
+
+ /* Data timeout in abort, error is non recoverable */
+ return SDMC_RC_NON_RECOVERABLE_ERROR;
+ }
+
+ /* Check data line signal level */
+ DELAY(1); /* Must wait at least 40 microseconds */
+ if(csrptr->pre_state & SDMC_PRE_STATE_DATA_LN_SIG_LVL) {
+ return SDMC_RC_RECOVERABLE_ERR;
+ }
+ return SDMC_RC_NON_RECOVERABLE_ERROR;
+}
+
+devcall sdmc_issue_cmd_async (
+ volatile struct sdmc_csreg *csrptr, /* SD controller CSR */
+ uint16 cmd_value, /* SDMC Command to issue*/
+ uint32 arg_value /* Command argument */
+ )
+{
+ /* Wait for command inhibit bits to be cleared */
+
+ kprintf("State Prior to CMD: %08X %08X %08X %08X %08X %04X %04X\n",
+ csrptr->pre_state, csrptr->response0, csrptr->response2,
+ csrptr->response4, csrptr->response6,
+ csrptr->nml_int_status, csrptr->err_int_status);
+
+ while(csrptr->pre_state & SDMC_PRE_STATE_CMD_INHIBIT_CMD) {
+ DELAY(SDMC_CMD_DELAY);
+ }
+ while(csrptr->pre_state & SDMC_PRE_STATE_CMD_INHIBIT_DAT) {
+ DELAY(SDMC_CMD_DELAY);
+ }
+
+ kprintf("Issuing command %04X %08X\n", cmd_value, arg_value);
+
+ /* Ensure that the command complete interrupt status are enabled*/
+ csrptr->nrm_int_status_en |= SDMC_CMD_COMP_STAT_EN |
+ SDMC_TX_COMP_STAT_EN | SDMC_CRD_INT_STAT_EN;
+ csrptr->err_int_stat_en |= SDMC_ERR_INT_CMD_TIMEOUT_ERR_STAT_EN |
+ SDMC_ERR_INT_CMD_CRC_ERR_STAT_EN |
+ SDMC_ERR_INT_CMD_END_BIT_ERR_STAT_EN |
+ SDMC_ERR_INT_CMD_IND_ERR_STAT_EN;
+
+ /* Asynchronous command execution, ensure that interrupt */
+ /* signals are enabled */
+ csrptr->nrm_int_sig_en |= SDMC_CMD_COMP_SIG_EN |
+ SDMC_TX_COMP_SIG_EN | SDMC_CRD_INT_SIG_EN;
+ csrptr->err_int_sig_en |= SDMC_ERR_INT_CMD_TIMEOUT_ERR_SIG_EN |
+ SDMC_ERR_INT_CMD_CRC_ERR_SIG_EN |
+ SDMC_ERR_INT_CMD_END_BIT_ERR_SIG_EN |
+ SDMC_ERR_INT_CMD_IND_ERR_SIG_EN;
+
+ /* Issue the command */
+ csrptr->argument = arg_value;
+ csrptr->cmd = cmd_value;
+
+ return SDMC_RC_OK;
+}
+
+devcall sdmc_finalize_cmd_async (
+ volatile struct sdmc_csreg *csrptr, /* SD controller CSR */
+ uint16* error_sts /* Error status */
+ )
+{
+ kprintf("CMD INT: %04X %04X\n", csrptr->nml_int_status,
+ csrptr->err_int_status);
+
+ /* Clear the command complete interrupt */
+ if(csrptr->nml_int_status & SDMC_NML_INT_CMD_COMP) {
+ csrptr->nml_int_status |= SDMC_NML_INT_CMD_COMP;
+ }
+
+ /* Clear the error interrupt and perform error recovery */
+ if(csrptr->nml_int_status & SDMC_NML_INT_ERR_INT) {
+ csrptr->nml_int_status |= SDMC_NML_INT_ERR_INT;
+ return sdmc_cmd_err_rcvy(csrptr, error_sts);
+ }
+
+ kprintf("State After CMD: %08X %08X %08X %08X %08X %04X %04X\n",
+ csrptr->pre_state, csrptr->response0, csrptr->response2,
+ csrptr->response4, csrptr->response6,
+ csrptr->nml_int_status, csrptr->err_int_status);
+
+ return SDMC_RC_OK;
+}
+
+devcall sdmc_issue_cmd_sync (
+ volatile struct sdmc_csreg *csrptr, /* SD controller CSR */
+ uint16 cmd_value, /* SDMC Command to issue*/
+ uint32 arg_value, /* Command argument */
+ uint16* error_sts, /* Error status */
+ uint8 flags /* Command execut. flags*/
+ )
+{
+ uint8 rc = SDMC_RC_OK;
+
+ /* Save old contents of interrupt registers */
+ uint16 save_nrm_int_stat_en = csrptr->nrm_int_status_en;
+ uint16 save_nrm_int_sig_en = csrptr->nrm_int_sig_en;
+ uint16 save_err_int_stat_en = csrptr->err_int_stat_en;
+ uint16 save_err_int_sig_en = csrptr->err_int_sig_en;
+
+ /* Wait for command inhibit bits to be cleared */
+
+ kprintf("State Prior to CMD: %08X %08X %08X %08X %08X %04X %04X\n",
+ csrptr->pre_state, csrptr->response0, csrptr->response2,
+ csrptr->response4, csrptr->response6,
+ csrptr->nml_int_status, csrptr->err_int_status);
+
+ while(csrptr->pre_state & SDMC_PRE_STATE_CMD_INHIBIT_CMD) {
+ DELAY(SDMC_CMD_DELAY);
+ }
+ while(csrptr->pre_state & SDMC_PRE_STATE_CMD_INHIBIT_DAT) {
+ DELAY(SDMC_CMD_DELAY);
+ }
+
+ kprintf("Issuing command %04X %08X\n", cmd_value, arg_value);
+
+ /* Ensure that the command complete interrupt status are enabled*/
+
+ csrptr->nrm_int_status_en |= SDMC_CMD_COMP_STAT_EN |
+ SDMC_TX_COMP_STAT_EN | SDMC_CRD_INT_STAT_EN;
+ csrptr->err_int_stat_en |= SDMC_ERR_INT_CMD_TIMEOUT_ERR_STAT_EN |
+ SDMC_ERR_INT_CMD_CRC_ERR_STAT_EN |
+ SDMC_ERR_INT_CMD_END_BIT_ERR_STAT_EN |
+ SDMC_ERR_INT_CMD_IND_ERR_STAT_EN;
+
+ if(flags & SDMC_CMD_DAT_TRNS) {
+ csrptr->nrm_int_status_en |= SDMC_TX_COMP_STAT_EN;
+ csrptr->err_int_stat_en |=
+ SDMC_ERR_INT_DATA_TIMEOUT_ERR_STAT_EN |
+ SDMC_ERR_INT_DATA_CRC_ERR_STAT_EN |
+ SDMC_ERR_INT_DATA_END_BIT_ERR_STAT_EN;
+ }
+
+ /* Synchronous command execution, ensure that interrupt */
+ /* signals are not enabled */
+ csrptr->nrm_int_sig_en &= ~(SDMC_CMD_COMP_SIG_EN |
+ SDMC_TX_COMP_SIG_EN | SDMC_CRD_INT_SIG_EN);
+ csrptr->err_int_sig_en &= ~(
+ SDMC_ERR_INT_CMD_TIMEOUT_ERR_SIG_EN |
+ SDMC_ERR_INT_CMD_CRC_ERR_SIG_EN |
+ SDMC_ERR_INT_CMD_END_BIT_ERR_SIG_EN |
+ SDMC_ERR_INT_CMD_IND_ERR_SIG_EN |
+ SDMC_ERR_INT_DATA_TIMEOUT_ERR_SIG_EN |
+ SDMC_ERR_INT_DATA_CRC_ERR_SIG_EN |
+ SDMC_ERR_INT_DATA_END_BIT_ERR_SIG_EN);
+
+ /* Issue the command */
+ csrptr->argument = arg_value;
+ csrptr->cmd = cmd_value;
+
+ /* Wait for command to complete */
+ while(!(csrptr->nml_int_status & SDMC_NML_INT_CMD_COMP) &&
+ !(csrptr->nml_int_status & SDMC_NML_INT_ERR_INT)) {
+ DELAY(SDMC_CMD_DELAY);
+ }
+
+ /* Clear the command complete interrupt */
+ if(csrptr->nml_int_status & SDMC_NML_INT_CMD_COMP) {
+ csrptr->nml_int_status |= SDMC_NML_INT_CMD_COMP;
+ }
+
+ if(flags & SDMC_CMD_DAT_TRNS) {
+
+ /* Wait for data transmission to complete */
+ while(!(csrptr->nml_int_status & SDMC_NML_INT_TX_COMP) &&
+ !(csrptr->nml_int_status & SDMC_NML_INT_ERR_INT)) {
+ kprintf(
+ "Waiting for data trans %08X %04X %04X %08X %02X\n",
+ csrptr->sys_adr, csrptr->nml_int_status,
+ csrptr->err_int_status, csrptr->pre_state,
+ csrptr->blk_gap_ctl);
+ DELAY(SDMC_CMD_DELAY);
+ }
+
+ /* Clear the data transmission complete interrupt */
+ if(csrptr->nml_int_status & SDMC_NML_INT_TX_COMP) {
+ csrptr->nml_int_status |= SDMC_NML_INT_TX_COMP;
+ }
+ }
+
+ /* Clear the error interrupt and perform error recovery */
+ if(csrptr->nml_int_status & SDMC_NML_INT_ERR_INT) {
+ csrptr->nml_int_status |= SDMC_NML_INT_ERR_INT;
+ if(!(flags & SDMC_CMD_NO_ERR_RCVY)) {
+ rc = sdmc_cmd_err_rcvy(csrptr, error_sts);
+ }
+ }
+
+ kprintf("State After CMD: %08X %08X %08X %08X %08X %04X %04X\n",
+ csrptr->pre_state, csrptr->response0, csrptr->response2,
+ csrptr->response4, csrptr->response6,
+ csrptr->nml_int_status, csrptr->err_int_status);
+
+ /* Restore saved interrupt enable bits */
+ csrptr->nrm_int_status_en = save_nrm_int_stat_en;
+ csrptr->nrm_int_sig_en = save_nrm_int_sig_en;
+ csrptr->err_int_stat_en = save_err_int_stat_en;
+ csrptr->err_int_sig_en = save_err_int_sig_en;
+
+ return rc;
+}
diff --git a/device/sdmc/sdmcdispatch.S b/device/sdmc/sdmcdispatch.S
new file mode 100644
index 0000000..d191360
--- /dev/null
+++ b/device/sdmc/sdmcdispatch.S
@@ -0,0 +1,20 @@
+/* sdmcDispatch.S - sdmcDispatch */
+
+#include <icu.s>
+ .text
+ .globl sdmcdispatch
+ .globl sdmcinterrupt
+sdmcdispatch:
+ pushal
+ pushfl
+ cli
+ movb $EOI,%al # clear the interrupt
+ outb %al,$OCW1_2
+ movb $EOI,%al
+ outb %al,$OCW2_2
+
+ call sdmcinterrupt
+
+ popfl
+ popal
+ iret
diff --git a/device/sdmc/sdmcinit.c b/device/sdmc/sdmcinit.c
new file mode 100644
index 0000000..0ad852a
--- /dev/null
+++ b/device/sdmc/sdmcinit.c
@@ -0,0 +1,56 @@
+/* sdmcInit.c - sdmcInit */
+
+#include <xinu.h>
+#include <sdmc.h>
+
+struct sdmcblk sdmctab[Nsdmc];
+
+/*------------------------------------------------------------------------
+ * sdmcinit - initialize the SD memory card device
+ *------------------------------------------------------------------------
+ */
+devcall sdmcinit (
+ struct dentry *devptr /* entry in device switch table */
+ )
+{
+ volatile struct sdmc_csreg *csrptr; /* address of SD controller's CSR */
+ uint32 pciinfo; /* PCI info to read config */
+
+ /* Search for the SD memory card device on the PCI bus */
+ pciinfo = find_pci_device(INTEL_QUARK_SDIO_PCI_DID, INTEL_QUARK_SDIO_PCI_VID, 0);
+ if((int)pciinfo == SYSERR) {
+ kprintf("[SDMC] Device not found\n");
+ return SYSERR;
+ }
+
+ /* Read PCI config space to get memory base address */
+ if(pci_read_config_dword(pciinfo, 0x10, (uint32 *)&devptr->dvcsr) == SYSERR) {
+ kprintf("[SDMC] Unable to retrieve CSR\n");
+ return SYSERR;
+ }
+
+ /* Enable CSR Memory Space, Enable Bus Master */
+ pci_write_config_word(pciinfo, 0x4, 0x0006);
+
+ /* Set interrupt IRQ */
+ set_evec(devptr->dvirq, (uint32)sdmcdispatch);
+
+ /* Initialize the SD CS register */
+ csrptr = (struct sdmc_csreg *)devptr->dvcsr;
+
+ /* Enable and register for card insertion and removal interrupts */
+ csrptr->nrm_int_status_en = SDMC_CRD_INS_STAT_EN | SDMC_CRD_RMV_STAT_EN | SDMC_CRD_INT_STAT_EN;
+ csrptr->nrm_int_sig_en = SDMC_CRD_INS_SIG_EN | SDMC_CRD_RMV_SIG_EN | SDMC_CRD_INT_SIG_EN;
+ csrptr->err_int_stat_en = 0;
+ csrptr->err_int_sig_en = 0;
+
+ /*
+ csrptr->nrm_int_status_en = 0x1FF;
+ csrptr->nrm_int_sig_en = 0x1FF;
+
+ csrptr->err_int_stat_en = 0x7FF;
+ csrptr->err_int_sig_en = 0x7FF;
+ */
+
+ return OK;
+}
diff --git a/device/sdmc/sdmcinterrupt.c b/device/sdmc/sdmcinterrupt.c
new file mode 100644
index 0000000..c0b6359
--- /dev/null
+++ b/device/sdmc/sdmcinterrupt.c
@@ -0,0 +1,72 @@
+/* sdmcinterrupt.c - sdmcinterrupt */
+
+#include <xinu.h>
+#include <sdmc.h>
+
+/*------------------------------------------------------------------------
+ * sdmcinterrupt - handle an interrupt for a SD memory card device
+ *------------------------------------------------------------------------
+ */
+void sdmcinterrupt(void) {
+ struct dentry *devptr; /* address of device control blk*/
+ volatile struct sdmc_csreg *csrptr; /* address of SD controller's CSR */
+ struct sdmcblk *sdmcptr; /* Pointer to sdmctab entry */
+
+ /* Get CSR address of the device */
+
+ devptr = (struct dentry *) &devtab[SDMC];
+ csrptr = (struct sdmc_csreg *) devptr->dvcsr;
+ sdmcptr = &sdmctab[devptr->dvminor];
+
+ kprintf("SDMC INT: %04X %04X\n", csrptr->nml_int_status, csrptr->err_int_status);
+
+ /* Check for card insertion interrupt */
+ if(csrptr->nml_int_status & SDMC_NML_INT_CRD_INS) {
+
+ /* Clear the card insertion interrupt */
+ csrptr->nml_int_status |= SDMC_NML_INT_CRD_INS;
+
+ /* Check current card present status to see if it is actually inserted */
+ if(csrptr->pre_state & SDMC_PRE_STATE_CRD_INS) {
+
+ /* Open the device */
+ sdmcopen(devptr, "", "");
+ }
+ return;
+ }
+
+ /* Check for card removal interrupt */
+ if(csrptr->nml_int_status & SDMC_NML_INT_CRD_RM) {
+
+ /* Clear the card removal interrupt */
+ csrptr->nml_int_status |= SDMC_NML_INT_CRD_RM;
+
+ /* Check current card present status to see if it is actually removed */
+ if(!(csrptr->pre_state & SDMC_PRE_STATE_CRD_INS)) {
+
+ /* Close the device */
+ //sdmcClose
+ }
+ return;
+ }
+
+ /* Check for command complete interrupt */
+ if(csrptr->nml_int_status & SDMC_NML_INT_CMD_COMP) {
+
+ /* Clear the command complete interrupt */
+ csrptr->nml_int_status |= SDMC_NML_INT_CMD_COMP;
+
+ /* Signal the command semaphore */
+ signal(sdmcptr->cmd_sem);
+ }
+
+ /* Check for transfer complete interrupt */
+ if(csrptr->nml_int_status & SDMC_NML_INT_TX_COMP) {
+
+ /* Clear the transfer complete interrupt */
+ csrptr->nml_int_status |= SDMC_NML_INT_TX_COMP;
+
+ /* Signal the transfer semaphore */
+ signal(sdmcptr->tx_sem);
+ }
+}
diff --git a/device/sdmc/sdmcopen.c b/device/sdmc/sdmcopen.c
new file mode 100644
index 0000000..8bf40d0
--- /dev/null
+++ b/device/sdmc/sdmcopen.c
@@ -0,0 +1,204 @@
+/* sdmcopen.c - sdmcopen */
+
+#include <xinu.h>
+#include <sdmc.h>
+
+/*------------------------------------------------------------------------
+ * sdmc_set_bus_power - set SD voltage
+ *------------------------------------------------------------------------
+ */
+devcall sdmc_set_bus_power (
+ volatile struct sdmc_csreg *csrptr /* address of SD controller's CSR */
+ )
+{
+ uint8 sdmc_voltage_select = 0;
+
+ /* Determine max supported voltage */
+ if(csrptr->capabilities & SDMC_CAP_VOLT_SUPPORT_3P3V) {
+ sdmc_voltage_select = SDMC_PWR_CTL_SD_BUS_VOL_SEL_3P3V;
+ } else if(csrptr->capabilities & SDMC_CAP_VOLT_SUPPORT_3P0V) {
+ sdmc_voltage_select = SDMC_PWR_CTL_SD_BUS_VOL_SEL_3P0V;
+ } else if(csrptr->capabilities & SDMC_CAP_VOLT_SUPPORT_1P8V) {
+ sdmc_voltage_select = SDMC_PWR_CTL_SD_BUS_VOL_SEL_1P8V;
+ } else {
+ /* Unknown supported voltage */
+ return SDMC_RC_NON_RECOVERABLE_ERROR;
+ }
+
+ /* Set the controller voltage */
+ csrptr->pwr_ctl &= SDMC_PWR_CTL_SD_BUS_VOL_SEL_CLR;
+ csrptr->pwr_ctl |= sdmc_voltage_select;
+
+ /* Set bus power flag */
+ csrptr->pwr_ctl |= SDMC_PWR_CTL_SD_BUS_PWR;
+
+ return SDMC_RC_OK;
+}
+
+/*------------------------------------------------------------------------
+ * sdmc_set_clock - set SDCLK frequency
+ *------------------------------------------------------------------------
+ */
+devcall sdmc_set_clock (
+ volatile struct sdmc_csreg *csrptr /* address of SD controller's CSR */
+ )
+{
+ /* Change to the SD Clock is not allowed while command inhibit is set */
+ while(csrptr->pre_state & SDMC_PRE_STATE_CMD_INHIBIT_CMD) {
+ DELAY(SDMC_CMD_DELAY);
+ }
+ while(csrptr->pre_state & SDMC_PRE_STATE_CMD_INHIBIT_DAT) {
+ DELAY(SDMC_CMD_DELAY);
+ }
+
+ /* Disable the SD Clock */
+ csrptr->clk_ctl &= ~(SDMC_CLK_CTL_SD_CLK_EN);
+
+ /* Set the SD clock frequency divisor */
+ csrptr->clk_ctl &= SDMC_CLK_CTL_SD_FREQ_HIGH_MASK;
+
+ /* Internal enable the SD clock */
+ csrptr->clk_ctl |= SDMC_CLK_CTL_INT_CLK_EN;
+
+ /* Wait for SD clock to be stable */
+ while(!(csrptr->clk_ctl & SDMC_CLK_CTL_INT_CLK_STABLE)) {
+ DELAY(SDMC_CMD_DELAY);
+ }
+
+ /* Set SD Clock enable */
+ csrptr->clk_ctl |= SDMC_CLK_CTL_SD_CLK_EN;
+
+ return SDMC_RC_OK;
+}
+
+/*------------------------------------------------------------------------
+ * sdmc_set_dat_timeout - set timeout for data lines
+ *------------------------------------------------------------------------
+ */
+devcall sdmc_set_dat_timeout (
+ volatile struct sdmc_csreg *csrptr /* address of SD controller's CSR */
+ )
+{
+ kprintf("TIMEOUT %08X %02X\n", csrptr->capabilities, csrptr->timeout_ctl);
+
+ return SDMC_RC_OK;
+}
+
+/*------------------------------------------------------------------------
+ * sdmcopen - open an SD memory card
+ *------------------------------------------------------------------------
+ */
+devcall sdmcopen (
+ struct dentry *devptr, /* entry in device switch table */
+ char *name, /* name to open */
+ char *mode /* mode argument */
+ )
+{
+ volatile struct sdmc_csreg *csrptr; /* address of SD controller's CSR */
+ struct sdmcblk *sdmcptr; /* Pointer to sdmctab entry */
+ uint16 error_sts = 0; /* SDMC command error status */
+ uint32 cmd_arg = 0; /* Value of argument register */
+ byte first_ACMD41 = 1; /* Set for the first ACMD41 */
+
+ /* Initialize structure pointers */
+ sdmcptr = &sdmctab[devptr->dvminor];
+ csrptr = (struct sdmc_csreg *) devptr->dvcsr;
+
+ /* Initialize card identifiers */
+ sdmcptr->rca = 0;
+ memset(sdmcptr->cid, 0x00, sizeof(sdmcptr->cid));
+
+ sdmcptr->cmd8 = 1; /* assume card supports CMD8 */
+ sdmcptr->sdio = 0; /* assume not an SDIO card */
+
+ /* Set the clock speed */
+ sdmc_set_clock(csrptr);
+
+ /* Set the bus voltage */
+ sdmc_set_bus_power(csrptr);
+
+ /* Set the data line timeout value */
+ sdmc_set_dat_timeout(csrptr);
+
+ /* Issue card reset command (CMD0) */
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD0, 0x00000000, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD0: %04X %04X", SDMC_CMD0, error_sts);
+ return SYSERR;
+ }
+
+ /* Issue voltage check command (CMD8) */
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD8, 0x00000101, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD8: %04X %04X", SDMC_CMD8, error_sts);
+ return SYSERR;
+ }
+ /* Error in CMD8 - card must not support it */
+ if(error_sts & SDMC_ERR_INT_CMD_TIMEOUT_ERR ||
+ csrptr->response0 != 0x00000101) {
+ sdmcptr->cmd8 = 0;
+ }
+
+ /* Issue inquiry voltage state (ACMD41) */
+ /* To send an application command (ACMD) a CMD55 must first be sent */
+ /* to tell the controller to expect an application command */
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD55, 0x00000000, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD55: %04X %04X", SDMC_CMD55, error_sts);
+ return SYSERR;
+ }
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_ACMD41, 0x00000000, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in ACMD41: %04X %04X", SDMC_ACMD41, error_sts);
+ return SYSERR;
+ }
+
+ /* Issue initialize card command (ACMD41) */
+ cmd_arg = SDMC_OCR_MASK & csrptr->response0; /* Set OCR */
+ if(csrptr->response0 & SDMC_R3_S18A) { /* Set switch to 1.8V is card supports */
+ cmd_arg |= SDMC_ACMD41_S18R;
+ }
+ cmd_arg |= SDMC_ACMD41_XPC | SDMC_ACMD41_HCS; /* Set high capacity support */
+ /* and extended performance control */
+
+ /* The card initialization command (ACMD41) must be continuously sent until */
+ /* unitialization has completed */
+ do {
+ if(!first_ACMD41) {
+ DELAY(SDMC_CMD_DELAY);
+ }
+
+ /* To send an application command (ACMD) a CMD55 must first be sent */
+ /* to tell the controller to expect an application command */
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD55, 0x00000000, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD55: %04X %04X", SDMC_CMD55, error_sts);
+ return SYSERR;
+ }
+ /* Send the card initialization command */
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_ACMD41, cmd_arg, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in ACMD41: %04X %04X", SDMC_ACMD41, error_sts);
+ return SYSERR;
+ }
+
+ first_ACMD41 = 0;
+ } while(!(csrptr->response0 & SDMC_R3_BUSY));
+
+ /* TODO run voltage switch procedure of the card supports 1.8V signaling */
+
+ /* Retrieve the card's card identifier (CID) */
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD2, 0, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD2: %04X %04X", SDMC_CMD2, error_sts);
+ return SYSERR;
+ }
+ memcpy(sdmcptr->cid, (char*)&csrptr->response0, 16);
+
+ /* Retrieve the card's relative card address (RCA) */
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD3, 0, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD3: %04X %04X", SDMC_CMD3, error_sts);
+ return SYSERR;
+ }
+ sdmcptr->rca = csrptr->response0 & SDMC_R6_RCA_MASK;
+
+ sdmcptr->cmd_sem = semcreate(0);
+ if((int)sdmcptr->cmd_sem == SYSERR) {
+ return SYSERR;
+ }
+
+ return devptr->dvnum;
+}
diff --git a/device/sdmc/sdmcread.c b/device/sdmc/sdmcread.c
new file mode 100644
index 0000000..39232bd
--- /dev/null
+++ b/device/sdmc/sdmcread.c
@@ -0,0 +1,211 @@
+/* sdmcRead.c - sdmcread */
+
+#include <xinu.h>
+#include <sdmc.h>
+
+devcall sdmcread_nodma (
+ struct dentry *devptr, /* entry in device switch table */
+ char *buff, /* buffer to hold disk block */
+ int32 blk /* block number of block to read*/
+ )
+{
+ volatile struct sdmc_csreg *csrptr; /* address of SD controller's CSR */
+ //struct sdmcblk *sdmcptr; /* Pointer to sdmctab entry */
+ uint16 error_sts = 0; /* SDMC command error status */
+ uint32 cmd_arg = 0;
+ char* buff_ptr = buff;
+ uint32 i;
+
+ //sdmcptr = &sdmctab[devptr->dvminor];
+ csrptr = (struct sdmc_csreg *) devptr->dvcsr;
+
+ /* Issue command CMD16 - set block size */
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD16, 512, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD16: %04X %04X", SDMC_CMD16, error_sts);
+ return SYSERR;
+ }
+
+ csrptr->nrm_int_status_en = 0x1FF;
+ csrptr->err_int_stat_en = 0x7FF;
+
+ csrptr->blk_size = 0x00000200;
+ csrptr->blk_count = 1;
+ cmd_arg = blk;
+
+ /* Set transmit mode */
+ /* Single block read no DMA */
+ csrptr->tx_mode = 0x0016;
+
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD17, cmd_arg, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD17: %04X %04X\n", SDMC_CMD17, error_sts);
+ return SYSERR;
+ }
+
+ kprintf("INTSTS %08X %08X\n", csrptr->nrm_int_status_en, csrptr->err_int_stat_en);
+
+ /*
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD12, 0x00000000, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD12: %04X %04X\n", SDMC_CMD17, error_sts);
+ return SYSERR;
+ }
+ */
+
+ for(i = 0; i < 512/sizeof(csrptr->buf_data_port); i++) {
+ while(!(csrptr->nml_int_status & SDMC_NML_INT_BUF_RD_RDY)) {
+ //kprintf("INT %08X %04X %04X %08X\n", csrptr->pre_state, csrptr->nml_int_status, csrptr->err_int_status, csrptr->buf_data_port);
+ DELAY(SDMC_CMD_DELAY);
+ }
+ csrptr->nml_int_status |= SDMC_NML_INT_BUF_RD_RDY;
+
+ memcpy(buff_ptr, (char*)&csrptr->buf_data_port, sizeof(csrptr->buf_data_port));
+ buff_ptr += sizeof(csrptr->buf_data_port);
+
+ kprintf("Read block: %d\n", i);
+ }
+
+ return OK;
+}
+
+
+devcall sdmcread_dma (
+ struct dentry *devptr, /* entry in device switch table */
+ char *buff, /* buffer to hold disk block */
+ int32 blk /* block number of block to read*/
+ )
+{
+ volatile struct sdmc_csreg *csrptr; /* address of SD controller's CSR */
+ struct sdmcblk *sdmcptr; /* Pointer to sdmctab entry */
+ uint16 error_sts = 0; /* SDMC command error status */
+ uint32 cmd_arg = 0;
+ char* buff_ptr = buff;
+ uint32 i;
+
+ sdmcptr = &sdmctab[devptr->dvminor];
+ csrptr = (struct sdmc_csreg *) devptr->dvcsr;
+
+ /* Issue command CMD16 - set block size */
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD16, 512, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD16: %04X %04X", SDMC_CMD16, error_sts);
+ return SYSERR;
+ }
+
+ csrptr->nrm_int_status_en = 0x1FF;
+ csrptr->err_int_stat_en = 0x7FF;
+ csrptr->err_int_stat_en &= ~(SDMC_ERR_INT_DATA_TIMEOUT_ERR);
+
+ csrptr->sys_adr = (uint32)buff;
+ csrptr->blk_size = 0x00000200;
+ csrptr->blk_count = 1;
+ cmd_arg = blk;
+
+ /* Set transmit mode */
+ /* Single block read DMA */
+ csrptr->tx_mode = 0x0011;
+
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD17, cmd_arg, &error_sts, SDMC_CMD_DAT_TRNS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD17: %04X %04X\n", SDMC_CMD17, error_sts);
+ //return SYSERR;
+ }
+
+ kprintf("INTSTS %08X %08X\n", csrptr->nrm_int_status_en, csrptr->err_int_stat_en);
+
+ cmd_arg = sdmcptr->rca;
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD13, cmd_arg, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD13: %04X %04X\n", SDMC_CMD13, error_sts);
+ return SYSERR;
+ }
+
+ return SYSERR;
+
+ /*
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD12, 0x00000000, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD12: %04X %04X\n", SDMC_CMD17, error_sts);
+ return SYSERR;
+ }
+ */
+
+ for(i = 0; i < 512/sizeof(csrptr->buf_data_port); i++) {
+ while(!(csrptr->nml_int_status & SDMC_NML_INT_BUF_RD_RDY)) {
+ //kprintf("INT %08X %04X %04X %08X\n", csrptr->pre_state, csrptr->nml_int_status, csrptr->err_int_status, csrptr->buf_data_port);
+ DELAY(SDMC_CMD_DELAY);
+ }
+ csrptr->nml_int_status |= SDMC_NML_INT_BUF_RD_RDY;
+
+ memcpy(buff_ptr, (char*)&csrptr->buf_data_port, sizeof(csrptr->buf_data_port));
+ buff_ptr += sizeof(csrptr->buf_data_port);
+
+ kprintf("Read block: %d\n", i);
+ }
+
+ return OK;
+}
+
+
+/*------------------------------------------------------------------------
+ * sdmcread - Read data from an SD memory card
+ *------------------------------------------------------------------------
+ */
+devcall sdmcread (
+ struct dentry *devptr, /* entry in device switch table */
+ char *buff, /* buffer to hold disk block */
+ int32 blk /* block number of block to read*/
+ )
+{
+ volatile struct sdmc_csreg *csrptr; /* address of SD controller's CSR */
+ struct sdmcblk *sdmcptr; /* Pointer to sdmctab entry */
+ uint16 error_sts = 0; /* SDMC command error status */
+ uint32 cmd_arg = 0;
+
+ /* Initialize structure pointers */
+ sdmcptr = &sdmctab[devptr->dvminor];
+ csrptr = (struct sdmc_csreg *) devptr->dvcsr;
+
+ /* Retrieve the current card status to ensure it is ready for I/O */
+ cmd_arg = sdmcptr->rca;
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD13, cmd_arg, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD13: %04X %04X", SDMC_CMD13, error_sts);
+ return SYSERR;
+ }
+
+ switch(csrptr->response0 & SDMC_R1_CURRENT_STATE) {
+
+ /* Card is in initial state the device */
+ /* must be reopened to allow I/O */
+ case SDMC_R1_IDLE_STATE:
+ case SDMC_R1_READY_STATE:
+ case SDMC_R1_IDENT_STATE:
+ /* TODO close and reopen the device */
+ return SYSERR;
+ break;
+
+ /* Standby state, issue CMD7 to select the card */
+ case SMDC_R1_STBY_STATE:
+ cmd_arg = sdmcptr->rca;
+ if(sdmc_issue_cmd_sync(csrptr, SDMC_CMD7, cmd_arg, &error_sts, SDMC_CMD_NO_FLAGS) != SDMC_RC_OK) {
+ kprintf("[SDMC] Error in CMD7: %04X %04X", SDMC_CMD7, error_sts);
+ return SYSERR;
+ }
+ break;
+
+ /* Card is already in data transfer state */
+ case SDMC_R1_TRAN_STATE:
+ case SDMC_R1_DATA_STATE:
+ case SDMC_R1_RCV_STATE:
+ break;
+
+ /* Card is in some other state */
+ /* must be reopened to allow I/O */
+ case SDMC_R1_PRG_STATE:
+ case SMDC_R1_DIS_STATE:
+ /* TODO close and reopen the device */
+ return SYSERR;
+ break;
+
+ default:
+ return SYSERR;
+ }
+
+ sdmcread_dma(devptr, buff, blk);
+
+ return OK;
+}
diff --git a/device/sdmc/sdmcwrite.c b/device/sdmc/sdmcwrite.c
new file mode 100644
index 0000000..ccaed87
--- /dev/null
+++ b/device/sdmc/sdmcwrite.c
@@ -0,0 +1,19 @@
+/* sdmcwrite.c - sdmcwrite */
+
+#include <xinu.h>
+#include <sdmc.h>
+
+/*------------------------------------------------------------------------
+ * sdmcwrite - Write a buffer to an SD memory card
+ *------------------------------------------------------------------------
+ */
+devcall sdmcwrite (
+ struct dentry *devptr, /* entry in device switch table */
+ char *buff, /* buffer to hold disk block */
+ int32 blk /* block number of disk block */
+ )
+{
+
+
+ return OK;
+}
diff --git a/device/tty/ttycontrol.c b/device/tty/ttycontrol.c
index 96b12da..4a1169e 100644
--- a/device/tty/ttycontrol.c
+++ b/device/tty/ttycontrol.c
@@ -26,7 +26,7 @@ devcall ttycontrol(
wait(typtr->tyisem);
ch = *typtr->tyitail;
signal(typtr->tyisem);
- return (devcall)ch;
+ return (devcall)(0xff & ch);
case TC_MODER:
typtr->tyimode = TY_IMRAW;
diff --git a/device/tty/ttygetc.c b/device/tty/ttygetc.c
index 66ad151..463ce2a 100644
--- a/device/tty/ttygetc.c
+++ b/device/tty/ttygetc.c
@@ -33,5 +33,5 @@ devcall ttygetc(
return (devcall)EOF;
}
- return (devcall)ch;
+ return (devcall)(0xff & ch);
}
diff --git a/device/tty/ttyhandle_in.c b/device/tty/ttyhandle_in.c
index a537a55..4f75e40 100644
--- a/device/tty/ttyhandle_in.c
+++ b/device/tty/ttyhandle_in.c
@@ -18,7 +18,7 @@ void ttyhandle_in (
char ch; /* Next char from device */
int32 avail; /* Chars available in buffer */
- ch = csrptr->buffer;
+ ch = io_inb(csrptr->buffer);
/* Compute chars available */
@@ -87,6 +87,7 @@ void ttyhandle_in (
if (typtr->tyiecho) { /* Are we echoing chars?*/
echoch(ch, typtr, csrptr);
}
+ signal(typtr->tyisem);
}
return;
diff --git a/device/tty/ttyhandle_out.c b/device/tty/ttyhandle_out.c
index f1f7540..0b1d287 100644
--- a/device/tty/ttyhandle_out.c
+++ b/device/tty/ttyhandle_out.c
@@ -30,8 +30,8 @@ void ttyhandle_out(
if ( (typtr->tyehead == typtr->tyetail) &&
(semcount(typtr->tyosem) >= TY_OBUFLEN) ) {
- ier = csrptr->ier;
- csrptr->ier = ier & ~UART_IER_ETBEI;
+ ier = io_inb(csrptr->ier);
+ io_outb(csrptr->ier,ier & ~UART_IER_ETBEI);
return;
}
@@ -43,7 +43,7 @@ void ttyhandle_out(
/* nonempty, xmit chars from the echo queue */
while ( (uspace>0) && typtr->tyehead != typtr->tyetail) {
- csrptr->buffer = *typtr->tyehead++;
+ io_outb(csrptr->buffer, *typtr->tyehead++);
if (typtr->tyehead >= &typtr->tyebuff[TY_EBUFLEN]) {
typtr->tyehead = typtr->tyebuff;
}
@@ -55,8 +55,11 @@ void ttyhandle_out(
ochars = 0;
avail = TY_OBUFLEN - semcount(typtr->tyosem);
+ if (avail > TY_OBUFLEN) { /* In case semcount < 0 */
+ avail = TY_OBUFLEN;
+ }
while ( (uspace>0) && (avail > 0) ) {
- csrptr->buffer = *typtr->tyohead++;
+ io_outb(csrptr->buffer, *typtr->tyohead++);
if (typtr->tyohead >= &typtr->tyobuff[TY_OBUFLEN]) {
typtr->tyohead = typtr->tyobuff;
}
diff --git a/device/tty/ttyhandler.c b/device/tty/ttyhandler.c
index 8d6caca..d05ff8f 100644
--- a/device/tty/ttyhandler.c
+++ b/device/tty/ttyhandler.c
@@ -12,7 +12,6 @@ void ttyhandler(void) {
struct uart_csreg *csrptr; /* Address of UART's CSR */
byte iir = 0; /* Interrupt identification */
-
/* Get CSR address of the device (assume console for now) */
devptr = (struct dentry *) &devtab[CONSOLE];
@@ -25,7 +24,7 @@ void ttyhandler(void) {
/* Decode hardware interrupt request from UART device */
/* Check interrupt identification register */
- iir = csrptr->iir;
+ iir = io_inb(csrptr->iir);
if (iir & UART_IIR_IRQ) {
return;
}
@@ -52,9 +51,9 @@ void ttyhandler(void) {
resched_cntl(DEFER_START);
- /* While chars avail. in UART buffer, call ttyinter_in */
+ /* While chars avail. in UART buffer, call ttyhandle_in */
- while ( (csrptr->lsr & UART_LSR_DR) != 0) {
+ while ( (io_inb(csrptr->lsr) & UART_LSR_DR) != 0) {
ttyhandle_in(typtr, csrptr);
}
diff --git a/device/tty/ttyinit.c b/device/tty/ttyinit.c
index e1b3858..1753549 100644
--- a/device/tty/ttyinit.c
+++ b/device/tty/ttyinit.c
@@ -54,12 +54,12 @@ devcall ttyinit(
uptr = (struct uart_csreg *)devptr->dvcsr;
/* Set baud rate */
- uptr->lcr = UART_LCR_DLAB;
- uptr->dlm = 0x00;
- uptr->dll = 0x18;
+ io_outb(uptr->lcr, UART_LCR_DLAB);
+ io_outb(uptr->dlm, 0x00);
+ io_outb(uptr->dll, 0x18);
- uptr->lcr = UART_LCR_8N1; /* 8 bit char, No Parity, 1 Stop*/
- uptr->fcr = 0x00; /* Disable FIFO for now */
+ io_outb(uptr->lcr,UART_LCR_8N1);/* 8 bit char, No Parity, 1 Stop*/
+ io_outb(uptr->fcr, 0x00); /* Disable FIFO for now */
/* Register the interrupt dispatcher for the tty device */
@@ -68,8 +68,8 @@ devcall ttyinit(
/* Enable interrupts on the device: reset the transmit and */
/* receive FIFOS, and set the interrupt trigger level */
- uptr->fcr = UART_FCR_EFIFO | UART_FCR_RRESET |
- UART_FCR_TRESET | UART_FCR_TRIG2;
+ io_outb(uptr->fcr, UART_FCR_EFIFO | UART_FCR_RRESET |
+ UART_FCR_TRESET | UART_FCR_TRIG2);
/* Start the device */
diff --git a/device/tty/ttykickout.c b/device/tty/ttykickout.c
index 4b4bb77..8161957 100644
--- a/device/tty/ttykickout.c
+++ b/device/tty/ttykickout.c
@@ -11,9 +11,9 @@ void ttykickout(
struct uart_csreg *csrptr /* Address of UART's CSRs */
)
{
- /* Force the UART hardware generate an output interrupt */
+ /* Force the UART hardware to generate an output interrupt */
- csrptr->ier = UART_IER_ERBFI | UART_IER_ETBEI;
+ io_outb(csrptr->ier, UART_IER_ERBFI | UART_IER_ETBEI);
return;
}
diff --git a/device/tty/ttyread.c b/device/tty/ttyread.c
index 88ca170..3b06753 100644
--- a/device/tty/ttyread.c
+++ b/device/tty/ttyread.c
@@ -9,7 +9,7 @@
devcall ttyread(
struct dentry *devptr, /* Entry in device switch table */
char *buff, /* Buffer of characters */
- int32 count /* Count of character to read */
+ int32 count /* Count of characters to read */
)
{
struct ttycblk *typtr; /* Pointer to tty control block */
diff --git a/device/tty/ttywrite.c b/device/tty/ttywrite.c
index f9f4ada..a8ce082 100644
--- a/device/tty/ttywrite.c
+++ b/device/tty/ttywrite.c
@@ -9,7 +9,7 @@
devcall ttywrite(
struct dentry *devptr, /* Entry in device switch table */
char *buff, /* Buffer of characters */
- int32 count /* Count of character to write */
+ int32 count /* Count of characters to write */
)
{
/* Handle negative and zero counts */
diff --git a/include/bufpool.h b/include/bufpool.h
index cafd248..14a5969 100644
--- a/include/bufpool.h
+++ b/include/bufpool.h
@@ -14,11 +14,10 @@
#endif
struct bpentry { /* Description of a single buffer pool */
- struct bpentry *bpnext;/* pointer to next free buffer */
- sid32 bpsem; /* semaphore that counts buffers */
+ struct bpentry *bpnext;/* Pointer to next free buffer */
+ sid32 bpsem; /* Semaphore that counts buffers */
/* currently available in the pool */
- uint32 bpsize; /* size of buffers in this pool */
};
extern struct bpentry buftab[];/* Buffer pool table */
-extern bpid32 nbpools; /* current number of allocated pools */
+extern bpid32 nbpools; /* Current number of allocated pools */
diff --git a/include/clock.h b/include/clock.h
index 4811df4..4c6860f 100644
--- a/include/clock.h
+++ b/include/clock.h
@@ -4,12 +4,13 @@
#define CLOCKBASE 0x40 /* I/O base port of clock chip */
#define CLOCK0 CLOCKBASE
-#define CLKCNTL (CLOCKBASE+3) /* chip CSW I/O port */
+#define CLKCNTL (CLOCKBASE+3) /* Chip CSW I/O port */
-#define CLKTICKS_PER_SEC 1000 /* clock timer resolution */
+#define CLKTICKS_PER_SEC 1000 /* Clock timer resolution */
-extern uint32 clktime; /* current time in secs since boot */
+extern uint32 clktime; /* Second since system boot */
+extern uint32 count1000; /* Ticks since clktime */
-extern qid16 sleepq; /* queue for sleeping processes */
-extern uint32 preempt; /* preemption counter */
+extern qid16 sleepq; /* Queue for sleeping processes */
+extern uint32 preempt; /* Preemption counter */
diff --git a/include/conf.h b/include/conf.h
index cb64009..c9312b6 100644
--- a/include/conf.h
+++ b/include/conf.h
@@ -49,6 +49,17 @@ extern struct dentry devtab[]; /* one entry per device */
#define LFILE3 21 /* type lfl */
#define LFILE4 22 /* type lfl */
#define LFILE5 23 /* type lfl */
+#define PIPE 24 /* type pipem */
+#define PIPE0 25 /* type pip */
+#define PIPE1 26 /* type pip */
+#define PIPE2 27 /* type pip */
+#define PIPE3 28 /* type pip */
+#define PIPE4 29 /* type pip */
+#define PIPE5 30 /* type pip */
+#define PIPE6 31 /* type pip */
+#define PIPE7 32 /* type pip */
+#define PIPE8 33 /* type pip */
+#define PIPE9 34 /* type pip */
/* Control block sizes */
@@ -62,8 +73,10 @@ extern struct dentry devtab[]; /* one entry per device */
#define Nlfs 1
#define Nlfl 6
#define Nnam 1
+#define Npipem 1
+#define Npip 10
-#define NDEVS 24
+#define NDEVS 35
/* Configuration and Size Constants */
@@ -75,4 +88,6 @@ extern struct dentry devtab[]; /* one entry per device */
#define IRQ_ATH_MISC IRQ_HW4 /* Misc. IRQ is wired to hardware 4 */
#define CLKFREQ 200000000 /* 200 MHz clock */
-#define LF_DISK_DEV RAM0
+#ifndef ETHER0
+#define ETHER0 0
+#endif
diff --git a/include/date.h b/include/date.h
index 4d64547..8ed9eeb 100644
--- a/include/date.h
+++ b/include/date.h
@@ -12,37 +12,37 @@
/* Conversion between network and local representations */
-#define ntim2xtim(x) ((x)-2208988800U) /* net-to-xinu time */
-#define xtim2ntim(x) ((x)+2208988800U) /* xinu-to-net time */
+#define ntim2xtim(x) ((x)-2208988800U) /* Net-to-xinu time */
+#define xtim2ntim(x) ((x)+2208988800U) /* Xinu-to-net time */
/* Constants for Daylight Savings Time */
-#define DATE_DST_OFF 0 /* force DST to be off */
-#define DATE_DST_ON 1 /* force DST to be on */
-#define DATE_DST_AUTO 2 /* compute DST automatically */
+#define DATE_DST_OFF 0 /* Force DST to be off */
+#define DATE_DST_ON 1 /* Force DST to be on */
+#define DATE_DST_AUTO 2 /* Compute DST automatically */
/* Days in months and month names used to format a date */
struct dateinfo {
- uint32 dt_boot; /* time when system booted */
+ uint32 dt_boot; /* Time when system booted */
/* add clktime to get the */
/* current time-of-day */
- bool8 dt_bootvalid; /* is dt_boot field valid? */
- int32 dt_daylight; /* whether to compute daylight */
+ bool8 dt_bootvalid; /* Is dt_boot field valid? */
+ int32 dt_daylight; /* Whether to compute daylight */
/* savings time */
- int32 dt_msize[12]; /* days per month */
- char *dt_mnam[12]; /* month names */
- char *dt_dnam[7]; /* day names */
+ int32 dt_msize[12]; /* Days per month */
+ char *dt_mnam[12]; /* Month names */
+ char *dt_dnam[7]; /* Day names */
};
extern struct dateinfo Date; /* Global date information */
/* Constants for converting time to month/day/year/hour/minute/second */
-#define isleap(x) ((x)%4==0) /* leap year? (1970-2099) */
-#define SECPERDY (60*60*24) /* one day in seconds */
-#define SECPERHR (60*60) /* one hour in seconds */
-#define SECPERMN (60) /* one minute in seconds */
+#define isleap(x) ((x)%4==0) /* Leap year? (1970-2099) */
+#define SECPERDY (60*60*24) /* One day in seconds */
+#define SECPERHR (60*60) /* One hour in seconds */
+#define SECPERMN (60) /* One minute in seconds */
/* The local time zone can be set to EST, CST, MST,or PST. */
@@ -50,7 +50,7 @@ extern struct dateinfo Date; /* Global date information */
#define ZONE_CST 6 /* hours west of England */
#define ZONE_MST 7
#define ZONE_PST 8
-#define TIMEZONE ZONE_EST /* timezone for this system */
+#define TIMEZONE ZONE_EST /* Timezone for this system */
/* In-line procedures to convert universal-to-local time and vice versa */
@@ -58,10 +58,10 @@ extern struct dateinfo Date; /* Global date information */
#define ltim2utim(x) ((x)+TIMEZONE*SECPERHR)
#define TIMERPORT 123 /* UDP port for time server */
-#define TIMELPORT 53678 /* local UDP port for time */
+#define TIMELPORT 53678 /* Local UDP port for time */
#ifndef TIMESERVER
-#define TIMESERVER "128.10.19.24" /* IP address of NTP time server*/
+#define TIMESERVER "pool.ntp.org" /* IP address of NTP time server*/
#endif
-#define TIMETIMEOUT 2000 /* timeout for time server (ms) */
+#define TIMETIMEOUT 2000 /* Timeout for time server (ms) */
diff --git a/include/device.h b/include/device.h
index 14f5c64..5d5386a 100644
--- a/include/device.h
+++ b/include/device.h
@@ -1,6 +1,6 @@
/* device.h - isbaddev */
-#define DEVNAMLEN 16 /* maximum size of a device name */
+#define DEVNAMLEN 16 /* Maximum size of a device name */
/* Macro used to verify device ID is valid */
diff --git a/include/dhcp.h b/include/dhcp.h
index 56710f9..c58c255 100644
--- a/include/dhcp.h
+++ b/include/dhcp.h
@@ -9,6 +9,7 @@
#define DHCP_ROUTER 3
#define DHCP_DNS_SERVER 6
#define DHCP_DOMAIN_NAME 15
+#define DHCP_NTP_SERVER_IP 42
#define DHCP_VENDER_OPTIONS 43
#define DHCP_REQUESTED_IP 50
#define DHCP_IP_ADDR_LEASE_TIME 51
diff --git a/include/e1000e.h b/include/e1000e.h
new file mode 100644
index 0000000..ba3b7da
--- /dev/null
+++ b/include/e1000e.h
@@ -0,0 +1,415 @@
+/* e1000.h - information for Intel 82545EM NIC (a form of E1000E) */
+
+#define INTEL_VENDOR_ID 0x8086
+#define INTEL_82545EM_DEVICE_ID 0x100F
+
+/* PCI Configuration Registers */
+
+#define E1000_PCI_COMMAND 0x04
+#define E1000_PCI_STATUS 0x06
+#define E1000_PCI_MEMBASE 0x10
+#define E1000_PCI_FLASHBASE 0x14
+#define E1000_PCI_IOBASE 0x18
+#define E1000_PCI_IRQ 0x3C
+
+#define E1000_PCI_CMD_MASK 0x0005
+
+#define E1000_IO_IOADDR 0x0000
+#define E1000_IO_IODATA 0x0004
+
+#define E1000_RX_RING_SIZE 32
+#define E1000_TX_RING_SIZE 16
+#define E1000_RING_BOUNDARY 16
+
+/* Receive Descriptor */
+
+struct eth_rx_desc {
+ uint64 buffer_addr; /* Address of the descriptor's */
+ /* data buffer */
+ uint16 length; /* Length of data DMAed into */
+ /* data buffer */
+ uint16 csum; /* Packet checksum */
+ uint8 status; /* Descriptor status */
+ uint8 errors; /* Descriptor Errors */
+ uint16 special;
+};
+
+/* Transmit Descriptor */
+
+struct eth_tx_desc {
+ uint64 buffer_addr; /* Address of the descriptor's */
+ /* data buffer */
+ union {
+ uint32 data;
+ struct {
+ uint16 length; /* Data buffer length */
+ uint8 cso; /* Checksum offset */
+ uint8 cmd; /* Descriptor control */
+ } flags;
+ } lower;
+ union {
+ uint32 data;
+ struct {
+ uint8 status; /* Descriptor status */
+ uint8 css; /* Checksum start */
+ uint16 special;
+ } fields;
+ } upper;
+};
+
+#define E1000_RDSIZE sizeof(struct eth_rx_desc)
+#define E1000_TDSIZE sizeof(struct eth_tx_desc)
+
+static inline void eth_io_writel(
+ uint32 iobase,
+ uint32 reg,
+ uint32 val
+ )
+{
+ outl(iobase + E1000_IO_IOADDR, reg);
+ outl(iobase + E1000_IO_IODATA, val);
+}
+
+static inline uint32 eth_io_readl(
+ uint32 iobase,
+ uint32 reg
+ )
+{
+ outl(iobase + E1000_IO_IOADDR, reg);
+ return inl(iobase + E1000_IO_IODATA);
+}
+
+#define eth_io_flush(iobase) \
+ eth_io_readl((iobase), E1000_STATUS);
+
+#define ADDR_BIT_MASK 0xFFFFFF
+
+/* Register Defination */
+
+#define E1000_CTRL 0x00000 /* Device Control */
+#define E1000_STATUS 0x00008 /* Device Status */
+#define E1000_CTRL_EXT 0x00018 /* Extended Device Control */
+#define E1000_MDIC 0x00020 /* MDI Control */
+#define E1000_ICR 0x000C0 /* Interrupt Cause Read */
+#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate */
+#define E1000_ICS 0x000C8 /* Interrupt Cause Set */
+#define E1000_IMS 0x000D0 /* Interrupt Mask Set */
+#define E1000_IMC 0x000D8 /* Interrupt Mask Clear */
+#define E1000_RCTL 0x00100 /* Rx Control */
+#define E1000_TCTL 0x00400 /* Tx Control */
+#define E1000_TIPG 0x00410 /* Tx Inter-packet gap */
+#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration */
+ /* Control */
+#define E1000_TBT 0x00448 /* Tx Burst Timer */
+#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing */
+ /* Throttle */
+#define E1000_PBA 0x01000 /* Packet Buffer Allocation */
+#define E1000_RXCSUM 0x05000 /* Rx Checksum Control */
+#define E1000_RFCTL 0x05008 /* Receive Filter Control */
+#define E1000_RDTR 0x02820 /* Rx Delay Timer */
+#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay */
+ /* Timer */
+#define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value */
+#define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay */
+ /* Val */
+#define E1000_MTA 0x05200 /* Multicast Table Array */
+#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface */
+#define E1000_GCR 0x05B00 /* PCI-Ex Control */
+#define E1000_FWSM 0x05B54 /* FW Semaphore */
+#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref */
+ /* Data */
+
+#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \
+ (0x0C000 + ((_n) * 0x40)))
+#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \
+ (0x0C004 + ((_n) * 0x40)))
+#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \
+ (0x0C008 + ((_n) * 0x40)))
+#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \
+ (0x0C010 + ((_n) * 0x40)))
+#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \
+ (0x0C018 + ((_n) * 0x40)))
+#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \
+ (0x0E000 + ((_n) * 0x40)))
+#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \
+ (0x0E004 + ((_n) * 0x40)))
+#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \
+ (0x0E008 + ((_n) * 0x40)))
+#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \
+ (0x0E010 + ((_n) * 0x40)))
+#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \
+ (0x0E018 + ((_n) * 0x40)))
+#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \
+ (0x0E028 + ((_n) * 0x40)))
+#define E1000_TARC(_n) (0x03840 + ((_n) * 0x100))
+#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
+ (0x054E0 + ((_i - 16) * 8)))
+#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
+ (0x054E4 + ((_i - 16) * 8)))
+
+/* Receive Descriptor bit definitions */
+
+#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
+#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */
+
+/* Receive Control */
+
+#define E1000_RCTL_RST 0x00000001 /* software reset */
+#define E1000_RCTL_EN 0x00000002 /* enable */
+#define E1000_RCTL_SBP 0x00000004 /* store bad packet */
+#define E1000_RCTL_UPE 0x00000008 /* unicast promisc */
+ /* enable */
+#define E1000_RCTL_MPE 0x00000010 /* multicast promisc */
+ /* enable */
+#define E1000_RCTL_LPE 0x00000020 /* long packet enable */
+#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */
+#define E1000_RCTL_DTYP_MASK 0x00000C00 /* descriptor type mask */
+#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min thresh */
+ /* size */
+#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift*/
+#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0*/
+#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1*/
+#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2*/
+#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4*/
+#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0*/
+#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */
+#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */
+#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */
+#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */
+#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control */
+ /* frames */
+#define E1000_RCTL_BSEX 0x02000000 /* buffer size extension*/
+#define E1000_RCTL_SECRC 0x04000000 /* strip Ethernet CRC */
+#define E1000_RCTL_FLXBUF_MASK 0x78000000 /* Flexible buffer size */
+
+
+/* Device Control */
+
+#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004
+ /*Blocks new Master reqs */
+#define E1000_CTRL_SLU 0x00000040 /* set link up */
+#define E1000_CTRL_FRCSPD 0x00000800 /* force speed */
+#define E1000_CTRL_FRCDPX 0x00001000 /* force duplex */
+#define E1000_CTRL_RST 0x04000000 /* global reset */
+#define E1000_CTRL_RFCE 0x08000000 /* receive flow control */
+ /* enable */
+#define E1000_CTRL_TFCE 0x10000000 /* transmit flow control*/
+ /* enable */
+#define E1000_CTRL_PHY_RST 0x80000000 /* PHY reset */
+
+/* Device Status */
+
+#define E1000_STATUS_LAN_INIT_DONE 0x00000200
+ /* Lan Init Completion by NVM */
+#define E1000_STATUS_PHYRA 0x00000400
+ /* PHY Reset Asserted */
+#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000
+ /* Master request status */
+
+/* Transmit Descriptor bit definitions */
+
+#define E1000_TXD_CMD_EOP 0x01000000 /* end of packet */
+#define E1000_TXD_CMD_IFCS 0x02000000 /* insert FCS */
+#define E1000_TXD_CMD_IC 0x04000000 /* insert checksum */
+#define E1000_TXD_CMD_RS 0x08000000 /* report status */
+#define E1000_TXD_CMD_DEXT 0x20000000 /* descriptor extension */
+#define E1000_TXD_CMD_IDE 0x80000000 /* enable Tidv register */
+#define E1000_TXD_STAT_DD 0x00000001 /* descriptor done */
+
+/* Transmit Control */
+
+#define E1000_TCTL_RST 0x00000001 /* software reset */
+#define E1000_TCTL_EN 0x00000002 /* enable Tx */
+#define E1000_TCTL_PSP 0x00000008 /* pad short packets */
+#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */
+#define E1000_TCTL_COLD 0x003ff000 /* collision distance */
+#define E1000_TCTL_RTLC 0x01000000 /* re-transmit on late */
+
+/* Receive Checksum Control */
+
+#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload*/
+#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP/UDP checksum */
+ /* offload */
+
+/* Header split receive */
+
+#define E1000_RFCTL_NFSW_DIS 0x00000040
+#define E1000_RFCTL_NFSR_DIS 0x00000080
+
+/* Extended Configuration Control and Size */
+
+#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020
+#define E1000_KABGTXD_BGSQLBIAS 0x00050000
+
+/* Collision related configuration parameters */
+
+#define E1000_COLLISION_THRESHOLD 15
+#define E1000_CT_SHIFT 4
+#define E1000_COLLISION_DISTANCE 63
+#define E1000_COLD_SHIFT 12
+
+/* Default values for the transmit IPG register */
+
+#define E1000_TIPG_IPGT_COPPER_DEFAULT 8
+#define E1000_TIPG_IPGR1_DEFAULT 8
+#define E1000_TIPG_IPGR1_SHIFT 10
+#define E1000_TIPG_IPGR2_DEFAULT 6
+#define E1000_TIPG_IPGR2_SHIFT 20
+
+#define E1000_PBA_10K 0x000A /* PBA constants - 10KB */
+#define E1000_PBA_48K 0x0030 /* PBA constants - 48KB */
+
+/* Interrupt Cause Read */
+
+#define E1000_ICR_TXDW 0x00000001 /* transmit desc written*/
+ /* back */
+#define E1000_ICR_LSC 0x00000004 /* Link status change */
+#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */
+#define E1000_ICR_RXO 0x00000040 /* rx overrun */
+#define E1000_ICR_RXT0 0x00000080 /* rx timer intr */
+
+/* Interrupt Mask Set */
+
+#define E1000_IMS_TXDW E1000_ICR_TXDW /* Tx desc written back */
+#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */
+#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */
+#define E1000_IMS_RXO E1000_ICR_RXO /* Rx overrun */
+#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */
+
+#define E1000_IMS_ENABLE_MASK ( E1000_IMS_TXDW | \
+ E1000_IMS_LSC | \
+ E1000_IMS_RXSEQ| \
+ E1000_IMS_RXT0 | \
+ E1000_IMS_RXO)
+
+/* Transmit Descriptor Control */
+
+#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL writeback */
+ /* threshold */
+#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL granularity */
+#define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /*GRAN=1,PTHRESH=31*/
+
+#define E1000_RAL_MAC_ADDR_LEN 4
+#define E1000_RAH_MAC_ADDR_LEN 2
+#define E1000_RAH_AV 0x80000000 /* receive descriptor */
+ /* valid */
+
+/* PCI Express Control */
+
+#define E1000_GCR_RXD_NO_SNOOP 0x00000001
+#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002
+#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004
+#define E1000_GCR_TXD_NO_SNOOP 0x00000008
+#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010
+#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020
+
+#define E1000_PCIE_NO_SNOOP_ALL ( \
+ E1000_GCR_RXD_NO_SNOOP | \
+ E1000_GCR_RXDSCW_NO_SNOOP | \
+ E1000_GCR_RXDSCR_NO_SNOOP | \
+ E1000_GCR_TXD_NO_SNOOP | \
+ E1000_GCR_TXDSCW_NO_SNOOP | \
+ E1000_GCR_TXDSCR_NO_SNOOP)
+
+/* PHY Control Register */
+#define E1000_MII_CR_RESTART_AUTO_NEG 0x0200 /* restart auto */
+ /* negotiation */
+#define E1000_MII_CR_AUTO_NEG_EN 0x1000 /* auto neg enable */
+#define E1000_MII_CR_RESET 0x8000 /* 0=normal, 1=PHY reset*/
+
+/* PHY Status Register */
+
+#define E1000_MII_SR_LINK_STATUS 0x0004 /* link status 1 = link */
+#define E1000_MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
+
+/* Autoneg Advertisement Register */
+
+#define E1000_NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex */
+#define E1000_NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex */
+#define E1000_NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex */
+#define E1000_NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex */
+#define E1000_NWAY_AR_PAUSE 0x0400 /* pause operation */
+ /* desired */
+#define E1000_NWAY_AR_ASM_DIR 0x0800 /* asymmetric pause */
+ /* direction bit */
+#define E1000_CR_1000T_HD_CAPS 0x0100 /* advertise 1000T HD */
+#define E1000_CR_1000T_FD_CAPS 0x0200 /* advertise 1000T FD */
+
+
+/* PHY 1000 MII Register/Bit Definitions */
+
+#define E1000_PHY_CONTROL 0x00 /* control register */
+#define E1000_PHY_STATUS 0x01 /* status register */
+#define E1000_PHY_AUTONEG_ADV 0x04 /* autoneg advertisement*/
+#define E1000_PHY_1000T_CTRL 0x09 /*1000Base-T control reg*/
+#define E1000_PHY_PAGE_SELECT 0x15 /* Page Address Reg */
+
+#define E1000_PHY_PAGE_SHIFT 5
+#define E1000_MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus */
+#define E1000_MAX_PHY_MULTI_PAGE_REG 0xF
+
+/* Timeout definitions */
+
+#define E1000_PHY_CFG_TIMEOUT 100
+#define E1000_MASTER_DISABLE_TIMEOUT 800
+#define E1000_SW_FLAG_TIMEOUT 1000
+
+/* M88E1000 Specific Registers */
+
+#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY specific control */
+ /* register */
+#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY specific status */
+ /* register */
+#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=polarity reverse */
+ /* enabled */
+#define M88E1000_PSCR_AUTO_X_MODE 0x0060
+
+/* BME1000 PHY Specific Control Register */
+
+#define E1000_BM_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */
+#define E1000_BM_PHY_PAGE_SELECT 22 /* Page Select for BM */
+
+
+/* MDI Control */
+
+#define E1000_MDIC_REG_SHIFT 16
+#define E1000_MDIC_PHY_MASK 0x03E00000
+#define E1000_MDIC_PHY_SHIFT 21
+#define E1000_MDIC_OP_WRITE 0x04000000
+#define E1000_MDIC_OP_READ 0x08000000
+#define E1000_MDIC_READY 0x10000000
+#define E1000_MDIC_ERROR 0x40000000
+
+/* SerDes Control */
+
+#define E1000_GEN_POLL_TIMEOUT 640
+
+#define E1000_RDTR_DEFAULT 0 /* receive interrupt delay */
+#define E1000_RADV_DEFAULT 8 /* receive Absolute interrupt */
+ /* delay */
+#define E1000_TIDV_DEFAULT 8 /* transmit interrupt delay */
+#define E1000_TADV_DEFAULT 32 /* transmit absolute interrupt */
+ /* delay */
+#define E1000_ITR_DEFAULT 20000 /* interrupt throttling rate */
+
+#define E1000_ICH_FWSM_RSPCIPHY 0x00000040
+#define E1000_ICH_LAN_INIT_TIMEOUT 1500
+
+#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000
+#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16
+#define E1000_KMRNCTRLSTA_REN 0x00200000
+#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */
+#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters*/
+
+
+/* 82545EM specific definitions */
+
+#define E1000_82545EM_MDIC_PHY_ADDR 1
+#define E1000_82545EM_RAR_ENTRIES 15
+#define E1000_82545EM_MTA_ENTRIES 128
+
+/* 82567LM specific definitions */
+
+#define E1000_82567LM_MDIC_PHY_ADDR 2
+#define E1000_82567LM_RAR_ENTRIES 7
+#define E1000_82567LM_MTA_ENTRIES 32
diff --git a/include/ether.h b/include/ether.h
index 4fc7be2..88f52db 100644
--- a/include/ether.h
+++ b/include/ether.h
@@ -8,7 +8,7 @@
*/
#define ETH_ADDR_LEN 6 /* Len. of Ethernet (MAC) addr. */
-typedef unsigned char Eaddr[ETH_ADDR_LEN];/* Physical Ethernet address*/
+typedef byte Eaddr[ETH_ADDR_LEN]; /* Physical Ethernet address */
/* Ethernet packet header */
@@ -44,18 +44,17 @@ struct etherPkt {
/* Ethernet device control functions */
#define ETH_CTRL_GET_MAC 1 /* Get the MAC for this device */
-#define ETH_CTRL_ADD_MCAST 2 /* Add a multicast address */
-#define ETH_CTRL_REMOVE_MCAST 3 /* Remove a multicast address */
+#define ETH_CTRL_SET_MAC 2 /* Set multicast MAC in a slot */
+#define ETH_CTRL_ADD_MCAST 3 /* Add a multicast address */
+#define ETH_CTRL_REMOVE_MCAST 4 /* Remove a multicast address */
-/* Ethernet multicast */
+/* NIC hardware types */
-#define ETH_NUM_MCAST 32 /* Max multicast addresses */
+#define NIC_TYPE_82545EM 1 /* The only possibility... */
-/* Ehternet NIC type */
+/* Ethernet multicast */
-#define ETH_TYPE_3C905C 1 /* 3COM 905C */
-#define ETH_TYPE_E1000E 2 /* Intel E1000E */
-#define ETH_TYPE_QUARK_ETH 3 /* Ethernet on Quark board */
+#define ETH_NUM_MCAST 32 /* Max multicast addresses */
/* Control block for Ethernet device */
@@ -70,8 +69,6 @@ struct ethcblk {
void *csr; /* Control and status regsiter address */
uint32 pcidev; /* PCI device number */
uint32 iobase; /* I/O base from config */
- uint32 flashbase; /* Flash base from config */
- uint32 membase; /* Memory base for device from config */
void *rxRing; /* Ptr to array of recv ring descriptors*/
void *rxBufs; /* Ptr to Rx packet buffers in memory */
diff --git a/include/file.h b/include/file.h
index 533517c..fc0c64d 100644
--- a/include/file.h
+++ b/include/file.h
@@ -15,6 +15,6 @@
#define F_CTL_DEL 1 /* Delete a file */
#define F_CTL_TRUNC 2 /* Truncate a file */
-#define F_CTL_MKDIR 3 /* make a directory */
-#define F_CTL_RMDIR 4 /* remove a directory */
+#define F_CTL_MKDIR 3 /* Make a directory */
+#define F_CTL_RMDIR 4 /* Remove a directory */
#define F_CTL_SIZE 5 /* Obtain the size of a file */
diff --git a/include/i386.h b/include/i386.h
new file mode 100644
index 0000000..cc11f97
--- /dev/null
+++ b/include/i386.h
@@ -0,0 +1,57 @@
+/* i386.h - DELAY */
+
+#define NBPG 4096
+
+#define NID 48
+#define NGD 8
+
+#define IRQBASE 32 /* base ivec for IRQ0 */
+
+struct idt {
+ unsigned short igd_loffset;
+ unsigned short igd_segsel;
+ unsigned int igd_rsvd : 5;
+ unsigned int igd_mbz : 3;
+ unsigned int igd_type : 5;
+ unsigned int igd_dpl : 2;
+ unsigned int igd_present : 1;
+ unsigned short igd_hoffset;
+};
+
+#define IGDT_TASK 5 /* task gate IDT descriptor */
+#define IGDT_INTR 14 /* interrupt gate IDT descriptor */
+#define IGDT_TRAPG 15 /* Trap Gate */
+
+
+/* Segment Descriptor */
+
+struct sd {
+ unsigned short sd_lolimit;
+ unsigned short sd_lobase;
+ unsigned char sd_midbase;
+ unsigned int sd_perm : 3;
+ unsigned int sd_iscode : 1;
+ unsigned int sd_isapp : 1;
+ unsigned int sd_dpl : 2;
+ unsigned int sd_present : 1;
+ unsigned int sd_hilimit : 4;
+ unsigned int sd_avl : 1;
+ unsigned int sd_mbz : 1; /* must be '0' */
+ unsigned int sd_32b : 1;
+ unsigned int sd_gran : 1;
+ unsigned char sd_hibase;
+};
+
+extern struct sd gdt_copy[];
+
+#define sd_type sd_perm
+
+/* System Descriptor Types */
+
+#define SDT_INTG 14 /* Interrupt Gate */
+
+/* Segment Table Register */
+struct segtr {
+ unsigned int len : 16;
+ unsigned int addr : 32;
+};
diff --git a/include/icmp.h b/include/icmp.h
index 87e1474..51a6f15 100644
--- a/include/icmp.h
+++ b/include/icmp.h
@@ -1,31 +1,31 @@
/* icmp.h - definintions for the Internet Control Message Protocol */
-#define ICMP_SLOTS 10 /* num. of open ICMP endpoints */
-#define ICMP_QSIZ 8 /* incoming packets per slot */
+#define ICMP_SLOTS 10 /* Num. of open ICMP endpoints */
+#define ICMP_QSIZ 8 /* Incoming packets per slot */
/* Constants for the state of an entry */
-#define ICMP_FREE 0 /* entry is unused */
-#define ICMP_USED 1 /* entry is being used */
-#define ICMP_RECV 2 /* entry has a process waiting */
+#define ICMP_FREE 0 /* Entry is unused */
+#define ICMP_USED 1 /* Entry is being used */
+#define ICMP_RECV 2 /* Entry has a process waiting */
-#define ICMP_HDR_LEN 8 /* bytes in an ICMP header */
+#define ICMP_HDR_LEN 8 /* Bytes in an ICMP header */
/* ICMP message types for ping */
#define ICMP_ECHOREPLY 0 /* ICMP Echo Reply message */
#define ICMP_ECHOREQST 8 /* ICMP Echo Request message */
-/* table of processes that are waiting for ping replies */
+/* Table of processes that are waiting for ping replies */
-struct icmpentry { /* entry in the ICMP table */
- int32 icstate; /* state of entry: free/used */
- uint32 icremip; /* remote IP address */
- int32 ichead; /* index of next packet to read */
- int32 ictail; /* index of next slot to insert */
- int32 iccount; /* count of packets enqueued */
+struct icmpentry { /* Entry in the ICMP table */
+ int32 icstate; /* State of entry: free/used */
+ uint32 icremip; /* Remote IP address */
+ int32 ichead; /* Index of next packet to read */
+ int32 ictail; /* Index of next slot to insert */
+ int32 iccount; /* Count of packets enqueued */
pid32 icpid; /* ID of waiting process */
- struct netpacket *icqueue[ICMP_QSIZ];/* circular packet queue */
+ struct netpacket *icqueue[ICMP_QSIZ];/* Circular packet queue */
};
-extern struct icmpentry icmptab[]; /* table of UDP endpoints */
+extern struct icmpentry icmptab[]; /* Table of UDP endpoints */
diff --git a/include/icu.h b/include/icu.h
index 2e2f5b2..246c1d0 100644
--- a/include/icu.h
+++ b/include/icu.h
@@ -6,4 +6,4 @@
#define OCR ICU1 /* Operation Command Register */
#define IMR (ICU1+1) /* Interrupt Mask Register */
-#define EOI 0x20 /* non-specific end of interrupt */
+#define EOI 0x20 /* Non-specific end of interrupt */
diff --git a/include/icu.s b/include/icu.s
index 96b86a6..25c28cb 100644
--- a/include/icu.s
+++ b/include/icu.s
@@ -12,4 +12,4 @@
.set IMR1,ICU1 + 1 /* Interrupt Mask Register for #1 */
.set IMR2,ICU2 + 1 /* Interrupt Mask Register for #2 */
- .set EOI,0x20 /* non-specific end of interrupt */
+ .set EOI,0x20 /* Non-specific end of interrupt */
diff --git a/include/io.h b/include/io.h
new file mode 100644
index 0000000..0cf237e
--- /dev/null
+++ b/include/io.h
@@ -0,0 +1,37 @@
+/* io.h - io_inb, io_inw, io_inl, io_outb, io_outw, io_outl */
+
+/* Define I/O macros used in device driver code to reference device */
+/* Control and Status Registers (CSRs). The macros either */
+/* generate the memory-mapped I/O references needed for newer x86 */
+/* platforms, such as the Galileo boards, or the port-mapped I/O */
+/* calls needed for traditional x86 machines and for VM platforms, */
+/* such as Vbox and VMWare. */
+
+#ifdef MEM_MAPPED
+
+/* Memory-mapped input merely references an item in the device's CSRs; */
+/* memory-mapped output assigns a value to an item */
+
+#define io_inb(item) (item)
+#define io_inw(item) (item)
+#define io_inl(item) (item)
+
+#define io_outb(item,val) ((item) = (val))
+#define io_outw(item,val) ((item) = (val))
+#define io_outl(item,val) ((item) = (val))
+
+#else
+
+/* Port-mapped input passes the address of an item in the CSRs to inb, */
+/* inw, or inl; port-mapped output calls outb, outw, or outl with */
+/* the address of an item (cast to in int32) and a value */
+
+#define io_inb(item) inb( (int32)&(item))
+#define io_inw(item) inw( (int32)&(item))
+#define io_inl(item) inl( (int32)&(item))
+
+#define io_outb(item,val) outb((int32)&(item),(val))
+#define io_outw(item,val) outw((int32)&(item),(val))
+#define io_outl(item,val) outl((int32)&(item),(val))
+
+#endif
diff --git a/include/kernel.h b/include/kernel.h
index 718e486..581c4c7 100644
--- a/include/kernel.h
+++ b/include/kernel.h
@@ -12,27 +12,28 @@ typedef unsigned long long uint64;
/* Xinu-specific types */
-typedef int32 sid32; /* semaphore ID */
-typedef int16 qid16; /* queue ID */
-typedef int32 pid32; /* process ID */
-typedef int32 did32; /* device ID */
-typedef int16 pri16; /* process priority */
-typedef uint32 umsg32; /* message passed among processes */
-typedef int32 bpid32; /* buffer pool ID */
+typedef int32 sid32; /* Semaphore ID */
+typedef int16 qid16; /* Queue ID */
+typedef int32 pid32; /* Process ID */
+typedef int32 did32; /* Device ID */
+typedef int16 pri16; /* Process priority */
+#define MAXPRIO 0x7fff /* Maximum possible priority */
+typedef uint32 umsg32; /* Message passed among processes */
+typedef int32 bpid32; /* Buffer pool ID */
typedef byte bool8; /* Boolean type */
-typedef uint32 intmask; /* saved interrupt mask */
-typedef int32 ibid32; /* index block ID (used in file system) */
-typedef int32 dbid32; /* data block ID (used in file system) */
+typedef uint32 intmask; /* Saved interrupt mask */
+typedef int32 ibid32; /* Index block ID (used in file system) */
+typedef int32 dbid32; /* Data block ID (used in file system) */
typedef int32 uid32; /* ID for UDP table descriptor */
/* Function declaration return types */
-typedef int32 syscall; /* system call declaration */
-typedef int32 devcall; /* device call declaration */
-typedef int32 shellcmd; /* shell command declaration */
-typedef int32 process; /* top-level function of a process */
-typedef void interrupt; /* interrupt procedure */
-typedef int32 status; /* returned status value (OK/SYSERR) */
+typedef int32 syscall; /* System call declaration */
+typedef int32 devcall; /* Device call declaration */
+typedef int32 shellcmd; /* Shell command declaration */
+typedef int32 process; /* Top-level function of a process */
+typedef void interrupt; /* Interrupt function */
+typedef int32 status; /* Returned status value (OK/SYSERR) */
#define local static /* Local procedure or variable declar. */
@@ -43,28 +44,28 @@ typedef int32 status; /* returned status value (OK/SYSERR) */
/* Null pointer, character, and string definintions */
-#define NULL 0 /* null pointer for linked lists */
-#define NULLCH '\0' /* null character */
-#define NULLSTR "" /* null string */
+#define NULL 0 /* Null pointer for linked lists */
+#define NULLCH '\0' /* Null character */
+#define NULLSTR "" /* Null string */
/* Universal return constants */
-#define OK ( 1) /* normal system call return */
-#define SYSERR (-1) /* system call failed */
+#define OK ( 1) /* Normal system call return */
+#define SYSERR (-1) /* System call failed */
#define EOF (-2) /* End-of-file (usually from read) */
-#define TIMEOUT (-3) /* system call timed out */
+#define TIMEOUT (-3) /* System call timed out */
-extern qid16 readylist; /* global ID for list of ready processes*/
+extern qid16 readylist; /* Global ID for list of ready processes*/
-#define MINSTK 400 /* minimum stack size in bytes */
+#define MINSTK 400 /* Minimum stack size in bytes */
-#define CONTEXT 64 /* bytes in a function call context on */
- /* the run-time stack */
-#define QUANTUM 2 /* time slice in milliseconds */
+#define CONTEXT 64 /* Bytes in a function call context on */
+ /* The run-time stack */
+#define QUANTUM 2 /* Time slice in milliseconds */
/* Size of the stack for the null process */
-#define NULLSTK 8192 /* stack size for null process */
+#define NULLSTK 8192 /* Stack size for null process */
/* Prototypes of I/O functions used throughout the kernel */
diff --git a/include/lfilesys.h b/include/lfilesys.h
index 8cf7fe5..0e39f90 100644
--- a/include/lfilesys.h
+++ b/include/lfilesys.h
@@ -32,13 +32,6 @@
#define Nlfl 1
#endif
-/* Use the remote disk device if no disk is defined (file system */
-/* *assumes* the underlying disk has a block size of 512 bytes) */
-
-#ifndef LF_DISK_DEV
-#define LF_DISK_DEV SYSERR
-#endif
-
#define LF_MODE_R F_MODE_R /* Mode bit for "read" */
#define LF_MODE_W F_MODE_W /* Mode bit for "write" */
#define LF_MODE_RW F_MODE_RW /* Mode bits for "read or write"*/
@@ -77,7 +70,7 @@ struct lfiblk { /* Format of index block */
/* File System ID */
-#define LFS_ID 0x58696E75 /* ID for Xinu Local File System*/
+#define LFS_ID 0x58696E75U /* ID for Xinu Local File System*/
/* Conversion functions below assume 7 index blocks per disk block */
@@ -121,7 +114,7 @@ struct lfdir { /* Entire directory on disk */
ibid32 lfd_ifree; /* List of free i-blocks on disk*/
int32 lfd_nfiles; /* Current number of files */
struct ldentry lfd_files[LF_NUM_DIR_ENT]; /* Set of files */
- uint32 lfd_revid; /* fsysid in reverse byte order */
+ uint32 lfd_revid; /* Fsysid in reverse byte order */
};
#pragma pack()
diff --git a/include/mark.h b/include/mark.h
index 2579015..1cdb0e3 100644
--- a/include/mark.h
+++ b/include/mark.h
@@ -4,13 +4,6 @@
extern int32 *(marks[]);
extern int32 nmarks;
-extern sid32 mkmutex;
typedef int32 memmark[1]; /* Declare a memory mark to be an array */
/* so user can reference the name */
/* without a leading & */
-
-/*------------------------------------------------------------------------
- * notmarked - Return nonzero if a location has not been marked
- *------------------------------------------------------------------------
- */
-#define notmarked(L) (L[0]<0 || L[0]>=nmarks || marks[L[0]]!=L)
diff --git a/include/memory.h b/include/memory.h
index 7916cf9..f2d8079 100644
--- a/include/memory.h
+++ b/include/memory.h
@@ -1,6 +1,8 @@
/* memory.h - roundmb, truncmb, freestk */
#define PAGE_SIZE 4096
+#define HOLESTART ((char *)(640 * 1024))
+#define HOLEEND ((char *)(1024 * 1024))
/*----------------------------------------------------------------------
* roundmb, truncmb - Round or truncate address to memory block size
diff --git a/include/name.h b/include/name.h
index 6dc9e38..fa81075 100644
--- a/include/name.h
+++ b/include/name.h
@@ -5,7 +5,7 @@
#define NM_PRELEN 64 /* Max size of a prefix string */
#define NM_REPLLEN 96 /* Maximum size of a replacement*/
#define NM_MAXLEN 256 /* Maximum size of a file name */
-#define NNAMES 40 /* Number of prefix definitions */
+#define NNAMES 128 /* Number of prefix definitions */
/* Definition of the name prefix table that defines all name mappings */
diff --git a/include/net.h b/include/net.h
index dd978bf..3c411ac 100644
--- a/include/net.h
+++ b/include/net.h
@@ -60,7 +60,7 @@ struct network { /* Network information */
uint32 bootserver; /* Boot server address */
uint32 dnsserver; /* DNS server address */
uint32 ntpserver; /* NTP (time) server address */
- bool8 ipvalid; /* nonzero => above are valid */
+ bool8 ipvalid; /* Nonzero => above are valid */
byte ethucast[ETH_ADDR_LEN]; /* Ethernet multicast address */
byte ethbcast[ETH_ADDR_LEN]; /* Ethernet broadcast address */
char bootfile[NETBOOTFILE]; /* Name of boot file */
diff --git a/include/pci.h b/include/pci.h
index f007325..3b75ebc 100755
--- a/include/pci.h
+++ b/include/pci.h
@@ -1,80 +1,80 @@
-/*
- * pci.h
+/* pci.h
+ *
+ * Benjamin A. Kuperman
+ * 10 July 2001
+ *
+ * Various structures and such used in pci.c
*/
+typedef struct bios32 {
+ unsigned long signature; /* "_32_" */
+ unsigned long bios32_entry; /* 32 bit physical address for
+ entry into the BIOS32 service
+ directory */
+ unsigned char revision; /* should be 0x00 */
+ unsigned char length; /* length of data in 16 byte units */
+ unsigned char checksum; /* sum of all bytes should be 0 */
+ unsigned char padding[5]; /* all zeros */
+} bios32;
-#define PCI_MAX_BUSES 256
-#define PCI_DEVICES_PER_BUS 32
-#define PCI_FUNCTIONS_PER_DEVICE 8
-#define PCI_BUS_MASK (PCI_MAX_BUSES - 1)
-#define PCI_DEV_MASK (PCI_DEVICES_PER_BUS - 1)
-#define PCI_FUNC_MASK (PCI_FUNCTIONS_PER_DEVICE - 1)
-#define PCIE_BYTES_PER_FUNCTION 0x1000
-#define PCIE_BYTES_PER_DEVICE (PCIE_BYTES_PER_FUNCTION * \
- PCI_FUNCTIONS_PER_DEVICE)
-#define PCIE_BYTES_PER_BUS (PCIE_BYTES_PER_DEVICE * \
- PCI_DEVICES_PER_BUS)
+/* the bios can only exist in a certain memory range */
+#define BIOS32_MIN_ADDR 0x0e0000
+#define BIOS32_MAX_ADDR 0x0ffff0
+#define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
+#define BIOS32_UNITS 16 /* used with bios32->length */
-#define PCI_BARS_PER_HEADER 6 /* PCI BARs per header */
+/* The string "$PCI" is used to interface with BIOS32 for PCI service */
+#define PCI_SERVICE (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
-#define PCI_HEADER_TYPE0_SIZE 0x40 /* Size of type0 header */
-#define PCI_HDR_TYPE_MULTIFCN (1 << 7)/* Multifunction device */
+/* stuff snagged from linux to make this work */
+#define save_flags(x) \
+__asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */ :"memory")
-#define PCI_BUS_SHIFT 16 /* Bits to shift bus */
-#define PCI_DEV_SHIFT 3 /* Bits to shift dev */
+#define restore_flags(x) \
+__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
-/* Definitions of PCI base address register (bar) bits:*/
-#define PCI_BAR_REGION_TYPE_IO_MASK 1 /* 0=mem space, 1=I/O */
-#define PCI_BAR_LOCATABLE_1MB_MASK 2 /* 1=Must be < 1MB */
-#define PCI_BAR_LOCATABLE_64B_MASK 4 /* 1=Any 64-bit phys */
-#define PCI_BAR_LOCATABLE_PREFETCH 8 /* 1=Prefetchable */
-#define PCI_BAR_BASE_ADDRESS_MASK 0xfffffff0/* mask: MMIO base */
+#define cli() __asm__ __volatile__ ("cli": : :"memory")
-#ifndef offsetof
-#define offsetof(type, member) ((int)((unsigned int)&((type *)0)->member))
-#endif
+#define PCIBIOS_PCI_BIOS_PRESENT 0xb101
+#define PCIBIOS_FIND_PCI_DEVICE 0xb102
+#define PCIBIOS_FIND_PCI_CLASS_CODE 0xb103
+#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106
+#define PCIBIOS_READ_CONFIG_BYTE 0xb108
+#define PCIBIOS_READ_CONFIG_WORD 0xb109
+#define PCIBIOS_READ_CONFIG_DWORD 0xb10a
+#define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b
+#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c
+#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d
+#define PCIBIOS_GET_IRQ_ROUTING_OPTIONS 0xb10e
+#define PCIBIOS_SET_PCI_IRQ 0xb10f
-/* Define the layout of PCI config headers (type 0) */
+#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
-struct __attribute__ ((__packed__)) pci_config_header {
- /* PCI header field Byte offset */
- unsigned short vendorID; /* 0x0 */
- unsigned short deviceID; /* 2 */
- unsigned short command; /* 4 */
- unsigned short status; /* 6 */
- unsigned char revID; /* 8 */
- unsigned char progIF; /* 9 */
- unsigned char subClass; /* a */
- unsigned char classCode; /* b */
- unsigned char clSize; /* c */
- unsigned char latencyTimer; /* d */
- unsigned char headerType; /* e */
- unsigned char BIST; /* f */
- unsigned int bars[PCI_BARS_PER_HEADER]; /* 10 */
- unsigned int cardbusCISPtr; /* 28 */
- unsigned short subsystemVendorID; /* 2c */
- unsigned short subsystemID; /* 2e */
- unsigned int expansionROMAddr; /* 30 */
- unsigned char capabilitiesPtr; /* 34 */
- unsigned char reserved0; /* 35 */
- unsigned char reserved1; /* 36 */
- unsigned char reserved2; /* 37 */
- unsigned int reserved3; /* 38 */
- unsigned char interruptLine; /* 3c */
- unsigned char interruptPin; /* 3d */
- unsigned char minGrant; /* 3e */
- unsigned char maxLatency; /* 3f */
-};
+#define PCIBIOS_ETHERNET_CLASS ((0x02<<16) + (0x00<<8) + 0)
+
+#define PCIBIOS_MAX_DEVICE 65535
+#define PCIBIOS_MAX_VENDOR 65534
+#define PCIBIOS_MAX_INDEX 255 /* arbitrary */
+
+
+/* PCI signature: "PCI " */
+#define PCI_SIGNATURE (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
extern int pci_init(void);
extern int find_pci_device(int32, int32, int32);
-extern struct eth_pd* eth_txring;
-extern struct eth_pd* eth_rxring;
+extern struct ether dev_eth;
+extern struct eth_pd* eth_txring;
+extern struct eth_pd* eth_rxring;
-extern int pci_read_config_byte(uint32, int, unsigned char *);
-extern int pci_read_config_word(uint32, int, uint16 *);
-extern int pci_read_config_dword(uint32, int, uint32 *);
-extern int pci_write_config_byte(uint32, int, unsigned char);
-extern int pci_write_config_word(uint32, int, uint16);
-extern int pci_write_config_dword(uint32, int, uint32);
-extern int pci_get_dev_mmio_base_addr(uint32, int, void **);
+extern int pci_bios_read_config_byte(uint32, int, unsigned char *);
+extern int pci_bios_read_config_word(uint32, int, uint16 *);
+extern int pci_bios_read_config_dword(uint32, int, uint32 *);
+extern int pci_bios_write_config_byte(uint32, int, unsigned char);
+extern int pci_bios_write_config_word(uint32, int, uint16);
+extern int pci_bios_write_config_dword(uint32, int, uint32);
diff --git a/include/pipe.h b/include/pipe.h
new file mode 100644
index 0000000..bf7cdc1
--- /dev/null
+++ b/include/pipe.h
@@ -0,0 +1,29 @@
+/* pipe.h */
+
+/* Definitions for a pipe device */
+
+#ifndef PIPE_BUF_SIZE
+#define PIPE_BUF_SIZE 20 /* Default size of a pipe buffer */
+#endif
+
+/* state constants for a pipe pseudo device */
+
+#define PIPE_FREE 0 /* Entry is not currently used */
+#define PIPE_OPEN 1 /* Entry is open for reading and writing*/
+#define PIPE_EOF 2 /* Entry has been closed for writes, but*/
+ /* remains open for reading until all */
+ /* chars have been read and EOF has */
+ /* returned */
+
+struct pipecblk {
+ int32 pstate; /* State of this pipe device */
+ byte pbuf[PIPE_BUF_SIZE]; /* Buffer for the pipe */
+ int32 phead; /* Index of next byte in pbuf to read */
+ int32 ptail; /* Index of next byte in pbuf to write */
+ sid32 ppsem; /* Producer semaphore for the pipe */
+ sid32 pcsem; /* Consumer semaphore for the pipe */
+ did32 pdevid; /* Device ID of this pseudo device */
+ int32 pavail; /* Available characters during drain */
+};
+
+extern struct pipecblk pipetab[];
diff --git a/include/process.h b/include/process.h
index 09a5b00..7fb1a30 100644
--- a/include/process.h
+++ b/include/process.h
@@ -36,7 +36,7 @@
/* Number of device descriptors a process can have open */
-#define NDESC 5 /* must be odd to make procent 4N bytes */
+#define NDESC 5 /* Must be odd to make procent 4N bytes */
/* Definition of the process table (multiple of 32 bits) */
diff --git a/include/prototypes.h b/include/prototypes.h
index 2fe3609..75ea366 100755
--- a/include/prototypes.h
+++ b/include/prototypes.h
@@ -1,5 +1,11 @@
+
+/* in file 82545EMInit.c */
+extern status _82545EMInit(struct ethcblk *);
+extern status _82545EM_read_phy_reg(struct ethcblk *, uint32, uint16 *);
+extern status _82545EM_write_phy_reg(struct ethcblk *, uint32, uint16);
+
/* in file addargs.c */
-extern status addargs(pid32, int32, int32[], int32,char *, void *);
+extern status addargs(pid32, int32, int32[], char *, void *);
/* in file arp.c */
extern void arp_init(void);
@@ -16,7 +22,7 @@ extern status ascdate(uint32, char *);
extern status bufinit(void);
/* in file chprio.c */
-extern pri16 chprio(pid32, pri16);
+extern syscall chprio(pid32, pri16);
/* in file clkupdate.S */
extern uint32 clkcount(void);
@@ -46,32 +52,19 @@ extern void ctxsw(void *, void *);
extern uint32 getlocalip(void);
/* in file dns.c */
-extern uint32 dnslookup(char *);
+extern status dnslookup(char *, uint32 *);
/* in file dot2ip.c */
-extern uint32 dot2ip(char *, uint32 *);
-
-/* in file ethinit.c */
-extern int32 ethinit(struct dentry *);
-
-/* in file ethhandler.c */
-extern interrupt ethhandler(void);
-
-/* in file ethcontrol.c */
-extern devcall ethcontrol(struct dentry *, int32, int32, int32);
+extern status dot2ip(char *, uint32 *);
-/* in file ethdispatch.S */
-extern void ethdispatch(void);
-
-/* in file ethmcast.c */
-extern int32 ethmcast_add(struct ethcblk *, byte[]);
-extern int32 ethmcast_remove(struct ethcblk *, byte[]);
+/* in file getticks.c */
+extern uint64 getticks(void);
-/* in file ethread.c */
-extern devcall ethread(struct dentry *, char *, int32);
+/* in file intutils.S */
+extern intmask disable(void);
-/* in file ethwrite.c */
-extern devcall ethwrite(struct dentry *, char *buf, int32);
+/* in file intutils.S */
+extern void enable(void);
/* in file exit.c */
extern void exit(void);
@@ -82,10 +75,30 @@ extern int console_init(void);
/* in file early_imr.c */
extern int remove_irm_protections(void);
+/* in file ethcontrol.c */
+extern devcall ethcontrol(struct dentry *, int32, int32, int32);
+extern void ethIrqDisable(struct ethcblk *);
+extern void ethIrqEnable(struct ethcblk *);
+
+/* in file ethdispatch.S */
+extern void ethdispatch(void);
+
+/* in file ethhandler.c */
+extern interrupt ethhandler(void);
+
+/* in file ethinit.c */
+extern devcall ethinit(struct dentry *);
+
+/* in file ethread.c */
+extern devcall ethread(struct dentry *, char *, int32);
+
+/* in file ethwrite.c */
+extern devcall ethwrite(struct dentry *, void *, int32);
+
/* in file evec.c */
extern int32 initevec(void);
extern int32 set_evec(uint32, uint32);
-extern void trap(int32, long *);
+extern void trap(int32);
/* in file exception.c */
extern void exception(int32, int32*);
@@ -119,9 +132,6 @@ extern syscall getprio(pid32);
/* in file getstk.c */
extern char *getstk(uint32);
-/* in file getticks.c */
-extern uint64 getticks(void);
-
/* in file gettime.c */
extern status gettime(uint32 *);
@@ -137,8 +147,7 @@ extern void icmp_in(struct netpacket *);
extern int32 icmp_register(uint32);
extern int32 icmp_recv(int32, char *, int32, uint32);
extern status icmp_send(uint32, uint16, uint16, uint16, char *, int32);
-extern struct netpacket *icmp_mkpkt(uint32, uint16, uint16, uint16,
- char *, int32);
+extern struct netpacket *icmp_mkpkt(uint32, uint16, uint16, uint16, char *, int32);
extern status icmp_release(int32);
extern uint16 icmp_cksum(char *, int32);
extern void icmp_hton(struct netpacket *);
@@ -159,10 +168,6 @@ extern status insertd(pid32, qid16, int32);
/* in file intr.S */
extern uint16 getirmask(void);
-/* in file intutils.S */
-extern intmask disable(void);
-extern void enable(void);
-
/* in file ioerr.c */
extern devcall ioerr(void);
@@ -194,7 +199,7 @@ extern uint16 getport(void);
extern syscall kill(pid32);
/* in file lexan.c */
-extern int32 lexan(char *, int32, char *, int32 *, int32 [], int32 []);
+extern int32 lexan(char *, int32, char *, int32 [], int32 []);
/* in file lfibclear.c */
extern void lfibclear(struct lfiblk *, int32);
@@ -320,6 +325,27 @@ extern syscall open(did32, char *, char *);
/* in file panic.c */
extern void panic(char *);
+/* in file pipe_close.c */
+extern devcall pipe_close(struct dentry *);
+
+/* in file pipe_getc.c */
+extern devcall pipe_getc(struct dentry *);
+
+/* in file pipe_init.c */
+extern devcall pipe_init(struct dentry *);
+
+/* in file pipe_open.c */
+extern devcall pipe_open(struct dentry *, char *, int32);
+
+/* in file pipe_putc.c */
+extern devcall pipe_putc(struct dentry *, char);
+
+/* in file pipe_read.c */
+extern devcall pipe_read(struct dentry *, char *, int32);
+
+/* in file pipe_write.c */
+extern devcall pipe_write(struct dentry *, char *, int32);
+
/* in file pci.c */
extern int32 pci_init(void);
@@ -371,7 +397,6 @@ extern devcall ramclose(struct dentry *);
extern devcall raminit(struct dentry *);
/* in file ramopen.c */
-
extern devcall ramopen(struct dentry *, char *, char *);
/* in file ramread.c */
@@ -380,33 +405,46 @@ extern devcall ramread(struct dentry *, char *, int32);
/* in file ramwrite.c */
extern devcall ramwrite(struct dentry *, char *, int32);
-/* in file rdsclose.c */
-extern devcall rdsclose(struct dentry *);
+/* in file rdsars.c */
+
+extern syscall rdsars(pid32);
+
+/* in file rdscomm.c */
+
+extern status rdscomm(struct rd_msg_hdr *, int32, struct rd_msg_hdr *, int32, struct rdscblk *);
/* in file rdscontrol.c */
+
extern devcall rdscontrol(struct dentry *, int32, int32, int32);
/* in file rdsinit.c */
+
extern devcall rdsinit(struct dentry *);
/* in file rdsopen.c */
+
extern devcall rdsopen(struct dentry *, char *, char *);
+/* in file rdsprocess.c */
+
+extern void rdsprocess(struct rdscblk *);
+
+/* in file rdsqfcns.c */
+
+extern void rdqadd(struct rdscblk *, struct rdqnode *);
+extern struct rdqnode * rdqfree(struct rdscblk *, struct rdqnode *);
+extern int32 rdcget(struct rdscblk *, uint32, char *);
+extern void rdcadd(struct rdscblk *, uint32, char *);
+extern void rdqdump(did32);
+extern void rdcdump(did32);
+
/* in file rdsread.c */
+
extern devcall rdsread(struct dentry *, char *, int32);
/* in file rdswrite.c */
-extern devcall rdswrite(struct dentry *, char *, int32);
-/* in file rdsbufalloc.c */
-extern struct rdbuff * rdsbufalloc(struct rdscblk *);
-
-/* in file rdscomm.c */
-extern status rdscomm(struct rd_msg_hdr *, int32, struct rd_msg_hdr *,
- int32, struct rdscblk *);
-
-/* in file rdsprocess.c */
-extern void rdsprocess(struct rdscblk *);
+extern devcall rdswrite(struct dentry *, char *, int32);
/* in file sdmcclose.c */
extern devcall sdmcclose(struct dentry *);
@@ -449,7 +487,7 @@ extern status resched_cntl(int32);
extern void restore(intmask);
/* in file resume.c */
-extern pri16 resume(pid32);
+extern syscall resume(pid32);
/* in file rfsgetmode.c */
extern int32 rfsgetmode(char * );
@@ -490,14 +528,6 @@ extern devcall rfsopen(struct dentry *devptr, char *, char *);
/* in file rfscomm.c */
extern int32 rfscomm(struct rf_msg_hdr *, int32,
struct rf_msg_hdr *, int32);
-
-/* in file rdscomm.c */
-extern status rdscomm(struct rd_msg_hdr *, int32, struct rd_msg_hdr *,
- int32, struct rdscblk *);
-
-/* in file rdsprocess.c */
-extern void rdsprocess(struct rdscblk *);
-
/* in file seek.c */
extern syscall seek(did32, uint32);
@@ -578,7 +608,6 @@ extern devcall ttyread(struct dentry *, char *, int32);
extern devcall ttywrite(struct dentry *, char *, int32);
/* in file udp.c */
-
extern void udp_init(void);
extern void udp_in(struct netpacket *);
extern uid32 udp_register(uint32, uint16, uint16);
@@ -591,7 +620,6 @@ extern status udp_release(uid32);
extern void udp_ntoh(struct netpacket *);
extern void udp_hton(struct netpacket *);
-
/* in file unsleep.c */
extern syscall unsleep(pid32);
@@ -614,9 +642,9 @@ extern void xdone(void);
extern syscall yield(void);
/* NETWORK BYTE ORDER CONVERSION NOT NEEDED ON A BIG-ENDIAN COMPUTER */
-#define htons(x) ((0xff & ((x)>>8)) | ((0xff & (x)) << 8))
-#define htonl(x) ((((x)>>24) & 0x000000ff) | (((x)>> 8) & 0x0000ff00) | \
- (((x)<<8) & 0x00ff0000) | (((x)<<24) & 0xff000000))
-#define ntohs(x) ((0xff & ((x)>>8)) | ( (0xff & (x)) << 8))
-#define ntohl(x) ((((x)>>24) & 0x000000ff) | (((x)>> 8) & 0x0000ff00) | \
- (((x)<<8) & 0x00ff0000) | (((x)<<24) & 0xff000000))
+#define htons(x) ( ( 0xff & ((x)>>8) ) | ( (0xff & (x)) << 8 ) )
+#define htonl(x) ( (((x)>>24) & 0x000000ff) | (((x)>> 8) & 0x0000ff00) | \
+ (((x)<< 8) & 0x00ff0000) | (((x)<<24) & 0xff000000) )
+#define ntohs(x) ( ( 0xff & ((x)>>8) ) | ( (0xff & (x)) << 8 ) )
+#define ntohl(x) ( (((x)>>24) & 0x000000ff) | (((x)>> 8) & 0x0000ff00) | \
+ (((x)<< 8) & 0x00ff0000) | (((x)<<24) & 0xff000000) )
diff --git a/include/quark_eth.h b/include/quark_eth.h
deleted file mode 100644
index b67016a..0000000
--- a/include/quark_eth.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/* quark_eth.h */
-
-/* Definitions for Intel Quark Ethernet */
-
-#define INTEL_ETH_QUARK_PCI_DID 0x0937 /* MAC PCI Device ID */
-#define INTEL_ETH_QUARK_PCI_VID 0x8086 /* MAC PCI Vendor ID */
-
-struct eth_q_csreg {
- uint32 maccr; /* MAC Configuration Register */
- uint32 macff; /* MAC Frame Filter Register */
- uint32 hthr; /* Hash Table High Register */
- uint32 htlr; /* Hash Table Low Register */
- uint32 gmiiar; /* GMII Address Register */
- uint32 gmiidr; /* GMII Data Register */
- uint32 fcr; /* Flow Control Register */
- uint32 vlantag; /* VLAV Tag Register */
- uint32 version; /* Version Register */
- uint32 debug; /* Debug Register */
- uint32 res1[4]; /* Skipped Addresses */
- uint32 ir; /* Interrupt Register */
- uint32 imr; /* Interrupt Mask Register */
- uint32 macaddr0h; /* MAC Address0 High Register */
- uint32 macaddr0l; /* MAC Address0 Low Register */
- uint32 res2[46];
- uint32 mmccr; /* MAC Management Counter Cntl Register */
- uint32 mmcrvcir; /* MMC Receive Interrupt Register */
- uint32 mmctxir; /* MMC Transmit Interrupt Register */
- uint32 res3[957]; /* Skipped Addresses */
- uint32 bmr; /* Bus Mode Register */
- uint32 tpdr; /* Transmit Poll Demand Register */
- uint32 rpdr; /* Receive Poll Demand Register */
- uint32 rdla; /* Receive Descriptor List Addr */
- uint32 tdla; /* Transmit Descriptor List Addr */
- uint32 sr; /* Status Register */
- uint32 omr; /* Operation Mode Register */
- uint32 ier; /* Interrupt Enable Register */
-};
-
-/* Individual Bits in Control and Status Registers */
-
-/* MAC Configuration Register */
-
-#define ETH_QUARK_MACCR_PE2K 0x08000000 /* Enable 2K Packets */
-#define ETH_QUARK_MACCR_WD 0x00800000 /* Watchdog Disable */
-#define ETH_QUARK_MACCR_JD 0x00400000 /* Jabber Disable */
-#define ETH_QUARK_MACCR_JE 0x00100000 /* Jumbo Frame Enable */
-
-/* Inter-frame gap values */
-#define ETH_QUARK_MACCR_IFG96 0x00000000 /* 96 bit times */
-#define ETH_QUARK_MACCR_IFG88 0x00020000 /* 88 bit times */
-#define ETH_QUARK_MACCR_IFG80 0x00040000 /* 80 bit times */
-#define ETH_QUARK_MACCR_IFG40 0x000E0000 /* 40 bit times */
-#define ETH_QUARK_MACCR_IFG64 0x00080000 /* 64 bit times */
-
-#define ETH_QUARK_MACCR_DCRS 0x00010000 /* Dis. C. Sense dur TX */
-#define ETH_QUARK_MACCR_RMIISPD10 0x00000000 /* RMII Speed = 10 Mbps */
-#define ETH_QUARK_MACCR_RMIISPD100 0x00004000 /* RMII Speed = 100 Mbps*/
-#define ETH_QUARK_MACCR_DO 0x00002000 /* Disable Receive Own */
-#define ETH_QUARK_MACCR_LM 0x00001000 /* Loopback Mode Enable */
-#define ETH_QUARK_MACCR_DM 0x00000800 /* Duplex Mode Enable */
-#define ETH_QUARK_MACCR_IPC 0x00000400 /* Checksum Offload */
-#define ETH_QUARK_MACCR_DR 0x00000200 /* Disable Retry */
-#define ETH_QUARK_MACCR_ACS 0x00000080 /* Auto Pad or CRC Strip*/
-#define ETH_QUARK_MACCR_DC 0x00000010 /* Deferral Check */
-#define ETH_QUARK_MACCR_TE 0x00000008 /* Transmitter Enable */
-#define ETH_QUARK_MACCR_RE 0x00000004 /* Receiver Enable */
-#define ETH_QUARK_MACCR_PRELEN7 0x00000000 /* Preamble = 7 bytes */
-#define ETH_QUARK_MACCR_PRELEN5 0x00000001 /* Preamble = 5 bytes */
-#define ETH_QUARK_MACCR_PRELEN3 0x00000002 /* Preamble = 3 bytes */
-
-#define ETH_QUARK_MMC_CNTFREEZ 0x00000008 /* Freeze MMC counter values*/
-#define ETH_QUARK_MMC_CNTRST 0x00000001 /* Reset all cntrs to zero */
-
-/* GMII Address Register */
-#define ETH_QUARK_GMIIAR_PAMASK 0x0000F800 /* Phys Layer Addr Mask */
-#define ETH_QUARK_GMIIAR_GRMASK 0x000007C0 /* GMII Register Mask */
-#define ETH_QUARK_GMIIAR_CR 0x00000004 /* Clk Range = 100-150 */
- /* MHz for Quark */
-#define ETH_QUARK_GMIIAR_GW 0x00000002 /* GMII Write Enable */
-#define ETH_QUARK_GMIIAR_GB 0x00000001 /* GMII Busy */
-
-/* Bus Mode Register */
-#define ETH_QUARK_BMR_SWR 0x00000001 /* Software Reset */
-
-/* Status Register */
-#define ETH_QUARK_SR_MMCI 0x08000000 /* MAC MMC interrupt */
-#define ETH_QUARK_SR_TS_SUSP 0x00600000 /* TX DMA is suspended */
-#define ETH_QUARK_SR_NIS 0x00010000 /* Normal Int summary */
-#define ETH_QUARK_SR_AIS 0x00008000 /* Abnorm Intrupt summ. */
-#define ETH_QUARK_SR_RI 0x00000040 /* Receive Interrupt */
-#define ETH_QUARK_SR_TI 0x00000001 /* Transmit Interrupt */
-
-/* Operation Mode Register */
-#define ETH_QUARK_OMR_TSF 0x00200000 /* Tx store and forward */
-#define ETH_QUARK_OMR_ST 0x00002000 /* Start/Stop TX */
-#define ETH_QUARK_OMR_SR 0x00000002 /* Start/Stop RX */
-
-/* Interrupt Enable Register */
-#define ETH_QUARK_IER_NIE 0x00010000 /* Enable Norm Int Summ.*/
-#define ETH_QUARK_IER_AIE 0x00008000 /* Enable Abnnom " " */
-#define ETH_QUARK_IER_RIE 0x00000040 /* Enable RX Interrupt */
-#define ETH_QUARK_IER_TIE 0x00000001 /* Enable TX Interrupt */
-
-/* Quark Ethernet Transmit Descriptor */
-
-struct eth_q_tx_desc {
- uint32 ctrlstat; /* Control and status */
- uint16 buf1size; /* Size of buffer 1 */
- uint16 buf2size; /* Size of buffer 2 */
- uint32 buffer1; /* Address of buffer 1 */
- uint32 buffer2; /* Address of buffer 2 */
-};
-
-#define ETH_QUARK_TDCS_OWN 0x80000000 /* Descrip. owned by DMA*/
-#define ETH_QUARK_TDCS_IC 0x40000000 /* Int on Completion */
-#define ETH_QUARK_TDCS_LS 0x20000000 /* Last Segment */
-#define ETH_QUARK_TDCS_FS 0x10000000 /* First Segment */
-#define ETH_QUARK_TDCS_TER 0x00200000 /* Transmit End of Ring */
-#define ETH_QUARK_TDCS_ES 0x00008000 /* Error Summary */
-
-/* Quark Ethernet Receive Descriptor */
-
-struct eth_q_rx_desc {
- uint32 status; /* Desc status word */
- uint16 buf1size; /* Size of buffer 1 */
- uint16 buf2size; /* Size of buffer 2 */
- uint32 buffer1; /* Address of buffer 1 */
- uint32 buffer2; /* Address of buffer 2 */
-};
-#define rdctl1 buf1size /* Buffer 1 size field has control bits too */
-#define rdctl2 buf2size /* Buffer 2 size field has control bits too */
-
-#define ETH_QUARK_RDST_OWN 0x80000000 /* Descrip. owned by DMA*/
-#define ETH_QUARK_RDST_ES 0x00008000 /* Error Summary */
-#define ETH_QUARK_RDST_FS 0x00000200 /* First Segment */
-#define ETH_QUARK_RDST_LS 0x00000100 /* Last segment */
-#define ETH_QUARK_RDST_FTETH 0x00000020 /* Frame Type = Ethernet*/
-
-#define ETH_QUARK_RDCTL1_DIC 0x8000 /* Dis. Int on Complet. */
-#define ETH_QUARK_RDCTL1_RER 0x8000 /* Recv End of Ring */
-
-#define ETH_QUARK_RX_RING_SIZE 32
-#define ETH_QUARK_TX_RING_SIZE 16
-
-#define ETH_QUARK_INIT_DELAY 500000 /* Delay in micro secs */
-#define ETH_QUARK_MAX_RETRIES 3 /* Max retries for init */
diff --git a/include/quark_irq.h b/include/quark_irq.h
index b971c0f..edafd0b 100644
--- a/include/quark_irq.h
+++ b/include/quark_irq.h
@@ -4,8 +4,8 @@
#define PABCDRC_OFFSET 0x60 /* PIRQ A-D Routing Control offset */
#define PEFGHRC_OFFSET 0x64 /* PIRQ E-H Routing control offset */
-#define PABCDRC_VALUE 0x06050403 /* PIRQ A-D routed to 8259 IRQ 3-6 resp. */
-#define PEFGHRC_VALUE 0x0C0B0A09 /* PIRQ E-H routed to 8259 IRQ 9-12 resp.*/
+#define PABCDRC_VALUE 0x06050403 /* PIRQ A-D routed to 8259 IRQ 2-5 resp. */
+#define PEFGHRC_VALUE 0x0C0B0A09 /* PIRQ E-H routed to 8259 IRQ 6-9 resp. */
#define RCBA_OFFSET 0xF0 /* RCBA offset in PCI config space */
#define RCBA_MASK 0xffffc000
diff --git a/include/quark_pdat.h b/include/quark_pdat.h
index 9134452..078e521 100644
--- a/include/quark_pdat.h
+++ b/include/quark_pdat.h
@@ -33,7 +33,7 @@ struct quark_pdat_entry {
char pdat_entry_desc[10]; /* Description string of the platform entry */
uint16 pdat_entry_ver; /* Version of the platform entry */
- /* variable length data for the entry */
+ /* Variable length data for the entry */
};
#pragma pack()
diff --git a/include/ramdisk.h b/include/ramdisk.h
index a5ee9d3..a8c8f0d 100644
--- a/include/ramdisk.h
+++ b/include/ramdisk.h
@@ -2,8 +2,8 @@
/* Ram disk block size */
-#define RM_BLKSIZ 512 /* block size */
-#define RM_BLKS 200 /* number of blocks */
+#define RM_BLKSIZ 512 /* Block size */
+#define RM_BLKS 200 /* Number of blocks */
struct ramdisk {
char disk[RM_BLKSIZ * RM_BLKS];
diff --git a/include/rdisksys.h b/include/rdisksys.h
index 21c1f54..7c3efa6 100644
--- a/include/rdisksys.h
+++ b/include/rdisksys.h
@@ -10,32 +10,39 @@
/* Global data for the remote disk server */
-#ifndef RD_SERVER_IP
-#define RD_SERVER_IP "255.255.255.255"
+#ifndef RD_SERVER
+#define RD_SERVER "example.com"
#endif
#ifndef RD_SERVER_PORT
-#define RD_SERVER_PORT 33124
+#define RD_SERVER_PORT 53124
#endif
#ifndef RD_LOC_PORT
-#define RD_LOC_PORT 33124 /* Base port number - minor dev */
+#define RD_LOC_PORT 53124 /* Base port number - minor dev */
/* number is added to insure */
/* that each device is unique */
#endif
-/* Control block for remote disk device */
+#define RD_SSIZE NPROC /* Number of serial queue nodes */
+#define RD_QNODES 30 /* Number of request queue nodes*/
+#define RD_CNODES 32 /* Number of cache bodes */
+
+
+/* Constants for remote disk device control block */
#define RD_IDLEN 64 /* Size of a remote disk ID */
-#define RD_BUFFS 64 /* Number of disk buffers */
#define RD_STACK 16384 /* Stack size for comm. process */
-#define RD_PRIO 200 /* Priorty of comm. process */
+#define RD_PRIO 600 /* Priorty of comm. process */
+ /* (Must be higher than any */
+ /* process that reads/writes */
/* Constants for state of the device */
-#define RD_FREE 0 /* Device is available */
-#define RD_OPEN 1 /* Device is open (in use) */
-#define RD_PEND 2 /* Open is pending */
+#define RD_CLOSED 0 /* Device is not in use */
+#define RD_OPEN 1 /* Device is open */
+#define RD_PEND 2 /* Device is being opened */
+#define RD_DELETING 3 /* Device is being deleted */
/* Operations for request queue */
@@ -43,53 +50,53 @@
#define RD_OP_WRITE 2 /* Write operation on req. list */
#define RD_OP_SYNC 3 /* Sync operation on req. list */
-/* Status values for a buffer */
+/* Definition of a serial queue node */
-#define RD_VALID 0 /* Buffer contains valid data */
-#define RD_INVALID 1 /* Buffer does not contain data */
+struct rdsent { /* Entry in the serial queue */
+ int32 rd_op; /* Operation - read/write/sync */
+ uint32 rd_blknum; /* Disk block number to use */
+ char *rd_callbuf; /* Address of caller's buffer */
+ pid32 rd_pid; /* Process that initiated the */
+}; /* request */
-/* Definition of a buffer with a header that allows the same node to be */
-/* used as a request on the request queue, an item in the cache, or a */
-/* node on the free list of buffers */
+/* Definition of a request queue node */
-struct rdbuff { /* Request list node */
- struct rdbuff *rd_next; /* Ptr to next node on a list */
- struct rdbuff *rd_prev; /* Ptr to prev node on a list */
+struct rdqnode { /* Node in the request queue */
+ struct rdqnode *rd_next; /* Pointer to next node */
+ struct rdqnode *rd_prev; /* Pointer to previous node */
int32 rd_op; /* Operation - read/write/sync */
- int32 rd_refcnt; /* Reference count of processes */
- /* reading the block */
- uint32 rd_blknum; /* Block number of this block */
- int32 rd_status; /* Is buffer currently valid? */
- pid32 rd_pid; /* Process that initiated a */
- /* read request for the block */
- char rd_block[RD_BLKSIZ]; /* Space to hold one disk block */
+ uint32 rd_blknum; /* Disk block number to use */
+ char *rd_callbuf; /* Address of caller's buffer */
+ pid32 rd_pid; /* Process making the request */
+ char rd_wbuf[RD_BLKSIZ]; /* Data for a write operation */
};
-struct rdscblk {
- int32 rd_state; /* State of device */
- char rd_id[RD_IDLEN]; /* Disk ID currently being used */
- int32 rd_seq; /* Next sequence number to use */
- /* Request queue head and tail */
- struct rdbuff *rd_rhnext; /* Head of request queue: next */
- struct rdbuff *rd_rhprev; /* and previous */
- struct rdbuff *rd_rtnext; /* Tail of request queue: next */
- struct rdbuff *rd_rtprev; /* (null) and previous */
-
- /* Cache head and tail */
+/* Definition of a node in the cache */
- struct rdbuff *rd_chnext; /* Head of cache: next and */
- struct rdbuff *rd_chprev; /* previous */
- struct rdbuff *rd_ctnext; /* Tail of cache: next (null) */
- struct rdbuff *rd_ctprev; /* and previous */
-
- /* Free list head (singly-linked) */
+struct rdcnode { /* Node in the cache */
+ struct rdcnode *rd_next; /* Pointer to next node */
+ struct rdcnode *rd_prev; /* Pointer to previous node */
+ uint32 rd_blknum; /* Number of this disk block */
+ byte rd_data[RD_BLKSIZ]; /* Data for the disk block */
+};
- struct rdbuff *rd_free; /* Pointer to free list */
+/* Device control block for a remote disk */
+struct rdscblk { /* Remote disk control block */
+ int32 rd_state; /* State of device */
+ char rd_id[RD_IDLEN]; /* Disk ID currently being used */
+ int32 rd_seq; /* Next sequence number to use */
+ struct rdcnode *rd_chead; /* Head of cache */
+ struct rdcnode *rd_ctail; /* Tail of cache */
+ struct rdcnode *rd_cfree; /* Free list of cache nodes */
+ struct rdqnode *rd_qhead; /* Head of request queue */
+ struct rdqnode *rd_qtail; /* Tail of request queue */
+ struct rdqnode *rd_qfree; /* Free list of request nodes */
+ struct rdsent rd_sq[RD_SSIZE];/* Serial queue circular buffer */
+ int32 rdshead; /* Head of the serial queue */
+ int32 rdstail; /* Tail of the serial queue */
+ int32 rdscount; /* Count serial queue items */
pid32 rd_comproc; /* Process ID of comm. process */
- bool8 rd_comruns; /* Has comm. process started? */
- sid32 rd_availsem; /* Semaphore ID for avail buffs */
- sid32 rd_reqsem; /* Semaphore ID for requests */
uint32 rd_ser_ip; /* Server IP address */
uint16 rd_ser_port; /* Server UDP port */
uint16 rd_loc_port; /* Local (client) UPD port */
@@ -97,18 +104,18 @@ struct rdscblk {
int32 rd_udpslot; /* Registered UDP slot */
};
-
extern struct rdscblk rdstab[]; /* Remote disk control block */
/* Definitions of parameters used during server access */
#define RD_RETRIES 3 /* Times to retry sending a msg */
-#define RD_TIMEOUT 2000 /* Timeout for reply (2 seconds)*/
+#define RD_TIMEOUT 1000 /* Timeout for reply (1 second) */
-/* Control functions for a remote file pseudo device */
+/* Control functions for a remote disk device */
-#define RDS_CTL_DEL 1 /* Delete (erase) an entire disk*/
-#define RDS_CTL_SYNC 2 /* Write all pending blocks */
+#define RDS_CTL_SYNC 1 /* Write all pending blocks */
+#define RDS_CTL_DEL 2 /* Delete the entire disk */
+#define RDS_CTL_CLOSE 3 /* Close the disk device */
/************************************************************************/
/* Definition of messages exchanged with the remote disk server */
@@ -149,7 +156,7 @@ extern struct rdscblk rdstab[]; /* Remote disk control block */
/* The standard header present in all messages with no extra fields */
#pragma pack(2)
struct rd_msg_hdr { /* Header fields present in each*/
- RD_MSG_HDR /* remote file system message */
+ RD_MSG_HDR /* remote disk system message */
};
#pragma pack()
@@ -157,14 +164,14 @@ struct rd_msg_hdr { /* Header fields present in each*/
/* Read */
/************************************************************************/
#pragma pack(2)
-struct rd_msg_rreq { /* Remote file read request */
+struct rd_msg_rreq { /* Remote disk read request */
RD_MSG_HDR /* Header fields */
uint32 rd_blk; /* Block number to read */
};
#pragma pack()
#pragma pack(2)
-struct rd_msg_rres { /* Remote file read reply */
+struct rd_msg_rres { /* Remote disk read reply */
RD_MSG_HDR /* Header fields */
uint32 rd_blk; /* Block number that was read */
char rd_data[RD_BLKSIZ]; /* Array containing one block */
@@ -175,7 +182,7 @@ struct rd_msg_rres { /* Remote file read reply */
/* Write */
/************************************************************************/
#pragma pack(2)
-struct rd_msg_wreq { /* Remote file write request */
+struct rd_msg_wreq { /* Remote disk write request */
RD_MSG_HDR /* Header fields */
uint32 rd_blk; /* Block number to write */
char rd_data[RD_BLKSIZ]; /* Array containing one block */
@@ -183,7 +190,7 @@ struct rd_msg_wreq { /* Remote file write request */
#pragma pack()
#pragma pack(2)
-struct rd_msg_wres { /* Remote file write response */
+struct rd_msg_wres { /* Remote disk write response */
RD_MSG_HDR /* Header fields */
uint32 rd_blk; /* Block number that was written*/
};
@@ -193,13 +200,13 @@ struct rd_msg_wres { /* Remote file write response */
/* Open */
/************************************************************************/
#pragma pack(2)
-struct rd_msg_oreq { /* Remote file open request */
+struct rd_msg_oreq { /* Remote disk open request */
RD_MSG_HDR /* Header fields */
};
#pragma pack()
#pragma pack(2)
-struct rd_msg_ores { /* Remote file open response */
+struct rd_msg_ores { /* Remote disk open response */
RD_MSG_HDR /* Header fields */
};
#pragma pack()
@@ -208,13 +215,13 @@ struct rd_msg_ores { /* Remote file open response */
/* Close */
/************************************************************************/
#pragma pack(2)
-struct rd_msg_creq { /* Remote file close request */
+struct rd_msg_creq { /* Remote disk close request */
RD_MSG_HDR /* Header fields */
};
#pragma pack()
#pragma pack(2)
-struct rd_msg_cres { /* Remote file close response */
+struct rd_msg_cres { /* Remote disk close response */
RD_MSG_HDR /* Header fields */
};
#pragma pack()
@@ -223,13 +230,13 @@ struct rd_msg_cres { /* Remote file close response */
/* Delete */
/************************************************************************/
#pragma pack(2)
-struct rd_msg_dreq { /* Remote file delete request */
+struct rd_msg_dreq { /* Remote disk delete request */
RD_MSG_HDR /* Header fields */
};
#pragma pack()
#pragma pack(2)
-struct rd_msg_dres { /* Remote file delete response */
+struct rd_msg_dres { /* Remote disk delete response */
RD_MSG_HDR /* Header fields */
};
#pragma pack()
diff --git a/include/rfilesys.h b/include/rfilesys.h
index d029c86..bc36188 100644
--- a/include/rfilesys.h
+++ b/include/rfilesys.h
@@ -17,16 +17,16 @@
/* Global data for the remote server */
-#ifndef RF_SERVER_IP
-#define RF_SERVER_IP "128.10.3.51"
+#ifndef RF_SERVER
+#define RF_SERVER "example.com"
#endif
#ifndef RF_SERVER_PORT
-#define RF_SERVER_PORT 0
+#define RF_SERVER_PORT 53224
#endif
#ifndef RF_LOC_PORT
-#define RF_LOC_PORT 33123
+#define RF_LOC_PORT 53224
#endif
struct rfdata {
@@ -60,7 +60,7 @@ extern struct rflcblk rfltab[]; /* Remote file control blocks */
/* Definitions of parameters used when accessing a remote server */
#define RF_RETRIES 3 /* Time to retry sending a msg */
-#define RF_TIMEOUT 3000 /* Wait one second for a reply */
+#define RF_TIMEOUT 1000 /* Wait one second for a reply */
/* Control functions for a remote file pseudo device */
@@ -104,7 +104,7 @@ extern struct rflcblk rfltab[]; /* Remote file control blocks */
#define RF_MSG_XREQ 0x0008 /* Rmdir request and response */
#define RF_MSG_XRES (RF_MSG_XREQ | RF_MSG_RESPONSE)
-#define RF_MSG_CREQ 0x0009
+#define RF_MSG_CREQ 0x0009 /* Close an open file */
#define RF_MSG_CRES (RF_MSG_CREQ | RF_MSG_RESPONSE)
#define RF_MIN_REQ RF_MSG_RREQ /* Minimum request type */
@@ -311,19 +311,3 @@ struct rf_msg_xres { /* Remote file rmdir response */
RF_MSG_HDR /* Header fields */
};
#pragma pack()
-
-/************************************************************************/
-/* */
-/* rfdirent */
-/* */
-/************************************************************************/
-
-#define RF_DIRENT_FILE 1
-#define RF_DIRENT_DIR 2
-
-#pragma pack(2)
-struct rfdirent {
- byte d_type; /* Type of the file */
- char d_name[256]; /* Name of the file */
-};
-#pragma pack()
diff --git a/include/sdmc.h b/include/sdmc.h
index 62973d0..1f19613 100644
--- a/include/sdmc.h
+++ b/include/sdmc.h
@@ -108,15 +108,6 @@ struct sdmc_capabilities {
/* Individual Bits in Control and Status Registers */
-/* Host Control Register */
-#define SDMC_HOST_CTL_LED_CTL 0x0001 /* LED Control */
-#define SDMC_HOST_DAT_TX_4BIT 0x0002 /* Set 4 Bit Bus Width */
-#define SDMC_HOST_HS_EN 0x0004 /* High Speed Enable */
-#define SDMC_HOST_ADMA_32 0x0010 /* 32 bit ADMA */
-#define SDMC_HOST_ADMA_64 0x0018 /* 64 bit ADMA */
-#define SDMC_HOST_CARD_DET_TST 0x0040 /* Card is inserted (test) */
-#define SDMC_HOST_CARD_DET_SIG 0x0080 /* Test signal: card inserted */
-
/* Normal Interrupt Status Enable */
#define SDMC_CMD_COMP_STAT_EN 0x0001 /* Command Complete Status Enable */
#define SDMC_TX_COMP_STAT_EN 0x0002 /* Transfer Complete Status Enable */
@@ -131,7 +122,6 @@ struct sdmc_capabilities {
#define SDMC_INT_B_STAT_EN 0x0400 /* INT_A Status Enable */
#define SDMC_INT_C_STAT_EN 0x0800 /* INT_A Status Enable */
#define SDMC_RE_TUNE_STAT_EN 0x1000 /* Re-Tuning Event Status Enable */
-#define SDMC_NML_INT_ALL_STAT_EN 0x1FFF /* Enable all interrupt status */
/* Normal Interrupt Signal Enable */
#define SDMC_CMD_COMP_SIG_EN 0x0001 /* Command Complete Signal Enable */
@@ -147,7 +137,6 @@ struct sdmc_capabilities {
#define SDMC_INT_B_SIG_EN 0x0400 /* INT_A Signal Enable */
#define SDMC_INT_C_SIG_EN 0x0800 /* INT_A Signal Enable */
#define SDMC_RE_TUNE_SIG_EN 0x1000 /* Re-Tuning Event Signal Enable */
-#define SDMC_NML_INT_ALL_SIG_EN 0x1FFF /* Enable all interrupt signals */
/* Normal Interrupt Status Register */
#define SDMC_NML_INT_CMD_COMP 0x0001 /* Command Complete */
@@ -181,7 +170,6 @@ struct sdmc_capabilities {
#define SDMC_ERR_INT_TUNE_ERR_STAT_EN 0x0400 /* Tuning Error Status Enable */
#define SDMC_ERR_INT_TGT_RSP_ERR_EN 0x1000 /* Target Response Error Status Enable */
#define SDMC_ERR_INT_CEATA_ERR_EN 0x2000 /* CEATA Error Status Enable */
-#define SDMC_ERR_INT_ALL_STAT_EN 0x3FFF /* Enable all interrupt signals */
/* Error Interrupt Signal Enable */
#define SDMC_ERR_INT_CMD_TIMEOUT_ERR_SIG_EN 0x0001 /* Command Timeout Error Signal Enable */
@@ -197,7 +185,6 @@ struct sdmc_capabilities {
#define SDMC_ERR_INT_TUNE_ERR_SIG_EN 0x0400 /* Tuning Error Signal Enable */
#define SDMC_ERR_INT_TGT_RSP_ERR_SIG_EN 0x1000 /* Target Response Error Signal Enable */
#define SDMC_ERR_INT_CEATA_ERR_SIG_EN 0x2000 /* CEATA Error Signal Enable */
-#define SDMC_ERR_INT_ALL_SIG_EN 0x3FFF /* Enable all interrupt signals */
/* Error Interrupt Status Register */
#define SDMC_ERR_INT_CMD_TIMEOUT_ERR 0x0001 /* Command Timeout Error */
@@ -237,9 +224,6 @@ struct sdmc_capabilities {
#define SDMC_CLK_CTL_CLK_GEN_SEL 0x0020 /* Clock Generator Select */
#define SDMC_CLK_CTL_SD_FREQ_HIGH_MASK 0x00FF /* Mask to set SD clock frequency to max*/
-/* Timeout Control Register */
-#define SDMC_TMR_CTL_HIGH 0x0E /* Mask to set timeout to max */
-
/* Power Control Register */
#define SDMC_PWR_CTL_SD_BUS_PWR 0x01 /* SD Bus Power */
#define SDMC_PWR_CTL_HW_RST 0x10 /* HW Reset */
@@ -248,13 +232,6 @@ struct sdmc_capabilities {
#define SDMC_PWR_CTL_SD_BUS_VOL_SEL_3P0V 0x0C /* Set mask for 3.0V */
#define SDMC_PWR_CTL_SD_BUS_VOL_SEL_1P8V 0x0A /* Set mask for 1.8V */
-/* Transfer Mode Register */
-#define SDMC_TXM_DMA_EN 0x0001 /* DMA Enable */
-#define SDMC_TXM_BLK_CNT_EN 0x0002 /* Block Count Enable */
-#define SDMC_TXM_AUTO_CMD12_EN 0x0004 /* Auto CMD12 Enable */
-#define SDMC_TXM_DAT_TX_RD 0x0010 /* Data Direction Read */
-#define SDMC_TXM_MB_SEL 0x0020 /* Multi block select */
-
/* Card Status Response (R1) */
#define SDMC_R1_AKE_SEQ_ERROR 0x00000008 /* Authentication Error */
#define SDMC_R1_APP_CMD 0x00000020 /* Next command is application */
@@ -277,7 +254,6 @@ struct sdmc_capabilities {
#define SDMC_R1_BLOCK_LEN_ERROR 0x20000000 /* TX block length not allowed */
#define SDMC_R1_ADDRESS_ERROR 0x40000000 /* Misaligned address */
#define SDMC_R1_OUT_OF_RANGE 0x80000000 /* Argument out of range */
-#define SDMC_R1_ANY_ERROR 0xFDF90008 /* Combined mask for any error */
/* Card state */
#define SDMC_R1_IDLE_STATE 0x00000000 /* Idle State */
@@ -315,58 +291,29 @@ struct sdmc_capabilities {
#define SDMC_R6_ILLEGAL_COMMAND 0x00004000 /* Not a legal command */
#define SDMC_R6_COM_CRC_ERROR 0x00008000 /* Previous command CRC failed */
-/* ACMD41 Argument Flags */
+/* ACMD41 Argument flags */
#define SDMC_OCR_MASK 0x00FFFF00 /* OCR set mask */
#define SDMC_ACMD41_S18R 0x01000000 /* Switching to 1.8V request */
#define SDMC_ACMD41_XPC 0x10000000 /* Extended capacity power ctl */
#define SDMC_ACMD41_HCS 0x40000000 /* High capacity card support */
-/* Command Resgitser */
-#define SDMC_CMD_TYPE_NML 0x0000 /* Normal Command Type */
-#define SDMC_CMD_TYPE_SUS 0x0040 /* Suspend Command Type */
-#define SDMC_CMD_TYPE_RSM 0x0080 /* Resume Command Type */
-#define SDMC_CMD_TYPE_ABT 0x00C0 /* Abort Command Type */
-#define SDMC_CMD_DAT_PRES 0x0020 /* Data Present Flag */
-#define SDMC_CMD_CMD_IDX_EN 0x0010 /* Index Check Enable Flag */
-#define SDMC_CMD_CMD_CRC_EN 0x0008 /* CRC Check Enable Flag */
-#define SDMC_CMD_CMD_RSP_LG 0x0001 /* 138 Bit Response Length */
-#define SDMC_CMD_CMD_RSP_ST 0x0002 /* 48 Bit Response Length */
-#define SDMC_CMD_CMD_RSP_ST_BSY 0x0003 /* 48 Bit Response Length Check Busy */
-
-/* Expected Command Response Types */
-#define SDMC_CMD_NO_RESP (0x0000)
-#define SDMC_CMD_R1 (SDMC_CMD_CMD_RSP_ST | SDMC_CMD_CMD_IDX_EN | SDMC_CMD_CMD_CRC_EN)
-#define SDMC_CMD_R1b (SDMC_CMD_CMD_RSP_ST_BSY | SDMC_CMD_CMD_IDX_EN | SDMC_CMD_CMD_CRC_EN)
-#define SDMC_CMD_R2 (SDMC_CMD_CMD_RSP_LG | SDMC_CMD_CMD_CRC_EN)
-#define SDMC_CMD_R3 (SDMC_CMD_CMD_RSP_ST)
-#define SDMC_CMD_R4 (SDMC_CMD_CMD_RSP_ST)
-#define SDMC_CMD_R5 (SDMC_CMD_CMD_RSP_ST | SDMC_CMD_CMD_IDX_EN | SDMC_CMD_CMD_CRC_EN)
-#define SDMC_CMD_R5b (SDMC_CMD_CMD_RSP_ST_BSY | SDMC_CMD_CMD_IDX_EN | SDMC_CMD_CMD_CRC_EN)
-#define SDMC_CMD_R6 (SDMC_CMD_CMD_RSP_ST | SDMC_CMD_CMD_IDX_EN | SDMC_CMD_CMD_CRC_EN)
-#define SDMC_CMD_R7 (SDMC_CMD_CMD_RSP_ST | SDMC_CMD_CMD_IDX_EN | SDMC_CMD_CMD_CRC_EN)
-
-/* Command Definitions with Expected Response Types */
-#define SDMC_CMD0 0x0000 | (SDMC_CMD_NO_RESP) /* CMD0 - Go Idle State (Reset) */
-#define SDMC_CMD2 0x0200 | (SDMC_CMD_R2) /* CMD2 - All send card identifier */
-#define SDMC_CMD3 0x0300 | (SDMC_CMD_R6) /* CMD3 - Send relative card address */
-#define SDMC_CMD7 0x0700 | (SDMC_CMD_R1b) /* CMD7 - Select/Deselect card */
-#define SDMC_CMD8 0x0800 | (SDMC_CMD_R7) /* CMD8 - Voltage check */
-#define SDMC_CMD9 0x0900 | (SDMC_CMD_R2) /* CMD9 - Send CSD */
-#define SDMC_CMD10 0x0A00 | (SDMC_CMD_R2) /* CMD10 - Send CID */
-#define SDMC_CMD12 0x0C00 | (SDMC_CMD_R1b) /* CMD12 - Stop Transmission */
-#define SDMC_ABT 0x0C00 | (SDMC_CMD_TYPE_ABT) /* CMD12 - Abort */
-#define SDMC_CMD13 0x0D00 | (SDMC_CMD_R1) /* CMD13 - Send status */
-#define SDMC_CMD16 0x1000 | (SDMC_CMD_R1) /* CMD16 - Set block length */
-#define SDMC_CMD17 0x1100 | (SDMC_CMD_R1 | SDMC_CMD_DAT_PRES) /* CMD17 - Single block read */
-#define SDMC_CMD55 0x3700 | (SDMC_CMD_R1) /* CMD55 - Application specific command */
-#define SDMC_ACMD6 0x0600 | (SDMC_CMD_R1) /* ACMD6 - Set bus width */
-#define SDMC_ACMD41 0x2900 | (SDMC_CMD_R3) /* ACMD41 - Card Initialization/Inquiry */
-#define SDMC_ACMD51 0x3300 | (SDMC_CMD_R1 | SDMC_CMD_DAT_PRES ) /* ACMD51 - Send SCR */
+#define SDMC_ABT 0x0CC0 /* CMD12 - Abort */
+#define SDMC_CMD0 0x0000 /* CMD0 - Go Idle State (Reset) */
+#define SDMC_CMD2 0x0209 /* CMD2 - All send card identifier */
+#define SDMC_CMD3 0x031A /* CMD3 - Send relative card address */
+#define SDMC_CMD7 0x071B /* CMD7 - Select/Deselect card */
+#define SDMC_CMD8 0x081A /* CMD8 - Voltage check */
+#define SDMC_CMD9 0x0909 /* CMD9 - Send CSD */
+#define SDMC_CMD10 0x0A09 /* CMD10 - Send CID */
+#define SDMC_CMD12 0x0C1B /* CMD12 - Stop Transmission */
+#define SDMC_CMD13 0x0D1A /* CMD13 - Send status */
+#define SDMC_CMD16 0x101A /* CMD16 - Set block length */
+#define SDMC_CMD17 0x113A /* CMD17 - Single block read */
+#define SDMC_CMD55 0x371A /* CMD55 - Application specific command */
+#define SDMC_ACMD41 0x2902 /* ACMD41 - Card Initialization/Inquiry */
#define SDMC_CMD_DELAY 100000 /* Delay in micro secs */
-#define SDMC_BLK_SIZE 512 /* Block size used for data transfers */
-
#define SDMC_RC_OK (0)
#define SDMC_RC_RECOVERABLE_ERR (-1)
#define SDMC_RC_NON_RECOVERABLE_ERROR (-2)
diff --git a/include/shell.h b/include/shell.h
index ffde865..c002766 100644
--- a/include/shell.h
+++ b/include/shell.h
@@ -30,11 +30,12 @@
#define SHELL_STRTMSG "Welcome to Xinu!\n"/* Welcome message */
#define SHELL_EXITMSG "Shell closed\n"/* Shell exit message */
#define SHELL_SYNERRMSG "Syntax error\n"/* Syntax error message */
-#define SHELL_CREATMSG "Cannot create process\n"/* command error */
+#define SHELL_CREATEMSG "Cannot create process\n"/* command error */
#define SHELL_INERRMSG "Cannot open file %s for input\n" /* Input err */
#define SHELL_OUTERRMSG "Cannot open file %s for output\n"/* Output err */
/* Builtin cmd error message */
-#define SHELL_BGERRMSG "Cannot redirect I/O or background a builtin\n"
+#define SHELL_BGERRMSG "Cannot redirect I/O or background a builtin\n" */
+#define SHELL_PIPEMSG "Cannot create a pipe\n"/* error opening a pipe */
/* Constants used for lexical analysis */
@@ -45,15 +46,17 @@
#define SH_TAB '\t' /* Tab character */
#define SH_SQUOTE '\'' /* Single quote character */
#define SH_DQUOTE '"' /* Double quote character */
-#define SH_LESS '<' /* Less-than character */
+#define SH_LESS '<' /* Less-than character */
#define SH_GREATER '>' /* Greater-than character */
+#define SH_PIPE '|' /* Pipeline symbol */
/* Token types */
#define SH_TOK_AMPER 0 /* Ampersand token */
#define SH_TOK_LESS 1 /* Less-than token */
#define SH_TOK_GREATER 2 /* Greater-than token */
-#define SH_TOK_OTHER 3 /* Token other than those */
+#define SH_TOK_PIPE 3 /* Pipeline token */
+#define SH_TOK_OTHER 4 /* Token other than those */
/* listed above (e.g., an */
/* alphanumeric string) */
@@ -67,7 +70,6 @@
struct cmdent { /* Entry in command table */
char *cname; /* Name of command */
- bool8 cbuiltin; /* Is this a builtin command? */
int32 (*cfunc)(int32,char*[]);/* Function for command */
};
diff --git a/include/shprototypes.h b/include/shprototypes.h
index d2059a4..3edf5d8 100644
--- a/include/shprototypes.h
+++ b/include/shprototypes.h
@@ -34,6 +34,9 @@ extern shellcmd xsh_help (int32, char *[]);
/* in file xsh_kill.c */
extern shellcmd xsh_kill (int32, char *[]);
+/* in file xsh_ls.c */
+extern shellcmd xsh_ls (int32, char *[]);
+
/* in file xsh_led.c */
extern shellcmd xsh_led (int32, char *[]);
@@ -46,6 +49,9 @@ extern shellcmd xsh_memstat (int32, char *[]);
/* in file xsh_netinfo.c */
extern shellcmd xsh_netinfo (int32, char *[]);
+/* in file xsh_ns.c */
+extern shellcmd xsh_ns (int32, char *[]);
+
/* in file xsh_nvram.c */
extern shellcmd xsh_nvram (int32, char *[]);
@@ -72,3 +78,6 @@ extern shellcmd xsh_uptime (int32, char *[]);
/* in file xsh_help.c */
extern shellcmd xsh_help (int32, char *[]);
+
+/* in file xsh_tee.c */
+extern shellcmd xsh_tee (int32, char *[]);
diff --git a/include/testsuite.h b/include/testsuite.h
index 3ce0539..ffb85bc 100644
--- a/include/testsuite.h
+++ b/include/testsuite.h
@@ -32,7 +32,7 @@ struct testcase {
process (*test) (bool8);/* Test case function */
};
-extern int ntests; /* total number of tests */
-extern struct testcase testtab[]; /* table of test cases */
+extern int ntests; /* Total number of tests */
+extern struct testcase testtab[]; /* Table of test cases */
-#define TESTSTK 8192 /* size of process stack used for test */
+#define TESTSTK 8192 /* Size of process stack used for test */
diff --git a/include/tftp.h b/include/tftp.h
index 51e58cf..184d50a 100644
--- a/include/tftp.h
+++ b/include/tftp.h
@@ -18,14 +18,14 @@
#define TFTP_ERROR_NO_SUCH_USER 7 /* No such user. */
#define TFTP_PORT 69 /* UDP Port for TFTP */
-#define TFTP_MAXNAM 64 /* Max length of a file name */
+#define TFTP_MAXNAM 64 /* Max length of a file name */
#define TFTP_MAXDATA 512 /* Max size of a data packet */
#define TFTP_MAXRETRIES 3 /* Number of retranmissions */
#define TFTP_WAIT 5000 /* Time to wait for reply (ms) */
-#define TFTP_FUNC_MAGIC 0xFFFFFF00 /* Magic value used to indicate */
- /* input to tftpget is a */
- /* function pointer */
+/* Xinu Specific Flags */
+#define TFTP_NON_VERBOSE 0 /* Do not use verbose output */
+#define TFTP_VERBOSE 1 /* Use verbose output */
/* Format of a TFTP message (items following opcode depend on msg type) */
@@ -63,4 +63,5 @@ struct tftp_msg {
};
#pragma pack()
-status tftpget(uint32, const char*, void*, uint32);
+status tftpget(uint32 serverip, const char* filename, char* rcv_buf, uint32 rcv_buf_size, byte verbose);
+status tftpget_mb(uint32 serverip, const char* filename, char** rcv_bufs, uint32* rcv_buf_sizes, uint32 rcv_buf_count, byte verbose);
\ No newline at end of file
diff --git a/include/uart.h b/include/uart.h
index 4056e3b..1472c1e 100755
--- a/include/uart.h
+++ b/include/uart.h
@@ -4,8 +4,8 @@
#define UART_OUT_IDLE 0x0016 /* determine if transmit idle */
#define UART_FIFO_SIZE 16 /* chars in UART onboard output FIFO */
/* (16 for later UART chips) */
-#define INTEL_QUARK_UART_PCI_DID 0x0936 /* UART PCI Device ID */
-#define INTEL_QUARK_UART_PCI_VID 0x8086 /* UART PCI Vendor ID */
+#define INTEL_UART_PCI_DID 0x0936 /* UART PCI Device ID */
+#define INTEL_UART_PCI_VID 0x8086 /* UART PCI Vendor ID */
/*
* Control and Status Register (CSR) definintions for the 16550 UART.
* The code maps the structure structure directly onto the base address
@@ -13,16 +13,16 @@
*/
struct uart_csreg
{
- volatile uint32 buffer; /* receive buffer (when read) */
+ volatile byte buffer; /* receive buffer (when read) */
/* OR transmit hold (when written) */
- volatile uint32 ier; /* interrupt enable */
- volatile uint32 iir; /* interrupt identification (when read) */
+ volatile byte ier; /* interrupt enable */
+ volatile byte iir; /* interrupt identification (when read) */
/* OR FIFO control (when written) */
- volatile uint32 lcr; /* line control register */
- volatile uint32 mcr; /* modem control register */
- volatile uint32 lsr; /* line status register */
- volatile uint32 msr; /* modem status register */
- volatile uint32 scr; /* scratch register */
+ volatile byte lcr; /* line control register */
+ volatile byte mcr; /* modem control register */
+ volatile byte lsr; /* line status register */
+ volatile byte msr; /* modem status register */
+ volatile byte scr; /* scratch register */
};
/* Alternative names for control and status registers */
diff --git a/include/xinu.h b/include/xinu.h
index 7961c00..31f109c 100644
--- a/include/xinu.h
+++ b/include/xinu.h
@@ -11,6 +11,7 @@
#include <bufpool.h>
#include <clock.h>
#include <ports.h>
+#include <io.h>
#include <uart.h>
#include <tty.h>
#include <device.h>
@@ -32,10 +33,12 @@
#include <date.h>
#include <prototypes.h>
#include <delay.h>
+#include <i386.h>
#include <pci.h>
-#include <quark_eth.h>
+#include <e1000e.h>
#include <quark_pdat.h>
#include <quark_irq.h>
#include <multiboot.h>
#include <stdio.h>
#include <string.h>
+#include <pipe.h>
diff --git a/lib/memchr.c b/lib/memchr.c
deleted file mode 100644
index e69de29..0000000
diff --git a/net/arp.c b/net/arp.c
index 2073317..13e372f 100644
--- a/net/arp.c
+++ b/net/arp.c
@@ -12,7 +12,7 @@ void arp_init(void)
{
int32 i; /* ARP cache index */
- for (i=1; i<ARP_SIZ; i++) { /* Initialize cache to empty */
+ for (i=0; i<ARP_SIZ; i++) { /* Initialize cache to empty */
arpcache[i].arstate = AR_FREE;
}
}
@@ -130,7 +130,7 @@ status arp_resolve (
} else if (msg == SYSERR) {
restore(mask);
return SYSERR;
- } else { /* entry is resolved */
+ } else { /* Entry is resolved */
break;
}
}
@@ -342,7 +342,7 @@ void arp_ntoh(
}
/*------------------------------------------------------------------------
- * arp_hton - Convert ARP packet fields from net to host byte order
+ * arp_hton - Convert ARP packet fields from host to net byte order
*------------------------------------------------------------------------
*/
void arp_hton(
diff --git a/net/dhcp.c b/net/dhcp.c
index e6c7980..2bfece6 100644
--- a/net/dhcp.c
+++ b/net/dhcp.c
@@ -64,7 +64,7 @@ void dhcp_bld_bootp_msg(struct dhcpmsg* dmsg)
memset(&dmsg->dc_chaddr,'\0',16);/* Client hardware address */
memcpy(&dmsg->dc_chaddr, NetData.ethucast, ETH_ADDR_LEN);
memset(&dmsg->dc_bootp,'\0',192);/* Zero the bootp area */
- dmsg->dc_cookie = htonl(0x63825363); /* Magic cookie for DHCP */
+ dmsg->dc_cookie = htonl(0x63825363U); /* Magic cookie for DHCP */
}
/*------------------------------------------------------------------------
@@ -83,9 +83,10 @@ int32 dhcp_bld_disc(struct dhcpmsg* dmsg)
dmsg->dc_opt[j++] = 0xff & 0; /* Options padding */
dmsg->dc_opt[j++] = 0xff & 55; /* DHCP parameter request list */
- dmsg->dc_opt[j++] = 0xff & 2; /* Option length */
+ dmsg->dc_opt[j++] = 0xff & 3; /* Option length */
dmsg->dc_opt[j++] = 0xff & 1; /* Request subnet mask */
dmsg->dc_opt[j++] = 0xff & 3; /* Request default router addr->*/
+ dmsg->dc_opt[j++] = 0xff & 42; /* Request NTP server address */
dmsg->dc_opt[j++] = 0xff; /* End of options */
return (uint32)((char *)&dmsg->dc_opt[j] - (char *)dmsg + 1);
diff --git a/net/dhcp_dump.c b/net/dhcp_dump.c
index 2fed6c0..c6c8366 100644
--- a/net/dhcp_dump.c
+++ b/net/dhcp_dump.c
@@ -133,8 +133,8 @@ void dhcp_dump(
}
- opt_tmp++; /* move to length octet */
+ opt_tmp++; /* Move to length octet */
opt_tmp += *(uint8*)opt_tmp + 1;
}
kprintf("\n");
-}
\ No newline at end of file
+}
diff --git a/net/dns.c b/net/dns.c
index 1e34459..23c498d 100644
--- a/net/dns.c
+++ b/net/dns.c
@@ -4,51 +4,85 @@
#include <string.h>
#include <dns.h>
-local uint32 dns_bldq(char *, char *);
-local uint32 dns_geta(char *, struct dnspkt *);
+local int32 dns_bldq(char *, char *);
+local status dns_geta(char *, struct dnspkt *, uint32 *);
local uint32 dns_getrname(char *, char *, char *);
/*------------------------------------------------------------------------
- * dnslookup - Send a DNS Address Query and wait for the Response
+ * dnslookup - Look up a domain name and obtain an IP address
*------------------------------------------------------------------------
*/
-uint32 dnslookup (
- char *dname /* Domain name to be resolved */
+status dnslookup (
+ char *dname, /* Domain name to be resolved */
+ uint32 *addr /* Returned IP address */
)
{
struct dnspkt qpkt; /* Query Packet buffer */
struct dnspkt rpkt; /* Response Packet buffer */
uint32 nsaddr; /* Name server IP address */
- uint32 qlen; /* Query length */
+ int32 qlen; /* Query length */
uid32 slot; /* UDP Slot */
int32 rlen; /* Response length */
uint32 ipaddr; /* IP address from response */
int32 retval; /* Return value */
int32 i; /* Loop index */
+ char *p; /* Pointer to walk the name */
+ char ch; /* One character in the name */
+ bool8 dotted; /* Is dname dotted decimal? */
- /* Check if we have a valid name pointer */
+ /* Check for a non-null argument */
if(dname == NULL) {
return (uint32)SYSERR;
}
- /* Obtain the IP address of a DNS server */
+ /* Check for a dotted decimal value and return the IP address */
+
+ p = dname;
+ ch = *p++;
+ dotted = TRUE;
+ while (ch != NULLCH) {
+ if ( (ch != '.') && ( (ch < '0') || (ch > '9') ) ) {
+ dotted = FALSE;
+ break;
+ }
+ ch = *p++;
+ }
+ if (dotted) {
+ /* String contains only digits and dots */
+ if (dot2ip(dname, &ipaddr) == OK) {
+ *addr = ipaddr;
+ return OK;
+ } else {
+ return SYSERR;
+ }
+ }
+
+ /* Check for 'localhost' */
+
+ if ( strncmp(dname, "localhost", 9) == 0 ) {
+ /* Make localhost into 127.0.0.1 */
+ *addr = 0x7f000001;
+ return OK;
+ }
+
+ /* Not dotted decimal, Find the address of a DNS server */
retval = getlocalip();
nsaddr = NetData.dnsserver;
if ( (retval == SYSERR) || (NetData.dnsserver == 0) ) {
kprintf("Cannot find a DNS server\n");
- return (uint32)SYSERR;
+ return SYSERR;
}
/* Register a UDP Slot */
slot = udp_register(nsaddr, DNSPORT, DNSLPORT);
if(slot == SYSERR) {
- return (uint32)SYSERR;
+ return SYSERR;
}
- /* Build the Query message */
+ /* Build a DNS Query message for the name */
memset((char *)&qpkt, 0, sizeof(struct dnspkt));
@@ -57,9 +91,13 @@ uint32 dnslookup (
qpkt.qucount = htons(1);
qlen = dns_bldq(dname, qpkt.data);
+ if (qlen == SYSERR) {
+ return SYSERR;
+ }
+
+ /* Repeatedly send the query and await a response */
- ipaddr = (uint32)SYSERR;
- for(i = 0; (ipaddr==(uint32)SYSERR) && (i < DNSRETRY); i++) {
+ for(i = 0 ; i < DNSRETRY ; i++) {
/* Send the Query message */
@@ -72,17 +110,29 @@ uint32 dnslookup (
if ( (rlen == SYSERR) || (rlen == TIMEOUT) ) {
continue;
}
- ipaddr = dns_geta(dname, &rpkt);
+
+ /* Extract the address from the response */
+
+ retval = dns_geta(dname, &rpkt, &ipaddr);
+ if (retval == SYSERR) {
+ continue;
+ }
+ break;
}
udp_release(slot);
- return ntohl(ipaddr);
+ if (i >= DNSRETRY) {
+ return SYSERR;
+ }
+ *addr = ntohl(ipaddr);
+ return OK;
}
+
/*------------------------------------------------------------------------
* dns_bldq - Build a DNS Question and return the length of the packet
*------------------------------------------------------------------------
*/
-uint32 dns_bldq (
+int32 dns_bldq (
char *dname, /* Domain Name */
char *data /* Pointer to buffer for data */
)
@@ -111,7 +161,7 @@ uint32 dns_bldq (
for(i = 0; i < dlen; i++) {
if(qlen >= DNSDATASIZ) {
- return (uint32)SYSERR;
+ return SYSERR;
}
if(dname[i] != '.') {
/* Add normal character to the existing label */
@@ -152,9 +202,10 @@ uint32 dns_bldq (
* dns_geta - return the best IP address in the Answer Section
*------------------------------------------------------------------------
*/
-uint32 dns_geta (
+status dns_geta (
char *dname, /* Domain Name */
- struct dnspkt *rpkt /* Pointer to a response packet */
+ struct dnspkt *rpkt, /* Pointer to a response packet */
+ uint32 *addr /* Returned IP address */
)
{
uint16 qcount; /* Number of Questions */
@@ -173,7 +224,7 @@ uint32 dns_geta (
/* Skip qcount questions */
- for(i = 0; i < qcount; i++) {
+ for (i = 0; i < qcount; i++) {
/* Get the label length */
@@ -181,7 +232,7 @@ uint32 dns_geta (
/* While we haven't reached the end of this domain name */
- while(llen != 0) {
+ while (llen != 0) {
/* Pointer means end of name */
@@ -218,7 +269,7 @@ uint32 dns_geta (
/* Check each answer to see if it matches the local net */
- for(i = 0; i < acount; i++) {
+ for (i = 0; i < acount; i++) {
char rname[1024];
uint16 tmptype;
@@ -261,9 +312,10 @@ uint32 dns_geta (
}
if (ipaddr != 0) {
- return ipaddr;
+ *addr = ipaddr;
+ return OK;
} else {
- return (uint32)SYSERR;
+ return SYSERR;
}
}
diff --git a/net/dot2ip.c b/net/dot2ip.c
index 9598a89..066a966 100644
--- a/net/dot2ip.c
+++ b/net/dot2ip.c
@@ -6,7 +6,7 @@
* dot2ip - Convert a string of dotted decimal to an unsigned integer
*------------------------------------------------------------------------
*/
-uint32 dot2ip (
+status dot2ip (
char *dotted, /* IP address in dotted decimal */
uint32 *result /* Location to which binary IP */
/* address will be stored */
@@ -34,11 +34,12 @@ uint32 dot2ip (
}
}
- /* Too many digits or non-digit is an error */
+ /* Non-digit is an error */
- if ( (nch>=3) || (ch<'0') || (ch>'9') ) {
+ if ( (ch<'0') || (ch>'9') ) {
return SYSERR;
}
+
val = 10*val + (ch-'0');
}
@@ -51,7 +52,7 @@ uint32 dot2ip (
break;
}
}
- if ( (seg >= 4) || (ch != NULLCH) ) {
+ if ( (seg != 3) || (ch != NULLCH) ) {
return SYSERR;
}
*result = ipaddr;
diff --git a/net/hexdump.c b/net/hexdump.c
index e860c85..5ace25b 100644
--- a/net/hexdump.c
+++ b/net/hexdump.c
@@ -7,12 +7,12 @@
*------------------------------------------------------------------------
*/
void hexdump (
- char *p, int32 len /* ptr to packet and length of */
+ char *p, int32 len /* Ptr to packet and length of */
/* payload (IP datagram) */
)
{
- int32 i; /* counts bytes */
- int32 word; /* counts 32 bits words */
+ int32 i; /* Counts bytes */
+ int32 word; /* Counts 32 bits words */
for (i=0; i<6; i++) {
kprintf("%02x", 0xff & *p++);
@@ -53,11 +53,11 @@ void hexdump (
*------------------------------------------------------------------------
*/
void hexadump (
- char *p, int32 len /* ptr to packet and length of */
+ char *p, int32 len /* Ptr to packet and length of */
/* payload (IP datagram) */
)
{
- int32 i; /* counts bytes */
+ int32 i; /* Counts bytes */
for (i=0; i<6; i++) {
kprintf("%02x", 0xff & *p++);
diff --git a/net/icmp.c b/net/icmp.c
index 9bdd8dc..155461f 100644
--- a/net/icmp.c
+++ b/net/icmp.c
@@ -11,7 +11,7 @@ struct icmpentry icmptab[ICMP_SLOTS]; /* Table of processes using ping*/
*/
void icmp_init(void) {
- int32 i; /* table index */
+ int32 i; /* Table index */
for(i=0; i<ICMP_SLOTS; i++) {
icmptab[i].icstate = ICMP_FREE;
@@ -74,9 +74,19 @@ void icmp_in(
/* in incomming packet matches IP address in table */
icmptr = &icmptab[slot];
- if ( (icmptr->icstate == ICMP_FREE) ||
- (pkt->net_ipsrc != icmptr->icremip) ) {
- freebuf((char *)pkt); /* discard packet */
+ if (icmptr->icstate == ICMP_FREE) {
+ freebuf((char *)pkt);
+ restore(mask);
+ return;
+ }
+
+ /* Check address in incoming packet */
+
+ if ( (pkt->net_ipsrc != icmptr->icremip) &&
+ (pkt->net_ipsrc != NetData.ipucast) &&
+ ( (pkt->net_ipsrc&0x7f000000) !=
+ 0x7f000000 ) ) {
+ freebuf((char *)pkt);
restore(mask);
return;
}
@@ -227,7 +237,7 @@ status icmp_send (
uint16 type, /* ICMP type (req. or reply) */
uint16 ident, /* ICMP identifier value */
uint16 seq, /* ICMP sequence number */
- char *buf, /* pointer to data buffer */
+ char *buf, /* Pointer to data buffer */
int32 len /* Length of data in buffer */
)
{
@@ -265,7 +275,7 @@ struct netpacket *icmp_mkpkt (
int32 len /* Length of data in buffer */
)
{
- struct netpacket *pkt; /* pointer to packet buffer */
+ struct netpacket *pkt; /* Pointer to packet buffer */
static uint32 ipident=32767; /* IP ident field */
/* Allocate packet */
@@ -379,7 +389,7 @@ uint16 icmp_cksum (
/* If buffer lenght is odd, add last byte */
if ( (buflen & 0x01) !=0 ) {
- cksum += (uint32) (*((char *)sptr) << 8);
+ cksum += 0xFFFF & ((uint32) (*((byte *) sptr) << 8));
}
cksum += (cksum >> 16);
cksum = 0xffff & ~cksum;
diff --git a/net/ip.c b/net/ip.c
index 920a1f1..ed5d1a1 100644
--- a/net/ip.c
+++ b/net/ip.c
@@ -19,7 +19,7 @@ void ip_in(
/* Verify checksum */
if (ipcksum(pktptr) != 0) {
- kprintf("IP header checksum failed\n\r");
+ // kprintf("IP header checksum failed\n");
freebuf((char *)pktptr);
return;
}
@@ -31,7 +31,7 @@ void ip_in(
/* Ensure version and length are valid */
if (pktptr->net_ipvh != 0x45) {
- kprintf("IP version failed\n\r");
+ kprintf("IP version failed\n");
freebuf((char *)pktptr);
return;
}
@@ -382,7 +382,7 @@ process ipout(void)
destip = pktptr->net_ipdst;
- /* Sanity check: packets sent to ioout should *not* */
+ /* Sanity check: packets sent to ipout should *not* */
/* contain a broadcast address. */
if ((destip == IP_BCAST)||(destip == NetData.ipbcast)) {
diff --git a/net/pxe.c b/net/pxe.c
index c3482dd..2973b70 100644
--- a/net/pxe.c
+++ b/net/pxe.c
@@ -60,18 +60,18 @@ char* get_uuid(uint16* uuid_len)
int32 build_dhcp_discover_pxe(struct dhcpmsg* dmsg)
{
uint32 i,j;
- uint32 xid; /* xid used for the exchange */
+ uint32 xid; /* Xid used for the exchange */
- memcpy(&xid, NetData.ethucast, 4); /* use 4 bytes from MAC as XID */
+ memcpy(&xid, NetData.ethucast, 4);/* Use 4 bytes from MAC as XID */
memset(dmsg, 0x00, sizeof(struct dhcpmsg));
dmsg->dc_bop = 0x01; /* Outgoing request */
- dmsg->dc_htype = 0x01; /* hardware type is Ethernet */
- dmsg->dc_hlen = 0x06; /* hardware address length */
+ dmsg->dc_htype = 0x01; /* Hardware type is Ethernet */
+ dmsg->dc_hlen = 0x06; /* Hardware address length */
dmsg->dc_hops = 0x00; /* Hop count */
- dmsg->dc_xid = htonl(xid); /* xid (unique ID) */
- dmsg->dc_secs = 0x0000; /* seconds */
- dmsg->dc_flags = 0x0000; /* flags */
+ dmsg->dc_xid = htonl(xid); /* Xid (unique ID) */
+ dmsg->dc_secs = 0x0000; /* Seconds */
+ dmsg->dc_flags = 0x0000; /* Flags */
dmsg->dc_cip = 0x00000000; /* Client IP address */
dmsg->dc_yip = 0x00000000; /* Your IP address */
dmsg->dc_sip = 0x00000000; /* Server IP address */
@@ -91,47 +91,47 @@ int32 build_dhcp_discover_pxe(struct dhcpmsg* dmsg)
}
dmsg->dc_opt[j++] = 0xff & 97; /* Client UUID/GUID Type */
- dmsg->dc_opt[j++] = 0xff & (uuid_len + 1); /* option length */
+ dmsg->dc_opt[j++] = 0xff & (uuid_len + 1); /* Option length */
dmsg->dc_opt[j++] = 0xff & 0; /* UUID */
for(i = 0; i < uuid_len; i++) {
dmsg->dc_opt[j++] = 0xff & uuid[i];
}
dmsg->dc_opt[j++] = 0xff & 94; /* Client network type */
- dmsg->dc_opt[j++] = 0xff & 3; /* option length */
+ dmsg->dc_opt[j++] = 0xff & 3; /* Option length */
dmsg->dc_opt[j++] = 0xff & 1; /* Type = UNDI */
dmsg->dc_opt[j++] = 0xff & 1; /* UNDI Major ver */
dmsg->dc_opt[j++] = 0xff & 2; /* UNDI Minor ver */
dmsg->dc_opt[j++] = 0xff & 93; /* Client architecture */
- dmsg->dc_opt[j++] = 0xff & 2; /* option length */
+ dmsg->dc_opt[j++] = 0xff & 2; /* Option length */
dmsg->dc_opt[j++] = 0xff & 0; /* Arch - byte 1 */
dmsg->dc_opt[j++] = 0xff & 0; /* Arch - byte 2 */
dmsg->dc_opt[j++] = 0xff & 53; /* DHCP message type option */
- dmsg->dc_opt[j++] = 0xff & 1; /* option length */
- dmsg->dc_opt[j++] = 0xff & 1; /* DHCP Discover message */
+ dmsg->dc_opt[j++] = 0xff & 1; /* Option length */
+ dmsg->dc_opt[j++] = 0xff & 1; /* DHCP Discover message */
dmsg->dc_opt[j++] = 0xff & 0; /* Options padding */
dmsg->dc_opt[j++] = 0xff & 55; /* DHCP parameter request list */
- dmsg->dc_opt[j++] = 0xff & 4; /* option length */
- dmsg->dc_opt[j++] = 0xff & 1; /* request subnet mask */
- dmsg->dc_opt[j++] = 0xff & 3; /* request default router addr-> */
- dmsg->dc_opt[j++] = 0xff & 43; /* Vendor options */
- dmsg->dc_opt[j++] = 0xff & 60; /* Vendor class identifier */
- dmsg->dc_opt[j++] = 0xff & 66; /* request TFTP Server */
- dmsg->dc_opt[j++] = 0xff & 67; /* request Boot file */
+ dmsg->dc_opt[j++] = 0xff & 4; /* Option length */
+ dmsg->dc_opt[j++] = 0xff & 1; /* Request subnet mask */
+ dmsg->dc_opt[j++] = 0xff & 3; /* Request default router addr->*/
+ dmsg->dc_opt[j++] = 0xff & 43; /* Vendor options */
+ dmsg->dc_opt[j++] = 0xff & 60; /* Vendor class identifier */
+ dmsg->dc_opt[j++] = 0xff & 66; /* Request TFTP Server */
+ dmsg->dc_opt[j++] = 0xff & 67; /* Request Boot file */
- dmsg->dc_opt[j++] = 0xff & 60; /* DHCP PXE Support */
- dmsg->dc_opt[j++] = 0xff & 32; /* option length */
+ dmsg->dc_opt[j++] = 0xff & 60; /* DHCP PXE Support */
+ dmsg->dc_opt[j++] = 0xff & 32; /* Option length */
char* pxe_client_tmp = PXE_CLIENT_STRING;
for(i = 0; i < PXE_CLIENT_STRING_LEN; i++) {
dmsg->dc_opt[j++] = 0xff & pxe_client_tmp[i];
}
- dmsg->dc_opt[j++] = 0xff & 0; /* options padding */
- dmsg->dc_opt[j++] = 0xff & 0; /* options padding */
- dmsg->dc_opt[j++] = 0xff & 0; /* options padding */
+ dmsg->dc_opt[j++] = 0xff & 0; /* Options padding */
+ dmsg->dc_opt[j++] = 0xff & 0; /* Options padding */
+ dmsg->dc_opt[j++] = 0xff & 0; /* Options padding */
return (uint32)((char *)&dmsg->dc_opt[j] - (char *)dmsg + 1);
}
diff --git a/net/tftp.c b/net/tftp.c
index 1d4eeee..70e5f6e 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -4,10 +4,6 @@
#include <stdlib.h>
#include <string.h>
-/* Prototype for TFTP callback function */
-
-typedef status (*tftp_recv_cb) (uint16, char*, uint32, byte);
-
/*------------------------------------------------------------------------
*
* tftp_send1 - Internal function to send one outgoing request (RRQ or
@@ -18,14 +14,14 @@ typedef status (*tftp_recv_cb) (uint16, char*, uint32, byte);
*/
status tftp_send1 (
- int32 sock, /* UDP socket to use */
- uint32 remip, /* Remote IP address */
- uint16 *remport, /* Remote port to use/set */
- struct tftp_msg *msg, /* Pointer to outgoing message */
- int32 mlen, /* Size of ougoing message */
- struct tftp_msg *inmsg, /* Pointer to buffer for an */
+ int32 sock, /* UDP socket to use */
+ uint32 remip, /* Remote IP address */
+ uint16 *remport, /* Remote port to use/set */
+ struct tftp_msg *msg, /* Pointer to outgoing message */
+ int32 mlen, /* Size of ougoing message */
+ struct tftp_msg *inmsg, /* Pointer to buffer for an */
/* incoming message */
- uint16 expected /* Block number expected next */
+ uint16 expected /* Block number expected next */
)
{
int32 ret; /* Return value for udp_send */
@@ -37,7 +33,7 @@ status tftp_send1 (
/* ------------------------------------------------ */
/* | Opcode | Filename | 0 | Mode | 0 | */
/* ------------------------------------------------ */
-
+
/* TFTP ACK Packet */
/* 2 bytes 2 bytes */
/* --------------------- */
@@ -45,7 +41,7 @@ status tftp_send1 (
/* --------------------- */
/* Send the outgoing message */
-
+
ret = udp_sendto(sock, remip, *remport, (char *) msg, mlen);
if (ret == SYSERR) {
@@ -74,7 +70,7 @@ status tftp_send1 (
}
/* If Error came back, give up */
-
+
if (ntohs(inmsg->tf_opcode) == TFTP_ERROR) {
kprintf("\n[tftp_send1] TFTP Error %d, %s\n",
ntohs(inmsg->tf_ercode),
@@ -94,19 +90,38 @@ status tftp_send1 (
}
}
+
/*------------------------------------------------------------------------
*
- * tftpget - Retrieve a file using TFTP
+ * tftpget - Use TFTP to download a specified file from a server
*
*------------------------------------------------------------------------
*/
status tftpget(
- uint32 serverip, /* IP address of server */
- const char* filename, /* Name of the file to download */
- void* user_ptr, /* User supplied buffer or */
- /* function pointer */
- uint32 user_len /* Size of buffer or special */
- /* value for function */
+ uint32 serverip, /* IP address of server */
+ const char* filename, /* Name of the file to download */
+ char* rcv_buf, /* Buffer to hold the file */
+ uint32 rcv_buf_size, /* Size of the buffer */
+ byte verbose /* Verbosity level */
+ )
+{
+ return tftpget_mb(serverip, filename, &rcv_buf, &rcv_buf_size, 1,
+ verbose);
+}
+
+/*------------------------------------------------------------------------
+ *
+ * tftpget_mb - multibuffer version of TFPT
+ *
+ *------------------------------------------------------------------------
+ */
+status tftpget_mb(
+ uint32 serverip, /* IP address of server */
+ const char* filename, /* Name of the file to download */
+ char** rcv_bufs, /* Buffer to hold the file */
+ uint32* rcv_buf_sizes, /* Size of each buffer */
+ uint32 rcv_buf_count, /* Number of buffers */
+ byte verbose /* Verbosity level */
)
{
int32 nlen; /* Length of file name */
@@ -122,26 +137,43 @@ status tftpget(
int32 mlen; /* Length of outgoing mesage */
struct tftp_msg inmsg; /* Buffer for response message */
int32 dlen; /* Size of data in a response */
- char* bptr; /* Current user buff position */
- byte lastpkt; /* Indicator of last packet */
+ char* curr_buf; /* Current buffer being used */
+ uint32 curr_buf_ind; /* Index of current buffer */
+ uint32 curr_used; /* Amount used in buffer */
/* Check args */
-
- if(filename == NULL || serverip == 0 ||
- user_ptr == NULL || user_len == 0) {
+
+ if(filename == NULL || serverip == 0 || rcv_bufs == NULL ||
+ rcv_buf_sizes == NULL || rcv_buf_count == 0) {
kprintf("[TFTP GET] ERROR: Invalid argument\n");
return SYSERR;
}
+ for(i = 0; i < rcv_buf_count; i++) {
+ if(rcv_bufs[i] == NULL || rcv_buf_sizes[i] == 0) {
+ kprintf("[TFTP GET] ERROR: Invalid argument\n");
+ return SYSERR;
+ }
+ }
nlen = strnlen(filename, TFTP_MAXNAM+1);
if ( (nlen <= 0) || (nlen > TFTP_MAXNAM) ) {
return SYSERR;
}
+
+ if(verbose & TFTP_VERBOSE) {
+ kprintf("[TFTP Get] Server: %08X File: %s\n",
+ serverip, filename);
+ }
/* Generate a local port */
localport = getport();
+ if (verbose & TFTP_VERBOSE) {
+ kprintf("[TFTP Get] Using local port %u\n",
+ 0xffff & localport);
+ }
+
/* Register a UDP socket */
sock = udp_register(serverip, 0, localport);
@@ -157,8 +189,9 @@ status tftpget(
/* Initialize the total file size to zero */
filesiz = 0;
- bptr = (char*)user_ptr;
- lastpkt = FALSE;
+ curr_buf_ind = 0;
+ curr_buf = (char*)rcv_bufs[curr_buf_ind];
+ curr_used = 0;
/* Form the first message and compute length (a Read Request) */
@@ -176,79 +209,81 @@ status tftpget(
/* retransmitting a request up to TFTP_MAXRETRIES times */
while(1) {
- for (i=0; i < TFTP_MAXRETRIES; i++) {
- n = tftp_send1(sock, serverip, &remport, &outmsg,
- mlen, &inmsg, expected);
- if (n > 0) {
- break;
- } else if (n == SYSERR) {
- kprintf("\n[TFTP Get] ERROR: TFTP Send "
- "fails\n");
- udp_release(sock);
- return SYSERR;
- } else if (n == TIMEOUT) {
- continue;
-
- }
- }
- if (i >= TFTP_MAXRETRIES) {
- kprintf("\n[TFTP Get] ERROR: Max retries %d "
- "exceeded\n", TFTP_MAXRETRIES);
+ for (i=0; i < TFTP_MAXRETRIES; i++) {
+ n = tftp_send1(sock, serverip, &remport, &outmsg, mlen,
+ &inmsg, expected);
+ if (n > 0) {
+ break;
+ } else if (n == SYSERR) {
+ kprintf("\n[TFTP Get] ERROR: TFTP Send fails\n");
udp_release(sock);
return SYSERR;
- }
-
- /* Compute size of data in the message */
-
- dlen = n - sizeof(inmsg.tf_opcode) -
- sizeof(inmsg.tf_dblk);
+ } else if (n == TIMEOUT) {
+ continue;
- if(dlen < 512) {
- lastpkt = TRUE;
}
+ }
+ if (i >= TFTP_MAXRETRIES) {
+ kprintf("\n[TFTP Get] ERROR: Max retries %d exceeded\n",
+ TFTP_MAXRETRIES);
+ udp_release(sock);
+ return SYSERR;
+ }
+
+ if(verbose & TFTP_VERBOSE) {
+ kprintf(".");
+ }
- /* Move the contents of this block into the file buffer */
+ /* Compute size of data in the message */
- for (i=0; i<dlen; i++) {
- if (user_len != TFTP_FUNC_MAGIC &&
- filesiz < user_len) {
- *bptr++ = inmsg.tf_data[i];
- }
- filesiz++;
- }
-
- /* Call the user supplied function */
+ dlen = n - sizeof(inmsg.tf_opcode) - sizeof(inmsg.tf_dblk);
- if(user_len == TFTP_FUNC_MAGIC) {
- ((tftp_recv_cb)user_ptr)(ntohs(inmsg.tf_dblk),
- inmsg.tf_data, dlen, lastpkt);
+ /* Move the contents of this block into the file buffer */
+ for (i=0; i<dlen; i++) {
+ if (curr_used >= rcv_buf_sizes[curr_buf_ind]) {
+ curr_buf_ind++;
+ if(curr_buf_ind >= rcv_buf_count) {
+ udp_release(sock);
+ if(verbose & TFTP_VERBOSE) {
+ kprintf("\n");
+ }
+ return filesiz;
+ }
+ curr_buf = (char*)rcv_bufs[curr_buf_ind];
+ curr_used = 0;
}
+ *curr_buf++ = inmsg.tf_data[i];
+ curr_used++;
+ filesiz++;
+ }
- /* Form an ACK */
+ /* Form an ACK */
- outmsg.tf_opcode = htons(TFTP_ACK);
- outmsg.tf_ablk = htons(expected);
- mlen = sizeof(outmsg.tf_opcode) + sizeof(outmsg.tf_ablk);
+ outmsg.tf_opcode = htons(TFTP_ACK);
+ outmsg.tf_ablk = htons(expected);
+ mlen = sizeof(outmsg.tf_opcode) + sizeof(outmsg.tf_ablk);
- /* If this was the last packet, send final ACK */
+ /* If this was the last packet, send final ACK */
- if (lastpkt) {
- ret = udp_sendto(sock, serverip, remport,
+ if (dlen < 512) {
+ ret = udp_sendto(sock, serverip, remport,
(char *) &outmsg, mlen);
- udp_release(sock);
-
- if (ret == SYSERR) {
- kprintf("\n[TFTP GET] Error on final "
- "ack\n");
- return SYSERR;
- }
-
- return filesiz;
+ udp_release(sock);
+
+ if(verbose & TFTP_VERBOSE) {
+ kprintf("\n");
+ }
+
+ if (ret == SYSERR) {
+ kprintf("\n[TFTP GET] Error on final ack\n");
+ return SYSERR;
}
+ return filesiz;
+ }
- /* Move to next block and continue */
+ /* Move to next block and continue */
- expected++;
+ expected++;
}
}
diff --git a/net/udp.c b/net/udp.c
index e1ccb1d..452dc2a 100644
--- a/net/udp.c
+++ b/net/udp.c
@@ -389,7 +389,7 @@ status udp_send (
pkt->net_ipfrag = 0x0000; /* IP flags & fragment offset */
pkt->net_ipttl = 0xff; /* IP time-to-live */
pkt->net_ipproto = IP_UDP; /* Datagram carries UDP */
- pkt->net_ipcksum = 0x0000; /* initial checksum */
+ pkt->net_ipcksum = 0x0000; /* Initial checksum */
pkt->net_ipsrc = locip; /* IP source address */
pkt->net_ipdst = remip; /* IP destination address */
@@ -398,9 +398,7 @@ status udp_send (
pkt->net_udplen = (uint16)(UDP_HDR_LEN+len); /* UDP length */
pkt->net_udpcksum = 0x0000; /* Ignore UDP checksum */
udataptr = (char *) pkt->net_udpdata;
- for (; len>0; len--) {
- *udataptr++ = *buff++;
- }
+ memcpy(udataptr, buff, len);
/* Call ipsend to send the datagram */
@@ -483,9 +481,7 @@ status udp_sendto (
pkt->net_udplen = (uint16)(UDP_HDR_LEN+len); /* UDP length */
pkt->net_udpcksum = 0x0000; /* Ignore UDP checksum */
udataptr = (char *) pkt->net_udpdata;
- for (; len>0; len--) {
- *udataptr++ = *buff++;
- }
+ memcpy(udataptr, buff, len);
/* Call ipsend to send the datagram */
@@ -505,7 +501,7 @@ status udp_release (
{
intmask mask; /* Saved interrupt mask */
struct udpentry *udptr; /* Pointer to udptab entry */
- struct netpacket *pkt; /* pointer to packet being read */
+ struct netpacket *pkt; /* Pointer to packet being read */
/* Ensure only one process can access the UDP table at a time */
diff --git a/shell/Notes_On_Pipes b/shell/Notes_On_Pipes
new file mode 100644
index 0000000..09dd4a0
--- /dev/null
+++ b/shell/Notes_On_Pipes
@@ -0,0 +1,74 @@
+This directory holds Xinu sources for the Beaglebone Black.
+
+==========================================================================================
+
+The code contains a PIPE mechanism and a shell that allows a pipeline of commands.
+
+
+ **** ***** **** ***** ****
+ * * * * * * *
+ **** * **** **** ***
+ * * * * *
+ * ***** * ***** ****
+
+
+==========================================================================================
+
+Assumptions
+
+ A given pipe only has 1 writer and 1 reader. When it finishes depositing data in
+ the pipe, the writer closes the pipe. After the reader consumes all the
+ data, subsequent reads return EOF.
+
+ A pipe will be closed twice: once when writer finishes sending data and once when
+ the reader exits. After the first close, a reader can still read to EOF.
+
+ Pipes will be used in the shell, so processes will have pipes as stdin or stdout.
+ If a process is killed, stdin and stdout will be colosed, so if the process
+ is uing pipe(s) the pipes will be closed.
+
+ Normally, a writer closes the pipe first, but a reader may close a pipe early if
+ the process is killed or encounters a condition that cause it to exit
+ before reading all the data in the pipe. Subsequent attempts to write to
+ the pipe will fail (the call will return SYSERR). If the writer ignores
+ the return code, the writer can continue making calls to write data until
+ it exhausts all the output and calls close, at which time the pipe will
+ be deallocated.
+
+Pipe devices
+
+ The system contains a main pipe device (PIPE) and a set of pipe pseudo-devices
+ (PIPE1, PIPE2, PIPE3...). The PIPE device only supports open; the opening
+ the PIPE device allocates a free pseudo device and returns the descriptor.
+ A pseudo device supports read, write, and close.
+
+==========================================================================================
+
+Shell algorithm
+
+ 1. Get an input line and use lexan to divide it into tokens.
+
+ 2. Divide tokens into segments separated by the pipe symbol, and set each segment input
+ and output devices to the device the shell is using (presumably, CONSOLE).
+
+ 3. Check for background (& as the last token) and remove the token.
+
+ 4. Check for input redirection on the first segment and output redirection on the last
+ segment, and remember the names of the input and output files, if any.
+
+ 5. Look up the command name in each segment.
+
+6. Open the redirected input and output files, if any, and record the device ID as the
+ first segment input device or the last segment output device.
+
+ 7. Create N-1 pipes for N segments, and record the device ID as the output device for
+ segment i and the input device for segment i+1.
+
+ 8. Create a process to run each segment and add arguments.
+
+ 9. If running in foreground, wait for the last process to exit (a message arrives with
+ the process ID of the last process in the pipeline).
+
+10. Continue with the main loop that reads the next input line.
+
+==========================================================================================
diff --git a/shell/addargs.c b/shell/addargs.c
index ba3b7f1..24a26a1 100644
--- a/shell/addargs.c
+++ b/shell/addargs.c
@@ -11,8 +11,7 @@
status addargs(
pid32 pid, /* ID of process to use */
int32 ntok, /* Count of arguments */
- int32 tok[], /* Index of tokens in tokbuf */
- int32 tlen, /* Length of data in tokbuf */
+ int32 tok[], /* Array of token indices */
char *tokbuf, /* Array of null-term. tokens */
void *dummy /* Dummy argument that was */
/* used at creation and must */
@@ -28,16 +27,19 @@ status addargs(
/* to place args vector */
char *argstr; /* Location in process's stack */
/* to place arg strings */
- uint32 *search; /* pointer that searches for */
+ uint32 *search; /* Pointer that searches for */
/* dummy argument on stack */
uint32 *aptr; /* Walks through args array */
int32 i; /* Index into tok array */
+ int32 len; /* Length of argument strings */
+ char *first, *last; /* Address of first and last */
+ /* tokens in tokbuf */
mask = disable();
/* Check argument count and data length */
- if ( (ntok <= 0) || (tlen < 0) ) {
+ if (ntok <= 0) {
restore(mask);
return SYSERR;
}
@@ -50,7 +52,7 @@ status addargs(
aloc = (uint32) (prptr->prstkbase
- prptr->prstklen + sizeof(uint32));
- argloc = (uint32*) ((aloc + 3) & ~0x3); /* round multiple of 4 */
+ argloc = (uint32*) ((aloc + 3) & ~0x3); /* Round to mult. of 4 */
/* Compute the first location beyond args array for the strings */
@@ -60,7 +62,7 @@ status addargs(
/* string area plus the offset of this argument */
for (aptr=argloc, i=0; i < ntok; i++) {
- *aptr++ = (uint32) (argstr + tok[i]);
+ *aptr++ = (uint32) (argstr + tok[i]-tok[0]);
}
/* Add a null pointer to the args array */
@@ -70,7 +72,11 @@ status addargs(
/* Copy the argument strings from tokbuf into process's stack */
/* just beyond the args vector */
- memcpy(aptr, tokbuf, tlen);
+ first = &tokbuf[tok[0]];
+ last = &tokbuf[tok[ntok-1]];
+ len = last - first + strlen(last) + 1;
+
+ memcpy(aptr, first, len);
/* Find the second argument in process's stack */
diff --git a/shell/lexan.c b/shell/lexan.c
index 4e0cb8b..ad4c56d 100644
--- a/shell/lexan.c
+++ b/shell/lexan.c
@@ -15,8 +15,6 @@ int32 lexan (
char *tokbuf, /* Buffer into which tokens are */
/* stored with a null */
/* following each token */
- int32 *tlen, /* Place to store number of */
- /* chars in tokbuf */
int32 tok[], /* Array of pointers to the */
/* start of each token */
int32 toktyp[] /* Array that gives the type */
@@ -46,7 +44,7 @@ int32 lexan (
return SYSERR;
}
- /* Skip whitespace before token */
+ /* Skip white space before token */
while ( (*p == SH_BLANK) || (*p == SH_TAB) ) {
p++;
@@ -56,14 +54,13 @@ int32 lexan (
ch = *p;
if ( (ch==SH_NEWLINE) || (ch==NULLCH) ) {
- *tlen = tbindex;
return ntok;
}
/* Set next entry in tok array to be an index to the */
/* current location in the token buffer */
- tok[ntok] = tbindex; /* the start of the token */
+ tok[ntok] = tbindex; /* The start of the token */
/* Set the token type */
@@ -76,6 +73,13 @@ int32 lexan (
p++;
continue;
+ case SH_PIPE: toktyp[ntok] = SH_TOK_PIPE;
+ tokbuf[tbindex++] = ch;
+ tokbuf[tbindex++] = NULLCH;
+ ntok++;
+ p++;
+ continue;
+
case SH_LESS: toktyp[ntok] = SH_TOK_LESS;
tokbuf[tbindex++] = ch;
tokbuf[tbindex++] = NULLCH;
@@ -96,7 +100,7 @@ int32 lexan (
/* Handle quoted string (single or double quote) */
if ( (ch==SH_SQUOTE) || (ch==SH_DQUOTE) ) {
- quote = ch; /* remember opening quote */
+ quote = ch; /* Remember opening quote */
/* Copy quoted string to arg area */
@@ -106,27 +110,27 @@ int32 lexan (
&& (ch != NULLCH) ) {
tokbuf[tbindex++] = ch;
}
- if (ch != quote) { /* string missing end quote */
+ if (ch != quote) { /* String missing end quote */
return SYSERR;
}
/* Finished string - count token and go on */
- tokbuf[tbindex++] = NULLCH; /* terminate token */
- ntok++; /* count string as one token */
- continue; /* go to next token */
+ tokbuf[tbindex++] = NULLCH; /* Terminate token */
+ ntok++; /* Count string as one token */
+ continue; /* Go to next token */
}
/* Handle a token other than a quoted string */
- tokbuf[tbindex++] = ch; /* put first character in buffer*/
+ tokbuf[tbindex++] = ch; /* Put first character in buffer*/
p++;
while ( ((ch = *p) != SH_NEWLINE) && (ch != NULLCH)
&& (ch != SH_LESS) && (ch != SH_GREATER)
&& (ch != SH_BLANK) && (ch != SH_TAB)
&& (ch != SH_AMPER) && (ch != SH_SQUOTE)
- && (ch != SH_DQUOTE) ) {
+ && (ch != SH_DQUOTE)&& (ch != SH_PIPE)) {
tokbuf[tbindex++] = ch;
p++;
}
@@ -138,11 +142,10 @@ int32 lexan (
return SYSERR;
}
- tokbuf[tbindex++] = NULLCH; /* terminate the token */
+ tokbuf[tbindex++] = NULLCH; /* Terminate the token */
- ntok++; /* count valid token */
+ ntok++; /* Count valid token */
}
- *tlen = tbindex;
return ntok;
}
diff --git a/shell/shell.c b/shell/shell.c
index c5b076d..97eb315 100644
--- a/shell/shell.c
+++ b/shell/shell.c
@@ -8,46 +8,72 @@
/* Table of Xinu shell commands and the function associated with each */
/************************************************************************/
const struct cmdent cmdtab[] = {
- {"argecho", TRUE, xsh_argecho},
- {"arp", FALSE, xsh_arp},
- {"cat", FALSE, xsh_cat},
- {"clear", TRUE, xsh_clear},
- {"date", FALSE, xsh_date},
- {"devdump", FALSE, xsh_devdump},
- {"echo", FALSE, xsh_echo},
- {"exit", TRUE, xsh_exit},
- {"help", FALSE, xsh_help},
- {"kill", TRUE, xsh_kill},
- {"memdump", FALSE, xsh_memdump},
- {"memstat", FALSE, xsh_memstat},
- {"netinfo", FALSE, xsh_netinfo},
- {"ping", FALSE, xsh_ping},
- {"ps", FALSE, xsh_ps},
- {"sleep", FALSE, xsh_sleep},
- {"udp", FALSE, xsh_udpdump},
- {"udpecho", FALSE, xsh_udpecho},
- {"udpeserver", FALSE, xsh_udpeserver},
- {"uptime", FALSE, xsh_uptime},
- {"?", FALSE, xsh_help}
+ {"argecho", xsh_argecho},
+ {"arp", xsh_arp},
+ {"cat", xsh_cat},
+ {"clear", xsh_clear},
+ {"date", xsh_date},
+ {"devdump", xsh_devdump},
+ {"echo", xsh_echo},
+ {"help", xsh_help},
+ {"ls" , xsh_ls},
+ {"kill", xsh_kill},
+ {"memdump", xsh_memdump},
+ {"memstat", xsh_memstat},
+ {"ns", xsh_ns},
+ {"netinfo", xsh_netinfo},
+ {"ping", xsh_ping},
+ {"ps", xsh_ps},
+ {"sleep", xsh_sleep},
+ {"tee", xsh_tee},
+ {"udp", xsh_udpdump},
+ {"udpecho", xsh_udpecho},
+ {"udpeserver", xsh_udpeserver},
+ {"uptime", xsh_uptime},
+ {"?", xsh_help}
};
uint32 ncmd = sizeof(cmdtab) / sizeof(struct cmdent);
+
+/************************************************************************/
+/* */
+/* cmdlookup -- return the index in cmdtab of a command name */
+/* */
+/************************************************************************/
+
+int32 cmdlookup(char *name) {
+ int32 indx; /* Index into cmdtab */
+ int32 len; /* Length of command name */
+
+ for (indx=0; indx < ncmd; indx++) {
+ len = strlen(cmdtab[indx].cname);
+ if ( strncmp(name,cmdtab[indx].cname, len) == 0 ) {
+ return indx;
+ }
+ }
+ return SYSERR;
+}
+
+
/************************************************************************/
/* shell - Provide an interactive user interface that executes */
-/* commands. Each command begins with a command name, has */
-/* a set of optional arguments, has optional input or */
-/* output redirection, and an optional specification for */
-/* background execution (ampersand). The syntax is: */
+/* commands. An input line contains one or more segments */
+/* separated by a pipe symbol '|'. Each segment begins with */
+/* a command name, and has a set of optional arguments, The */
+/* last segment in a pipeline can have output redirected. */
+/* The entire pipeline can be run in background by ending the */
+/* line with an ampersand, "&". The syntax is: */
+/* */
+/* seg [ pipe seg ]* [ out_redir ] [ & ] */
+/* where: */
/* */
-/* command_name [args*] [redirection] [&] */
+/* pipe is | */
/* */
-/* Redirection is either or both of: */
+/* seg is command_name [args*] */
/* */
-/* < input_file */
-/* or */
-/* > output_file */
+/* out_redir is > output_file */
/* */
/************************************************************************/
@@ -59,33 +85,47 @@ process shell (
/* one line from a tty device */
int32 len; /* Length of line read */
char tokbuf[SHELL_BUFLEN + /* Buffer to hold a set of */
- SHELL_MAXTOK]; /* Contiguous null-terminated */
- /* Strings of tokens */
- int32 tlen; /* Current length of all data */
- /* in array tokbuf */
+ SHELL_MAXTOK]; /* contiguous null-terminated */
+ /* strings of tokens */
int32 tok[SHELL_MAXTOK]; /* Index of each token in */
/* array tokbuf */
int32 toktyp[SHELL_MAXTOK]; /* Type of each token in tokbuf */
int32 ntok; /* Number of tokens on line */
- pid32 child; /* Process ID of spawned child */
bool8 backgnd; /* Run command in background? */
- char *outname, *inname; /* Pointers to strings for file */
- /* names that follow > and < */
- did32 stdinput, stdoutput; /* Descriptors for redirected */
- /* input and output */
+ char *inname; /* File name for input re- */
+ /* direction on first segment */
+ did32 indesc; /* Descriptor for redirected */
+ /* input */
+ char *outname; /* File name for output re- */
+ /* direction on last segment */
+ did32 outdesc; /* Descriptor for redirected */
+ /* output */
+ int32 nsegs; /* Number of segments found */
+ struct segent { /* One segment of the pipeline */
+ int32 sstart; /* Starting token index */
+ int32 send; /* Ending token index */
+ int32 scindex; /* Index in cmdtab of the */
+ /* command in this segment */
+ did32 soutdev; /* Output device (pipe, except */
+ /* for first segment) */
+ did32 sindev; /* Input device (pipe, except */
+ /* for the last segment) */
+ pid32 spid; /* Process ID for this segment */
+ };
+ struct segent segtab[SHELL_MAXTOK];/* One entry per segment */
+ struct segent *segptr; /* Pointer to a segtab entry */
+ int32 seg; /* Index into segtab */
+ int32 cindex; /* Index of command returned */
+ /* by cmdlookup */
+ did32 pipedev; /* Device ID of a pipe device */
int32 i; /* Index into array of tokens */
- int32 j; /* Index into array of commands */
+ char *p; /* Pointer to cmd name */
+ bool8 err; /* Did an error occur? */
int32 msg; /* Message from receive() for */
/* child termination */
- int32 tmparg; /* Address of this var is used */
- /* when first creating child */
- /* process, but is replaced */
- char *src, *cmp; /* Pointers used during name */
- /* comparison */
- bool8 diff; /* Was difference found during */
- /* comparison */
- char *args[SHELL_MAXTOK]; /* Argument vector passed to */
- /* builtin commands */
+ int32 tmparg; /* Temporary address used when */
+ /* creating a child process; */
+ /* later replaced by addargs */
/* Print shell banner and startup message */
@@ -113,17 +153,23 @@ process shell (
break;
}
+ /* If line only contains 'exit', exit gracefully */
+
+ if ( (len==5) && (strncmp(buf,"exit\n", 5)==0) ) {
+ break;
+ }
+
/* If line contains only NEWLINE, go to next line */
if (len <= 1) {
continue;
}
- buf[len] = SH_NEWLINE; /* terminate line */
+ buf[len] = SH_NEWLINE; /* Terminate line */
/* Parse input line and divide into tokens */
- ntok = lexan(buf, len, tokbuf, &tlen, tok, toktyp);
+ ntok = lexan(buf, len, tokbuf, tok, toktyp);
/* Handle parsing error */
@@ -139,172 +185,262 @@ process shell (
continue;
}
- /* If last token is '&', set background */
+ /* Set default input for first segment and output for */
+ /* last segment to the device used to call the shell */
- if (toktyp[ntok-1] == SH_TOK_AMPER) {
- ntok-- ;
- tlen-= 2;
- backgnd = TRUE;
- } else {
+ /* See if the last token is '&', and set background */
+
+ if (toktyp[ntok-1] != SH_TOK_AMPER) {
backgnd = FALSE;
+ } else {
+ backgnd = TRUE;
+ ntok-- ;
+ if (ntok == 0 ) {
+ fprintf(dev, "\n");
+ continue;
+ }
}
+ /* Use the pipe tokens to divide the pipeline into */
+ /* segments by placing the index of pipe tokens in */
+ /* successive locations of array segtab. */
- /* Check for input/output redirection (default is none) */
+ nsegs = 0;
+ segptr = &segtab[nsegs];
+ segptr->sstart = 0;
+ for (i=0; i<ntok; i++) {
- outname = inname = NULL;
- if ( (ntok >=3) && ( (toktyp[ntok-2] == SH_TOK_LESS)
- ||(toktyp[ntok-2] == SH_TOK_GREATER))){
- if (toktyp[ntok-1] != SH_TOK_OTHER) {
- fprintf(dev,"%s\n", SHELL_SYNERRMSG);
- continue;
- }
- if (toktyp[ntok-2] == SH_TOK_LESS) {
- inname = &tokbuf[tok[ntok-1]];
- } else {
- outname = &tokbuf[tok[ntok-1]];
- }
- ntok -= 2;
- tlen = tok[ntok];
- }
+ /* Check for pipe at end of segment */
+ if (toktyp[i] == SH_TOK_PIPE) {
- if ( (ntok >=3) && ( (toktyp[ntok-2] == SH_TOK_LESS)
- ||(toktyp[ntok-2] == SH_TOK_GREATER))){
- if (toktyp[ntok-1] != SH_TOK_OTHER) {
- fprintf(dev,"%s\n", SHELL_SYNERRMSG);
- continue;
- }
- if (toktyp[ntok-2] == SH_TOK_LESS) {
- if (inname != NULL) {
- fprintf(dev,"%s\n", SHELL_SYNERRMSG);
- continue;
- }
- inname = &tokbuf[tok[ntok-1]];
- } else {
- if (outname != NULL) {
+ /* Finish old segment and start new */
+
+ segptr->send = i - 1;
+
+ /* Check for empty segment */
+
+ if (segptr->sstart > segptr->send) {
fprintf(dev,"%s\n", SHELL_SYNERRMSG);
- continue;
+ break;
}
- outname = &tokbuf[tok[ntok-1]];
+ /* Move to new segment */
+ nsegs++;
+ segptr = &segtab[nsegs];
+ segptr->sstart = i+1;
}
- ntok -= 2;
- tlen = tok[ntok];
+ }
+ if (i < ntok) {
+ /* Error occurred, so go to next input */
+ continue;
}
- /* Verify remaining tokens are type "other" */
+ /* Fill in remaining details for last segment */
- for (i=0; i<ntok; i++) {
- if (toktyp[i] != SH_TOK_OTHER) {
- break;
- }
- }
- if ((ntok == 0) || (i < ntok)) {
- fprintf(dev, SHELL_SYNERRMSG);
+ segptr->send = ntok - 1;
+ if (segptr->sstart > segptr->send) {
+ fprintf(dev,"%s\n", SHELL_SYNERRMSG);
continue;
}
+ nsegs++;
- stdinput = stdoutput = dev;
-
- /* Lookup first token in the command table */
+ /* Check for output redirection on last segment */
- for (j = 0; j < ncmd; j++) {
- src = cmdtab[j].cname;
- cmp = tokbuf;
- diff = FALSE;
- while (*src != NULLCH) {
- if (*cmp != *src) {
- diff = TRUE;
- break;
- }
- src++;
- cmp++;
- }
- if (diff || (*cmp != NULLCH)) {
+ segptr = &segtab[nsegs - 1];
+ outname = NULL;
+ if ( ((segptr->send-segptr->sstart) > 1) &&
+ (toktyp[segptr->send-1] == SH_TOK_GREATER) ) {
+ if (toktyp[segptr->send] != SH_TOK_OTHER) {
+ fprintf(dev,"%s\n", SHELL_SYNERRMSG);
continue;
- } else {
- break;
}
+ outname = &tokbuf[tok[segptr->send]];
+ segptr->send -= 2;
}
- /* Handle command not found */
-
- if (j >= ncmd) {
- fprintf(dev, "command %s not found\n", tokbuf);
- continue;
- }
- /* Handle built-in command */
+ /* Check for input redirection on first segment */
- if (cmdtab[j].cbuiltin) { /* No background or redirect. */
- if (inname != NULL || outname != NULL || backgnd){
- fprintf(dev, SHELL_BGERRMSG);
+ segptr = &segtab[0];
+ inname = NULL;
+ if ( ((segptr->send-segptr->sstart) > 1) &&
+ (toktyp[segptr->send-1] == SH_TOK_LESS) ) {
+ if (toktyp[segptr->send] != SH_TOK_OTHER) {
+ fprintf(dev,"%s\n", SHELL_SYNERRMSG);
continue;
- } else {
- /* Set up arg vector for call */
+ }
+ inname = &tokbuf[tok[segptr->send]];
+ segptr->send -= 2;
+ }
- for (i=0; i<ntok; i++) {
- args[i] = &tokbuf[tok[i]];
- }
- /* Call builtin shell function */
+ /* Check that all tokens in each segment are "other" */
- if ((*cmdtab[j].cfunc)(ntok, args)
- == SHELL_EXIT) {
- break;
- }
+ err = FALSE;
+ for (seg = 0; seg < nsegs; seg++) {
+ segptr = &segtab[seg];
+ for (i=segptr->sstart; i<= segptr->send; i++) {
+ if (toktyp[i] != SH_TOK_OTHER) {
+ fprintf(dev,"%s\n", SHELL_SYNERRMSG);
+ err = TRUE;
+ break;
+ }
+ }
+ if (err) {
+ break;
}
+ }
+ if (err) {
+ continue;
+ }
+
+ /* For each command, look up the name of the command */
+
+ for (seg = 0; seg< nsegs; seg++) {
+ segptr = &segtab[seg];
+ p = &tokbuf[tok[segptr->sstart]];
+ cindex = cmdlookup(p);
+ if (cindex == SYSERR) {
+ fprintf(dev, "command %s not found\n", p);
+ break;
+ }
+ segptr->scindex = cindex;
+ }
+ if (seg < nsegs) {
+ /* Error occurred, so go to next input */
continue;
}
- /* Open files and redirect I/O if specified */
+
+ /* Open files for redirected input and output */
+
+ indesc = outdesc = dev;
if (inname != NULL) {
- stdinput = open(NAMESPACE,inname,"ro");
- if (stdinput == SYSERR) {
+ indesc = open(NAMESPACE,inname,"ro");
+ if (indesc == SYSERR) {
fprintf(dev, SHELL_INERRMSG, inname);
continue;
}
}
+ segtab[0].sindev = indesc;
+
if (outname != NULL) {
- stdoutput = open(NAMESPACE,outname,"w");
- if (stdoutput == SYSERR) {
+ outdesc = open(NAMESPACE,outname,"w");
+ if (outdesc == SYSERR) {
fprintf(dev, SHELL_OUTERRMSG, outname);
+
+ /* Close input file if it was opened */
+ if (indesc != dev) {
+ close(indesc);
+ }
+
continue;
- } else {
- control(stdoutput, F_CTL_TRUNC, 0, 0);
}
+ control(outdesc, F_CTL_TRUNC, 0, 0);
}
+ segtab[nsegs-1].soutdev = outdesc;
- /* Spawn child thread for non-built-in commands */
+ /* Create nsegs-1 pipes (to go "between" the segments) */
- child = create(cmdtab[j].cfunc,
- SHELL_CMDSTK, SHELL_CMDPRIO,
- cmdtab[j].cname, 2, ntok, &tmparg);
+ err = FALSE;
+ for (seg = 0; seg < nsegs - 1; seg++) {
+ segptr = &segtab[seg];
+ pipedev = open(PIPE,NULLSTR,"rw");
+ if (pipedev == SYSERR) {
+ err = TRUE;
+ fprintf(dev,"Pipe open failed\n");
+ break;
+ }
+ segptr->soutdev = pipedev;
+ segtab[seg+1].sindev= pipedev;
+ }
+ if (err) {
+ /* Close previously opened pipes */
+ for(seg--; seg >= 0; seg--) {
+ close(segtab[seg].soutdev);
+ }
+
+ /* Close previously opened infile */
+ if (indesc != dev) {
+ close(indesc);
+ }
- /* If creation or argument copy fails, report error */
+ /* Close previously opened outfile */
+ if (outdesc != dev) {
+ close(outdesc);
+ }
- if ((child == SYSERR) ||
- (addargs(child, ntok, tok, tlen, tokbuf, &tmparg)
- == SYSERR) ) {
- fprintf(dev, SHELL_CREATMSG);
continue;
}
- /* Set stdinput and stdoutput in child to redirect I/O */
+ /* Spawn a process for each segment */
+
+
+ int32 ntokens;
+
+ err = FALSE;
+ for (seg = 0; (seg<nsegs) && !err; seg++) {
+ segptr = &segtab[seg];
+ ntokens = segptr->send - segptr->sstart +1;
+ segptr->spid = create(cmdtab[segptr->scindex].cfunc,
+ SHELL_CMDSTK, SHELL_CMDPRIO,
+ cmdtab[segptr->scindex].cname, 2,
+ ntokens, &tmparg);
+
+ /* If creation fails, report the error */
+
+ if (segptr->spid == SYSERR) {
+ fprintf(dev, SHELL_CREATEMSG);
+ err = TRUE;
+ continue;
+ }
+
+ /* If adding arguments fails,report the error */
+
+ if (addargs(segptr->spid,ntokens,&tok[segptr->sstart],
+ tokbuf, &tmparg)== SYSERR) {
+ fprintf(dev, SHELL_CREATEMSG);
+ err = TRUE;
+ break;
+ }
+ }
+ if (err) {
+ /* Undo processes created before the error */
+ for(seg-- ; seg >= 0; seg--) {
+ kill(segtab[seg].spid);
+ }
+ }
- proctab[child].prdesc[0] = stdinput;
- proctab[child].prdesc[1] = stdoutput;
+ /* Redirect input and output for each process */
+ for (seg=0; seg< nsegs; seg++) {
+ segptr = &segtab[seg];
+ proctab[segptr->spid].prdesc[0] = segptr->sindev;
+ proctab[segptr->spid].prdesc[1] = segptr->soutdev;
+ }
msg = recvclr();
- resume(child);
+
+ /* Resume each process in the pipeline (the shell will */
+ /* remain running because it has higher priority) */
+
+ for (seg = 0; seg < nsegs; seg++) {
+ resume(segtab[seg].spid);
+ }
+
+ /* Either block to wait for the last process in the */
+ /* pipeline to finish or allow the pipeline to run */
+ /* in background */
+
+ pid32 tmppid = segtab[nsegs-1].spid; /* Last seg. pid */
+
if (! backgnd) {
msg = receive();
- while (msg != child) {
+ while (msg != tmppid) {
msg = receive();
}
}
- }
+ }
/* Terminate the shell process by returning from the top level */
diff --git a/shell/xsh_arp.c b/shell/xsh_arp.c
index a6bb23b..50d33dd 100644
--- a/shell/xsh_arp.c
+++ b/shell/xsh_arp.c
@@ -36,8 +36,8 @@ shellcmd xsh_arp(int nargs, char *args[])
*/
static void arp_dmp ()
{
- int32 i, j; /* index into the ARP table */
- struct arpentry *arptr; /* pointer to entry in cache */
+ int32 i, j; /* Index into the ARP table */
+ struct arpentry *arptr; /* Pointer to entry in cache */
/* Print entries from the ARP table */
diff --git a/shell/xsh_cat.c b/shell/xsh_cat.c
index 13b3af1..abf6fab 100644
--- a/shell/xsh_cat.c
+++ b/shell/xsh_cat.c
@@ -10,10 +10,10 @@
*/
shellcmd xsh_cat(int nargs, char *args[])
{
- int32 i; /* index into proctabl */
- int32 nextch; /* character read from file */
- did32 descr; /* descriptor for a file */
- char *argptr; /* pointer to next arg string */
+ int32 i; /* Index into proctabl */
+ int32 nextch; /* Character read from file */
+ did32 descr; /* Descriptor for a file */
+ char *argptr; /* Pointer to next arg string */
/* For argument '--help', emit help about the 'cat' command */
diff --git a/shell/xsh_date.c b/shell/xsh_date.c
index 2f27822..6c53d55 100644
--- a/shell/xsh_date.c
+++ b/shell/xsh_date.c
@@ -10,9 +10,9 @@
*/
shellcmd xsh_date(int nargs, char *args[]) {
- int32 retval; /* return value */
- uint32 now; /* current local time */
- char datestr[64]; /* printable date in ascii */
+ int32 retval; /* Return value */
+ uint32 now; /* Current local time */
+ char datestr[64]; /* Printable date in ascii */
/* Output info for '--help' argument */
diff --git a/shell/xsh_devdump.c b/shell/xsh_devdump.c
index 1e41454..658453c 100644
--- a/shell/xsh_devdump.c
+++ b/shell/xsh_devdump.c
@@ -8,12 +8,12 @@
*------------------------------------------------------------------------
*/
shellcmd xsh_devdump (
- int nargs, /* number of arguments */
- char *args[] /* list of arguments */
+ int nargs, /* Number of arguments */
+ char *args[] /* List of arguments */
)
{
- struct dentry *devptr; /* pointer to device entry */
- int32 i; /* walks through device table */
+ struct dentry *devptr; /* Pointer to device entry */
+ int32 i; /* Walks through device table */
/* No arguments are expected */
diff --git a/shell/xsh_echo.c b/shell/xsh_echo.c
index 393c81a..6986439 100644
--- a/shell/xsh_echo.c
+++ b/shell/xsh_echo.c
@@ -9,7 +9,7 @@
*/
shellcmd xsh_echo(int nargs, char *args[])
{
- int32 i; /* walks through args array */
+ int32 i; /* Walks through args array */
if (nargs > 1) {
printf("%s", args[1]);
diff --git a/shell/xsh_help.c b/shell/xsh_help.c
index 0ebfece..7142d55 100644
--- a/shell/xsh_help.c
+++ b/shell/xsh_help.c
@@ -11,18 +11,18 @@
shellcmd xsh_help(int nargs, char *args[])
{
int32 i;
- char *argv[2]; /* argument vector for call */
- char *src, *cmp; /* used for string compare */
- int32 len; /* length of a command name */
- int32 maxlen; /* maximum length of all */
+ char *argv[2]; /* Argument vector for call */
+ char *src, *cmp; /* Used for string compare */
+ int32 len; /* Length of a command name */
+ int32 maxlen; /* Maximum length of all */
/* command names */
- int32 cols; /* number of columns in the */
+ int32 cols; /* Number of columns in the */
/* formatted command list */
- int32 spac; /* space per column in the */
+ int32 spac; /* Space per column in the */
/* formatted command list */
- int32 lines; /* total lines of output in the */
+ int32 lines; /* Total lines of output in the */
/* formatted command list */
- int32 j; /* index of commands across one */
+ int32 j; /* Index of commands across one */
/* line of formatted output */
/* For argument '--help', emit help about the 'help' command */
@@ -67,7 +67,7 @@ shellcmd xsh_help(int nargs, char *args[])
continue;
}
- /* prepare args for shell command */
+ /* Prepare args for shell command */
argv[0] = args[1];
argv[1] = "--help";
@@ -107,7 +107,7 @@ shellcmd xsh_help(int nargs, char *args[])
lines = (ncmd+(cols-1))/cols;
- /* print the lines of command names */
+ /* Print the lines of command names */
for (i=0; i<lines; i++) {
for (j=i; j<ncmd; j+=lines) {
diff --git a/shell/xsh_kill.c b/shell/xsh_kill.c
index 1c903e9..e36eb21 100644
--- a/shell/xsh_kill.c
+++ b/shell/xsh_kill.c
@@ -10,10 +10,10 @@
*/
shellcmd xsh_kill(int nargs, char *args[]) {
- int32 retval; /* return value */
+ int32 retval; /* Return value */
pid32 pid; /* ID of process to kill */
- char ch; /* next character of argument */
- char *chptr; /* walks along argument string */
+ char ch; /* Next character of argument */
+ char *chptr; /* Walks along argument string */
/* Output info for '--help' argument */
@@ -36,7 +36,7 @@ shellcmd xsh_kill(int nargs, char *args[]) {
return SYSERR;
}
- /* compute process ID from argument string */
+ /* Compute process ID from argument string */
chptr = args[1];
ch = *chptr++;
diff --git a/shell/xsh_ls.c b/shell/xsh_ls.c
new file mode 100644
index 0000000..6081e1e
--- /dev/null
+++ b/shell/xsh_ls.c
@@ -0,0 +1,121 @@
+/* xsh_ls.c - xsh_ls */
+
+#include <xinu.h>
+#include <stdio.h>
+
+/*------------------------------------------------------------------------
+ * xsh_ls - shell command to copy stdin to a file and to stdout
+ *------------------------------------------------------------------------
+ */
+shellcmd xsh_ls(int nargs, char *args[])
+{
+ did32 dev; /* Device to use */
+ char *fname; /* File name to map to a device */
+ struct lfdir dir; /* Copy oif lfs directory */
+ char nbuf[NM_MAXLEN]; /* Buffer namespace can use for */
+ /* a replacement name */
+ int32 retval; /* Return value */
+ bool8 loption = FALSE; /* Did the user specify -l? */
+ int32 i; /* Walks through file names */
+ int32 nextarg; /* Walks through arguments */
+ did32 fd; /* File desc. for remote dir. */
+ char buf[512]; /* Buffer for remote directory */
+
+ /* For argument '--help', emit help about the 'ls' command */
+
+ if (nargs > 1 && strncmp(args[1], "--help", 7) == 0) {
+ printf("Use: %s [-l] [dir]\n\n", args[0]);
+ printf("Description:\n");
+ printf("\tlist files in the default directory or\n");
+ printf("\tthe directory specfified by dir\n");
+ printf("Options:\n");
+ printf("\t-l\t list file size as well as name\n");
+ printf("\t--help\t display this help and exit\n");
+ }
+
+ if (nargs > 3) {
+ fprintf(stderr, "Use: %s [-l] [dir]\n\n", args[0]);
+ return 1;
+ }
+ nextarg = 1;
+ if (nargs > 1 && strncmp(args[nextarg], "-l", 3) == 0) {
+ loption = TRUE;
+ nextarg++;
+ nargs--;
+ }
+ if (nargs > 1) {
+ if (args[nextarg][0] == '-') {
+ fprintf(stderr, "Use: %s [-l] [dir]\n\n",args[0]);
+ return 1;
+ }
+ fname = args[nextarg];
+ } else {
+ fname = ".";
+ }
+ dev = namrepl(fname, nbuf);
+ if (dev == (did32)SYSERR) {
+ fprintf(stderr, "%s: cannot access device for %s\n",
+ args[0], fname);
+ return 1;
+ }
+
+ /* Handle local file system */
+
+ if (dev == LFILESYS) {
+
+ wait(Lf_data.lf_mutex);
+ if ( ! Lf_data.lf_dirpresent ) {
+ retval = read(Lf_data.lf_dskdev,(char *)&Lf_data.lf_dir,
+ LF_AREA_DIR);
+ if (retval == SYSERR ) {
+ fprintf(stderr, "%s: cannot obtain directory\n",
+ args[0]);
+ signal(Lf_data.lf_mutex);
+ return 1;
+ }
+ if (lfscheck(&Lf_data.lf_dir) == SYSERR ) {
+ fprintf(stderr, "%s: file system uninitialized\n",
+ args[0]);
+ signal(Lf_data.lf_mutex);
+ return 1;
+ }
+ }
+ signal(Lf_data.lf_mutex);
+ memcpy((void *)&dir, (void *)&Lf_data.lf_dir, sizeof(dir));
+ for (i = 0; i < dir.lfd_nfiles; i++) {
+ if (loption) {
+ fprintf(stdout, "%6d %s\n", dir.lfd_files[i].ld_size,
+ dir.lfd_files[i].ld_name);
+ } else {
+ fprintf(stdout, " %s\n",
+ dir.lfd_files[i].ld_name);
+ }
+ }
+
+ /* Handle remote file system */
+
+ } else if (dev == RFILESYS) {
+
+ fd = open(RFILESYS, nbuf, "r");
+ if (fd < 0){
+ fprintf(stderr, "Cnanot open remote file %s\n", nbuf);
+ return 1;
+ }
+ retval = read(fd, buf, 512);
+ while (retval > 0) {
+ fprintf(stdout, " %s\n",buf);
+ retval = read(fd, buf, 512);
+ }
+ close(fd);
+ return 0;
+
+ } else {
+
+ /* Handle erro case for unknown file system */
+
+ fprintf(stderr, "%s: file system is an unknown type\n",
+ args[0]);
+ return 1;
+ }
+ return 0;
+}
diff --git a/shell/xsh_memdump.c b/shell/xsh_memdump.c
index 96a0787..cb7c841 100644
--- a/shell/xsh_memdump.c
+++ b/shell/xsh_memdump.c
@@ -14,16 +14,16 @@ extern uint32 start;
*/
shellcmd xsh_memdump(int nargs, char *args[])
{
- bool8 force = FALSE; /* ignore address sanity checks */
- uint32 begin; /* begining address */
- uint32 stop; /* last address to dump */
- uint32 length; /* length of region to dump */
- int32 arg; /* index into args array */
- uint32 l; /* counts length during dump */
- int32 i; /* counts words during dump */
- uint32 *addr; /* address to dump */
- char *chptr; /* character address to dump */
- char ch; /* next character to print */
+ bool8 force = FALSE; /* Ignore address sanity checks */
+ uint32 begin; /* Begining address */
+ uint32 stop; /* Last address to dump */
+ uint32 length; /* Length of region to dump */
+ int32 arg; /* Index into args array */
+ uint32 l; /* Counts length during dump */
+ int32 i; /* Counts words during dump */
+ uint32 *addr; /* Address to dump */
+ char *chptr; /* Character address to dump */
+ char ch; /* Next character to print */
/* For argument '--help', emit help about the 'memdump' command */
@@ -86,12 +86,12 @@ shellcmd xsh_memdump(int nargs, char *args[])
stop = begin + length;
- /* verify that the address and length are reasonable */
+ /* Verify that the address and length are reasonable */
if ( force || ( (begin >= (uint32)&start) && (stop > begin) &&
(((void *)stop) < maxheap)) ) {
- /* values are valid; perform dump */
+ /* Values are valid; perform dump */
chptr = (char *)begin;
for (l=0; l<length; l+=16) {
@@ -124,20 +124,20 @@ shellcmd xsh_memdump(int nargs, char *args[])
*------------------------------------------------------------------------
*/
static uint32 parseval(
- char *string /* argument string to parse */
+ char *string /* Argument string to parse */
)
{
- uint32 value; /* value to return */
- char ch; /* next character */
+ uint32 value; /* Value to return */
+ char ch; /* Next character */
value = 0;
- /* argument string must consists of decimal digits or */
+ /* Argument string must consists of decimal digits or */
/* 0x followed by hex digits */
ch = *string++;
- if (ch == '0') { /* hexadecimal */
+ if (ch == '0') { /* Hexadecimal */
if (*string++ != 'x') {
return 0;
}
@@ -152,7 +152,7 @@ static uint32 parseval(
return 0;
}
}
- } else { /* decimal */
+ } else { /* Decimal */
while (ch != NULLCH) {
if ( (ch < '0') || (ch > '9') ) {
return 0;
diff --git a/shell/xsh_ns.c b/shell/xsh_ns.c
new file mode 100644
index 0000000..f1c7584
--- /dev/null
+++ b/shell/xsh_ns.c
@@ -0,0 +1,136 @@
+/* xsh_ns.c - xsh_ns */
+
+#include <xinu.h>
+#include <stdio.h>
+
+/*------------------------------------------------------------------------
+ * xsh_ns - shell command to print info from the device switch table
+ *------------------------------------------------------------------------
+ */
+shellcmd xsh_ns (
+ int nargs, /* Number of arguments */
+ char *args[] /* List of arguments */
+ )
+{
+ int32 i; /* Walks through the namespace */
+ struct nmentry *nptr; /* Pointer to a namespace entry */
+ char *pptr; /* Pointer to a prefix */
+ char *rptr; /* Pointer to a replacement */
+ char nullstr[] = "NULLSTR"; /* Used when an item is "" */
+ char repname[NM_MAXLEN]; /* Buffer to hold a mapped name */
+ did32 dev; /* Device for a mapped name */
+ int32 slen; /* Length of an argument */
+ int32 cpylen; /* Bytes to copy */
+ int32 d; /* Walks through devtab */
+
+ char err[] = "invalid arguments - type --help for details";
+ char *use[] = {
+ "With no arguments, ns prints the namespace. Arguments are",
+ "interpreted as follows:",
+ " --help displays this message.",
+ " -d prefix removes the prefix from the namspace",
+ " -m ppp rrr ddd mount a namespace entry with prefix ppp,",
+ " repalcement rrr and device name ddd",
+ " xxx causes ns to map file name xxx through",
+ " the namspace and display the result."
+ };
+
+ if ( (nargs == 4) || (nargs > 5) ) {
+
+ return 1;
+ }
+
+ /* Handle no arguments by dumping the namespace */
+
+ if (nargs == 1) {
+ if (nnames <= 0) {
+ fprintf(stderr, "namespace is empty!\n");
+ return 1;
+ }
+ printf("%s %s %s\n",
+ " Prefix ",
+ " Replacement ",
+ " Device ");
+ printf("%s %s %s\n",
+ "-----------------------",
+ "-----------------------",
+ "-------------------");
+ /* Walk through the namespace */
+ for (i=0; i<nnames; i++) {
+ nptr = &nametab[i];
+ pptr = nptr->nprefix;
+ if (*pptr == NULLCH) {
+ pptr = nullstr;
+ }
+ rptr = nptr->nreplace;
+ if (*rptr == NULLCH) {
+ rptr = nullstr;
+ }
+ printf("%-24s %-24s %s\n", pptr, rptr,
+ devtab[nptr->ndevice].dvname);
+ }
+ return 0;
+ }
+
+ /* Handle the case of one argument by mapping the name */
+
+ if (nargs == 2) {
+
+ if (strncmp(args[1], "--help", 7) == 0) {
+ fprintf(stderr, "use:\n %s\n %s\n %s\n ",
+ use[0], use[1], use[2]);
+ fprintf(stderr,"%s\n %s\n %s\n\n",
+ use[3], use[4], use[5]);
+ return 0;
+ }
+ if (args[1][0] == NULLCH) {
+ fprintf(stderr, "%s\n", err);
+ return 1;
+ }
+ dev = namrepl(args[1], repname);
+ printf(" %s becomes %s on device %d\n",
+ args[1], repname, dev);
+ return 0;
+ }
+
+ /* Handle the -d option */
+
+ if (nargs == 3) {
+
+ if (strncmp(args[1], "-d", 3) != 0) {
+ fprintf(stderr, "%s\n", err);
+ return 1;
+ }
+ slen = strlen(args[2]) + 1;
+ for (i=0; i<nnames; i++) {
+ nptr = &nametab[i];
+ if (strncmp(args[2],nptr->nprefix, slen)
+ == 0) {
+ cpylen = (nnames-i-1)*sizeof(struct nmentry);
+ if (cpylen > 0) {
+ memcpy((void *)nptr,(void *)&nametab[i+1],
+ cpylen);
+ }
+ nnames--;
+ return 0;
+ }
+ }
+ fprintf(stderr, "No such entry in the namepace\n");
+ return 1;
+ }
+
+ /* Handle the -m option */
+ if ( strncmp(args[1], "-m", 2) != 0 ) {
+ fprintf(stderr, "%s\n", err);
+ return 1;
+ }
+ slen = strlen(args[4]);
+ for (d=0; d < NDEVS; d++) {
+ if (strncmp(args[4], devtab[d].dvname, slen) == 0) {
+ mount(args[2], args[3], d);
+ return 0;
+ }
+ }
+ fprintf(stderr, "invalid device name\n");
+ return 1;
+}
diff --git a/shell/xsh_ping.c b/shell/xsh_ping.c
index 2b94c68..bf2014a 100644
--- a/shell/xsh_ping.c
+++ b/shell/xsh_ping.c
@@ -11,13 +11,12 @@
shellcmd xsh_ping(int nargs, char *args[])
{
uint32 ipaddr; /* IP address in binary */
- int32 retval; /* return value */
+ int32 retval; /* Return value */
int32 slot; /* Slot in ICMP to use */
- static int32 seq = 0; /* sequence number */
- char buf[56]; /* buffer of chars */
- int32 i; /* index into buffer */
- int32 nextval; /* next value to use */
- bool8 dname;
+ static int32 seq = 0; /* Sequence number */
+ char buf[56]; /* Buffer of chars */
+ int32 i; /* Index into buffer */
+ int32 nextval; /* Next value to use */
/* For argument '--help', emit help about the 'ping' command */
@@ -40,35 +39,14 @@ shellcmd xsh_ping(int nargs, char *args[])
return 1;
}
- dname = FALSE;
- for(i = 0; i < strlen(args[1]); i++) {
- if( ( (args[1][i] >= 65) && (args[1][i] <= 90) ) ||
- ( (args[1][i] >= 97) && (args[1][i] <= 122)) ) {
- dname = TRUE;
- break;
- }
+ if(dnslookup(args[1], &ipaddr) == SYSERR) {
+ fprintf(stderr, "DNS cannot resolve %s\n", args[1]);
+ return 1;
}
-
- if(dname == TRUE) {
- ipaddr = dnslookup(args[1]);
- if((int32)ipaddr == SYSERR) {
- fprintf(stderr, "DNS cannot resolve %s\n", args[1]);
- return 1;
- }
- printf("Pinging %d.%d.%d.%d\n", (ipaddr>>24)&0xff,
+ printf("Pinging %d.%d.%d.%d\n", (ipaddr>>24)&0xff,
(ipaddr>>16)&0xff,
(ipaddr>>8)&0xff,
(ipaddr)&0xff);
- }
- else {
- /* convert argument to binary */
-
- retval = dot2ip(args[1], &ipaddr);
- if ((int32)retval == SYSERR) {
- fprintf(stderr, "%s: invalid IP address\n", args[0]);
- return 1;
- }
- }
/* Register to receive an ICMP Echo Reply */
@@ -90,18 +68,19 @@ shellcmd xsh_ping(int nargs, char *args[])
retval = icmp_send(ipaddr, ICMP_ECHOREQST, slot,
seq++, buf, sizeof(buf));
if (retval == SYSERR) {
- fprintf(stderr, "%s: no response from host %s\n", args[0], args[1]);
+ fprintf(stderr, "%s: cannot send ping\n", args[0]);
icmp_release(slot);
return 1;
}
- /* Read a reply */
+ /* Read a reply, waiting up to 3 seconds */
retval = icmp_recv(slot, buf, sizeof(buf), 3000);
icmp_release(slot);
if (retval == TIMEOUT) {
fprintf(stderr, "%s: no response from host %s\n", args[0],
args[1]);
+ icmp_release(slot);
return 1;
}
@@ -110,5 +89,6 @@ shellcmd xsh_ping(int nargs, char *args[])
sizeof(buf), retval);
}
fprintf(stderr, "host %s is alive\n", args[1]);
+ icmp_release(slot);
return 0;
}
diff --git a/shell/xsh_ps.c b/shell/xsh_ps.c
index 9d5738f..9e13b97 100644
--- a/shell/xsh_ps.c
+++ b/shell/xsh_ps.c
@@ -10,9 +10,9 @@
*/
shellcmd xsh_ps(int nargs, char *args[])
{
- struct procent *prptr; /* pointer to process */
- int32 i; /* index into proctabl */
- char *pstate[] = { /* names for process states */
+ struct procent *prptr; /* Pointer to process */
+ int32 i; /* Index into proctabl */
+ char *pstate[] = { /* Names for process states */
"free ", "curr ", "ready", "recv ", "sleep", "susp ",
"wait ", "rtime"};
@@ -50,7 +50,7 @@ shellcmd xsh_ps(int nargs, char *args[])
for (i = 0; i < NPROC; i++) {
prptr = &proctab[i];
- if (prptr->prstate == PR_FREE) { /* skip unused slots */
+ if (prptr->prstate == PR_FREE) { /* Skip unused slots */
continue;
}
printf("%3d %-16s %s %4d %4d 0x%08X 0x%08X %8d\n",
diff --git a/shell/xsh_rdstest.c b/shell/xsh_rdstest.c
index 949e2e9..6937064 100644
--- a/shell/xsh_rdstest.c
+++ b/shell/xsh_rdstest.c
@@ -19,27 +19,27 @@ shellcmd xsh_rdstest(int nargs, char *args[])
retval = open(RDISK,dskname,"rw");
if (retval < 0) {
- kprintf("xsh_rdstest: open %s returns %s, stopping\r\n",
+ kprintf("xsh_rdstest: open %s returns %s, stopping\n",
dskname, retval==SYSERR?"SYSERR":"TIMEOUT");
close( RDISK );
return 1;
} else {
- kprintf("xsh_rdstest: open %s returns %d\r\n",
+ kprintf("xsh_rdstest: open %s returns %d\n",
dskname, retval);
}
- kprintf("writing eight blocks to the disk\r\n");
+ kprintf("writing eight blocks to the disk\n");
for (i=7; i>=0; i--) {
memset(buff, (char)(i&0xff), RD_BLKSIZ);
- kprintf("\n\r*** writing block %d\n\r",i);
+ kprintf("\n*** writing block %d\n",i);
retval = write(RDISK, buff, i);
if (retval < 0) {
- kprintf("write to block %d returns %d\r\n", i, retval);
+ kprintf("write to block %d returns %d\n", i, retval);
}
}
- kprintf("reading block 1\n\r");
+ kprintf("reading block 1\n");
retval = read(RDISK, buff, 1);
- kprintf("read from block 1 has return value %d\r\n", retval);
+ kprintf("read from block 1 has return value %d\n", retval);
err = 0;
for (i=0; i<RD_BLKSIZ; i++) {
@@ -49,12 +49,12 @@ shellcmd xsh_rdstest(int nargs, char *args[])
}
}
if (err == 0) {
- kprintf("Block 1 came back intact!!!\r\n");
+ kprintf("Block 1 came back intact!!!\n");
} else {
- kprintf("Sadly :-( byte %d is not correct!!!\r\n", i);
+ kprintf("Sadly :-( byte %d is not correct!!!\n", i);
}
- kprintf("reading block 6\n\r");
+ kprintf("reading block 6\n");
retval = read(RDISK, buff, 6);
err = 0;
for (i=0; i<RD_BLKSIZ; i++) {
@@ -64,9 +64,9 @@ shellcmd xsh_rdstest(int nargs, char *args[])
}
}
if (err == 0) {
- kprintf("Block 6 came back intact!!!\r\n");
+ kprintf("Block 6 came back intact!!!\n");
} else {
- kprintf("Sadly :-( byte %d is not correct!!!\r\n", i);
+ kprintf("Sadly :-( byte %d is not correct!!!\n", i);
}
j = 0;
@@ -75,11 +75,11 @@ shellcmd xsh_rdstest(int nargs, char *args[])
j %= 13;
}
- kprintf("rewriting block 5\n\r");
+ kprintf("rewriting block 5\n");
retval = write(RDISK, buff2, 5);
- kprintf("write to block 5 has return value %d\r\n", retval);
+ kprintf("write to block 5 has return value %d\n", retval);
- kprintf("reading block 5\n\r");
+ kprintf("reading block 5\n");
retval = read(RDISK, buff2, 5);
err = 0;
@@ -91,16 +91,16 @@ shellcmd xsh_rdstest(int nargs, char *args[])
}
if (err == 0) {
- kprintf("Block 5 came back intact!!!\r\n");
+ kprintf("Block 5 came back intact!!!\n");
} else {
- kprintf("Sadly :-( byte %d is not correct!!!\r\n", i);
+ kprintf("Sadly :-( byte %d is not correct!!!\n", i);
}
memset(buff, NULLCH, RD_BLKSIZ);
- kprintf("reading block 6 again\n\r");
+ kprintf("reading block 6 again\n");
retval = read(RDISK, buff, 6);
- kprintf("read from block 6 has return value %d\r\n", retval);
+ kprintf("read from block 6 has return value %d\n", retval);
err = 0;
for (i=0; i<RD_BLKSIZ; i++) {
@@ -110,9 +110,9 @@ shellcmd xsh_rdstest(int nargs, char *args[])
}
}
if (err == 0) {
- kprintf("Got back identical results!!!\r\n");
+ kprintf("Got back identical results!!!\n");
} else {
- kprintf("Sadly :-( byte %d differs!!!\r\n", i);
+ kprintf("Sadly :-( byte %d differs!!!\n", i);
}
return 0;
}
diff --git a/shell/xsh_tee.c b/shell/xsh_tee.c
new file mode 100644
index 0000000..3b3d481
--- /dev/null
+++ b/shell/xsh_tee.c
@@ -0,0 +1,47 @@
+/* xsh_tee.c - xsh_tee */
+
+#include <xinu.h>
+#include <stdio.h>
+#include <string.h>
+
+/*------------------------------------------------------------------------
+ * xsh_tee - shell command to copy stdin to a file and to stdout
+ *------------------------------------------------------------------------
+ */
+shellcmd xsh_tee(int nargs, char *args[])
+{
+ int32 nextch; /* Character read from file */
+ did32 descr; /* Descriptor for a file */
+
+
+ /* For argument '--help', emit help about the 'tee' command */
+
+ if (nargs != 2 && strncmp(args[1], "--help", 7) == 0) {
+ fprintf(stderr,"Use: %s file\n\n", args[0]);
+ fprintf(stderr,"Description:\n");
+ fprintf(stderr,"\tcopies stdin to stdout and a file\n");
+ fprintf(stderr,"Options:\n");
+ fprintf(stderr,"\t--help\t display this help and exit\n");
+ return 0;
+ }
+
+ descr = open(NAMESPACE, args[1], "w");
+ if (descr == (did32)SYSERR) {
+ fprintf(stderr, "%s: cannot open file %s\n",
+ args[0], args[1]);
+ return 1;
+ }
+ control(descr, F_CTL_TRUNC, 0, 0);
+ nextch = getc(stdin);
+ while (nextch != EOF) {
+ putc(stdout, nextch);
+ putc(descr, nextch);
+ nextch = getc(stdin);
+ }
+ close(descr);
+ return 0;
+}
+
+
+
+
diff --git a/shell/xsh_udpdump.c b/shell/xsh_udpdump.c
index c157b8d..8923a7a 100644
--- a/shell/xsh_udpdump.c
+++ b/shell/xsh_udpdump.c
@@ -10,12 +10,12 @@
*/
shellcmd xsh_udpdump(int nargs, char *args[])
{
- int32 i; /* index into udptab */
- char *udpstate[] = { /* names for entry states */
+ int32 i; /* Index into udptab */
+ char *udpstate[] = { /* Names for entry states */
"free ", "used ", "recv "};
- struct udpentry *uptr; /* ptr to entry in udptab */
- uint32 remip; /* variables to hold the info */
- int32 r1,r2,r3,r4; /* from an entry for printing */
+ struct udpentry *uptr; /* Ptr to entry in udptab */
+ uint32 remip; /* Variables to hold the info */
+ int32 r1,r2,r3,r4; /* From an entry for printing */
int32 remprt, locprt;
int32 state;
pid32 pid;
@@ -53,7 +53,7 @@ shellcmd xsh_udpdump(int nargs, char *args[])
/* Output information for each valid entry in udptab */
for (i = 0; i < UDP_SLOTS; i++) {
uptr = &udptab[i];
- if (uptr->udstate == UDP_FREE) { /* skip unused slots */
+ if (uptr->udstate == UDP_FREE) { /* Skip unused slots */
printf("%3d ---- slot is free ---\n", i);
continue;
}
@@ -66,8 +66,7 @@ shellcmd xsh_udpdump(int nargs, char *args[])
locprt = uptr->udlocport;
pid = uptr->udpid;
state = uptr->udstate;
- printf(
- " %4s %3d.%3d.%3d.%3d %5d %6d%5d%6d\n",
+ printf(" %4s %3d.%3d.%3d.%3d %5d %6d%5d%6d\n",
udpstate[state], r1, r2, r3, r4, remprt, locprt, pid,
uptr->udcount);
}
diff --git a/shell/xsh_udpecho.c b/shell/xsh_udpecho.c
index d1f67ab..d6a168f 100644
--- a/shell/xsh_udpecho.c
+++ b/shell/xsh_udpecho.c
@@ -4,6 +4,8 @@
#include <stdio.h>
#include <string.h>
+extern int atoi(char *);
+
/*------------------------------------------------------------------------
* xsh_udpecho - shell command that can send a message to a remote UDP
* echo server and receive a reply
@@ -11,58 +13,60 @@
*/
shellcmd xsh_udpecho(int nargs, char *args[])
{
- int i; /* index into buffer */
- int retval; /* return value */
- char msg[] = "Xinu testing UDP echo"; /* message to send */
- char inbuf[1500]; /* buffer for incoming reply */
+ int i; /* Index into buffer */
+ int retval; /* Return value */
+ char msg[] = "Xinu testing UDP echo"; /* Message to send */
+ char inbuf[1500]; /* Buffer for incoming reply */
int32 slot; /* UDP slot to use */
- int32 msglen; /* length of outgoing message */
- uint32 remoteip; /* remote IP address to use */
- //uint32 localip; /* local IP address to use */
- uint16 echoport= 7; /* port number for UDP echo */
- uint16 locport = 52743; /* local port to use */
- int32 retries = 3; /* number of retries */
- int32 delay = 2000; /* reception delay in ms */
+ int32 msglen; /* Length of outgoing message */
+ uint32 remoteip; /* Remote IP address to use */
+ uint16 remport= 7; /* Remote port number to use */
+ uint16 locport = 52743; /* Local port to use */
+ int32 retries = 3; /* Number of retries */
+ int32 delay = 500; /* Reception delay in ms */
/* For argument '--help', emit help about the 'udpecho' command */
if (nargs == 2 && strncmp(args[1], "--help", 7) == 0) {
- printf("Use: %s REMOTEIP\n\n", args[0]);
+ printf("Use: %s remote_ip [remote_port]\n\n", args[0]);
printf("Description:\n");
printf("\tBounce a message off a remote UDP echo server\n");
printf("Options:\n");
- printf("\tREMOTEIP:\tIP address in dotted decimal\n");
- printf("\t--help\t display this help and exit\n");
+ printf("\tremote_ip:\tIP address in dotted decimal\n");
+ printf("\tremote_port:\tport number\n");
+ printf("\t--help\t\tdisplay this help and exit\n");
return 0;
}
/* Check for valid IP address argument */
- if (nargs != 2) {
- fprintf(stderr, "%s: invalid argument(s)\n", args[0]);
+ if ( (nargs < 2) || (nargs > 3) ) {
+ fprintf(stderr, "%s: invalid number of argument(s)\n", args[0]);
fprintf(stderr, "Try '%s --help' for more information\n",
args[0]);
return 1;
}
if (dot2ip(args[1], &remoteip) == SYSERR) {
- fprintf(stderr, "%s: invalid IP address argument\r\n",
+ fprintf(stderr, "%s: invalid IP address argument\n",
args[0]);
return 1;
}
- /*
- localip = getlocalip();
- if (localip == SYSERR) {
- fprintf(stderr,
- "%s: could not obtain a local IP address\n",
- args[0]);
- return 1;
+ if (nargs == 3) {
+ retval = atoi(args[2]);
+ if ( (retval <= 0) || (retval > 64535) ) {
+ fprintf(stderr, "%s: invalid port argument\n",
+ args[0]);
+ return 1;
+ }
+ remport = (uint16) retval;
}
- */
- /* register local UDP port */
+ fprintf(stderr, "using remote port %d\n", remport);
+
+ /* Register local UDP port */
- slot = udp_register(remoteip, echoport, locport);
+ slot = udp_register(remoteip, remport, locport);
if (slot == SYSERR) {
fprintf(stderr, "%s: could not reserve UDP port %d\n",
args[0], locport);
diff --git a/shell/xsh_udpserver.c b/shell/xsh_udpserver.c
index 7ab19c0..d35aacc 100644
--- a/shell/xsh_udpserver.c
+++ b/shell/xsh_udpserver.c
@@ -11,14 +11,14 @@
*/
shellcmd xsh_udpeserver(int nargs, char *args[])
{
- int32 retval; /* return value from sys calls */
- uint32 localip; /* local IP address */
- uint32 remip; /* remote sender's IP address */
- uint16 remport; /* remote sender's UDP port */
- char buff[1500]; /* buffer for incoming reply */
- int32 msglen; /* length of outgoing message */
- int32 slot; /* slot in UDP table */
- uint16 echoserverport= 7; /* port number for UDP echo */
+ int32 retval; /* Return value from sys calls */
+ uint32 localip; /* Local IP address */
+ uint32 remip; /* Remote sender's IP address */
+ uint16 remport; /* Remote sender's UDP port */
+ char buff[1500]; /* Buffer for incoming reply */
+ int32 msglen; /* Length of outgoing message */
+ int32 slot; /* Slot in UDP table */
+ uint16 echoserverport= 7; /* Port number for UDP echo */
/* For argument '--help', emit a help message */
@@ -48,7 +48,7 @@ shellcmd xsh_udpeserver(int nargs, char *args[])
return 1;
}
- /* register local UDP port */
+ /* Register local UDP port */
slot = udp_register(0, 0, echoserverport);
if (slot == SYSERR) {
diff --git a/shell/xsh_uptime.c b/shell/xsh_uptime.c
index bceb8f5..74461f5 100644
--- a/shell/xsh_uptime.c
+++ b/shell/xsh_uptime.c
@@ -10,11 +10,11 @@
*/
shellcmd xsh_uptime(int nargs, char *args[])
{
- uint32 days, hrs, mins, secs; /* days, hours, minutes, and */
+ uint32 days, hrs, mins, secs; /* Days, hours, minutes, and */
/* seconds since system boot */
- uint32 secperday = 86400; /* seconds in a day */
- uint32 secperhr = 3600; /* seconds in an hour */
- uint32 secpermin = 60; /* seconds in a minute */
+ uint32 secperday = 86400; /* Seconds in a day */
+ uint32 secperhr = 3600; /* Seconds in an hour */
+ uint32 secpermin = 60; /* Seconds in a minute */
/* For argument '--help', emit help about the 'uptime' command */
@@ -36,19 +36,19 @@ shellcmd xsh_uptime(int nargs, char *args[])
return 1;
}
- secs = clktime; /* total seconds since boot */
+ secs = clktime; /* Total seconds since boot */
- /* subtract number of whole days */
+ /* Subtract number of whole days */
days = secs/secperday;
secs -= days*secperday;
- /* subtract number of hours */
+ /* Subtract number of hours */
hrs = secs/secperhr;
secs -= hrs*secperhr;
- /* subtract number of minutes */
+ /* Subtract number of minutes */
mins = secs/secpermin;
secs -= mins*secpermin;
diff --git a/system/chprio.c b/system/chprio.c
index 6c567d4..ec9a126 100644
--- a/system/chprio.c
+++ b/system/chprio.c
@@ -6,7 +6,7 @@
* chprio - Change the scheduling priority of a process
*------------------------------------------------------------------------
*/
-pri16 chprio(
+syscall chprio(
pid32 pid, /* ID of process to change */
pri16 newprio /* New priority */
)
@@ -18,11 +18,11 @@ pri16 chprio(
mask = disable();
if (isbadpid(pid)) {
restore(mask);
- return (pri16) SYSERR;
+ return SYSERR;
}
prptr = &proctab[pid];
oldprio = prptr->prprio;
prptr->prprio = newprio;
restore(mask);
- return oldprio;
+ return 0xffff & oldprio;
}
diff --git a/system/conf.c b/system/conf.c
index 4b2724f..be47c97 100644
--- a/system/conf.c
+++ b/system/conf.c
@@ -24,7 +24,7 @@ struct dentry devtab[NDEVS] =
(void *)ttyinit, (void *)ionull, (void *)ionull,
(void *)ttyread, (void *)ttywrite, (void *)ioerr,
(void *)ttygetc, (void *)ttyputc, (void *)ttycontrol,
- (void *)0x3f8, (void *)ttydispatch, 42 },
+ (void *)0x3f8, (void *)ttydispatch, 36 },
/* NULLDEV is null */
{ 1, 0, "NULLDEV",
@@ -38,7 +38,7 @@ struct dentry devtab[NDEVS] =
(void *)ethinit, (void *)ioerr, (void *)ioerr,
(void *)ethread, (void *)ethwrite, (void *)ioerr,
(void *)ioerr, (void *)ioerr, (void *)ethcontrol,
- (void *)0x0, (void *)ethdispatch, 43 },
+ (void *)0x0, (void *)ethdispatch, 0 },
/* NAMESPACE is nam */
{ 3, 0, "NAMESPACE",
@@ -49,7 +49,7 @@ struct dentry devtab[NDEVS] =
/* RDISK is rds */
{ 4, 0, "RDISK",
- (void *)rdsinit, (void *)rdsopen, (void *)rdsclose,
+ (void *)rdsinit, (void *)rdsopen, (void *)ioerr,
(void *)rdsread, (void *)rdswrite, (void *)ioerr,
(void *)ioerr, (void *)ioerr, (void *)rdscontrol,
(void *)0x0, (void *)ionull, 0 },
@@ -185,5 +185,82 @@ struct dentry devtab[NDEVS] =
(void *)lflinit, (void *)ioerr, (void *)lflclose,
(void *)lflread, (void *)lflwrite, (void *)lflseek,
(void *)lflgetc, (void *)lflputc, (void *)lflcontrol,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE is pipem */
+ { 24, 0, "PIPE",
+ (void *)ionull, (void *)pipe_open, (void *)ioerr,
+ (void *)ioerr, (void *)ioerr, (void *)ioerr,
+ (void *)ioerr, (void *)ioerr, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE0 is pip */
+ { 25, 0, "PIPE0",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE1 is pip */
+ { 26, 1, "PIPE1",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE2 is pip */
+ { 27, 2, "PIPE2",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE3 is pip */
+ { 28, 3, "PIPE3",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE4 is pip */
+ { 29, 4, "PIPE4",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE5 is pip */
+ { 30, 5, "PIPE5",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE6 is pip */
+ { 31, 6, "PIPE6",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE7 is pip */
+ { 32, 7, "PIPE7",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE8 is pip */
+ { 33, 8, "PIPE8",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
+ (void *)0x0, (void *)ionull, 0 },
+
+/* PIPE9 is pip */
+ { 34, 9, "PIPE9",
+ (void *)pipe_init, (void *)ioerr, (void *)pipe_close,
+ (void *)pipe_read, (void *)pipe_write, (void *)ioerr,
+ (void *)pipe_getc, (void *)pipe_putc, (void *)ioerr,
(void *)0x0, (void *)ionull, 0 }
};
diff --git a/system/create.c b/system/create.c
index 2a54e03..98d5585 100644
--- a/system/create.c
+++ b/system/create.c
@@ -26,9 +26,9 @@ pid32 create(
uint32 *saddr; /* Stack address */
mask = disable();
- if (ssize < MINSTK)
+ if (ssize < MINSTK) {
ssize = MINSTK;
- ssize = (uint32) roundmb(ssize);
+ }
if ( (priority < 1) || ((pid=newpid()) == SYSERR) ||
((saddr = (uint32 *)getstk(ssize)) == (uint32 *)SYSERR) ) {
restore(mask);
@@ -64,7 +64,7 @@ pid32 create(
a = (uint32 *)(&nargs + 1); /* Start of args */
a += nargs -1; /* Last argument */
for ( ; nargs > 0 ; nargs--) /* Machine dependent; copy args */
- *--saddr = *a--; /* onto created process's stack */
+ *--saddr = *a--; /* onto created process's stack*/
*--saddr = (long)INITRET; /* Push on return address */
/* The following entries on the stack must match what ctxsw */
diff --git a/system/ctxsw.S b/system/ctxsw.S
index 35671e1..1e8e339 100644
--- a/system/ctxsw.S
+++ b/system/ctxsw.S
@@ -24,7 +24,7 @@ ctxsw:
/* The next instruction switches from the old process's */
/* stack to the new process's stack. */
- movl (%eax),%esp /* Pop up new process's SP */
+ movl (%eax),%esp /* Pick up new process's SP */
/* Restore new seg. registers here, if multiple allowed */
diff --git a/system/early_imr.c b/system/early_imr.c
deleted file mode 100644
index 6a99c93..0000000
--- a/system/early_imr.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * early_imr.c
- *
- * Copyright (c) 2012, 2013 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; version 2
- * of the License.
- */
-
-#include <xinu.h>
-
-#define INTEL_CLN_SB_CMD_ADDR (0x000000D0)
-#define INTEL_CLN_SB_DATA_ADDR (0x000000D4)
-
-#define INTEL_CLN_SB_MCR_SHIFT (24)
-#define INTEL_CLN_SB_PORT_SHIFT (16)
-#define INTEL_CLN_SB_REG_SHIFT (8)
-#define INTEL_CLN_SB_BYTEEN (0xF0) /* Enable all 32 bits */
-
-/* IMR related reg address */
-#define CFG_READ_OPCODE (0x10) /* Control Read */
-#define CFG_WRITE_OPCODE (0x11) /* Control write */
-#define DRAM_IMR0L (0x40) /* IMR0RL address */
-#define DRAM_IMR0H (0x41) /* IMR0RL address */
-#define DRAM_IMR0RM (0x42) /* IMR0RM address */
-#define DRAM_IMR0WM (0x43) /* IMR0WM address */
-#define DRAM_IMR1L (0x44) /* IMR1L address */
-#define DRAM_IMR1H (0x45) /* IMR1H address */
-#define DRAM_IMR1RM (0x46) /* IMR1RM address */
-#define DRAM_IMR1WM (0x47) /* IMR1WM address */
-#define DRAM_IMR3L (0x4C) /* IMR3L address */
-#define DRAM_IMR3H (0x4D) /* IMR3H address */
-#define DRAM_IMR3RM (0x4E) /* IMR3RM address */
-#define DRAM_IMR3WM (0x4F) /* IMR3WM address */
-#define DRAM_IMR7L (0x5C) /* IMR7RM address */
-#define DRAM_IMR7H (0x5D) /* IMR7RM address */
-#define DRAM_IMR7RM (0x5E) /* IMR7RM address */
-#define DRAM_IMR7WM (0x5F) /* IMR7WM address */
-
-#define IMR_WRITE_ENABLE_ALL (0xFFFFFFFF)
-#define IMR_READ_ENABLE_ALL (0xBFFFFFFF)
-#define IMR_BASE_ADDR (0x0000)
-#define IMR_LOCK_BIT (0x80000000)
-
-/* Mask of the last 2 bit of IMR address [23:2] */
-#define IMR_MASK (0xFFFFFC)
-/* Mask that enables IMR access for Non-SMM Core, Core Snoops Only.*/
-#define IMR_SNOOP_NON_SMM_ENABLE (0x40000001)
-/* Mask that enables IMR access for Non-SMM Core Only.*/
-#define IMR_NON_SMM_ENABLE (0x00000001)
-
-typedef enum {
- SB_ID_HUNIT = 0x03,
- SB_ID_THERMAL = 0x04,
- SB_ID_ESRAM = 0x05,
-}cln_sb_id;
-
-static uint32 sb_pcidev;
-
-/**
- * intel_cln_early_sb_read_reg
- *
- * @param cln_sb_id: Sideband identifier
- * @param command: Command to send to destination identifier
- * @param reg: Target register w/r to cln_sb_id
- * @return nothing
- *
- * Utility function to allow thread-safe read of side-band
- * command - can be different read op-code types - which is why we don't
- * hard-code this value directly into msg
- */
-void intel_cln_early_sb_read_reg(cln_sb_id id, unsigned char cmd,
- unsigned char reg, uint32 *data)
-{
- uint32 msg = (cmd << INTEL_CLN_SB_MCR_SHIFT) |
- ((id << INTEL_CLN_SB_PORT_SHIFT) & 0xFF0000)|
- ((reg << INTEL_CLN_SB_REG_SHIFT) & 0xFF00)|
- INTEL_CLN_SB_BYTEEN;
-
- if (data == NULL) {
- return;
- }
-
- pci_write_config_dword(sb_pcidev, INTEL_CLN_SB_CMD_ADDR, msg);
- pci_read_config_dword(sb_pcidev, INTEL_CLN_SB_DATA_ADDR, data);
-
-}
-
-/**
- * intel_cln_early_sb_write_reg
- *
- * @param cln_sb_id: Sideband identifier
- * @param command: Command to send to destination identifier
- * @param reg: Target register w/r to cln_sb_id
- * @return nothing
- *
- * Utility function to allow thread-safe write of side-band
- */
-void intel_cln_early_sb_write_reg(cln_sb_id id, unsigned char cmd,
- unsigned char reg, uint32 data)
-{
- uint32 msg = (cmd << INTEL_CLN_SB_MCR_SHIFT) |
- ((id << INTEL_CLN_SB_PORT_SHIFT) & 0xFF0000)|
- ((reg << INTEL_CLN_SB_REG_SHIFT) & 0xFF00)|
- INTEL_CLN_SB_BYTEEN;
-
- pci_write_config_dword(sb_pcidev, INTEL_CLN_SB_DATA_ADDR, data);
- pci_write_config_dword(sb_pcidev, INTEL_CLN_SB_CMD_ADDR, msg);
-}
-
-/* Clanton hardware */
-#define PCI_VENDOR_ID_INTEL 0x8086
-#define PCI_DEVICE_ID_CLANTON_SB 0x0958
-
-/**
- * sb_probe
- *
- * @param dev: the PCI device matching
- * @param id: entry in the match table
- * @return 0
- *
- * Callback from PCI layer when dev/vendor ids match.
- * Sets up necessary resources
- */
-static int intel_cln_early_sb_probe(void)
-{
- int sb_dev;
-
- sb_dev = find_pci_device(PCI_DEVICE_ID_CLANTON_SB,
- PCI_VENDOR_ID_INTEL, 0);
- if (sb_dev < 0) {
- kprintf("%s(): error finding PCI device DID 0x%x\n",
- __FUNCTION__, PCI_DEVICE_ID_CLANTON_SB);
- // Reflect the error.
- return sb_dev;
- }
- return 0;
-}
-
-/**
- * cln_remove_imr
- *
- * write default values to reg to set imr free
- *
- */
-static void cln_remove_imr(unsigned char reg_l, unsigned char reg_h,
- unsigned char reg_rm, unsigned char reg_wm)
-{
- intel_cln_early_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
- reg_rm, IMR_READ_ENABLE_ALL);
- intel_cln_early_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
- reg_wm, IMR_WRITE_ENABLE_ALL);
- intel_cln_early_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
- reg_h, IMR_BASE_ADDR);
- intel_cln_early_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
- reg_l, IMR_BASE_ADDR);
-}
-
-/**
- * cln_remove_imr_grub
- *
- * remove imr protection from grub,
- * set imr rw masks to default
- */
-static void cln_remove_imr_grub(void)
-{
- cln_remove_imr(DRAM_IMR0L, DRAM_IMR0H, DRAM_IMR0RM, DRAM_IMR0WM);
-}
-
-/**
- * cln_remove_imr_boot_params
- *
- * remove imr protection from grub,
- * set imr rw masks to default
- */
-static void cln_remove_imr_boot_params(void)
-{
- cln_remove_imr(DRAM_IMR1L, DRAM_IMR1H, DRAM_IMR1RM, DRAM_IMR1WM);
-}
-
-/**
- * cln_remove_imr_bzimage
- *
- * remove imr protection from bzImage,
- * set imr rw masks to default
- */
-static void cln_remove_imr_bzimage(void)
-{
- cln_remove_imr(DRAM_IMR7L, DRAM_IMR7H, DRAM_IMR7RM, DRAM_IMR7WM);
-}
-
-int remove_irm_protections(void)
-{
- uint32 tmp_addr;
-
- if (intel_cln_early_sb_probe() != 0) {
- kprintf("%s() error probing for IRM device\n", __FUNCTION__);
- /* Critial error - bail out */
- return SYSERR;
- }
-
- intel_cln_early_sb_read_reg(SB_ID_ESRAM, CFG_READ_OPCODE,
- DRAM_IMR3L, &tmp_addr);
- if (tmp_addr & IMR_LOCK_BIT) {
- return SYSERR;
- }
-
- if (tmp_addr) {
- intel_cln_early_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
- DRAM_IMR3RM, IMR_READ_ENABLE_ALL);
- intel_cln_early_sb_write_reg(SB_ID_ESRAM, CFG_WRITE_OPCODE,
- DRAM_IMR3WM,
- IMR_WRITE_ENABLE_ALL);
- }
-
- cln_remove_imr_boot_params();
- cln_remove_imr_bzimage();
- cln_remove_imr_grub();
-
- return OK;
-}
diff --git a/system/evec.c b/system/evec.c
index e140c14..8870452 100755
--- a/system/evec.c
+++ b/system/evec.c
@@ -1,55 +1,35 @@
-/* evec.c - initevec, doevec */
+/* evec.c -- initevec, doevec */
#include <xinu.h>
+#include <stdio.h>
-/* Interrupt Descriptor */
-
-struct __attribute__ ((__packed__)) idt {
- unsigned short igd_loffset;
- unsigned short igd_segsel;
- unsigned int igd_rsvd : 5;
- unsigned int igd_mbz : 3;
- unsigned int igd_type : 5;
- unsigned int igd_dpl : 2;
- unsigned int igd_present : 1;
- unsigned short igd_hoffset;
-};
+/*#define STKTRACE*/
+/*#define REGDUMP*/
-/* Note:
- * Global girmask is used as a mask for interrupts that don't have a
- * handler set. disable() & restore() are OR-ed with it to get the
- * mask actually used.
+/*
+ * The girmask is used as a mask for interrupts that don't have a
+ * handler set. disable() & restore() are OR-ed with it to get the
+ * mask actually used.
*/
uint16 girmask;
-#define IMR1 0x21 /* Interrupt Mask Register #1 */
-#define IMR2 0xA1 /* Interrupt Mask Register #2 */
-
-#define ICU1 0x20 /* I/O port address, 8259A #1 */
-#define ICU2 0xA0 /* I/O port address, 8258A #2 */
-
-#define OCR ICU1 /* Operation Command Register */
-#define IMR (ICU1+1) /* Interrupt Mask Register */
-
-#define EOI 0x20 /* non-specific end of interrupt */
-
-#define NID 48 /* Number of interrupt descriptors */
-#define IGDT_TRAPG 15 /* Trap Gate */
-
-void setirmask(void); /* Set interrupt mask */
-
-extern struct idt idt[NID]; /* Interrupt descriptor table */
-extern long defevec[]; /* Default exception vector */
+extern void setirmask(void);
+extern struct idt idt[NID];
+extern struct segtr idtr;
+extern long defevec[];
+extern void userret(void);
+extern void init8259();
+extern int lidt();
/*------------------------------------------------------------------------
- * initevec - Initialize exception vectors to a default handler
+ * initevec - initialize exception vectors to a default handler
*------------------------------------------------------------------------
*/
int32 initevec()
{
int i;
- girmask = 0; /* Until vectors initialized */
+ girmask = 0; /* until vectors initialized */
for (i=0; i<NID; ++i) {
set_evec(i, (long)defevec[i]);
@@ -59,33 +39,15 @@ int32 initevec()
* "girmask" masks all (bus) interrupts with the default handler.
* initially, all, then cleared as handlers are set via set_evec()
*/
- girmask = 0xfffb; /* Leave bit 2 enabled for IC cascade */
+ girmask = 0xfffb; /* leave bit 2 enabled for IC cascade */
lidt();
-
- /* Initialize the 8259A interrupt controllers */
-
- /* Master device */
- outb(ICU1, 0x11); /* ICW1: icw4 needed */
- outb(ICU1+1, 0x20); /* ICW2: base ivec 32 */
- outb(ICU1+1, 0x4); /* ICW3: cascade on irq2 */
- outb(ICU1+1, 0x1); /* ICW4: buf. master, 808x mode */
- outb(ICU1, 0xb); /* OCW3: set ISR on read */
-
- /* Slave device */
- outb(ICU2, 0x11); /* ICW1: icw4 needed */
- outb(ICU2+1, 0x28); /* ICW2: base ivec 40 */
- outb(ICU2+1, 0x2); /* ICW3: slave on irq2 */
- outb(ICU2+1, 0xb); /* ICW4: buf. slave, 808x mode */
- outb(ICU2, 0xb); /* OCW3: set ISR on read */
-
- setirmask();
-
- return OK;
+ init8259();
+ return(OK);
}
/*------------------------------------------------------------------------
- * set_evec - Set exception vector to point to an exception handler
+ * set_evec - set exception vector to point to an exception handler
*------------------------------------------------------------------------
*/
int32 set_evec(uint32 xnum, uint32 handler)
@@ -94,7 +56,7 @@ int32 set_evec(uint32 xnum, uint32 handler)
pidt = &idt[xnum];
pidt->igd_loffset = handler;
- pidt->igd_segsel = 0x8; /* Kernel code segment */
+ pidt->igd_segsel = 0x8; /* kernel code segment */
pidt->igd_mbz = 0;
pidt->igd_type = IGDT_TRAPG;
pidt->igd_dpl = 0;
@@ -102,26 +64,12 @@ int32 set_evec(uint32 xnum, uint32 handler)
pidt->igd_hoffset = handler >> 16;
if (xnum > 31 && xnum < 48) {
- /* Enable the interrupt in the global IR mask */
+ /* enable the interrupt in the global IR mask */
xnum -= 32;
girmask &= ~(1<<xnum);
- setirmask(); /* Pass it to the hardware */
+ setirmask(); /* pass it to the hardware */
}
- return OK;
-}
-
-/*------------------------------------------------------------------------
- * setirmask - Set the interrupt mask in the controller
- *------------------------------------------------------------------------
- */
-void setirmask(void)
-{
- if (girmask == 0) { /* Skip until girmask initialized */
- return;
- }
- outb(IMR1, girmask&0xff);
- outb(IMR2, (girmask>>8)&0xff);
- return;
+ return(OK);
}
char *inames[] = {
@@ -143,55 +91,40 @@ char *inames[] = {
"coprocessor error"
};
+static long *fp;
/*------------------------------------------------------------------------
- * trap - print debugging info when a trap occurrs
+ * trap -- print some debugging info when a trap occurred
+ * Note: Need some more work.
*------------------------------------------------------------------------
*/
-void trap (
- int inum, /* Interrupt number */
- long *sp /* Saved stack pointer */
- )
-{
- intmask mask; /* Saved interrupt mask */
- long *regs; /* Pointer to saved regs*/
+#define REGDUMP
- /* Disable interrupts */
+void trap(int inum)
+{
+ long *sp;
+ intmask mask;
mask = disable();
-
- /* Get the location of saved registers */
-
- regs = sp;
-
- /* Print the trap message */
-
+ kprintf("TRAP\n");
+ asm("movl %ebp,fp");
+ sp = fp + 15; /* eflags/CS/eip/ebp/regs/trap#/Xtrap/ebp */
kprintf("Xinu trap!\n");
- if (inum < 16) {
+ if (inum < 16)
kprintf("exception %d (%s) currpid %d (%s)\n", inum,
inames[inum], currpid, proctab[currpid].prname);
- } else {
- kprintf("exception %d currpid %d (%s)\n", inum, currpid,
+ else
+ kprintf("exception %d currpid %d (%s)\n", inum, currpid,
proctab[currpid].prname);
- }
-
- /* Adjust stack pointer to get debugging information */
- /* 8 registers and 1 %ebp pushed in Xint */
-
- sp = regs + 1 + 8;
-
- /* Print the debugging information related to interrupt */
-
+#ifdef REGDUMP
+ kprintf("eflags %X ", *sp--);
+ sp--; /* skip OLD CS */
+ kprintf("eip %X ", *sp);
+ sp--;
if (inum == 8 || (inum >= 10 && inum <= 14)) {
kprintf("error code %08x (%u)\n", *sp, *sp);
- sp++;
+ sp--;
}
- kprintf("CS %X eip %X\n", *(sp + 1), *sp);
- kprintf("eflags %X\n", *(sp + 2));
-
- /* Dump the register values */
-
- sp = regs + 7;
-
+ sp--; /* skip FP for Xint call */
kprintf("register dump:\n");
kprintf("eax %08X (%u)\n", *sp, *sp);
sp--;
@@ -204,11 +137,16 @@ void trap (
kprintf("esp %08X (%u)\n", *sp, *sp);
sp--;
kprintf("ebp %08X (%u)\n", *sp, *sp);
+ fp = sp;
sp--;
kprintf("esi %08X (%u)\n", *sp, *sp);
sp--;
kprintf("edi %08X (%u)\n", *sp, *sp);
sp--;
+#endif // REGDUMP
+#ifdef STKTRACE
+ stacktrace(currpid);
+#endif // STKTRACE
panic("Trap processing complete...\n");
restore(mask);
diff --git a/system/getutime.c b/system/getutime.c
index 7c941ac..708bda5 100644
--- a/system/getutime.c
+++ b/system/getutime.c
@@ -43,7 +43,7 @@ status getutime(
/* use the default server */
if (NetData.ntpserver == 0) {
- if (dot2ip(TIMESERVER, &NetData.ntpserver) == SYSERR) {
+ if (dnslookup(TIMESERVER, &NetData.ntpserver) == SYSERR) {
return SYSERR;
}
}
diff --git a/system/i386.c b/system/i386.c
new file mode 100644
index 0000000..204edd2
--- /dev/null
+++ b/system/i386.c
@@ -0,0 +1,139 @@
+/* i386.c - setsegs */
+
+#include <xinu.h>
+#include <icu.h>
+#include <stdio.h>
+
+#define BOOTP_CODE
+#define KCODE 1
+#define KSTACK 2
+#define KDATA 3
+
+struct sd gdt_copy[NGD] = {
+ /* 0th entry NULL */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ /* 1st, Kernel Code Segment */
+ { 0xffff, 0, 0, 6, 1, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 },
+ /* 2nd, Kernel Data Segment */
+ { 0xffff, 0, 0, 2, 0, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 },
+ /* 3rd, Kernel Stack Segment */
+ { 0xffff, 0, 0, 2, 0, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 },
+ /* 4st, Bootp Code Segment */
+ { 0xffff, 0, 0, 6, 1, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 },
+ /* 5th, Code Segment for BIOS32 request */
+ { 0xffff, 0, 0, 6, 1, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 },
+ /* 6th, Data Segment for BIOS32 request */
+ { 0xffff, 0, 0, 2, 0, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 },
+};
+
+extern void setirmask(void);
+extern struct sd gdt[];
+extern struct segtr gdtr;
+
+long initsp; /* initial SP for nulluser() */
+
+extern void *maxheap;
+
+/*------------------------------------------------------------------------
+ * setsegs - initialize the 386 processor
+ *------------------------------------------------------------------------
+ */
+void setsegs()
+{
+ extern int etext;
+ struct sd *psd;
+ uint32 np, npages;
+
+ npages = 4096; /* 16 Meg for now */
+ maxheap = (char *)(npages * NBPG - 1);
+
+ psd = &gdt_copy[1]; /* kernel code segment */
+ np = ((int)&etext + NBPG-1) / NBPG; /* # code pages */
+ psd->sd_lolimit = np;
+ psd->sd_hilimit = np >> 16;
+
+ psd = &gdt_copy[2]; /* kernel data segment */
+ psd->sd_lolimit = npages;
+ psd->sd_hilimit = npages >> 16;
+
+ psd = &gdt_copy[3]; /* kernel stack segment */
+ psd->sd_lolimit = npages;
+ psd->sd_hilimit = npages >> 16;
+
+ psd = &gdt_copy[4]; /* bootp code segment */
+ psd->sd_lolimit = npages; /* Allows execution of 0x100000 CODE */
+ psd->sd_hilimit = npages >> 16;
+
+ memcpy(gdt, gdt_copy, sizeof(gdt_copy));
+ initsp = npages*NBPG - 4;
+}
+
+extern int outb(int, int);
+
+/*------------------------------------------------------------------------
+ * init8259 - initialize the 8259A interrupt controllers
+ *------------------------------------------------------------------------
+ */
+void init8259()
+{
+
+ /* Master device */
+ outb(ICU1, 0x11); /* ICW1: icw4 needed */
+ outb(ICU1+1, 0x20); /* ICW2: base ivec 32 */
+ outb(ICU1+1, 0x4); /* ICW3: cascade on irq2 */
+ outb(ICU1+1, 0x1); /* ICW4: buf. master, 808x mode */
+ outb(ICU1, 0xb); /* OCW3: set ISR on read */
+
+ /* Slave device */
+ outb(ICU2, 0x11); /* ICW1: icw4 needed */
+ outb(ICU2+1, 0x28); /* ICW2: base ivec 40 */
+ outb(ICU2+1, 0x2); /* ICW3: slave on irq2 */
+ outb(ICU2+1, 0xb); /* ICW4: buf. slave, 808x mode */
+ outb(ICU2, 0xb); /* OCW3: set ISR on read */
+
+ setirmask();
+}
+
+void pseg(struct sd *psd)
+{
+ int i;
+ unsigned char *pb = (unsigned char *)psd;
+ unsigned int base;
+ unsigned int limit;
+
+ kprintf("pseg (%X)\n", pb);
+ kprintf("hex: %02x", (unsigned int)*pb++);
+ for(i=1; i<8; ++i) {
+ kprintf(" (%X)", pb);
+ kprintf(" %02x", (unsigned int)*pb++);
+ }
+ limit = ((int)psd->sd_hilimit) << 16;
+ limit |= psd->sd_lolimit;
+ base = ((int)psd->sd_hibase) << 24;
+ base |= ((int)psd->sd_midbase)<< 16;
+ base |= psd->sd_lobase;
+
+ kprintf("\nby field: base %X limit %d perm %d\n", base, limit,
+ psd->sd_perm);
+ kprintf("iscode %d isapp %d dpl %d present %d avl %d\n",
+ psd->sd_iscode, psd->sd_isapp, psd->sd_dpl, psd->sd_present,
+ psd->sd_avl);
+ kprintf("mbz %d 32b %d gran %d\n", psd->sd_mbz, psd->sd_32b,
+ psd->sd_gran);
+}
+#define IMR1 0x21
+#define IMR2 0xA1
+
+/*------------------------------------------------------------------------
+ * setirmask - set the interrupt mask in the controller
+ *------------------------------------------------------------------------
+ */
+void setirmask(void)
+{
+ if (girmask == 0) { /* skip until girmask initialized */
+ return;
+ }
+ outb(IMR1, girmask&0xff);
+ outb(IMR2, (girmask>>8)&0xff);
+ return;
+}
diff --git a/system/initialize.c b/system/initialize.c
index 789cf8c..a6d6a98 100644
--- a/system/initialize.c
+++ b/system/initialize.c
@@ -78,10 +78,9 @@ void nulluser()
enable();
- /* Limit network relevant calls for CS503 courses */
- ///* Initialize the network stack and start processes */
+ /* Initialize the network stack and start processes */
- //net_init();
+ net_init();
/* Create a process to finish startup and start main */
@@ -101,32 +100,31 @@ void nulluser()
/*------------------------------------------------------------------------
*
* startup - Finish startup takss that cannot be run from the Null
- * process and then create and resumethe main process
+ * process and then create and resume the main process
*
*------------------------------------------------------------------------
*/
local process startup(void)
{
- /* Limit network relevant calls for CS503 courses */
- //uint32 ipaddr; /* Computer's IP address */
- //char str[128]; /* String used to format output */
-
-
- ///* Use DHCP to obtain an IP address and format it */
-
- //ipaddr = getlocalip();
- //if ((int32)ipaddr == SYSERR) {
- // kprintf("Cannot obtain an IP address\n");
- //} else {
- // /* Print the IP in dotted decimal and hex */
- // ipaddr = NetData.ipucast;
- // sprintf(str, "%d.%d.%d.%d",
- // (ipaddr>>24)&0xff, (ipaddr>>16)&0xff,
- // (ipaddr>>8)&0xff, ipaddr&0xff);
- //
- // kprintf("Obtained IP address %s (0x%08x)\n", str,
- // ipaddr);
- //}
+ uint32 ipaddr; /* Computer's IP address */
+ char str[128]; /* String used to format output */
+
+
+ /* Use DHCP to obtain an IP address and format it */
+
+ ipaddr = getlocalip();
+ if ((int32)ipaddr == SYSERR) {
+ kprintf("Cannot obtain an IP address\n");
+ } else {
+ /* Print the IP in dotted decimal and hex */
+ ipaddr = NetData.ipucast;
+ sprintf(str, "%d.%d.%d.%d",
+ (ipaddr>>24)&0xff, (ipaddr>>16)&0xff,
+ (ipaddr>>8)&0xff, ipaddr&0xff);
+
+ kprintf("Obtained IP address %s (0x%08x)\n", str,
+ ipaddr);
+ }
/* Create a process to execute function main() */
@@ -151,10 +149,6 @@ static void sysinit()
struct procent *prptr; /* Ptr to process table entry */
struct sentry *semptr; /* Ptr to semaphore table entry */
- /* Platform Specific Initialization */
-
- platinit();
-
/* Reset the console */
kprintf(CONSOLE_RESET);
@@ -216,6 +210,11 @@ static void sysinit()
readylist = newqueue();
+
+ /* initialize the PCI bus */
+
+ pci_init();
+
/* Initialize the real time clock */
clkinit();
diff --git a/system/kprintf.c b/system/kprintf.c
index 5abbc70..27d30dc 100644
--- a/system/kprintf.c
+++ b/system/kprintf.c
@@ -3,46 +3,51 @@
#include <xinu.h>
#include <stdarg.h>
-
/*------------------------------------------------------------------------
* kputc - use polled I/O to write a character to the console
*------------------------------------------------------------------------
*/
-syscall kputc(byte c) /* Character to write */
+syscall kputc(
+ byte c /* character to write */
+ )
{
struct dentry *devptr;
- volatile struct uart_csreg *csrptr;
+ volatile struct uart_csreg *csrptr;
intmask mask;
/* Disable interrupts */
mask = disable();
+ /* Get CSR address of the console */
+
devptr = (struct dentry *) &devtab[CONSOLE];
csrptr = (struct uart_csreg *)devptr->dvcsr;
/* Fail if no console device was found */
+
if (csrptr == NULL) {
restore(mask);
return SYSERR;
}
/* Repeatedly poll the device until it becomes nonbusy */
- while ((csrptr->lsr & UART_LSR_THRE) == 0) {
+
+ while ((io_inb(csrptr->lsr) & UART_LSR_THRE) == 0) {
;
}
/* Write the character */
- csrptr->buffer = c;
+ io_outb(csrptr->buffer, c);
/* Honor CRLF - when writing NEWLINE also send CARRIAGE RETURN */
+
if (c == '\n') {
/* Poll until transmitter queue is empty */
- while ((csrptr->lsr & UART_LSR_THRE) == 0) {
+ while ((io_inb(csrptr->lsr) & UART_LSR_THRE) == 0) {
;
}
- csrptr->buffer = '\r';
+ io_outb(csrptr->buffer, '\r');
}
-
restore(mask);
return OK;
}
@@ -54,7 +59,7 @@ syscall kputc(byte c) /* Character to write */
syscall kgetc(void)
{
int irmask;
- volatile struct uart_csreg *csrptr;
+ volatile struct uart_csreg *csrptr;
byte c;
struct dentry *devptr;
intmask mask;
@@ -71,25 +76,25 @@ syscall kgetc(void)
return SYSERR;
}
- irmask = csrptr->ier; /* Save UART interrupt state. */
- csrptr->ier = 0; /* Disable UART interrupts. */
+ irmask = io_inb(csrptr->ier); /* Save UART interrupt state. */
+ io_outb(csrptr->ier, 0); /* Disable UART interrupts. */
/* wait for UART transmit queue to empty */
- while (0 == (csrptr->lsr & UART_LSR_DR)) {
+ while ((io_inb(csrptr->lsr) & UART_LSR_DR) == 0) {
; /* Do Nothing */
}
/* Read character from Receive Holding Register */
- c = csrptr->rbr;
- csrptr->ier = irmask; /* Restore UART interrupts. */
+ c = io_inb(csrptr->rbr);
+ io_outb(csrptr->ier, irmask); /* Restore UART interrupts. */
restore(mask);
return c;
}
-extern void _doprnt(char *, va_list ap, int (*)(int));
+extern void _doprnt(char *, va_list, int (*)(int));
/*------------------------------------------------------------------------
* kprintf - use polled I/O to print formatted output on the console
diff --git a/system/main.c b/system/main.c
index a29e555..9d70277 100644
--- a/system/main.c
+++ b/system/main.c
@@ -4,28 +4,27 @@
process main(void)
{
-
- kprintf("\nHello World!\n");
- kprintf("\nI'm the first XINU app and running function main() in system/main.c.\n");
- kprintf("\nI was created by nulluser() in system/initialize.c using create().\n");
- kprintf("\nMy creator will turn itself into the do-nothing null process.\n");
- kprintf("\nI will create a second XINU app that runs shell() in shell/shell.c as an example.\n");
- kprintf("\nYou can do something else, or do nothing; it's completely up to you.\n");
- kprintf("\n...creating a shell\n");
+ pid32 shpid; /* Shell process ID */
+
+ printf("\n\n");
+
+ /* Create a local file system on the RAM disk */
+
+ lfscreate(RAM0, 40, 20480);
/* Run the Xinu shell */
recvclr();
- resume(create(shell, 8192, 50, "shell", 1, CONSOLE));
+ resume(shpid = create(shell, 8192, 50, "shell", 1, CONSOLE));
/* Wait for shell to exit and recreate it */
while (TRUE) {
- receive();
+ if (receive() == shpid) {
sleepms(200);
kprintf("\n\nMain process recreating shell\n\n");
- resume(create(shell, 4096, 20, "shell", 1, CONSOLE));
+ resume(shpid = create(shell, 4096, 20, "shell", 1, CONSOLE));
+ }
}
return OK;
-
}
diff --git a/system/mark.c b/system/mark.c
index f20a304..e1f060a 100644
--- a/system/mark.c
+++ b/system/mark.c
@@ -17,31 +17,56 @@ void markinit(void)
}
+/*------------------------------------------------------------------------
+ * notmarked - Return nonzero if a location has not been marked
+ *------------------------------------------------------------------------
+ */
+syscall notmarked(memmark loc)
+{
+ intmask mask; /* Saved interrupt mask */
+
+ mask = disable();
+
+ /* See if the location has been marked */
+
+ if (loc[0]<0 || loc[0]>=nmarks || marks[loc[0]] != loc) {
+ restore(mask);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
/*------------------------------------------------------------------------
* mark - Mark a specified memory location
*------------------------------------------------------------------------
*/
-status mark(
+syscall mark(
int32 *loc /* Location to mark */
)
+
{
+ intmask mask; /* Saved interrupt mask */
+
+ mask = disable();
/* If location is already marked, do nothing */
if ( (*loc>=0) && (*loc<nmarks) && (marks[*loc]==loc) ) {
+ restore(mask);
return OK;
}
/* If no more memory marks are available, indicate an error */
if (nmarks >= MAXMARK) {
+ restore(mask);
return SYSERR;
}
/* Obtain exclusive access and mark the specified location */
- wait(mkmutex);
marks[ (*loc) = nmarks++ ] = loc;
- signal(mkmutex);
+ restore(mask);
return OK;
}
diff --git a/system/meminit.c b/system/meminit.c
index f2bd045..8f3b3b7 100644
--- a/system/meminit.c
+++ b/system/meminit.c
@@ -1,5 +1,3 @@
-/* meminit.c - memory bounds and free list init */
-
#include <xinu.h>
/* Memory bounds */
@@ -7,170 +5,38 @@
void *minheap; /* Start of heap */
void *maxheap; /* Highest valid heap address */
-/* Memory map structures */
-
-uint32 bootsign = 1; /* Boot signature of the boot loader */
-
-struct mbootinfo *bootinfo = (struct mbootinfo *)1;
- /* Base address of the multiboot info */
- /* provided by GRUB, initialized just */
- /* to guarantee it is in the DATA */
- /* segment and not the BSS */
-
-/* Segment table structures */
-
-/* Segment Descriptor */
-
-struct __attribute__ ((__packed__)) sd {
- unsigned short sd_lolimit;
- unsigned short sd_lobase;
- unsigned char sd_midbase;
- unsigned char sd_access;
- unsigned char sd_hilim_fl;
- unsigned char sd_hibase;
-};
-
-#define NGD 4 /* Number of global descriptor entries */
-#define FLAGS_GRANULARITY 0x80
-#define FLAGS_SIZE 0x40
-#define FLAGS_SETTINGS (FLAGS_GRANULARITY | FLAGS_SIZE)
-
-struct sd gdt_copy[NGD] = {
-/* sd_lolimit sd_lobase sd_midbase sd_access sd_hilim_fl sd_hibase */
-/* 0th entry NULL */
-{ 0, 0, 0, 0, 0, 0, },
-/* 1st, Kernel Code Segment */
-{ 0xffff, 0, 0, 0x9a, 0xcf, 0, },
-/* 2nd, Kernel Data Segment */
-{ 0xffff, 0, 0, 0x92, 0xcf, 0, },
-/* 3rd, Kernel Stack Segment */
-{ 0xffff, 0, 0, 0x92, 0xcf, 0, },
-};
-
-extern struct sd gdt[]; /* Global segment table */
-
/*------------------------------------------------------------------------
* meminit - initialize memory bounds and the free memory list
*------------------------------------------------------------------------
*/
void meminit(void) {
- struct memblk *memptr; /* Ptr to memory block */
- struct mbmregion *mmap_addr; /* Ptr to mmap entries */
- struct mbmregion *mmap_addrend; /* Ptr to end of mmap region */
- struct memblk *next_memptr; /* Ptr to next memory block */
- uint32 next_block_length; /* Size of next memory block */
-
- mmap_addr = (struct mbmregion*)NULL;
- mmap_addrend = (struct mbmregion*)NULL;
-
- /* Initialize the free list */
- memptr = &memlist;
- memptr->mnext = (struct memblk *)NULL;
- memptr->mlength = 0;
-
- /* Initialize the memory counters */
- /* Heap starts at the end of Xinu image */
- minheap = (void*)&end;
- maxheap = minheap;
-
- /* Check if Xinu was loaded using the multiboot specification */
- /* and a memory map was included */
- if(bootsign != MULTIBOOT_SIGNATURE) {
- panic("could not find multiboot signature");
- }
- if(!(bootinfo->flags & MULTIBOOT_BOOTINFO_MMAP)) {
- panic("no mmap found in boot info");
- }
-
- /* Get base address of mmap region (passed by GRUB) */
- mmap_addr = (struct mbmregion*)bootinfo->mmap_addr;
-
- /* Calculate address that follows the mmap block */
- mmap_addrend = (struct mbmregion*)((uint8*)mmap_addr + bootinfo->mmap_length);
-
- /* Read mmap blocks and initialize the Xinu free memory list */
- while(mmap_addr < mmap_addrend) {
-
- /* If block is not usable, skip to next block */
- if(mmap_addr->type != MULTIBOOT_MMAP_TYPE_USABLE) {
- mmap_addr = (struct mbmregion*)((uint8*)mmap_addr + mmap_addr->size + 4);
- continue;
- }
-
- if((uint32)maxheap < ((uint32)mmap_addr->base_addr + (uint32)mmap_addr->length)) {
- maxheap = (void*)((uint32)mmap_addr->base_addr + (uint32)mmap_addr->length);
- }
-
- /* Ignore memory blocks within the Xinu image */
- if((mmap_addr->base_addr + mmap_addr->length) < ((uint32)minheap)) {
- mmap_addr = (struct mbmregion*)((uint8*)mmap_addr + mmap_addr->size + 4);
- continue;
- }
-
- /* The block is usable, so add it to Xinu's memory list */
-
- /* This block straddles the end of the Xinu image */
- if((mmap_addr->base_addr <= (uint32)minheap) &&
- ((mmap_addr->base_addr + mmap_addr->length) >
- (uint32)minheap)) {
-
- /* This is the first free block, base address is the minheap */
- next_memptr = (struct memblk *)roundmb(minheap);
-
- /* Subtract Xinu image from length of block */
- next_block_length = (uint32)truncmb(mmap_addr->base_addr + mmap_addr->length - (uint32)minheap);
- } else {
-
- /* Handle a free memory block other than the first one */
- next_memptr = (struct memblk *)roundmb(mmap_addr->base_addr);
-
- /* Initialize the length of the block */
- next_block_length = (uint32)truncmb(mmap_addr->length);
- }
-
- /* Add then new block to the free list */
- memptr->mnext = next_memptr;
- memptr = memptr->mnext;
- memptr->mlength = next_block_length;
- memlist.mlength += next_block_length;
-
- /* Move to the next mmap block */
- mmap_addr = (struct mbmregion*)((uint8*)mmap_addr + mmap_addr->size + 4);
- }
-
- /* End of all mmap blocks, and so end of Xinu free list */
- if(memptr) {
- memptr->mnext = (struct memblk *)NULL;
- }
-}
-
-
-/*------------------------------------------------------------------------
- * setsegs - Initialize the global segment table
- *------------------------------------------------------------------------
- */
-void setsegs()
-{
- extern int etext;
- struct sd *psd;
- uint32 np, ds_end;
-
- ds_end = 0xffffffff/PAGE_SIZE; /* End page number of Data segment */
-
- psd = &gdt_copy[1]; /* Kernel code segment: identity map from address
- 0 to etext */
- np = ((int)&etext - 0 + PAGE_SIZE-1) / PAGE_SIZE; /* Number of code pages */
- psd->sd_lolimit = np;
- psd->sd_hilim_fl = FLAGS_SETTINGS | ((np >> 16) & 0xff);
-
- psd = &gdt_copy[2]; /* Kernel data segment */
- psd->sd_lolimit = ds_end;
- psd->sd_hilim_fl = FLAGS_SETTINGS | ((ds_end >> 16) & 0xff);
-
- psd = &gdt_copy[3]; /* Kernel stack segment */
- psd->sd_lolimit = ds_end;
- psd->sd_hilim_fl = FLAGS_SETTINGS | ((ds_end >> 16) & 0xff);
-
- memcpy(gdt, gdt_copy, sizeof(gdt_copy));
+ struct memblk *memptr; /* Ptr to memory block */
+
+ /* Initialize the free memory list */
+
+ /* Note: we pre-allocate the "hole" between 640K and 1024K */
+
+ maxheap = (void *)0x600000; /* Assume 64 Mbytes for now */
+ minheap = &end;
+
+ memptr = memlist.mnext = (struct memblk *)roundmb(minheap);
+ if ((char *)(maxheap+1) > HOLESTART) {
+ /* create two blocks that straddle the hole */
+ memptr->mnext = (struct memblk *)HOLEEND;
+ memptr->mlength = (int) truncmb((unsigned) HOLESTART -
+ (unsigned)&end - 4);
+ memptr = (struct memblk *) HOLEEND;
+ memptr->mnext = (struct memblk *) NULL;
+ memptr->mlength = (int) truncmb( (uint32)maxheap -
+ (uint32)HOLEEND - NULLSTK);
+ } else {
+ /* initialize free memory list to one block */
+ memlist.mnext = memptr = (struct memblk *) roundmb(&end);
+ memptr->mnext = (struct memblk *) NULL;
+ memptr->mlength = (uint32) truncmb((uint32)maxheap -
+ (uint32)&end - NULLSTK);
+ }
+
+ return;
}
diff --git a/system/mkbufpool.c b/system/mkbufpool.c
index 9191b62..48040a6 100644
--- a/system/mkbufpool.c
+++ b/system/mkbufpool.c
@@ -27,7 +27,10 @@ bpid32 mkbufpool(
bufsiz = ( (bufsiz + 3) & (~3) );
- buf = (char *)getmem( numbufs * (bufsiz+sizeof(bpid32)) );
+ /* Increase buffer size to include a pool ID */
+
+ bufsiz += sizeof(bpid32);
+ buf = (char *)getmem( numbufs * bufsiz );
if ((int32)buf == SYSERR) {
restore(mask);
return (bpid32)SYSERR;
@@ -35,14 +38,12 @@ bpid32 mkbufpool(
poolid = nbpools++;
bpptr = &buftab[poolid];
bpptr->bpnext = (struct bpentry *)buf;
- bpptr->bpsize = bufsiz;
if ( (bpptr->bpsem = semcreate(numbufs)) == SYSERR) {
- freemem(buf, numbufs * (bufsiz+sizeof(bpid32)) );
+ freemem(buf, numbufs * bufsiz );
nbpools--;
restore(mask);
return (bpid32)SYSERR;
}
- bufsiz+=sizeof(bpid32);
for (numbufs-- ; numbufs>0 ; numbufs-- ) {
bpptr = (struct bpentry *)buf;
buf += bufsiz;
diff --git a/system/pci.c b/system/pci.c
index 1a6732b..b73c9a1 100755
--- a/system/pci.c
+++ b/system/pci.c
@@ -2,255 +2,374 @@
#include <xinu.h>
-/*
- * Base and length of memory-mapped PCI configuration space.
- *
- * These values are correct for Galileo and many other X86 platforms,
- * but may need to be changed for some platforms. In the general case,
- * BIOS sets up MMConfig space and passes the base and length values to
- * the OS via ACPI tables. For simplicity, Xinu avoids parsing ACPI.
- * Note: If these values are in doubt, one easy way to determine the
- * correct values is to boot Linux and scan its dmesg log file, as
- * follows:
- * dmesg -s 30000000 | grep -i mmconfig
- */
+static int pcibios_init(void);
+static int check_pcibios(void);
+static unsigned long bios32_service(unsigned long service);
+static bios32 *bios32ptr; /* pointer to the BIOS 32 structure */
-#define MMCONFIG_BASE 0xe0000000 /* Base of MMConfig space */
-#define MMCONFIG_LEN 0x10000000 /* Length of MMConfig space */
+/* from linux */
+static unsigned long bios32_entry = 0;
+static struct {
+ unsigned long address;
+ unsigned short segment;
+} bios32_indirect = { 0, 0 + 5*0x08 /* 0x10 KERNEL_CS */ };
+
+static long pcibios_entry = 0;
+static struct {
+ unsigned long address;
+ unsigned short segment;
+} pci_indirect = { 0, 0+5*0x08 /* 0x10 KERNEL_CS */ };
/*------------------------------------------------------------------------
- * pci_init - Initialize the PCI bios structures
+ * pci_init - initialize the PCI bios structures and such
*------------------------------------------------------------------------
*/
int32 pci_init(void)
{
+ if (pcibios_init() == OK) {
return OK;
+ } else {
+ kprintf("pci_init: PCI BIOS initialization failed\n");
+ return SYSERR;
+ }
}
/*------------------------------------------------------------------------
- * regAddress_MMConfig - Get the address of a register in MMConfig space
+ * pcibios_init
*------------------------------------------------------------------------
*/
-static inline void *
-regAddress_MMConfig(
- unsigned int mmconfigBase,
- unsigned int bus,
- unsigned int device,
- unsigned int function,
- unsigned int offset
-)
+int pcibios_init(void)
{
- void *retval;
-
- retval = (void *)
- (mmconfigBase +
- (bus * PCIE_BYTES_PER_BUS) +
- (device * PCIE_BYTES_PER_DEVICE) +
- (function * PCIE_BYTES_PER_FUNCTION) +
- offset);
- return retval;
-}
+ unsigned char *ptr;
+ bios32 *bptr;
+ int i,length;
+ unsigned char cksum;
-/*------------------------------------------------------------------------
- * encodePCIDevice - Encode PCI bus/device/func into an an unsigned int
- *------------------------------------------------------------------------
- */
-static inline unsigned int
-encodePCIDevice(unsigned int bus, unsigned int dev, unsigned int func)
-{
- unsigned int retval;
+ /* search for it */
+ for (bptr = (bios32 *)BIOS32_MIN_ADDR;
+ bptr <= (bios32 *)BIOS32_MAX_ADDR; bptr++) {
+ /* check for signature first */
+ if (bptr->signature != BIOS32_SIGNATURE)
+ continue;
+ /* now check the checksum */
+ cksum=0;
+ length = bptr->length * BIOS32_UNITS;
+ ptr=(unsigned char *)bptr;
+ for (i=0; i<length; i++) {
+ cksum += ptr[i];
+ }
+ if (cksum != 0) {
+ kprintf("pcibios_init: invalid checksum at 0x%08lx\n",bptr);
+ continue;
+ }
+ /* verify the revision */
+ if (bptr->revision != 0) {
+ kprintf("pcibios_init: invalid revision %d at 0x%08lx\n",
+ bptr->revision,bptr);
+ continue;
+ }
+ /* If I am here, then all tests were valid */
+ bios32ptr = bptr; /* set the global reference */
- retval = (bus << PCI_BUS_SHIFT) | (dev << PCI_DEV_SHIFT) | func;
- return retval;
-}
+ bios32_entry = bios32ptr->bios32_entry;
+ bios32_indirect.address = bios32_entry;
+
+ if (check_pcibios()) {
+ return OK;
+ } else {
+ return SYSERR;
+ }
+ }
+
+ /* If this point is reached, nothing was found */
+ kprintf("pcibios_init: no BIOS32 Service Directory was found\n");
+ return SYSERR;
-/*------------------------------------------------------------------------
- * encodedPCIDevToBus - Extact bus from encoded bus/device/func
- *------------------------------------------------------------------------
- */
-static inline unsigned int
-encodedPCIDevToBus(unsigned int encodedDev)
-{
- return ((encodedDev >> PCI_BUS_SHIFT) & PCI_BUS_MASK);
}
+
/*------------------------------------------------------------------------
- * encodedPCIDevToDevice - Extract device from encoded bus/device/func
+ * check_pcibios - Check for a PCI BIOS
*------------------------------------------------------------------------
*/
-static inline unsigned int
-encodedPCIDevToDevice(unsigned int encodedDev)
+int check_pcibios(void)
{
- return ((encodedDev >> PCI_DEV_SHIFT) & PCI_DEV_MASK);
+ unsigned long signature;
+ unsigned char present_status;
+#ifdef DEBUG
+ unsigned char major_revision;
+ unsigned char minor_revision;
+#endif
+ unsigned long flags;
+ int pack;
+
+ if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
+ pci_indirect.address = pcibios_entry;
+ save_flags(flags);
+ cli();
+ __asm__( "lcall *(%%edi)\n\t"
+ "jc 1f\n\t"
+ "xorb %%ah, %%ah\n"
+ "1:\tshl $8, %%eax\n\t"
+ "movw %%bx, %%ax"
+ : "=d" (signature),
+ "=a" (pack)
+ : "1" (PCIBIOS_PCI_BIOS_PRESENT),
+ "D" (&pci_indirect)
+ : "bx", "cx");
+ restore_flags(flags);
+
+ present_status = (pack >> 16) & 0xff;
+#ifdef DEBUG
+ major_revision = (pack >> 8) & 0xff;
+ minor_revision = pack & 0xff;
+#endif
+ if (present_status || (signature != PCI_SIGNATURE)) {
+ kprintf ("pcibios_init : %s : BIOS32 Service Directory says PCI BIOS is present,\n"
+ " but PCI_BIOS_PRESENT subfunction fails with present status of 0x%x\n"
+ " and signature of 0x%08lx (%c%c%c%c).\n",
+ (signature == PCI_SIGNATURE) ? "WARNING" : "ERROR",
+ present_status, signature,
+ (char) (signature >> 0), (char) (signature >> 8),
+ (char) (signature >> 16), (char) (signature >> 24));
+
+ if (signature != PCI_SIGNATURE)
+ pcibios_entry = 0;
+ }
+ if (pcibios_entry != 0) {
+#ifdef DEBUG
+ kprintf ("pcibios_init : PCI BIOS revision %x.%02x entry at 0x%x\n",
+ major_revision, minor_revision, pcibios_entry);
+#endif
+ return 1;
+ }
+ }
+ return 0;
}
-/*------------------------------------------------------------------------
- * encodedPCIDevToFunction - Extract func from encoded bus/device/func
- *------------------------------------------------------------------------
- */
-static inline unsigned int
-encodedPCIDevToFunction(unsigned int encodedDev)
+static unsigned long bios32_service(unsigned long service)
{
- return encodedDev & PCI_FUNC_MASK;
+ unsigned char return_code; /* %al */
+ unsigned long address; /* %ebx */
+ unsigned long length; /* %ecx */
+ unsigned long entry; /* %edx */
+ unsigned long flags;
+
+ /* According to the PCI BIOS specification, the following needs to
+ * take place before the "CALL FAR":
+ *
+ * 1. The CS code segment selector and the DS data segment
+ * selector must be set up to encompass the physical page holding
+ * the entry point *as well as* the immediately following physical
+ * page.
+ *
+ * 2. Them must also have the same base.
+ *
+ * 3. Platform BIOS writers must assume that CS is execute-only
+ * and DS is read-only.
+ *
+ * 4. The SS stack segment selectore must provide at least 1K of
+ * stack space.
+ */
+
+ save_flags(flags);
+ cli();
+ asm( "nop\n"
+ "nop\n"
+ "lcall *(%%edi)\n"
+ : "=a" (return_code),
+ "=b" (address),
+ "=c" (length),
+ "=d" (entry)
+ : "0" (service),
+ "1" (0),
+ "D" (&bios32_indirect));
+ restore_flags(flags);
+
+ switch (return_code) {
+ case 0:
+ return address + entry;
+ case 0x80: /* Not present */
+ kprintf("bios32_service(0x%lx) : not present\n", service);
+ return 0;
+ default: /* Shouldn't happen */
+ kprintf("bios32_service(0x%lx) : returned unexpected value 0x%x\n",
+ service, return_code);
+ return 0;
+ }
}
+
/*------------------------------------------------------------------------
- * find_pci_device - find a specified PCI device on the bus
+ * find_pci_device - find a specified PCI device
*------------------------------------------------------------------------
*/
int find_pci_device(int32 deviceID, int32 vendorID, int32 index)
{
- int count;
- int multifunction;
- unsigned int info;
- unsigned int bus, dev, func;
- struct pci_config_header *devfuncHdr;
-
- /* Traverse memory-mapped PCI configuration space looking for
- a match for the target device */
- count = 0;
- for (bus = 0; bus < PCI_MAX_BUSES; bus++) {
- for (dev = 0; dev < PCI_DEVICES_PER_BUS; dev++) {
- for (func = 0; func < PCI_FUNCTIONS_PER_DEVICE;
- func++) {
- devfuncHdr =
- regAddress_MMConfig(MMCONFIG_BASE,
- bus, dev, func, 0);
- if ((devfuncHdr->vendorID == vendorID) &&
- (devfuncHdr->deviceID == deviceID) &&
- (index == count++)) {
- /* Match: return the matching PCI
- Bus:Device:Function encoded
- into an unsigned int. */
- info = encodePCIDevice(bus, dev,
- func);
- return info;
- }
- /* Evaluate sub-functions only if the
- device is multi-function */
- if (func == 0) {
- multifunction =
- devfuncHdr->headerType &
- PCI_HDR_TYPE_MULTIFCN;
- if (!multifunction) {
- break; /* Inner for */
- }
- }
- }
- }
- }
- /* The target device was not found. */
+ unsigned long retval, info, error;
+#ifdef DEBUG
+ int busNum, deviceNum, functionNum;
+#endif
+
+ /*
+ * Returns the location of a PCI device based on the Device ID
+ * and Vendor ID.
+ */
+#ifdef DEBUG
+ kprintf("find_pci_device: vendor=0x%x device=0x%x index=%d\n",
+ vendorID, deviceID, index);
+#endif
+ /*
+ * Entry
+ * -----
+ * AH - PCI_FUNCTION_CODE
+ * AL - FIND_PCI_DEVICE
+ * CX - Device ID
+ * DX - Vendor ID
+ * SI - Index (0..N)
+ *
+ * Exit
+ * ----
+ * BH - Bus Number (0-255)
+ * BL - Dev Num (upper 5 bits), Function Number (lower 3 bits)
+ * AH - Return Code
+ * CF - Completion status: set=error, cleared=success
+ */
+/*
+ save_flags(flags);
+ cli();
+*/
+ asm( "lcall *(%%edi)\n" /* call the function */
+#if 0
+ /* Really need to check the carry flag here */
+#else
+ "xor %%ecx, %%ecx\n" /* placeholding */
+#endif
+ :"=a" (retval),
+ "=b" (info),
+ "=c" (error)
+ :"0" (PCIBIOS_FIND_PCI_DEVICE),
+ "2" (deviceID),
+ "d" (vendorID),
+ "S" (index),
+ "D" (&pci_indirect));
+/*
+ restore_flags(flags);
+*/
+#ifdef DEBUG
+ /* set up the return values */
+ busNum = 0xff & (info >> 8);
+ deviceNum = 0x07 & info; /* lower 3 bits */
+ functionNum = 0x1f & (info >> 3); /* next 5 bits */
+ kprintf("find_pci_device: error=0x%x bus=%d dev=0x%x fun=0x%x (info=0x%x)\n",
+ error, busNum, deviceNum, functionNum, info);
+ kprintf("retval = 0x%lx\n",0xff & (retval>>8));
+#endif
+ if (PCIBIOS_SUCCESSFUL == (0xff & (retval>>8))) {
+ return info;
+ } else
return SYSERR;
}
-int pci_read_config_byte(uint32 encodedDev, int offset,
- unsigned char *value)
+int pci_bios_read_config_byte(uint32 dev, int where, unsigned char *value)
{
- unsigned int bus, dev, func;
- void *reg;
-
- bus = encodedPCIDevToBus(encodedDev);
- dev = encodedPCIDevToDevice(encodedDev);
- func = encodedPCIDevToFunction(encodedDev);
- reg = regAddress_MMConfig(MMCONFIG_BASE, bus, dev, func, offset);
- *value = *((uint8 volatile *) reg);
- return OK;
-}
+ unsigned long ret;
-int pci_read_config_word(uint32 encodedDev, int offset,
- unsigned short *value)
-{
- unsigned int bus, dev, func;
- void *reg;
-
- bus = encodedPCIDevToBus(encodedDev);
- dev = encodedPCIDevToDevice(encodedDev);
- func = encodedPCIDevToFunction(encodedDev);
- reg = regAddress_MMConfig(MMCONFIG_BASE, bus, dev, func, offset);
- *value = *(uint16 volatile *) reg;
- return OK;
+ __asm__("lcall *(%%esi); cld\n\t"
+ "jc 1f\n\t"
+ "xorb %%ah, %%ah\n"
+ "1:"
+ : "=c" (*value),
+ "=a" (ret)
+ : "1" (PCIBIOS_READ_CONFIG_BYTE),
+ "b" (dev),
+ "D" ((long) where),
+ "S" (&pci_indirect));
+ return (int) (ret & 0xff00) >> 8;
}
-int pci_read_config_dword(uint32 encodedDev, int offset, uint32 *value)
+int pci_bios_read_config_word(uint32 dev, int where, unsigned short *value)
{
- unsigned int bus, dev, func;
- void *reg;
-
- bus = encodedPCIDevToBus(encodedDev);
- dev = encodedPCIDevToDevice(encodedDev);
- func = encodedPCIDevToFunction(encodedDev);
- reg = regAddress_MMConfig(MMCONFIG_BASE, bus, dev, func, offset);
- *value = *(uint32 volatile *) reg;
- return OK;
+ unsigned long ret;
+
+ __asm__("lcall *(%%esi); cld\n\t"
+ "jc 1f\n\t"
+ "xorb %%ah, %%ah\n"
+ "1:"
+ : "=c" (*value),
+ "=a" (ret)
+ : "1" (PCIBIOS_READ_CONFIG_WORD),
+ "b" (dev),
+ "D" ((long) where),
+ "S" (&pci_indirect));
+ return (int) (ret & 0xff00) >> 8;
}
-int pci_write_config_byte(uint32 encodedDev, int offset,
- unsigned char value)
+int pci_bios_read_config_dword(uint32 dev, int where, uint32 *value)
{
- unsigned int bus, dev, func;
- void *reg;
-
- bus = encodedPCIDevToBus(encodedDev);
- dev = encodedPCIDevToDevice(encodedDev);
- func = encodedPCIDevToFunction(encodedDev);
- reg = regAddress_MMConfig(MMCONFIG_BASE, bus, dev, func, offset);
- *(uint8 volatile *) reg = value;
- return OK;
+ unsigned long ret;
+
+ __asm__("lcall *(%%esi); cld\n\t"
+ "jc 1f\n\t"
+ "xorb %%ah, %%ah\n"
+ "1:"
+ : "=c" (*value),
+ "=a" (ret)
+ : "1" (PCIBIOS_READ_CONFIG_DWORD),
+ "b" (dev),
+ "D" ((long) where),
+ "S" (&pci_indirect));
+ return (int) (ret & 0xff00) >> 8;
}
-int pci_write_config_word(uint32 encodedDev, int offset,
- unsigned short value)
+int pci_bios_write_config_byte(uint32 dev, int where, unsigned char value)
{
- unsigned int bus, dev, func;
- void *reg;
-
- bus = encodedPCIDevToBus(encodedDev);
- dev = encodedPCIDevToDevice(encodedDev);
- func = encodedPCIDevToFunction(encodedDev);
- reg = regAddress_MMConfig(MMCONFIG_BASE, bus, dev, func, offset);
- *(uint16 volatile *) reg = value;
- return OK;
+ unsigned long ret;
+
+ __asm__("lcall *(%%esi); cld\n\t"
+ "jc 1f\n\t"
+ "xorb %%ah, %%ah\n"
+ "1:"
+ : "=a" (ret)
+ : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
+ "c" (value),
+ "b" (dev),
+ "D" ((long) where),
+ "S" (&pci_indirect));
+ return (int) (ret & 0xff00) >> 8;
}
-int pci_write_config_dword(uint32 encodedDev, int offset, uint32 value)
+int pci_bios_write_config_word(uint32 dev, int where, unsigned short value)
{
- unsigned int bus, dev, func;
- void *reg;
-
- bus = encodedPCIDevToBus(encodedDev);
- dev = encodedPCIDevToDevice(encodedDev);
- func = encodedPCIDevToFunction(encodedDev);
- reg = regAddress_MMConfig(MMCONFIG_BASE, bus, dev, func, offset);
- *(uint32 volatile *) reg = value;
- return OK;
+ unsigned long ret;
+
+ __asm__("lcall *(%%esi); cld\n\t"
+ "jc 1f\n\t"
+ "xorb %%ah, %%ah\n"
+ "1:"
+ : "=a" (ret)
+ : "0" (PCIBIOS_WRITE_CONFIG_WORD),
+ "c" (value),
+ "b" (dev),
+ "D" ((long) where),
+ "S" (&pci_indirect));
+ return (int) (ret & 0xff00) >> 8;
}
-int pci_get_dev_mmio_base_addr(uint32 encodedDev, int barIndex,
- void **mmio_base_address)
+int pci_bios_write_config_dword(uint32 dev, int where, uint32 value)
{
- unsigned int bar_value;
- int status;
-
- /* Determine the value of the target PCI device's MMIO base
- address register */
- bar_value = 0;
- status = pci_read_config_dword(encodedDev,
- offsetof(struct pci_config_header,
- bars[barIndex]),
- &bar_value);
- if (status < 0) {
- return status;
- }
- if (bar_value & PCI_BAR_REGION_TYPE_IO_MASK) {
- /* Reject port I/O regions */
- return SYSERR;
- }
- if (bar_value & PCI_BAR_LOCATABLE_64B_MASK) {
- /* Reject addresses beyond the 32 bit address range */
- return SYSERR;
- }
- *mmio_base_address = (void *) (bar_value &
- PCI_BAR_BASE_ADDRESS_MASK);
- return OK;
+ unsigned long ret;
+
+ __asm__("lcall *(%%esi); cld\n\t"
+ "jc 1f\n\t"
+ "xorb %%ah, %%ah\n"
+ "1:"
+ : "=a" (ret)
+ : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
+ "c" (value),
+ "b" (dev),
+ "D" ((long) where),
+ "S" (&pci_indirect));
+ return (int) (ret & 0xff00) >> 8;
}
diff --git a/system/platinit.c b/system/platinit.c
deleted file mode 100755
index d6a2101..0000000
--- a/system/platinit.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/* platinit.c - platinit */
-#include <xinu.h>
-
-#define QUARK_CONS_PORT 1 /* Index: console UART */
-#define QUARK_CONS_BAR_INDEX 0 /* Index: console's MMIO
- base addr register */
-#define QUARK_CPUID_VALUE 0x590 /* CPUID value for Intel
- Quark microprocessor */
-#define CPUID_MAJOR_MASK 0xfffffff0 /* Mask for CPUID w/o
- cpu stepping value */
-
-/*------------------------------------------------------------------
- * cpu_is_quark - return true if the processor is an Intel Quark,
- * false otherwise.
- *------------------------------------------------------------------
- */
-int cpu_is_quark(void)
-{
- return (cpuid() & CPUID_MAJOR_MASK) == QUARK_CPUID_VALUE;
-}
-
-/*------------------------------------------------------------------
- * console_init - initialize the serial console. The serial console
- * is on the second memory-mapped 16550 UART device.
- *------------------------------------------------------------------
- */
-int console_init(void)
-{
- int status;
- int pciDev;
-
- pciDev = find_pci_device(INTEL_QUARK_UART_PCI_DID,
- INTEL_QUARK_UART_PCI_VID,
- QUARK_CONS_PORT);
- if (pciDev < 0) {
- /* Error finding console device */
- return pciDev;
- }
- /* Store the console device CSR base address into the console
- device's device table entry. */
- status = pci_get_dev_mmio_base_addr(pciDev, QUARK_CONS_BAR_INDEX,
- &devtab[CONSOLE].dvcsr);
- return status;
-}
-
-/*------------------------------------------------------------------
- * platinit - platform specific initialization for Galileo
- *------------------------------------------------------------------
- */
-void platinit()
-{
-
- int32 pcidev;
-
- /* Initialize the PCI bus */
- pci_init();
-
- /* Initialize the console serial port */
- console_init();
-
- if (cpu_is_quark()) {
- /* Remove Quark Isolated Memory Region Protections */
- remove_irm_protections();
- }
-
- /* Intel Quark Irq Routing */
- quark_irq_routing();
-
- /* Find the Ethernet device */
- pcidev = find_pci_device(INTEL_ETH_QUARK_PCI_DID,
- INTEL_ETH_QUARK_PCI_VID, 0);
- if(pcidev != SYSERR) {
-
- /* Store the pcidev for future use */
- ethertab[0].pcidev = pcidev;
-
- pci_get_dev_mmio_base_addr(pcidev, 0,
- &devtab[ETHER0].dvcsr);
- }
-}
diff --git a/system/quark_irq.c b/system/quark_irq.c
deleted file mode 100644
index 60ea085..0000000
--- a/system/quark_irq.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* quark_irq.c - quark_irq_routing */
-
-#include <xinu.h>
-
-/*------------------------------------------------------------------------
- * quark_irq_routing - Set IRQ indirection for devices
- *------------------------------------------------------------------------
- */
-int32 quark_irq_routing(void)
-{
- int pciinfo; /* PCI info for Legacy bridge */
- uint32 rcba; /* Root Complex Base Address */
-
- pciinfo = find_pci_device(INTEL_QUARK_LEGBR_PCI_DID,
- INTEL_QUARK_LEGBR_PCI_VID, 0);
- if(pciinfo == SYSERR) {
- return SYSERR;
- }
-
- /* Route PIRQ A-D to 8259 IRQ 3-6 respectively */
-
- pci_write_config_dword(pciinfo, PABCDRC_OFFSET, PABCDRC_VALUE);
-
- /* Route PIRQ E-H to 8259 IRQ 9-12 respectively */
-
- pci_write_config_dword(pciinfo, PEFGHRC_OFFSET, PEFGHRC_VALUE);
-
- /* Read the Root Complex Base Address */
-
- pci_read_config_dword(pciinfo, RCBA_OFFSET, &rcba);
- rcba &= RCBA_MASK;
-
- /* Route PCI interrupts to PIRQA-H, refer to quark_irq.h file
- * for specific IRQ assignments
- */
- *(uint16 *)(rcba + IRQAGENT0_OFFSET) = IRQAGENT0_VALUE;
- *(uint16 *)(rcba + IRQAGENT1_OFFSET) = IRQAGENT1_VALUE;
- *(uint16 *)(rcba + IRQAGENT2_OFFSET) = IRQAGENT2_VALUE;
- *(uint16 *)(rcba + IRQAGENT3_OFFSET) = IRQAGENT3_VALUE;
-
- outb(0x4d1, 0x1E);
- return OK;
-}
diff --git a/system/quark_pdat.c b/system/quark_pdat.c
deleted file mode 100644
index 0b14277..0000000
--- a/system/quark_pdat.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* quark_pdat.c - Functions for retrieving platform data from the quark SPI flash */
-
-#include <xinu.h>
-
-/*------------------------------------------------------------------------
- * get_quark_pdat_entry_data_by_id - Retrieve platform data by type identifier
- *------------------------------------------------------------------------
- */
-int get_quark_pdat_entry_data_by_id(uint16 type_id, char* buf, uint32 size)
-{
- uint32 offset = 0;
- struct quark_pdat_header* header = (struct quark_pdat_header*)QUARK_PDAT_MEMORY_LOC;
-
- if(memcmp(header->quark_pdat_magic, QUARK_PDAT_MAGIC, 4) != 0) {
- kprintf("Invalid platform data magic\n");
- return SYSERR;
- }
-
- struct quark_pdat_entry* entry = (struct quark_pdat_entry*)(header + 1);
- while(offset < header->quark_pdat_len) {
-
- /* Found the requested ID, copy the data to the caller's buffer */
- if(entry->pdat_entry_id == type_id) {
- memset(buf, 0x00, size);
- size = size < entry->pdat_entry_len ? size : entry->pdat_entry_len;
- memcpy(buf, (char*)(entry + 1), size);
- return size;
- }
-
- entry = (struct quark_pdat_entry*)(((char*)entry) + (sizeof(struct quark_pdat_entry) + entry->pdat_entry_len));
- offset += (sizeof(struct quark_pdat_entry) + entry->pdat_entry_len);
- }
-
- return SYSERR;
-}
-
-/*------------------------------------------------------------------------
- * get_quark_pdat_entry_data_by_desc - Retrieve platform data by description
- *------------------------------------------------------------------------
- */
-int get_quark_pdat_entry_data_by_desc(const char* entry_desc, char* buf, uint32 size)
-{
- uint32 offset = 0;
- struct quark_pdat_header* header = (struct quark_pdat_header*)QUARK_PDAT_MEMORY_LOC;
-
- if(memcmp(header->quark_pdat_magic, QUARK_PDAT_MAGIC, 4) != 0) {
- kprintf("Invalid platform data magic\n");
- return SYSERR;
- }
-
- struct quark_pdat_entry* entry = (struct quark_pdat_entry*)(header + 1);
- while(offset < header->quark_pdat_len) {
-
- /* Found the requested description, copy the data to the caller's buffer */
- if(strncmp(entry->pdat_entry_desc, entry_desc, 10) == 0) {
- memset(buf, 0x00, size);
- size = size < entry->pdat_entry_len ? size : entry->pdat_entry_len;
- memcpy(buf, (char*)(entry + 1), size);
- return size;
- }
-
- entry = (struct quark_pdat_entry*)(((char*)entry) + (sizeof(struct quark_pdat_entry) + entry->pdat_entry_len));
- offset += (sizeof(struct quark_pdat_entry) + entry->pdat_entry_len);
- }
-
- return SYSERR;
-}
\ No newline at end of file
diff --git a/system/queue.c b/system/queue.c
index 64beb65..facf0bf 100644
--- a/system/queue.c
+++ b/system/queue.c
@@ -34,7 +34,7 @@ pid32 enqueue(
*------------------------------------------------------------------------
*/
pid32 dequeue(
- qid16 q /* ID queue to use */
+ qid16 q /* ID of queue to use */
)
{
pid32 pid; /* ID of process removed */
diff --git a/system/resume.c b/system/resume.c
index 5ba2750..1abc5bb 100644
--- a/system/resume.c
+++ b/system/resume.c
@@ -6,7 +6,7 @@
* resume - Unsuspend a process, making it ready
*------------------------------------------------------------------------
*/
-pri16 resume(
+syscall resume(
pid32 pid /* ID of process to unsuspend */
)
{
@@ -17,15 +17,15 @@ pri16 resume(
mask = disable();
if (isbadpid(pid)) {
restore(mask);
- return (pri16)SYSERR;
+ return SYSERR;
}
prptr = &proctab[pid];
if (prptr->prstate != PR_SUSP) {
restore(mask);
- return (pri16)SYSERR;
+ return SYSERR;
}
prio = prptr->prprio; /* Record priority to return */
ready(pid);
restore(mask);
- return prio;
+ return 0xffff & prio;
}
diff --git a/system/sleep.c b/system/sleep.c
index 71b69d9..b3f2922 100644
--- a/system/sleep.c
+++ b/system/sleep.c
@@ -15,8 +15,7 @@ syscall sleep(
if ( (delay < 0) || (delay > MAXSECONDS) ) {
return SYSERR;
}
- sleepms(1000*delay);
- return OK;
+ return sleepms(1000*delay);
}
/*------------------------------------------------------------------------
diff --git a/system/stacktrace.c b/system/stacktrace.c
index 56b1e8f..f45beba 100644
--- a/system/stacktrace.c
+++ b/system/stacktrace.c
@@ -1,7 +1,5 @@
/* stacktrace.c - stacktrace */
#include <xinu.h>
-static unsigned long *esp;
-static unsigned long *ebp;
#define STKDETAIL
@@ -17,13 +15,11 @@ syscall stacktrace(int pid)
if (pid != 0 && isbadpid(pid))
return SYSERR;
if (pid == currpid) {
- asm("movl %esp,esp");
- asm("movl %ebp,ebp");
- sp = esp;
- fp = ebp;
+ asm("movl %%esp, %0\n" :"=r"(sp));
+ asm("movl %%ebp, %0\n" :"=r"(fp));
} else {
sp = (unsigned long *)proc->prstkptr;
- fp = sp + 2; /* where ctxsw leaves it */
+ fp = sp + 2; /* Where ctxsw leaves it */
}
kprintf("sp %X fp %X proc->prstkbase %X\n", sp, fp, proc->prstkbase);
#ifdef STKDETAIL
diff --git a/system/start.S b/system/start.S
index 90b53b7..529cdd5 100755
--- a/system/start.S
+++ b/system/start.S
@@ -44,38 +44,31 @@
*/
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
-#define MULTIBOOT_HEADER_FLAGS 0x00010003
-#define MULTIBOOT_SIGNATURE 0x2BADB002 /* Multiboot signature verification */
-#define MULTIBOOT_BOOTINFO_MMAP 0x00000040 /* mmap_length mmap_addr valid */
-#define GDT_ENTRIES 4
-#define GDT_ENTRY_SIZE 8
-#define GDT_BYTES (GDT_ENTRIES * GDT_ENTRY_SIZE)
-#define IDT_ENTRIES 256
-#define IDT_ENTRY_SIZE 8
-#define IDT_BYTES (IDT_ENTRIES * IDT_ENTRY_SIZE)
-#define NULLSTK (8192) /* This must match NULLSTK defined in kernel.h */
-
+#define MULTIBOOT_HEADER_FLAGS 0x00000003
+#define MULTIBOOT_SIGNATURE 0x2BADB002 /* Multiboot signature verification */
+#define MULTIBOOT_BOOTINFO_MMAP 0x00000040 /* mmap_length mmap_addr valid */
.data
- .align 16
+ .align 16
.globl gdt
-gdt: .space GDT_BYTES
-gdtr: .word (GDT_BYTES-1) # sizeof _gdt -1 (in bytes)
- .long gdt # global pointer to the gdt
-
- .align 16
+ .globl gdtr
.globl idt
-idt: .space IDT_BYTES
-idtr: .word (IDT_BYTES-1) # size of _idt -1 (in bytes)
- .long idt # global pointer to the idt
+ .globl idtr
+
+gdt: .space 64 # must equal NGD*8 (64 = 8 segments)
+gdtr: .word 63 # sizeof _gdt -1 (in bytes)
+ .long gdt # global pointer to the gdt
+idt: .space 1024 # must equal NID*8 (1024 == 256 entries * 8 bytes per entry)
+idtr: .word 1023 # size of _idt -1 (in bytes)
+ .long idt
.globl cpudelay
cpudelay: .long 1
.text
- jmp start # Handle loaders that start at first byte of
- # text rather than the entry point
+
.align 4
+
mbootheader: # Beginning of multiboot header, embedded in ELF header
.long MULTIBOOT_HEADER_MAGIC
.long MULTIBOOT_HEADER_FLAGS
@@ -86,138 +79,98 @@ mbootheader: # Beginning of multiboot header, embedded in ELF header
.long ebss # bss end address
.long start # Entry address: end of multiboot header, end of a.out kludge
+ .align 2
+ .globl _end
+ .globl _edata
+ .globl nulluser
+ .globl _bootdev
+ .globl _cyloffset
+ .globl lidt
+ .globl jumptocode
+ .globl jumptobootcode
+
+ .globl __zero # artificial value for entry point
+ .set __zero,0
+
+entry: .globl entry
.globl start
+
+ movl $BRELOC,%esi # Move from BRELOC to
+ movl $0,%edi # to relocated area
+ movl $2000*1024,%ecx # Size to Move (should be _edata)
+ cld
+ rep
+ movsb
+ # relocate program counter to relocation base
+ movl $BRELOC+2000*1024, %esp #Put Stack pointer somewhere safe.
+ pushl $start
+ ret
+
start:
+ /* Save the stack pointer */
+
+ movl %esp,%esi
+
/*
- * Store the boot arguments.
- */
- movl %eax, bootsign
- movl %ebx, bootinfo
-
- /*
- * Test the multiboot signature and memory map flags
- */
- cmpl $MULTIBOOT_SIGNATURE, %eax
- jne halt
- testb $MULTIBOOT_BOOTINFO_MMAP, (%ebx)
- je halt
-
- /*
- * Iterate through the memory map segments to find the highest
- * address that will fit the null stack
+ * Clear Bss and up to 64K heap
*/
- movl 0x30(%ebx), %ecx # Load mmap_addr
- movl 0x2C(%ebx), %edx # Load mmap_length
- andl $0xfffffffc, %edx # Load mmap_end
- addl %ecx, %edx
- movl $0x0, %esp # Initialize stack pointer to some small value
-
-mmap_search_start:
- cmpl %edx, %ecx # If mmap_addr >= mmap_end then quit
- jae mmap_search_done
-
- # skip memory segment if it is not usable
- movl 20(%ecx), %eax # Test the address block type
- cmpl $0x01, %eax # If type is not equal to 1
- jne mmap_search_next_sgmt # then this is not a usable block
-
- # skip memory segment if it is within the memory for Xinu
- movl 4(%ecx), %eax # Load memory address of segment
- movl 12(%ecx), %ebx # Load segment size
- add %ebx, %eax # Find end of memory segment
- movl $end, %ebx # Load end of xinu
- cmpl %ebx, %eax # Compare segment and xinu end
- jle mmap_search_next_sgmt # Skip if segment is within xinu
-
- # Segment is usable and not within xinu memory region
- # Check if it is big enough to hold the null stack
- # Subtract off any memory location that overlaps the
- # the Xinu memory region
- movl 4(%ecx), %eax # Load memory address of segment
- movl $end, %ebx # Load end of xinu
- subl %eax, %ebx # Determine overlap
- movl 12(%ecx), %eax # Load segment size
- cmpl $0x0, %ebx # Check if overlap is greater than zero
- jl mmap_search_no_overlap
- subl %ebx, %eax # Subtract overlap size
-mmap_search_no_overlap:
- cmpl $NULLSTK, %eax # Compare with nullstack size
- jl mmap_search_next_sgmt
-
- # Segment is big enough to hold the null stack
- # want to save the highest possible address
- # check if segment is larger than current stack pointer
- movl 4(%ecx), %eax # Load memory address of segment
- movl 12(%ecx), %ebx # Load segment size
- addl %ebx, %eax # Retrieve segment end
- cmpl %esp, %eax # Compare segment and stack pointer
- jl mmap_search_next_sgmt # Skip segment if less than
-
- # Segment is big enough to hold the nullstack
- # and larger than the current stack pointer
- # Use the end of the new segment as the null stack
- # Round to the nearest block and subtract 4 (for STACKMAGIC)
- movl %eax, %esp
- addl $0x7, %esp
- andl $0xFFFFFFF8, %esp
- subl $0x4, %esp
-
-mmap_search_next_sgmt:
- movl (%ecx), %eax # Load the entry_size
- addl %eax, %ecx # mmap_addr += entry_size + 4
- addl $0x4, %ecx
- jmp mmap_search_start
-
-mmap_search_done:
-
- # Stack pointer set continue with boot
- movl %esp, %ebp
-
+ movl $64*1024,%ebx
+ movl $_end,%eax # should be movl $_end-_edata but ...
+ subl $_edata,%eax
+ addl %ebx,%eax
+ pushl %eax
+ pushl $_edata
+ call bzero
+
/*
- * Clear flags.
+ * Clear 64K of stack
*/
+ movl %esi,%eax
+ subl %ebx,%eax
+ subl $5*4,%ebx
+ pushl %ebx
+ pushl %eax
+ call bzero
+
+ movl %esi,%esp
+
pushl $0
popf
-
- /*
- * Zero the bss space
- */
- movl $ebss, %ebx
- movl $bss, %ecx # start of bss in %ecx
- subl %ecx, %ebx # bss size in %ebx
- pushl %ebx
- pushl %ecx
- call sbzero
- popl %ecx
- popl %ebx
-
- /*
- * Set up the global descriptor table.
- */
+
+ movl %esp,%ebp
call setsegs
lgdt gdtr
/*
- * Reload segment registers; load code segment by a far
+ * reload segment registers; we do code segment by a far
* jump
*/
- ljmp $0x8, $gdt1 /* CS descriptor 1 */
+ ljmp $0x8,$gdt1 /* CS descriptor 1 */
gdt1:
- movl $0x10, %eax /* DS descriptor 2 */
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %fs
- movw %ax, %gs
- movl $0x18, %eax /* SS descriptor 3 */
- movw %ax, %ss
-
+ movl $0x10,%eax /* DS descriptor 2 */
+ movw %ax,%ds
+ movw %ax,%es
+ movl $0x18,%eax /* SS descriptor 3 */
+ movw %ax,%ss
+ movl initsp,%esp /* set new stack pointer base */
+ movl %esp,%ebp
+
/*
* Call the nulluser to initialize the system
*/
+
call nulluser
call halt
+ .data
+_bootdev: .long 0
+_cyloffset: .long 0
+savearea: .long 0,0 # sp & bp to return to
+
+ .text
+ .globl delay
+
.globl inb
inb: movl 4(%esp), %edx
xorl %eax, %eax # clr eax
@@ -278,7 +231,10 @@ ___divsi3:
idivl 8(%esp)
ret
- # sbzero (base, cnt)
+ #
+ # bzero (base,cnt)
+ #
+
.globl sbzero
sbzero:
pushl %edi
@@ -291,6 +247,25 @@ sbzero:
popl %edi
ret
+ #
+ # bcopy(src, dst, count)
+ #
+
+ .globl bcopy
+bcopy:
+ pushl %esi
+ pushl %edi
+ movl 12(%esp),%esi
+ movl 16(%esp),%edi
+L1:
+ movl 20(%esp),%ecx
+ cld
+ rep
+ movsb
+ popl %edi
+ popl %esi
+ ret
+
# insw(port, addr, cnt)
.globl insw
insw:
@@ -317,34 +292,16 @@ outsw:
popl %esi
ret
- # bcopy(src, dst, count)
- .globl bcopy
-bcopy:
- pushl %esi
- pushl %edi
- movl 12(%esp), %esi
- movl 16(%esp), %edi
-L1:
- movl 20(%esp), %ecx
- cld
- rep
- movsb
- popl %edi
- popl %esi
- ret
-
+ #
# lidt() - load interrupt descriptor table from idtr
+ #
.globl lidt
lidt:
lidt idtr
ret
- # cpuid() - report basic CPU type information
- .globl cpuid
-cpuid:
- pushl %ebx
- movl $1, %eax # request basic CPU type
- xorl %ecx, %ecx
- cpuid
- popl %ebx
- ret # return value in %eax
+jumptocode:
+ ljmp $0x20,$0x100000 /* CS descriptor 1 */
+
+jumptobootcode:
+ ljmp $0x20,$BOOTPLOC /* CS descriptor 1 */
--
2.47.1.windows.1
From 554535084b175f27a6621e5be7ddbf96392af47b Mon Sep 17 00:00:00 2001
From: Eric Park <[email protected]>
Date: Tue, 4 Mar 2025 21:07:55 -0500
Subject: [PATCH 2/4] Patch out Ethernet
This makes initialization fail, and CS 354 doesn't require Ethernet
anyway.
---
device/eth/ethinit.c | 3 +++
system/initialize.c | 22 +++++++++++++---------
2 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/device/eth/ethinit.c b/device/eth/ethinit.c
index 59b18cd..48f3409 100644
--- a/device/eth/ethinit.c
+++ b/device/eth/ethinit.c
@@ -15,6 +15,9 @@ devcall ethinit (
struct dentry *devptr
)
{
+ // Skip initializing Ethernet
+ return OK;
+
struct ethcblk *ethptr;
int32 dinfo; /* device information */
diff --git a/system/initialize.c b/system/initialize.c
index a6d6a98..d4d2b92 100644
--- a/system/initialize.c
+++ b/system/initialize.c
@@ -80,7 +80,8 @@ void nulluser()
/* Initialize the network stack and start processes */
- net_init();
+ // Disable network
+ //net_init();
/* Create a process to finish startup and start main */
@@ -106,6 +107,17 @@ void nulluser()
*/
local process startup(void)
{
+ /* Create a process to execute function main() */
+
+ resume(create((void *)main, INITSTK, INITPRIO,
+ "Main process", 0, NULL));
+
+ /* Startup process exits at this point */
+
+ return OK;
+
+ // The code below are for networking which we skip over
+
uint32 ipaddr; /* Computer's IP address */
char str[128]; /* String used to format output */
@@ -126,14 +138,6 @@ local process startup(void)
ipaddr);
}
- /* Create a process to execute function main() */
-
- resume(create((void *)main, INITSTK, INITPRIO,
- "Main process", 0, NULL));
-
- /* Startup process exits at this point */
-
- return OK;
}
--
2.47.1.windows.1
From 03f9a542a771c4bad7b2114749a0431d79652126 Mon Sep 17 00:00:00 2001
From: Eric Park <[email protected]>
Date: Tue, 4 Mar 2025 21:08:41 -0500
Subject: [PATCH 3/4] Remove TFTP copy step
We don't need no TFTP where we're going
---
compile/Makefile | 2 --
1 file changed, 2 deletions(-)
diff --git a/compile/Makefile b/compile/Makefile
index 4929de0..cf0a6d5 100644
--- a/compile/Makefile
+++ b/compile/Makefile
@@ -111,8 +111,6 @@ ECHO$(MACHINE) = echo; echo "On Vbox, the following command would be run: "
xinu: Makefile rebuild $(BLDDIRS) $(DEFSFILE) $(DEPSFILE) $(CONFH) $(CONFC) $(LD_LIST)
@echo;echo 'Loading object files to produce GRUB bootable xinu'
@$(LD) $(LDFLAGS) $(LD_LIST) -o $(XINU)
- @echo Copying xinu.elf to xinu.boot in the TFTP directory.
- @$(ECHOxinu00) cp xinu.elf /srv/tftp/xinu.boot
@echo
--
2.47.1.windows.1
From cfd2151bf1673ccba380fa0cff9593ef53d51234 Mon Sep 17 00:00:00 2001
From: Eric Park <[email protected]>
Date: Tue, 4 Mar 2025 21:12:06 -0500
Subject: [PATCH 4/4] Add ISO generation script and grub configuration
---
compile/grub.cfg | 6 ++++++
compile/mkiso.sh | 21 +++++++++++++++++++++
2 files changed, 27 insertions(+)
create mode 100644 compile/grub.cfg
create mode 100755 compile/mkiso.sh
diff --git a/compile/grub.cfg b/compile/grub.cfg
new file mode 100644
index 0000000..79cba14
--- /dev/null
+++ b/compile/grub.cfg
@@ -0,0 +1,6 @@
+menuentry "xinu" {
+ terminal_output --append console
+ terminal_input --append console
+ echo "Booting XINU! Please connect to serial to see output."
+ multiboot /boot/xinu.elf
+}
diff --git a/compile/mkiso.sh b/compile/mkiso.sh
new file mode 100755
index 0000000..4c8388e
--- /dev/null
+++ b/compile/mkiso.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+XINU_KERNEL_IMG=xinu.elf
+
+if [ ! -f $XINU_KERNEL_IMG ]; then
+ echo "XINU kernel image not found! Did you run make?"
+ return
+fi
+
+# Make temporary directory to package grub
+mkdir -p iso/boot/grub
+
+# Copy files
+cp $XINU_KERNEL_IMG iso/boot/
+cp grub.cfg iso/boot/grub/
+
+# Generate ISO
+grub-mkrescue -o xinu.iso iso
+
+# Delete temporary directory
+rm -r iso
--
2.47.1.windows.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment