Created
March 5, 2025 02:17
-
-
Save ericswpark/4e41c8af1d01e59d1726711dd0814fce to your computer and use it in GitHub Desktop.
XINU x86_32 (i386) and grub ISO generation patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
zcmZ`=33yaRw!XK+B?-_pOFHSSoj_t1f?3!SWC=@?4r{>R2FN-f%P^=UEG9He6X9}c | |
z2-Z0A6i^uy5gi2-0wM{BG>b~Wjd6Gw6s3CtvWODd`u(Tsrn|#?ufMPEsXBX|I(4e< | |
z4b&ep)E_duA0~&ZHi`e#UG3!=hKQ}h%68;V3_tZ%rS)L;`2n*|kGS&UuGJxTLge90 | |
z4b774ckK<G(njvOD=wlzmS1LJkx$C~cFl+^mfL>UQj(k>Z@BIAg_xGtvQMMZhZf0_ | |
zq$y!p2FclYue7!2T&N_eO5=kDV6Wp@S?h>&D;LnCpS$uM2ve_NlBS#nwyy*QrO|HX | |
zAnR+fB)!8$7N%&*W+IwFbXYXyMGWlg?Jn~iR%WrYMbWL<F-u3oPs7;g=ty?MlAU?J | |
zD>$^udZ<_1xs~G>-t+l<-r0A2zN!YfN~<KdxsL0sI67Unv&GSm^w=>R?zb>-{2S=o | |
z<+^^pdb>+eXrL-NWs>Brffsg7=}IP4x91X5Vp1OUWr|VTTuiv~eJJ-X;C$Q%O;V54 | |
zgkkLYG7B0e+(!u~%3h)jLhk?tq^1?&-eAjOI`&;hlvqE-NR$e~h5B)=2{)5)zd~4O | |
zh#=fpb}FW$V*pW3_$h6P(v@&~{5TWgq6zm8Kdv3&6vD0b<JuGM+JjiKC2l@XP$(Qf | |
zbP)mA-UFnmnt3;kHRS|=I`$h1)a;z5&@>E2NLLNzA^pdE@OKC2W?jM8q@Xhp>vY6m | |
zgtVap5KDE$$ZkN$Rji9Ojn&6y%B9R0mmojFGUNKl|HWp;B~Hk*OOk1Ki*}|1wGEM4 | |
zWp&e9O98yfGr)VJ5ecCwg&90!=l9f<KIm4~QqJX~=g+wm40vALVL!*E=iW+(K&`AQ | |
z*U-Uiu0u0TGA57q#A`4ZQaS+B2NgMQ(vZ*t;?0)#FjkL%zeeYG-t_t0N)?+MA1{}& | |
z^YM{vb9|~LuTc2kM=nj#Dz`Mbe;y2ZiD^0!le23t@)ReHG&k~KC(BRhDgT|#ONf>e | |
z*s6q7+ZqTEWo1v=a&JK!Z9mMqSDKjhW15nQu9$Tv^!&3nW58#9iT$3C*x^d5?tYH0 | |
z@)MS3?VtD^N{SxtV2`d25q77s71n;S<FEUC8n<rO#x_o~cZo<zgB$Y|&kwBL8sYde | |
zbXV4zDt7|uR>on3Ohegtoa0Mdxs_o$4ykbU0r*u}TiO==!}G|D^52BglygCpmj&g7 | |
zpxh9Y`SEtm>=CF_1P<1RV4sh)Yg}Wlr)>=MY04VTVyxl7{1)f@A;j*AYkxp05EGkj | |
zCK%#58NnsC5RYoBH|;jBV+RvEPFM$oYOAwrghPaCc_{ZFEEKJkwv!r&sACb7L5YOk | |
z)50*lvUWZs>Qv<kZrWCl$vup2LvAp8dzO<FllzFC3-{@oNNDIX)zq1G+fK>>D=DlZ | |
zDLS^x|4VPrb|l5gH`o_R3637LtkAMvwSDER_)03xL|Epfh)HV76!b8=V5dTYBrpdL | |
zJa0?}KLTLyV)LlV7y1a{Sg9za3Zx?xJ#eVXZIEFp-n62dBC*+>OpeY)fr=c3zNpBE | |
z@Bv-Z%64$-6b%r0P5A^pIOWYiwRbC}7*Q5^=PHy`(=nu<cOr(GG7dw^xYI3YG-57x | |
zF74>S=x9nm8a6uQC9SHtNG?RG4N&Gy<HA;5cmss1TM)h-$A{|pRfKOz_(rb&N@rng | |
zp&wt*@!#tB>3;lCj<4Z(hpDoJ2pve#`<$><7Z^zRj)Y&&@oRN_HsR^?@Gj-}1v)-~ | |
z@N@=wpW^t5I=&6z=>+l?b9|wWzZC+!gANvN9w%h!1P>9~5I&LPqjdZ?gr~#F8^-az | |
zPGZJ~2~S6k_bPgta#6?cBs?8b-ZLD3QpdkWcslC6wIL1?*rOBH5P{Aq?^|5pRUKbW | |
zcsi@RRUE%U$Il`>ombw496xHdzQRM$@lNEpaXRl{;-&M{JDlSO3H(EqxfmkDGBKt- | |
ze4y5w$uZ_uz-UTi5;AY<RdCSQuAbTl9e{4n3oJXuoPL4ml-%icPLHhG&LDNU3~-dX | |
z<{vqO@)?_(5;g3w7`#hBlqFOptsqWSc5{mPAA(_ZGX`jRm=G%ITP8SWvAUEf#}qLb | |
zb{~6jn5J-v^>+CXT<7%sL(ib@m`&i-Y-doGP&HH~8$-{;Fr3_cr(<5r!f9|8Viyw0 | |
zsLkW7I4jLh10sa%U=KmAk!aDHa!v5mYqqnrEhpW=txHq>%^VNpIz9l6ex9hyJ|C)H | |
z7f_~ge#Hf#DGX1F+M$F0vC4I)8lAQAC`H~<oM4)=7)08=n<(Cz(vb_gJzuoJ8m{6v | |
za};R_%q0&)&x}w$7f3kLxrnVE{a>tNDqi*nIcUB|W27np|3cU`3fvXK>Cqv&C(^I+ | |
z43SWVAh}U=J>EjhxXR1OA(!GFByuAo66Y^_FZI=Kw-X?OP!b3-R1gL|XF&Lf2wbJP | |
zPO$D}%hEbJ4$@#f4>n)I4{4l#=vfo2%+#&K(eb32R|&ai3HVKD1>JFcQpBI*Wb<GG | |
z>2-Ezqg>jmnv&SNmX|#0RiX#hV!;}nU|=27`#*j&9wM4jPasHfp0m+Vn(gLz2$Kt+ | |
z3(nomIn9SKR*U1j4~QMLRd7|sv)T+xikC_QWS0o+jApV3i3hZ2m?u3!eujl+jEZ#D | |
z8thZ+u-8DK@bNq6%j~I)^auA3fF`7Fua2aV7_gAG&ze^8jX0Wzc?}230#=h@m49I0 | |
zXGDe-3sgS4o6#jKUJP2Y>@GdSx5h#SD*wX%(j_+RBN}PS7WP7yo(`K%+W0fiYFd#^ | |
z1;T;L?NQHchgIcI;PGxpa6G-h<)$!64Lv*=7-%?lTFfV@rwWAB9!Pmiem)rbAx2nl | |
zb&+T5ml$fc{g{u|!xu_4&FEnxGgBQFNU6#<L|5wY#F|Gzei`w=`+xmJE}AN*;Iu>p | |
zHgi!$BM?|n^Gg_GnQ$dS2O5SrD~?K~7PpP33Do710MuP>iCJU;Px~7B#t2`OhuG~* | |
ztD_gVG}}>1SEH3A@S;e7TRO@MohAQ}X$@TfHFJ0qx2D{SHb|!$<vQ$r&Gr>vWaByD | |
zpukPQuYfPS*5eST8MkxVd0g(U*|lhUw8)4l9Vn=S!r<O3LdSCU&#uu?r~8Ru-!*a9 | |
zXA4>hJJ;3XcoYNj9Cxze9B<AS<W2<qkrMSGgK$(I__fAt5}b{e|IH~0PAZs9+~<i+ | |
zQ;s*|P8SKSyaB9ctF~(s8jpSQt102uSiAa@U{-B6Ahw)sdhh|q*LVe?`(=Z|*Jq{e | |
zR}IvrYi2K^2CkVmROM-I)7FTpJqumBW(L^Pdi(EyH=GqW9$FHC3+1n*&HU$lVdp*r | |
zhO&G%AloAMVNYg78wT=$IarO|X={|>?K|wvtVFvOg&C{1#v`_0WzBZU@8?6kn)!K2 | |
zRZ59d<9^OXm;4N{XR@~0F_x$GsdJYC#Ko*2J36+YX)5`)OQkOd3lAZ>oXOT?7bH3( | |
zxj!D9)AOi{a>38(aeSZ*X1`=7<@Cb<^+vT_KpLe8N?QWWashcBE@;<TK~7@Wc{Ax# | |
zj<ct7^21&e1C?#d={anQ7z`ueSD_VHRHcMd%mV~NMso&pPmHlM;Y6Zf2sg7U*_O8a | |
z82BsZOS`gy73an{_C$!u@SFE(eSjrDiEdROo$Ss_xJ4*?fkgz~2H+R$ZG0>(N3A#` | |
z_Vx;3z&MY9-(|4_77|XsT5x*)p|U&^n5Th&UE%#ZSD}pMD$EH4(y_Z6!7_jb;tJ6d | |
zT~7y=)GgNWc}HL|m6Z_mEUo8tHMAN7si90$Lcxf#L>9K_j1!5mBdS`%BM8o$z*6Gq | |
zr?wlzDlpdo(w%O1t!lf2@p~BaO{=_tp6<oV=o&#}f_bI#S9Y{pT;B=AfjbMmOpd0$ | |
zrt~Hd2n9UK^(;U|1nFi6;xMLhMss_X)IGs$&^5$B!|$A~eBXhc>KRd}jm3)-KfY>E | |
zNImy37q}a|>G>+D6^))N;$YrN^6-Xqy&`liCtXnqrsZ!#94<Vgvpfx!>4Ifc2UeFC | |
z;dmS)to2X;p6U65+KE75I+{6$5Na{f!yGACeC>l-G;?d9MLPaQ6ugZ48Bp|T=NddH | |
zuXq!?1_IqN=rhiO9!AH<g8xlFe_hkX_dQNAZx9TX%@|M@+aZOk1WhHNDr5M_JX;`3 | |
z2n5Z7I4pwnH~`-b_Vx}W!~}myMRXJGYK2EFy--sCCp`yn<+W3OIx89_<e5v^jZZ0* | |
zkn3>wqnT-AFQ~;9-Yc-sO=LY$pC>td?69i?ao$jV<6^=y)uqhWHH;z+%+a%N#9!ON | |
zRecf5sIMs#SzXWgu+d`BoBh@^&DfIbq*%H=w^&B6c=>x~@72|O%oLFRnEIOXrU@w! | |
z$zJP~7PjW!xCgjBTUlMNSotA#sn>k-xwZj;)6~ahvn>QHAz_{$Syf(_2&c|LDYHOu | |
zOkyYV%#K+YAY;Y>@QfKMh}{ST#o9cO5F%qz1xveTESfnEW1cZeOQK-*Sul3X$ldvo | |
zKtLae^cC=PBUVe_oQF80`GnyAz|Zf`wx95-;8xrq=-C!j>9D6s0QaBeN3qJV>lAwC | |
z`1Md0a)zy(L7Bn@+KP?#h~VzeuI5`ESz=%b5*4>PcpSo|g!ebwkn<jTMY=>?P5F(0 | |
zK5?%=ohHzH;vNH^$pujKnKa8+2X>|Mj?h$EYIoy=<sKtXNDr32D^&_rSt%?m(^)B( | |
zN8tM^aWtaX@GNyjd<tRm?Fq2)kI6*;>07!aQsybWN!+cZ0?^O<PrRoSe`mtGis==v | |
z9d&V?Tftv_+_tNDhXjjRBD`k1%3m*OOP~b|{--slqV~Olj|ebzhA{ZTLqOj;8}T8T | |
z9I^|CuR=ao_t^NhV1I=GkKj?i|EU50%Ry$@y&@gh(e-i}zH8a);rBg24;({PSYBHi | |
zsbgu<e(ZexbI|*kjVKPE(#uP;;*g^Iw;pRiI-DMZ$}>_g5hw{L@Wm(zY($^w@*(y? | |
zpCtJN`=-x><EU=X`w1E*c$g-rB390dtD^3dWQ(c41oLj&1w8SsT*EblzxkYj@2Euf | |
zsmEag5k5}k&ET|Mz|HCcd!la!KC8ntMPI}?0e=)}?)%Lw_D0_a9gz={>!@5V<9GP} | |
zZ&$y7Km5S;botunqjO2}ypCSr8hUfIBn9OpUQ)sg%@O}<hR~Fcn~m+7a<mE2mS1hv | |
ziaVO^j;d^8llnzFmVy{uq;dRVCX|hHn^QF9PfdE7sTtLr4f#7682X_*B+wlc=oaf; | |
zw=y!&wFl_lP``qo^)3%mAPx;BnAbhfXp7VFe4YCE0usuu<ws4<#piz@PYC1(1oV9` | |
zs)xrUKA60%YoP1KCc(TSh?!TZQYZ8-BP>$qNinUtthT?E9qZGk>)bDWzM$eq*F1`# | |
zT6&e|3XdeebBqNe`>0PW>t4_&d_-4~Z#&tdg81nr#WXs&4@oE;;04B|SagoY(?|=# | |
zdCsBdthgZYci0S_yyz4m&&o?CVFq_bK@WX5cGhAOpkf%KIU6OJ=X-XiAja_(vAB%C | |
zWRk@|@?C}+VPz_;V7?oO54+2y9OSI@myn~p=k_cGGt~?nDavxL&-^ZtT*jB~Q~P(n | |
z+BU-ZKEnI8x~8plKA-1d1O}VaS>ci9x55r3U-_)`sV>u*7qe3Xq8y9(h)47#@<UbH | |
z@mVY31n8xE4K0y~0;)F^@GnMk?+Who?jo#<Nlze6E+w8b&{WfOo85(pcS!*b{*lsD | |
zUM*?ni@8#>uM5}x6M>+BuJ-FT@VT4~Su#U+3fCFL%DjV1@QIuRGbU0jtQ4{117jR5 | |
zh0hD`(`)tXeUXG*%2>`oKF{Diw`Y#fc6kK%`DX(9V(p~9%iNC`UB>wPR3ARs6pr3? | |
zJ_jYicH&1~A{hR>H0f4SVa1<~sXB7!7w}0_p4H{jg5;ufmMgI0w$+0oH9P>`LgJ;W | |
z>N5VAPUb{X#)IzZ4qm6N9#ys;1-$7rb19k3H^`iGZ#c0ZscA*5$AsnoaNNOtR^Xa; | |
z(t!-(b9<&U+u+WQ&8af|vBS<^i|CA;hYUeM)|4v9Y9s24RQS?E6GEaiFM)FIhmveC | |
zNcpz<^3C9%6l}kXus>Y49~)$Uif;cXSlnUy)Tgu2gQMhR7HaG2I5!NRPEXm@>#%DH | |
zw)^?#O?KG>GPk=HcHaZLf8LA1qA4XZy{Rop*33iE1CK^LIAek$N>M83++`p-8$*^P | |
z^Yu$`Aa~qYD(FOS9~aTjq|2X?_Cn4tFG+5QK#|G8h+gv5ZxGWsDD*fl(FVTcthgjO | |
z&cV2ejDzTaG=_~sY1llA<_jy_AqRNA)_L$D(Z6m>be_jy11vi^i@w~ILiHwHEG|fF | |
zoG#W$h&`vXBm}WMs<ZgG7Kief&XW?vQ=;>n1&^lu?voK<)0$=AfG?@KKw^-<FkN7~ | |
zaIFQgxXdSj9Rv8e4jXiMo8WMlv1huJAq{saLof#0bOOi)m${T9dOX7s`f?m(PZVZ2 | |
zo=?6ngY8WjJg111^jH@x^VA87UMWA*wUuXu|AWA&jnz}VnTdSP&iBO})GO={`*;D1 | |
zhhyTciX^inc1Ursl@MmJCtJR-OFA(knCNCD_SDI1{lu?%vgvbLd7S*io8G)U-CiF) | |
zEbb0-;~+DD@5f`oG9{3~>3>(IzhYoJR-}M8i^)YDJA5ekJiEZc|FuIaLjUP+I(iMz | |
zVkd8bG(=6Sd(&M_Q@$#s$m{8~^%%$1a-7?fhav41)AH?zpQbzoS-x2cgS{Ha78P}t | |
z=dz7OaVGi`Jhp%+A2*J&qeWIr>tNiGqfL%{#(YJot#1sG=vzyMrtD)mLu1-~kFj2+ | |
z8q)ANh>aT>BfrSXhNc-;r@{yQAJZ&l+lS^l?%qa5h@0maH~xi8zPKRcy}Gs>sdO$t | |
z?ndO8CbF`c(!pi^IKa?>82;c{g2h+%3x*8=hHFQ_aK_K@8G0xn=H~(&b;Lpc0EVxp | |
zvvxel;{)U!L|z{t&jGn_fcyf;4duG%aL|$hv@)Vi;xy$Q(%>?OfLg52{V^gB6yyzp | |
z{L?LeWO@@d87qB$FeFir@b%wcYi?ufQ^~5t^sB1a$q_Mq#)2PzwK0`tX~u2zmmf`e | |
zfh6gs@9N<b0%C#R2CKM8Btl+OX0c_%lRH)tH+_|-myRQL^;?gVRS#bxZ(&c5u(C%+ | |
z#K^PITiA2Q;ea7!AUE_22i(xOWMG;yspY3lhRT_BWa`Wd#MfkkUnMp}8E(Yw>02;v | |
zXYrKejph6CJxEi^^bscX+yHK8TENa9orCO@LyMTub@VhPj=eWBxg)-b1g!B1jb%TN | |
z?CMzYNnis1F5rp}bNyqh5viPD#b?1P6p!JG%WqO$b#z5=*OAD5%hFHCdV2W%iREH8 | |
zi19!Beuh6cu@^=~$kW)?QS>i;J{|Rd+@D<<l_XzgZHqg}$5~EsWc05GX+MuRgSDvJ | |
zS5K+IuNj_LHmNvW-oaKC#}?RPDON{Kt2^QIre+?}pHC!<=HoI-otk9CirWu0&Eo)i | |
zo@3CDyM2t~6*8nJ&6R#!!x^rKUio@_okUvns&EyoA{5i1f@dwSDeHfuly!Tq)*=;~ | |
zy;&sE$1_ct0fxS`MVCB?KSBy4&yo?Bar~>?Lf~G%+Hb@ljPUp0-=Vt6%b`L+H{m6v | |
z_QGH<hxrv8WZ#YM{G<`Zqj|<PKpEXHHRJide8R`MMxMOAf>r$hMls>Xpwwx*fdpN0 | |
zgMxmed>t;0=(5Q}Bji`uyfKeDo~@z8yZb8^n*Q;~4Rrp`Xxz30MdMx{?!iTJ#AU2V | |
z1PHp5OMVB+C;<A$fLSoq6pRBxersPTv1y~1a3%Vh)qqz_p$D7(aO#sA$xyTXHx3*k | |
z8l#1--aIHg8m3@XWBjU)q9>x!7IUF!xbSTYT^@}tFO-bKr^xXopA0<_DNC+mSv4O* | |
zr&(t3cTUZ?kNz^DnLpt`+3*lXt{xi`0Gg7n`eU9{yJnBAY_)UJ(w2_NyL`Uf4@H|F | |
z)L(=C=AiL@^uIy7iq_%-pU;ApiB^DCg7y?zIa(Fk7PJr1>d>yBHR&hl)5q<EO@l9K | |
zmptQ@7LF^seLnLZpD!7$8`@vcR-nC#wg>Gb+C?<ue&_&<s`mM^&<fEeqAfsMi?$W5 | |
z2JKt4D`=s6g^U%j8`?0m*=Vn$y@ZBsBu$?@e^>0Bl$LqVpYi!#MB9S4^j|)o4Q(3Q | |
zCm8>LwgLTpXlL{m0+@`(+CSTA*UQfwmmSsHeZF}HNotR2{ta;2KA*1|kbMLxf^eU{ | |
z2TnVH5Qa$7cC39K-~=S(c)$|u4Ekp`KLTz5T#8-0AFv(j=2^h60q+2op$x{gKncKs | |
z&<AibPN4BEB!{#K2T(Z>uj78P0q`W?e!%Ux!kh)X2uS~M>L#E?k)$wOi1GlV0UrZQ | |
z2V4l)8*n|~XuxW~*??yND*+n;Uj($^k1+25<^i_Hz45V@Q*olAvk-{0fa?JjT!*Ux | |
zlL5~F-oeMMM!+b<(-JC4Zv*B5euOwa2Kdc)kOw?<7V>}({Ws(R-RB?=Xknk0*2JG| | |
zg>|#FZTGxkkg;XRkydR&!?0x~iLN6B?DewFDWyAnzK3DQ&t-FlgxFdVqZ9`;{VRwq | |
z%v)wP?5bw}To{9QC@c?4UtpC7vm!iavzZGz%YQHz`gQEx1=ghgShS50^{X`e&9Baa | |
zMcvOXgEx~I7h2_0tSg>l*a$p(vp+Ai4!DaY?F$=z>5%R+iIX#w8ZlVfkYKvumR~!i | |
z%w6{RLTgfMEd1GKK77f!EWlABxtVcMtbCEBFS5$tvLZZ>vYB}9Wh$QA*fu<0X2<Yc | |
z$GmuIEPSz5u4L(Wma-x|=dhW0?qDjO{n)m})}%g2GTi3_o=@T?MHrC_Hs%HIU>5$I | |
zRldX0@w~~3@SMeF;yI3~cs|0m;hDpZ;rSf%;(3vUms@2EOE3RkF5eYiaWOPUMd6|! | |
z4-+81CQAmXomAd~qouV1Nci_f9KV_+RYnzkl%=C7c=#3S)O_5x>BqAG@ChCNB`Pxg | |
zP@nm4rjGxJEvt-*UX8Ez^efc0EzqfXY)563{1rP^xfS7h`uQmNOQt@*K+b0JiUsm% | |
zwrE9-e1+w&%#sV(%#~L8BvV)RkDiK;xAa@BYa4^D*TK+UDre_cPL$te1JtbW76qI| | |
zN@t7I)bQ5$`xX5*vTf=Lc{Iyel_meoCa;Q$?pnYJl2rgH2BGhO=uBbjRux7cLA9qJ | |
zPa(k3I`tmAwrV2Mc(gWAKE`%vQSu^oOv?(tsZakblUJu2O#N8K>LKy~_VnsPc@x`< | |
z=UYs6Wyx={9M=N*N4CvXi2t~74VZeCv?fcw%SPkbpDkN6QMR)4Yqmxw<As-g_!l_* | |
s_bxUox%V-9eQlJ?*xt1h<@{aIRa=cnfP)*e!pp}B#`0Z%Y@8ADKPbtixBvhE | |
delta 12379 | |
zcmZu%349bq*6&UzNCHC+(z#CvM*<<-BrHb|1||?7up*!!f(oL*0w!D%MvRd(oe9xW | |
z7x{oya0L`p#AN|F!XX2Q8Wc2Yl<1<&n4lm*0wVMMUsY!^VYh#&epT=N-%(Yss;hfa | |
zbJVZqsNcH*YTz=fBCch-L)F=S;YAtCHdip~D>r{UmzjHb{)i8L{k?E^ssC+%bpY2} | |
zWvD;y-q&ho8#Q)!TzIXj{(}cZJg5%aJv$;#ZF`}mq7)t6@Q26aAN=fx{KLpp`&d;` | |
z3>J{#rxZ2ZDG1q1o?PFxQWTwC>+T29W!#G^>=90O0X4du#XDeuYPAm;>|<~TDX>xy | |
z?PLegP*Il<R1|jyMh><LD@!{XY$M?{i0n}YD-T4=w$A3zX7hznHgz!H9~JLcGn#)J | |
zAIYyoWpt}fhukQxfkQpS$v#B$j>qG1&${jLl-H`|Mltn9Sh&nbN2l_AQLVW>I=AnR | |
zT)1uFCnT?;Zc{4<dunVBrcgs?-4-LZ!wAD>urB08ce>8M5YsW}RyWzW(UWJyB&Y}Y | |
z*qCVh<_w^R0ey(NeK-g;R~hj#yu3EVTTZ-KFV8}}S;TAQ<+Uc>1mazTDQPd9c!P;| | |
z!ONo|a-|XPBgNhbY)i}tV*c9;3?`l*@wRw*A;kNoJ9uloyinqO4PNa^XYsq{45Ihn | |
zc9k7|u`fgq8`>^v8|(y#{sj%oy*+J62cc3s93xmfN{ry9eBk>4xzRLmhzxW9qts-i | |
z_W~mfjHgUSf4(#Jesuv4h)Yn%^UiSt)ff3AaY@s9!$I(#79qihDrzH);=PSi`o~Bw | |
zUl$YY{<Q(~Zm@gOM84+tGgyCAiz_Iz(oyqfRuURw@^A3(<5H(zPlZB-s<S#&(1*+L | |
zNPY9qq!sZh9QqdwMW-P}vIiUNfT$IuyT@bL43Y83(l^1?Pe6aaslW1u$KzxMpA#Ri | |
zF667@2SxQZV;-m$bTo=zZ|q7nua3`5>d@37oAHv!YO+TCq-b{XJ_-HQ=lK%}(P}g= | |
zPUvjaP07N3w5Ybh8m&Q$K(8)x1ST7-Gpcd~;!*RCKnNOQ1TOKb2}xl;cQ!-sW|}<2 | |
zJ0uQCI*-l89D3h~YDdV3rt@bK2dk6#k;G{Gx4(Hjr;c3<PPjGErvLa?TTxx6!5)Lz | |
z;)>wn_Yjto-G>&&3k&{U!7m7MvJoZ^c~IL4Ar)5?v_<{!0+B^k#4^}dK9ZND<b;&` | |
zDkb^xcAKI7NAk`PIa1?~MQt;L#a=G|7}ztIE)bUef@oU=@CSdJBQErik}do6phnc+ | |
z<qQ`Z{~(NRtqI<vl?p9uO-YE&u-1U-LNbG=Tj7USC0RzkhjF3dDzScQfQg+eoYE<l | |
z*#B<fH><cJAF7o)n`oNCRx=jW+Fri!HoRMMOw@QY8Sb)mKYuVeIyNasT3nZ9tt?pY | |
ztK5m?Y8$>IIZpkRpGr=!_n<k1_jS7UTv6dUrJx%I;)#y3TLznk8hYSs<IeCV4aDn0 | |
zl-E*#r(Sopx^#BRYz6O8N|-{XAUZ+g1%%FihZvsXgID)v3ZK<J*q(rR8~58V)a8DQ | |
zG2LfcqA_J>sDZII*df#qlsgT(xsxqGi}J=jA5RM>n}H@>?&;#;aUYtLW1qF4%(BhL | |
zlBK0Q1Qmm2QL};9w~tn1c-sz<(S9a+4bXdA!m7JL=>5zGL;6_<X=|2OdQwRD^ZAf& | |
zHl_EFv>oZL6Vf$&6QqkwX#z<DNcxzN-p@aQ^d3`s%O6tO<=vS=n#S)y8fHqrASpc; | |
z+yO#*i+4|njQ*j$xr#_iPXl)qY6d&aAB6NhQ(8t++V0)kgmgVGONq2UV@e+<DQ)uZ | |
zr9wLD33Hr=qT-$|c=wsu;e@4Uk~>%M2b=s}XknT<qluZvcI@sZI2r@TVAql{eGgv& | |
zg4#Cy?0!{=hX%GT$1iv)|AA=}CkXfNsA0Wc;6ppMvkNsO4yAzh9oaCLlZbZ-8`+uI | |
z7G^?xSc<pZC63eCE+Nr2Nx<r604R<nhE5(<NW`O!2)o!NoY|S^F9kJC%11QH<tAd} | |
z1sF^iS!Yv^B0?e0I=To8S_=Z!uvTHc1FW;IXu2i^;HfB<6}rDHkQ&ucyO2b2SY1Vh | |
z)k=OBFz$3A4l)*s*Qjc+I*F+<tktvz9=e4ijKRL(%RBXI{|;nyxxy}cJlIaULNZ<8 | |
zSqX^2%J?Up;_L;e)0)^M`o!7_gwu7R4d!%>;Avq5Zwk6Mny%@sM9{FAA~dWusJatn | |
z$Zmd<0?}?#+h9Ks@lKIV4A9TS!zc`*VIY93t=Hn`B*Wr{>N;6<xksXF<!(*^IoQ!* | |
zGFQU*8=bcV{GI?f#*2^d5@p{*4WX-jB>C?Xxy$<j;;j>7DW>RMYG)mNG8o1mF^#vN | |
z-QCcNrIq>3tQgsSkY+TZi-lMlLL{})mQvK976k331aYs%p0k(cz+H$Mu%jh5oVQ6G | |
zI_0-`Xc+7pBHrkbzC{gw1wEXC4^@ibq(ts&j?@mKt>?wL+slQuS)z=1emE^^xSI}c | |
z&|N0EGn?sRd|Z&t6EdpW0&IGvE%l^sJ!8WrZe%ARU*>bav~gjMJU?RDjO+k;h<lFD | |
zPD}0n!BCh-x^`$sZb*)-hqjs5ug6j6G>0H;F+Y@+sQ$#iON$5?Cs~>Nc3RhfIN4x4 | |
zqieswH)5d!lk@rfuCW38sb#P&{Q0i^?88mbhMz<x(=2VwmH~VfitWvMTxX8}<9-Vx | |
z=IRHOlg3V|?dwWK!@$1YBA>KoXG^Uu&~ml);^64}80kImlE~c8&@`+E&>y4komM0> | |
zESLD0Zk_Fs(9+p?lCw{7M;=5%|7pS?`l=r(#NgtYcpPB_UK6Tp4Uwi<)?P*%b7wFI | |
zDzGr3sPLpx5aqOr%z?R{qyTg7mgq$W_>@PmH(tiV2Jl<m67BtfGOQ;lg)IrBVK5;V | |
zo=)OKV`N8V9Stsf8_I?j(1<qJpV5BG*#@-|&v_XA4_Z(?L&O^-%{a_Dg-m-_$Z-Bq | |
zPuq+bW8yhV2F>Z35Jm$!3`lL0w6dD-N{@~_KUfa*<zNx^d?}m6zfX^{-;V}Gjl<12 | |
z!Pf>#aYrIP0nkR8PCUvgac0oMB=V1_|3>;tB<+ul=!*oyn`JXJVnxq%wv9jCJ)$+q | |
zbZb3OtNCl)JE>LtWcT>d18|!6Ifm8iEMJ(iHb8M6s&oviM_lsM)^&jQ6jWbSSpS!m | |
z;lX>X*GQ}_;5{-T)MfmsjA(TTpMkrT>YA^Lt;pJ-B7%4L_KYN3StNqitqmuv*Hpt= | |
z=XEl;f3ukCbhea`hKOk)suWWbJcEb!h>6apj)-ICHD6(2CSQ>er4HlMdPMu>$VLW# | |
zzDIV_a}mP33kR+zsfx8Np0*E)1{=w*_DG&G6pf+^Kizr}^WH^DLWwk+JY-KBDZ8#U | |
z%FLuhr=TyMfmWOXw2K75MDZtjW(91KjZ(g&XTMR8%Enl)g-V&$I-4XU+HeU-Zw}D1 | |
z(8dab?G6%vqjIkVdogB;*44b$phfds7~yIi%SZMS2XUS450~8*C)V?31N_fWEpK{l | |
z!CMQ?2<!m37^|Hi;$XT%w3TPE1yso;y9OKppCn>$Hb8ivB_^_)jtK&gb#!qs>a)Q| | |
z!n<D<CfH<QLQ5u+ibdN1$Z%@N!$20Qu9)i{51t+QA-LIRVE-P0M^S!g?R~&jwgVQu | |
zF2Vc1;wq{UyJ#zMz^YwrupsDT6C%f3P2_X}w!<Dq`r3AIDbLK^{WO~803QXV)7_p5 | |
z-Fh4C_s|y0lx;)J3~nP;4fe9Yw!lk3G5@G{+}|D|HlmD&`FkZ~5Rs+<LPWh>`Pl!U | |
zeJhNNSh@<J7A}Byy^MWI4?Nu;U`Aq?j)Cc$LXrKzclFWu6Mcg48D?>xq}V$7Kz@^? | |
zCUTQRV*BcoY%eec3t?i86iguE8(sdr@HG`&O#c`Vu}lU^aL49gL+e8fJr5b9MN5cZ | |
zGl-$JMO!9pLns}3@JI@6^hgPcoyX6G-4t&%^?X6!$kYlF8*IB5C07OxxbF#x_74dt | |
z;qUehkLR*cN(3*J5;0#gu`Ty)7ZEEPQ$a-Pk4B|@8b6yG&J+5zjC~siQyZmTQDK9E | |
zTyd~{_>@3dwTchv7uf=pWqew{*udo``yRfk-%zb21P;w1UO{z(JsQHx`$x2GD4^9j | |
zN%FG!AN{&mZs8;>yXtiP!h7_OSAXPV`=^J08r)>$7}X87gRkvBB<00#@G!>bj;|@B | |
zSGK}i1Rj@cKkj75rRSx%hVtL~=W7?+Hd&~my1|aLr7&7I6a=__!bd=S1LS81wd3z( | |
zhS_x!P19c}(X)vB*Yqy{7t=ojL`;941ZOn|8=8$6a{ALHB%&F_(AuLdrk}NG`+$r! | |
z1Kt&hc3bZDPG7@5C$8KAPEys-&I-czd*R;9ap8-PlYMOA3;Sv#*((IVG3D8lVx%-( | |
z>Mio>Q7#F<Rsmp-Nd>W{rb@8Yg7FLItp@}>)>m>8eAMLu3_%8(niTM#Z75(Dy}<lN | |
zRfGLO1nEJ2{Z+E6h%_7NFc%Zi|I7;q#M<AJDg^~j>us8E1AEUp;E@OIX<6&6TpH3% | |
zAm!>rd_kmKy^M2|P{5P>Lnu=WGk_DHPYF=>CC-av5q7f4fRm+z&?QcnHoL)6iSNjx | |
zSFH%D;)u1n8~~@a0SQbdTY;?~#iFGn)@^Tuw9VJIhDdx4<#=z0m;ZnPel-!X3p?1h | |
zo-*2O5iRYz-e@gd-k11)5)s36(i?nFpWuu6k-unmz2IU|;YD?2cLUFAn8~|iqtm)t | |
zi6#ClPOgn?^reZNA0!?P?w#n&;cVPoAJ98Sv&G-t46zJT03*_HgPs=!LwGz*#FwDF | |
z02`k?aJKppuNauDe#w6r*!@1;T8DE8#`!3^28&m)om`RI$)i1Fr(c3Yr`3f!J_1uz | |
z4<i}z_Ni8q)rWEZoOlJtP}-yXimdbmckw3%r6n5^>wvo=$F>VT?l%uOs0ZIWsJlJ& | |
zukd0_Y_K^jm+`6FrhkH27u|IYKJW1yrm1$lk6PpBNjx4WD9SYN=Sob~^#H%-jJjqF | |
zJa3z|q47;4BSd`i)C(ym@Filr!q*OtR5^DHj<&A?sJzLM!Im~^HB*||9EJqV2Zt_H | |
zr!-aXYpOnMR`Eg1TYI2Me7hCt)05W8Zt|`}Vzp2RX<5=Elu_MazqF#|ZpYLO!KZ5Q | |
zzk?R|P9o-Vm5bgLCqF|RBngbrBYu|zulE6q4W^(7CSD{i4AY?lA*@1^F4uKTqL`Yd | |
zK?$W}mmEG?qV(|b4AC^bpq|d-B2)076w7NiBoTaYb}QA*M`RBSoSsh8?Q|XIMt1zH | |
zS$WhtvL8vO9HMOmn?#z42>Kj}Ks?u#&v2+Jyr_tm$APBUI7`fGb>&0oSX;6~Uqp*4 | |
z@L~ZgmaYOuY2~`g+YXJf|1^%QTNE!}rke+5q?ZDC!7#i{IQ=LB`Mev|=!5>(qULnH | |
z05I(i*eBV`!k%`RL=MY#foRI&ZC<kpGI+a;{x#FmzDkeB^(cC%Tk&bhrQ`=;0a2`? | |
zS7uka2`&W~UG-Zz+w3C_FmS3FLN11RJ4L3m_7s%CVu{fEZy61#7#Dj5l<>!D#)^O^ | |
z+!gRm_>kl9H!|g583I7PA7F+tLi#vN1`M{Bh&dLe!lo8VK!@c<R}h~Sy@^cs7c&_y | |
zx>xP*?Flw2>d7&oB6{*Y(CEob>E!`leNT)%O4zroxyx`*Z_Has2_F^&fMQ-IYEIWm | |
zY0Wc6#N0r{jQKd#9a<g%9hQu{On>od<8b6wdhC=J2MLc<MIXJXnrwQ>f){UsW|_?6 | |
zpCBfK6`OipeDqRHhzdQYwFVNUwiB>Z2umBQ!*V^9+{uK(H(A9s0udEiYp~JQ_&kXm | |
zY%mWUuJsHNUQQeiBIq~L^X*(2aUyt)i>oq?cuv<+K52Ld^?m--@aP$vfiuR`<mm9* | |
zccTQz#ZeAJ!YAwJ=ci;@YgTMVl#7I2)7K#B>p|03tdFmJ)7RJhI(+rx(bjbPmC^WM | |
zdDf=?23Kjmt}cAs=<1)HRN-nZTpa-%OHg*J6cB^WQt35mWs0FqMGcsZgmGBvd<KjL | |
zp-iAlAS`O|UzsANC&7-?_zE*2m-QK;Vm@~~XUO^#fmc_i)P`eQ8HN_Uu<Ku7$hyOz | |
z>xDX6vUNp;b&CBvI8P?$5IzrWG=oI5d6GOQy@-J9z+4(dDo6I?o1J%B%1z7@@Bzqi | |
z0WrJ%cWL@vQ!UO%ZJw#tN2)nYNP-V!jtL1B5IcL^#B}t*%rY^*h#?42Xn=#uRsn%n | |
zvP^{}ABAbA!a*5Y1VJ3yx8P0yy<pNmO=?L4Ki6Tgr7CGku7gb`ZHKm$2y(%ptrm>F | |
z&kBY)9iQ{LBh&2bQdIis$tGU5aiVe9u!Z5+V6c@rWTfvFU!CP2(dZRGY;7<~s%88W | |
z0W>C>+1<>=XaOgy3+9pvtWT9RFBcx-auiLGi(;m)7mcUcQle^XiYe^mEBuPjvURq< | |
z<`rHN$!7Lx{b`C1u`S3n{S6e&ygqO@4?07|68y$jXBKn}7IH^baAL;_EbIvEP+%#A | |
za31ugkW*^8K0J;6O8jmg_dif?n5b7_R<7(le~RT6TsnXbYX<viB-u7|Z{I1w`%Lhh | |
zu2E>xLJEHNEqFHAa_EW&<P>RE?i%-UBd3G<G=C>2F1Ww1pyet4bxvYbyf3fnWMd%T | |
z@z7D7+q8r$?9gfW5Sq;AkBSbtIs);?6sYZDuxI$ZQ8DUPUNWkSWm9JaVg6Id3;f`y | |
zUiM(Ti<k$GN1XTtD+^B@G1NsBE0Abc{_u*eB#vnmvr<YHhxTa`AcX)oMGhe~*Z~Q6 | |
zy9wY=fGRKG3~Jb3G)EKShZ8{1e|DH5Ooe!UllT~k*ENafLOiZX{5r(7D@@f~$a*)) | |
zN=WvQkg*+P!J%o8=9zteoW%D?@dhcram(BFT#}|>s;>=)CejF>;k{{O=|nuI>+k4Y | |
zc{%@nOpI+d@V26c;Kdn+<pcUz#$d0LCcOwa`i4pcIrRqsm8Xba&^OqMM3J}h?TcrR | |
z4UbI14*Yl0rmt;ytw8$dU%Fo6r*l`Tdw9;6EOiC$iG1^zDgBNeZ*m-Yk8rFA|HARS | |
z6mS~f8lpaIbX>-Jj_o|>cY-&%5a){bVGPIMQ2NS?(_1`ceZz_a_~2l$60?O4I)(~A | |
zi-kMkr?s!2GFXuvYypo3>&}miO=*_{eXlpsq1n7)Y`XoGV@(~noGlE0A?#1wi;)}F | |
z!KVYi04fbX0vGsM@P>+YU{A+jZy}YtrYTSAx<-2ANf&C9poWbCKOy0FApZKeaCI@? | |
zH!fZ+;a`sHgn!bxGcH;6@T9!<J*tn=cog7BIkD2_z@b8(*BRJ0V@wq$r*eM{<&HRn | |
zxYGHeyj1lV-;ftOcv374-pSz7_V_euXp@JCo(-iAIxJ!B8+Bw#+z*4YW0k16zB%$j | |
zwnpy*V|E^C8XQ%c_*oEoE$n+Knar3Qr=QoxQq)9Vi*4u4>y*?^m){Zo;P^=UGBgL# | |
zlEsU*wt;^8!10SrIxM?{xu)~^CODT-g-eUbM5imjC#0!T-zr0*Okd+0(loDu&rx$) | |
z>lKC9kB_w{Vo&j=f=IkSE5tw}x2_EmAyo^@BDZpUP1XY_V|pAWi>&p?)AD*6>iQMW | |
zqbI1+yA^&Tq!&H>%z31SVd3wLCXePbl9x>w-LCjBWl%8i_$;NfmZ<QD#%p#9klyhL | |
zk-^*~;;^hu0`WPshk0WuK~1hyr)vcaH|_+L14U={2{WQIvxE(E%FY5RJ2Mgn<oG=O | |
z*F^g}gm1Pm=K)D)a>MelG@09EGTGPUBVLnVqbA2EDN2ry!(bY!|7&~(36G8AlW^}i | |
z^(vo#@3Gu(BUHtar|Q}{RPOpkK`(4DENAFf3PU?D2z&c4XgT`6gTs|KFHaxDCVA?Z | |
zqU?TZVsQ|!@C$kGp{HBgXYKZQ`u|IoWj=L|`c|Lz5!AmyxsDR}zQ+@f(i6psG6iKG | |
z$|{tXP`0D&M>&sDkJ4zLXbaPqCaIsN({6S4|Fy8!@9}tI{_XLkqGY1vqm-h&j&cCy | |
z97-KZ*a6ts>+!^)^g+o*c?4wz%8MvFP>!Qiqtv6c*(Y^UKr>PDP!^!PfwBQb!8L0} | |
z{_fbh9b0DRS7EMDUO<`umB-T?Wdh1Bv@228puP>|gjueF7lt|yeX{-T^@~oc_JeQ1 | |
zyq}^(pxZBk&e)F+5}@TDcsx}^5q<;l4|zOM{)(~<*^vo)KN4>$=y<HA6`(bs8$g$1 | |
z#UB6-!j@YN`YGsb&;{5*<60=nQta#lK_9@wY-$Vqx8_TDmaPEeC7e|@fF1)q0J;vx | |
zp=!``p!82k7eS-&@$))pCTL3>vL=H@fG!2?47v_<Fz8;;$)HuBi$EJdp8<`+2cTC# | |
zGePfwPHy?IqP&HZ>QXRHfvy9+2D%qC4Cn7E(4Wu404T%QMYTd;pqZfCF^-c#kK@by | |
zQqaTI&<9QZ7W$z7`VRV_E%}E9hvUx$Vcx85L!R>+W@+jFQBa#!0SeZiLMIz5e{FGx | |
zj>~s>Jfq>qi?SB^`wwbKKqU_Ba8*%W<L<?Y>bpE}Ng}@Gr{X@8=ivSrpR=Tc`a5@^ | |
z{xRRVBr$m)=4(B)yw?1l_gcb_yUHGZ8Q4zTvNRE2FVk_)<zsN~!{;qcY<~l@IRO5= | |
z+WtLNQl~g5D?*R)pd~Sk65}fWcxhs?2h)7MnY%N>T@-kfF7I>8vRL&TPhFO%9_Kl@ | |
z|BKJT{SB_;{xaW=`)Ym)_m$j@`%)gbJW*Z5Q*ockb8w%+=it7H>$rF2+m|OMry`Z` | |
z_R|#P4B=7^7G}IRcLUpt2R@ak{>)Qx|B>h5KAF$KJ%{VK59ix)Pvoa?pTpg_pXY%% | |
zSheJ-D=w&WcLx?;YSps{n-pDQL_qOb8n1C7%Cf$Kt*n(q!G8$}zRr`2BXjm<m~0wH | |
zTq8~CV4TqD5_1iDzsaw_R!SH4X>rXl`Fr`Q;>c(nU-#)6X<A!iN_+8L#gXa}eyVt@ | |
z`V3$AT%=mb_2-tT@myWKM6KY<Rv%Ws<yj>eYIi=TBoR}fmkfy>KVDiZHLXp+0t@pC | |
zRp#>VOQx&q`A|J0@G2h8bfxiSdgs6Z{NzQ~dcIv>jsHFGxh6yXoX=Pj86BG~1WKYL | |
zN(_cR45KrSKfh*V^g-<G;xavrH>Gv_>YC~5B|hGmt{&vOj7W7BKV@VD)|%Zv&(+e- | |
zezynlw9*j>ePQWHbsgV_`(~~>GSpXjPsbAVEZ^=JiGSt43eJx_xhzAy!N=pC&R3O9 | |
z$G?4kU$!+m4DZi$;eThuwG&H{!h4gywl)$kQv23US3B*FF5hZF0vy?x5jc0E1kT-k | |
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 *)ðptr->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ðptr->devAddress[0], | |
+ 0xffðptr->devAddress[1], | |
+ 0xffðptr->devAddress[2], | |
+ 0xffðptr->devAddress[3], | |
+ 0xffðptr->devAddress[4], | |
+ 0xffðptr->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 = ðertab[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 = ðertab[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 = ðertab[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 = ðertab[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ðptr->devAddress[0], | |
- 0xffðptr->devAddress[1], | |
- 0xffðptr->devAddress[2], | |
- 0xffðptr->devAddress[3], | |
- 0xffðptr->devAddress[4], | |
- 0xffðptr->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 = ðertab[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 = ðertab[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