Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

lab6

  • Loading branch information...
commit bde6cefeb699c4c29df9ccf4e17cfab9e32ec797 1 parent fe0c7e6
@aclements aclements authored
Showing with 36,484 additions and 13 deletions.
  1. +30 −2 GNUmakefile
  2. +2 −2 conf/lab.mk
  3. +3 −0  fs/Makefrag
  4. +11 −0 fs/index.html
  5. +130 −0 grade-lab6.sh
  6. +24 −0 inc/lib.h
  7. +87 −0 inc/ns.h
  8. +1 −0  inc/syscall.h
  9. +11 −4 kern/Makefrag
  10. +1 −0  kern/e100.c
  11. +3 −0  kern/e100.h
  12. +10 −3 kern/init.c
  13. +250 −0 kern/pci.c
  14. +33 −0 kern/pci.h
  15. +710 −0 kern/pcireg.h
  16. +12 −0 kern/picirq.c
  17. +1 −1  kern/picirq.h
  18. +10 −0 kern/syscall.c
  19. +26 −0 kern/time.c
  20. +11 −0 kern/time.h
  21. +5 −0 kern/trap.c
  22. +4 −0 lib/Makefrag
  23. +4 −0 lib/entry.S
  24. +1 −1  lib/file.c
  25. +140 −0 lib/malloc.c
  26. +158 −0 lib/nsipc.c
  27. +56 −0 lib/sockets.c
  28. +6 −0 lib/syscall.c
  29. +21 −0 net/Makefrag
  30. +11 −0 net/input.c
  31. +13 −0 net/lwip/FILES
  32. +72 −0 net/lwip/Makefrag
  33. +571 −0 net/lwip/api/api_lib.c
  34. +1,210 −0 net/lwip/api/api_msg.c
  35. +74 −0 net/lwip/api/err.c
  36. +235 −0 net/lwip/api/netbuf.c
  37. +353 −0 net/lwip/api/netdb.c
  38. +126 −0 net/lwip/api/netifapi.c
  39. +1,924 −0 net/lwip/api/sockets.c
  40. +559 −0 net/lwip/api/tcpip.c
  41. +1,553 −0 net/lwip/core/dhcp.c
  42. +814 −0 net/lwip/core/dns.c
  43. +253 −0 net/lwip/core/init.c
  44. +432 −0 net/lwip/core/ipv4/autoip.c
  45. +317 −0 net/lwip/core/ipv4/icmp.c
  46. +808 −0 net/lwip/core/ipv4/igmp.c
  47. +278 −0 net/lwip/core/ipv4/inet.c
  48. +426 −0 net/lwip/core/ipv4/inet_chksum.c
  49. +624 −0 net/lwip/core/ipv4/ip.c
  50. +84 −0 net/lwip/core/ipv4/ip_addr.c
  51. +783 −0 net/lwip/core/ipv4/ip_frag.c
  52. +1 −0  net/lwip/core/ipv6/README
  53. +179 −0 net/lwip/core/ipv6/icmp6.c
  54. +163 −0 net/lwip/core/ipv6/inet6.c
  55. +375 −0 net/lwip/core/ipv6/ip6.c
  56. +72 −0 net/lwip/core/ipv6/ip6_addr.c
  57. +631 −0 net/lwip/core/mem.c
  58. +370 −0 net/lwip/core/memp.c
  59. +663 −0 net/lwip/core/netif.c
  60. +779 −0 net/lwip/core/pbuf.c
  61. +336 −0 net/lwip/core/raw.c
  62. +657 −0 net/lwip/core/snmp/asn1_dec.c
  63. +611 −0 net/lwip/core/snmp/asn1_enc.c
  64. +4,126 −0 net/lwip/core/snmp/mib2.c
  65. +1,183 −0 net/lwip/core/snmp/mib_structs.c
  66. +1,453 −0 net/lwip/core/snmp/msg_in.c
  67. +683 −0 net/lwip/core/snmp/msg_out.c
  68. +149 −0 net/lwip/core/stats.c
  69. +344 −0 net/lwip/core/sys.c
  70. +1,420 −0 net/lwip/core/tcp.c
  71. +1,350 −0 net/lwip/core/tcp_in.c
  72. +953 −0 net/lwip/core/tcp_out.c
  73. +824 −0 net/lwip/core/udp.c
  74. +105 −0 net/lwip/include/ipv4/lwip/autoip.h
  75. +121 −0 net/lwip/include/ipv4/lwip/icmp.h
  76. +162 −0 net/lwip/include/ipv4/lwip/igmp.h
  77. +100 −0 net/lwip/include/ipv4/lwip/inet.h
  78. +58 −0 net/lwip/include/ipv4/lwip/inet_chksum.h
  79. +173 −0 net/lwip/include/ipv4/lwip/ip.h
  80. +165 −0 net/lwip/include/ipv4/lwip/ip_addr.h
  81. +76 −0 net/lwip/include/ipv4/lwip/ip_frag.h
  82. +100 −0 net/lwip/include/ipv6/lwip/icmp.h
  83. +68 −0 net/lwip/include/ipv6/lwip/inet.h
  84. +127 −0 net/lwip/include/ipv6/lwip/ip.h
  85. +97 −0 net/lwip/include/ipv6/lwip/ip_addr.h
  86. +217 −0 net/lwip/include/lwip/api.h
  87. +160 −0 net/lwip/include/lwip/api_msg.h
  88. +228 −0 net/lwip/include/lwip/arch.h
  89. +97 −0 net/lwip/include/lwip/debug.h
  90. +47 −0 net/lwip/include/lwip/def.h
  91. +246 −0 net/lwip/include/lwip/dhcp.h
  92. +92 −0 net/lwip/include/lwip/dns.h
  93. +87 −0 net/lwip/include/lwip/err.h
  94. +48 −0 net/lwip/include/lwip/init.h
  95. +103 −0 net/lwip/include/lwip/mem.h
  96. +94 −0 net/lwip/include/lwip/memp.h
  97. +101 −0 net/lwip/include/lwip/memp_std.h
  98. +76 −0 net/lwip/include/lwip/netbuf.h
  99. +109 −0 net/lwip/include/lwip/netdb.h
  100. +263 −0 net/lwip/include/lwip/netif.h
  101. +100 −0 net/lwip/include/lwip/netifapi.h
  102. +1,704 −0 net/lwip/include/lwip/opt.h
  103. +118 −0 net/lwip/include/lwip/pbuf.h
  104. +97 −0 net/lwip/include/lwip/raw.h
  105. +81 −0 net/lwip/include/lwip/sio.h
  106. +364 −0 net/lwip/include/lwip/snmp.h
  107. +97 −0 net/lwip/include/lwip/snmp_asn1.h
Sorry, we could not display the entire diff because it was too big.
View
32 GNUmakefile
@@ -89,6 +89,10 @@ PERL := perl
CFLAGS := $(CFLAGS) $(DEFS) $(LABDEFS) -O1 -fno-builtin -I$(TOP) -MD
CFLAGS += -Wall -Wno-format -Wno-unused -Werror -gstabs -m32
+CFLAGS += -I$(TOP)/net/lwip/include \
+ -I$(TOP)/net/lwip/include/ipv4 \
+ -I$(TOP)/net/lwip/jos
+
# Add -fno-stack-protector if the option exists.
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
@@ -114,7 +118,8 @@ all:
# make it so that no intermediate .o files are ever deleted
.PRECIOUS: %.o $(OBJDIR)/boot/%.o $(OBJDIR)/kern/%.o \
- $(OBJDIR)/lib/%.o $(OBJDIR)/fs/%.o $(OBJDIR)/user/%.o
+ $(OBJDIR)/lib/%.o $(OBJDIR)/fs/%.o $(OBJDIR)/net/%.o \
+ $(OBJDIR)/user/%.o
KERN_CFLAGS := $(CFLAGS) -DJOS_KERNEL -gstabs
USER_CFLAGS := $(CFLAGS) -DJOS_USER -gstabs
@@ -128,10 +133,16 @@ include kern/Makefrag
include lib/Makefrag
include user/Makefrag
include fs/Makefrag
+include net/Makefrag
+
+PORT7 := $(shell expr $(GDBPORT) + 1)
+PORT80 := $(shell expr $(GDBPORT) + 2)
IMAGES = $(OBJDIR)/kern/kernel.img $(OBJDIR)/fs/fs.img
-QEMUOPTS = -hda $(OBJDIR)/kern/kernel.img -hdb $(OBJDIR)/fs/fs.img -serial mon:stdio
+QEMUOPTS = -hda $(OBJDIR)/kern/kernel.img -hdb $(OBJDIR)/fs/fs.img -serial mon:stdio \
+ -net user -net nic,model=i82559er -redir tcp:$(PORT7)::7 \
+ -redir tcp:$(PORT80)::80 $(QEMUEXTRA)
.gdbinit: .gdbinit.tmpl
sed "s/localhost:1234/localhost:$(GDBPORT)/" < $^ > $@
@@ -188,6 +199,23 @@ xrun-%:
$(V)$(MAKE) "DEFS=-DTEST=_binary_obj_user_$*_start -DTESTSIZE=_binary_obj_user_$*_size" $(IMAGES)
$(QEMU) $(QEMUOPTS)
+# For network connections
+which-ports:
+ @echo "Local port $(PORT7) forwards to JOS port 7 (echo server)"
+ @echo "Local port $(PORT80) forwards to JOS port 80 (web server)"
+
+nc-80:
+ nc localhost $(PORT80)
+
+nc-7:
+ nc localhost $(PORT7)
+
+telnet-80:
+ telnet localhost $(PORT80)
+
+telnet-7:
+ telnet localhost $(PORT7)
+
# This magic automatically generates makefile dependencies
# for header files included from C source files we compile,
# and keeps those dependencies up-to-date every time we recompile.
View
4 conf/lab.mk
@@ -1,2 +1,2 @@
-LAB=5
-PACKAGEDATE=Tue Nov 3 13:41:56 EST 2009
+LAB=6
+PACKAGEDATE=Fri Nov 13 02:30:19 EST 2009
View
3  fs/Makefrag
@@ -18,6 +18,9 @@ USERAPPS := $(OBJDIR)/user/cat \
FSIMGTXTFILES := fs/newmotd \
fs/motd
+FSIMGTXTFILES := $(FSIMGTXTFILES) \
+ fs/index.html
+
FSIMGFILES := $(FSIMGTXTFILES) $(USERAPPS)
View
11 fs/index.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+ <title>jhttpd on JOS</title>
+</head>
+<body>
+ <center>
+ <h2>This file came from JOS.</h2>
+ <blink>Cheesy web page!</blink>
+ </center>
+</body>
+</html>
View
130 grade-lab6.sh
@@ -0,0 +1,130 @@
+#!/bin/sh
+
+qemuopts="-hda obj/kern/kernel.img -hdb obj/fs/fs.img"
+. ./grade-functions.sh
+
+$make
+
+rand() {
+ perl -e "my \$r = int(1024 + rand() * (65535 - 1024));print \"\$r\\n\";"
+}
+
+qemu_test_httpd() {
+ pts=5
+
+ echo ""
+
+ perl -e "print ' wget localhost:$http_port/: '"
+ if wget -o wget.log -O /dev/null localhost:$http_port/; then
+ echo "WRONG, got back data";
+ else
+ if egrep "ERROR 404" wget.log >/dev/null; then
+ score=`expr $pts + $score`
+ echo "OK";
+ else
+ echo "WRONG, did not get 404 error";
+ fi
+ fi
+
+ perl -e "print ' wget localhost:$http_port/index.html: '"
+ if wget -o /dev/null -O qemu.out localhost:$http_port/index.html; then
+ if diff qemu.out fs/index.html > /dev/null; then
+ score=`expr $pts + $score`
+ echo "OK";
+ else
+ echo "WRONG, returned data does not match index.html";
+ fi
+ else
+ echo "WRONG, got error";
+ fi
+
+ perl -e "print ' wget localhost:$http_port/random_file.txt: '"
+ if wget -o wget.log -O /dev/null localhost:$http_port/random_file.txt; then
+ echo "WRONG, got back data";
+ else
+ if egrep "ERROR 404" wget.log >/dev/null; then
+ score=`expr $pts + $score`
+ echo "OK";
+ else
+ echo "WRONG, did not get 404 error";
+ fi
+ fi
+
+ kill $qemu_pid
+ wait 2> /dev/null
+
+ t1=`date +%s.%N 2>/dev/null`
+ time=`echo "scale=1; ($t1-$t0)/1" | sed 's/.N/.0/g' | bc 2>/dev/null`
+ time="(${time}s)"
+}
+
+qemu_test_echosrv() {
+ pts=85
+
+ str="$t0: network server works"
+ echo $str | nc -q 3 localhost $echosrv_port > qemu.out
+
+ kill $qemu_pid
+ wait 2> /dev/null
+
+ t1=`date +%s.%N 2>/dev/null`
+ time=`echo "scale=1; ($t1-$t0)/1" | sed 's/.N/.0/g' | bc 2>/dev/null`
+ time="(${time}s)"
+
+ if egrep "^$str\$" qemu.out > /dev/null
+ then
+ score=`expr $pts + $score`
+ echo OK $time
+ else
+ echo WRONG $time
+ fi
+}
+
+# Override run to start QEMU and return without waiting
+run() {
+ t0=`date +%s.%N 2>/dev/null`
+ # The timeout here doesn't really matter, but it helps prevent
+ # runaway qemu's
+ (
+ ulimit -t $timeout
+ exec $qemu -nographic $qemuopts -serial file:jos.out -monitor null -no-reboot
+ ) >$out 2>$err &
+ qemu_pid=$!
+
+ sleep 8 # wait for qemu to start up
+}
+
+# Make continuetest a no-op and run the tests ourselves
+continuetest () {
+ return
+}
+
+# Reset the file system to its original, pristine state
+resetfs() {
+ rm -f obj/fs/fs.img
+ $make obj/fs/fs.img >$out
+}
+
+score=0
+
+http_port=`rand`
+echosrv_port=`rand`
+echo "using http port: $http_port"
+echo "using echo server port: $echosrv_port"
+
+qemuopts="$qemuopts -net user -net nic,model=i82559er"
+qemuopts="$qemuopts -redir tcp:$echosrv_port::7 -redir tcp:$http_port::80"
+
+resetfs
+
+runtest1 -tag 'tcp echo server [echosrv]' echosrv
+qemu_test_echosrv
+
+runtest1 -tag 'web server [httpd]' httpd
+qemu_test_httpd
+
+echo "Score: $score/100"
+
+if [ $score -lt 100 ]; then
+ exit 1
+fi
View
24 inc/lib.h
@@ -20,6 +20,8 @@
#include <inc/fs.h>
#include <inc/fd.h>
#include <inc/args.h>
+#include <inc/malloc.h>
+#include <inc/ns.h>
#define USED(x) (void)(x)
@@ -52,6 +54,7 @@ int sys_page_map(envid_t src_env, void *src_pg,
int sys_page_unmap(envid_t env, void *pg);
int sys_ipc_try_send(envid_t to_env, uint32_t value, void *pg, int perm);
int sys_ipc_recv(void *rcv_pg);
+unsigned int sys_time_msec(void);
// This must be inlined. Exercise for reader: why?
static __inline envid_t sys_exofork(void) __attribute__((always_inline));
@@ -103,6 +106,27 @@ int fsipc_dirty(int fileid, off_t offset);
int fsipc_remove(const char *path);
int fsipc_sync(void);
+// sockets.c
+int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+int bind(int s, struct sockaddr *name, socklen_t namelen);
+int shutdown(int s, int how);
+int closesocket(int s);
+int connect(int s, const struct sockaddr *name, socklen_t namelen);
+int listen(int s, int backlog);
+int recv(int s, void *mem, int len, unsigned int flags);
+int send(int s, const void *dataptr, int size, unsigned int flags);
+int socket(int domain, int type, int protocol);
+
+// nsipc.c
+int nsipc_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+int nsipc_bind(int s, struct sockaddr *name, socklen_t namelen);
+int nsipc_shutdown(int s, int how);
+int nsipc_close(int s);
+int nsipc_connect(int s, const struct sockaddr *name, socklen_t namelen);
+int nsipc_listen(int s, int backlog);
+int nsipc_recv(int s, void *mem, int len, unsigned int flags);
+int nsipc_send(int s, const void *dataptr, int size, unsigned int flags);
+int nsipc_socket(int domain, int type, int protocol);
// pageref.c
int pageref(void *addr);
View
87 inc/ns.h
@@ -0,0 +1,87 @@
+// See COPYRIGHT for copyright information.
+
+#ifndef JOS_INC_NS_H
+#define JOS_INC_NS_H
+
+#include <inc/types.h>
+#include <lwip/sockets.h>
+
+// Definitions for requests from clients to network server
+
+#define NSREQ_ACCEPT 1
+#define NSREQ_BIND 2
+#define NSREQ_SHUTDOWN 3
+#define NSREQ_CLOSE 4
+#define NSREQ_CONNECT 5
+#define NSREQ_LISTEN 6
+#define NSREQ_RECV 7
+#define NSREQ_SEND 8
+#define NSREQ_SOCKET 9
+
+// The following two messages pass a page containing a struct jif_pkt
+#define NSREQ_INPUT 10
+#define NSREQ_OUTPUT 11
+
+// The following message passes no page
+#define NSREQ_TIMER 12
+
+struct Nsreq_accept {
+ int req_s;
+};
+
+struct Nsret_accept {
+ struct sockaddr ret_addr;
+ socklen_t ret_addrlen;
+};
+
+struct Nsreq_bind {
+ int req_s;
+ struct sockaddr req_name;
+ socklen_t req_namelen;
+};
+
+struct Nsreq_shutdown {
+ int req_s;
+ int req_how;
+};
+
+struct Nsreq_close {
+ int req_s;
+};
+
+struct Nsreq_connect {
+ int req_s;
+ struct sockaddr req_name;
+ socklen_t req_namelen;
+};
+
+struct Nsreq_listen {
+ int req_s;
+ int req_backlog;
+};
+
+struct Nsreq_recv {
+ int req_s;
+ int req_len;
+ unsigned int req_flags;
+};
+
+struct Nsreq_send {
+ int req_s;
+ int req_size;
+ unsigned int req_flags;
+ char req_dataptr[0];
+};
+
+struct Nsreq_socket {
+ int req_domain;
+ int req_type;
+ int req_protocol;
+};
+
+struct jif_pkt {
+ int jp_len;
+ char jp_data[0];
+};
+
+#endif // !JOS_INC_NS_H
View
1  inc/syscall.h
@@ -18,6 +18,7 @@ enum
SYS_yield,
SYS_ipc_try_send,
SYS_ipc_recv,
+ SYS_time_msec,
NSYSCALLS
};
View
15 kern/Makefrag
@@ -31,18 +31,25 @@ KERN_SRCFILES := kern/entry.S \
lib/readline.c \
lib/string.c
+# Source files for LAB6
+KERN_SRCFILES += kern/e100.c \
+ kern/pci.c \
+ kern/time.c
+
# Only build files if they exist.
KERN_SRCFILES := $(wildcard $(KERN_SRCFILES))
-# Binary program images to embed within the kernel.
KERN_BINFILES := user/idle \
- user/forktree \
user/pingpong \
user/primes \
- user/testfsipc \
user/writemotd \
user/icode \
- fs/fs
+ user/testtime \
+ user/httpd \
+ user/echosrv \
+ user/echotest \
+ fs/fs \
+ net/ns
KERN_OBJFILES := $(patsubst %.c, $(OBJDIR)/%.o, $(KERN_SRCFILES))
KERN_OBJFILES := $(patsubst %.S, $(OBJDIR)/%.o, $(KERN_OBJFILES))
View
1  kern/e100.c
@@ -0,0 +1 @@
+// LAB 6: Your driver code here
View
3  kern/e100.h
@@ -0,0 +1,3 @@
+#ifndef JOS_KERN_E100_H
+#define JOS_KERN_E100_H
+#endif // JOS_KERN_E100_H
View
13 kern/init.c
@@ -12,6 +12,8 @@
#include <kern/trap.h>
#include <kern/sched.h>
#include <kern/picirq.h>
+#include <kern/time.h>
+#include <kern/pci.h>
void
@@ -42,21 +44,26 @@ i386_init(void)
pic_init();
kclock_init();
+ time_init();
+ pci_init();
+
// Should always have an idle process as first one.
ENV_CREATE(user_idle);
// Start fs.
ENV_CREATE(fs_fs);
+ // Start ns.
+ ENV_CREATE(net_ns);
+
// Start init
#if defined(TEST)
// Don't touch -- used by grading script!
ENV_CREATE2(TEST, TESTSIZE);
#else
// Touch all you want.
- // ENV_CREATE(user_writemotd);
- // ENV_CREATE(user_testfsipc);
- // ENV_CREATE(user_icode);
+ // ENV_CREATE(user_echosrv);
+ // ENV_CREATE(user_httpd);
#endif
View
250 kern/pci.c
@@ -0,0 +1,250 @@
+#include <inc/x86.h>
+#include <inc/assert.h>
+#include <inc/string.h>
+#include <kern/pci.h>
+#include <kern/pcireg.h>
+#include <kern/e100.h>
+
+// Flag to do "lspci" at bootup
+static int pci_show_devs = 1;
+static int pci_show_addrs = 0;
+
+// PCI "configuration mechanism one"
+static uint32_t pci_conf1_addr_ioport = 0x0cf8;
+static uint32_t pci_conf1_data_ioport = 0x0cfc;
+
+// Forward declarations
+static int pci_bridge_attach(struct pci_func *pcif);
+
+// PCI driver table
+struct pci_driver {
+ uint32_t key1, key2;
+ int (*attachfn) (struct pci_func *pcif);
+};
+
+struct pci_driver pci_attach_class[] = {
+ { PCI_CLASS_BRIDGE, PCI_SUBCLASS_BRIDGE_PCI, &pci_bridge_attach },
+ { 0, 0, 0 },
+};
+
+struct pci_driver pci_attach_vendor[] = {
+ { 0, 0, 0 },
+};
+
+static void
+pci_conf1_set_addr(uint32_t bus,
+ uint32_t dev,
+ uint32_t func,
+ uint32_t offset)
+{
+ assert(bus < 256);
+ assert(dev < 32);
+ assert(func < 8);
+ assert(offset < 256);
+ assert((offset & 0x3) == 0);
+
+ uint32_t v = (1 << 31) | // config-space
+ (bus << 16) | (dev << 11) | (func << 8) | (offset);
+ outl(pci_conf1_addr_ioport, v);
+}
+
+static uint32_t
+pci_conf_read(struct pci_func *f, uint32_t off)
+{
+ pci_conf1_set_addr(f->bus->busno, f->dev, f->func, off);
+ return inl(pci_conf1_data_ioport);
+}
+
+static void
+pci_conf_write(struct pci_func *f, uint32_t off, uint32_t v)
+{
+ pci_conf1_set_addr(f->bus->busno, f->dev, f->func, off);
+ outl(pci_conf1_data_ioport, v);
+}
+
+static int __attribute__((warn_unused_result))
+pci_attach_match(uint32_t key1, uint32_t key2,
+ struct pci_driver *list, struct pci_func *pcif)
+{
+ uint32_t i;
+
+ for (i = 0; list[i].attachfn; i++) {
+ if (list[i].key1 == key1 && list[i].key2 == key2) {
+ int r = list[i].attachfn(pcif);
+ if (r > 0)
+ return r;
+ if (r < 0)
+ cprintf("pci_attach_match: attaching "
+ "%x.%x (%p): e\n",
+ key1, key2, list[i].attachfn, r);
+ }
+ }
+ return 0;
+}
+
+static int
+pci_attach(struct pci_func *f)
+{
+ return
+ pci_attach_match(PCI_CLASS(f->dev_class),
+ PCI_SUBCLASS(f->dev_class),
+ &pci_attach_class[0], f) ||
+ pci_attach_match(PCI_VENDOR(f->dev_id),
+ PCI_PRODUCT(f->dev_id),
+ &pci_attach_vendor[0], f);
+}
+
+static const char *pci_class[] =
+{
+ [0x0] = "Unknown",
+ [0x1] = "Storage controller",
+ [0x2] = "Network controller",
+ [0x3] = "Display controller",
+ [0x4] = "Multimedia device",
+ [0x5] = "Memory controller",
+ [0x6] = "Bridge device",
+};
+
+static void
+pci_print_func(struct pci_func *f)
+{
+ const char *class = pci_class[0];
+ if (PCI_CLASS(f->dev_class) < sizeof(pci_class) / sizeof(pci_class[0]))
+ class = pci_class[PCI_CLASS(f->dev_class)];
+
+ cprintf("PCI: %02x:%02x.%d: %04x:%04x: class: %x.%x (%s) irq: %d\n",
+ f->bus->busno, f->dev, f->func,
+ PCI_VENDOR(f->dev_id), PCI_PRODUCT(f->dev_id),
+ PCI_CLASS(f->dev_class), PCI_SUBCLASS(f->dev_class), class,
+ f->irq_line);
+}
+
+static int
+pci_scan_bus(struct pci_bus *bus)
+{
+ int totaldev = 0;
+ struct pci_func df;
+ memset(&df, 0, sizeof(df));
+ df.bus = bus;
+
+ for (df.dev = 0; df.dev < 32; df.dev++) {
+ uint32_t bhlc = pci_conf_read(&df, PCI_BHLC_REG);
+ if (PCI_HDRTYPE_TYPE(bhlc) > 1) // Unsupported or no device
+ continue;
+
+ totaldev++;
+
+ struct pci_func f = df;
+ for (f.func = 0; f.func < (PCI_HDRTYPE_MULTIFN(bhlc) ? 8 : 1);
+ f.func++) {
+ struct pci_func af = f;
+
+ af.dev_id = pci_conf_read(&f, PCI_ID_REG);
+ if (PCI_VENDOR(af.dev_id) == 0xffff)
+ continue;
+
+ uint32_t intr = pci_conf_read(&af, PCI_INTERRUPT_REG);
+ af.irq_line = PCI_INTERRUPT_LINE(intr);
+
+ af.dev_class = pci_conf_read(&af, PCI_CLASS_REG);
+ if (pci_show_devs)
+ pci_print_func(&af);
+ pci_attach(&af);
+ }
+ }
+
+ return totaldev;
+}
+
+static int
+pci_bridge_attach(struct pci_func *pcif)
+{
+ uint32_t ioreg = pci_conf_read(pcif, PCI_BRIDGE_STATIO_REG);
+ uint32_t busreg = pci_conf_read(pcif, PCI_BRIDGE_BUS_REG);
+
+ if (PCI_BRIDGE_IO_32BITS(ioreg)) {
+ cprintf("PCI: %02x:%02x.%d: 32-bit bridge IO not supported.\n",
+ pcif->bus->busno, pcif->dev, pcif->func);
+ return 0;
+ }
+
+ struct pci_bus nbus;
+ memset(&nbus, 0, sizeof(nbus));
+ nbus.parent_bridge = pcif;
+ nbus.busno = (busreg >> PCI_BRIDGE_BUS_SECONDARY_SHIFT) & 0xff;
+
+ if (pci_show_devs)
+ cprintf("PCI: %02x:%02x.%d: bridge to PCI bus %d--%d\n",
+ pcif->bus->busno, pcif->dev, pcif->func,
+ nbus.busno,
+ (busreg >> PCI_BRIDGE_BUS_SUBORDINATE_SHIFT) & 0xff);
+
+ pci_scan_bus(&nbus);
+ return 1;
+}
+
+// External PCI subsystem interface
+
+void
+pci_func_enable(struct pci_func *f)
+{
+ pci_conf_write(f, PCI_COMMAND_STATUS_REG,
+ PCI_COMMAND_IO_ENABLE |
+ PCI_COMMAND_MEM_ENABLE |
+ PCI_COMMAND_MASTER_ENABLE);
+
+ uint32_t bar_width;
+ uint32_t bar;
+ for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END;
+ bar += bar_width)
+ {
+ uint32_t oldv = pci_conf_read(f, bar);
+
+ bar_width = 4;
+ pci_conf_write(f, bar, 0xffffffff);
+ uint32_t rv = pci_conf_read(f, bar);
+
+ if (rv == 0)
+ continue;
+
+ int regnum = PCI_MAPREG_NUM(bar);
+ uint32_t base, size;
+ if (PCI_MAPREG_TYPE(rv) == PCI_MAPREG_TYPE_MEM) {
+ if (PCI_MAPREG_MEM_TYPE(rv) == PCI_MAPREG_MEM_TYPE_64BIT)
+ bar_width = 8;
+
+ size = PCI_MAPREG_MEM_SIZE(rv);
+ base = PCI_MAPREG_MEM_ADDR(oldv);
+ if (pci_show_addrs)
+ cprintf(" mem region %d: %d bytes at 0x%x\n",
+ regnum, size, base);
+ } else {
+ size = PCI_MAPREG_IO_SIZE(rv);
+ base = PCI_MAPREG_IO_ADDR(oldv);
+ if (pci_show_addrs)
+ cprintf(" io region %d: %d bytes at 0x%x\n",
+ regnum, size, base);
+ }
+
+ pci_conf_write(f, bar, oldv);
+ f->reg_base[regnum] = base;
+ f->reg_size[regnum] = size;
+
+ if (size && !base)
+ cprintf("PCI device %02x:%02x.%d (%04x:%04x) "
+ "may be misconfigured: "
+ "region %d: base 0x%x, size %d\n",
+ f->bus->busno, f->dev, f->func,
+ PCI_VENDOR(f->dev_id), PCI_PRODUCT(f->dev_id),
+ regnum, base, size);
+ }
+}
+
+int
+pci_init(void)
+{
+ static struct pci_bus root_bus;
+ memset(&root_bus, 0, sizeof(root_bus));
+
+ return pci_scan_bus(&root_bus);
+}
View
33 kern/pci.h
@@ -0,0 +1,33 @@
+#ifndef JOS_KERN_PCI_H
+#define JOS_KERN_PCI_H
+
+#include <inc/types.h>
+
+// PCI subsystem interface
+enum { pci_res_bus, pci_res_mem, pci_res_io, pci_res_max };
+
+struct pci_bus;
+
+struct pci_func {
+ struct pci_bus *bus; // Primary bus for bridges
+
+ uint32_t dev;
+ uint32_t func;
+
+ uint32_t dev_id;
+ uint32_t dev_class;
+
+ uint32_t reg_base[6];
+ uint32_t reg_size[6];
+ uint8_t irq_line;
+};
+
+struct pci_bus {
+ struct pci_func *parent_bridge;
+ uint32_t busno;
+};
+
+int pci_init(void);
+void pci_func_enable(struct pci_func *f);
+
+#endif
View
710 kern/pcireg.h
@@ -0,0 +1,710 @@
+/* $NetBSD: pcireg.h,v 1.45 2004/02/04 06:58:24 soren Exp $ */
+
+/*
+ * Copyright (c) 1995, 1996, 1999, 2000
+ * Christopher G. Demetriou. All rights reserved.
+ * Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Charles M. Hannum.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DEV_PCI_PCIREG_H_
+#define _DEV_PCI_PCIREG_H_
+
+/*
+ * Standardized PCI configuration information
+ *
+ * XXX This is not complete.
+ */
+
+#include <inc/types.h>
+
+/*
+ * Device identification register; contains a vendor ID and a device ID.
+ */
+#define PCI_ID_REG 0x00
+
+typedef uint16_t pci_vendor_id_t;
+typedef uint16_t pci_product_id_t;
+
+#define PCI_VENDOR_SHIFT 0
+#define PCI_VENDOR_MASK 0xffff
+#define PCI_VENDOR(id) \
+ (((id) >> PCI_VENDOR_SHIFT) & PCI_VENDOR_MASK)
+
+#define PCI_PRODUCT_SHIFT 16
+#define PCI_PRODUCT_MASK 0xffff
+#define PCI_PRODUCT(id) \
+ (((id) >> PCI_PRODUCT_SHIFT) & PCI_PRODUCT_MASK)
+
+#define PCI_ID_CODE(vid,pid) \
+ ((((vid) & PCI_VENDOR_MASK) << PCI_VENDOR_SHIFT) | \
+ (((pid) & PCI_PRODUCT_MASK) << PCI_PRODUCT_SHIFT)) \
+
+/*
+ * Command and status register.
+ */
+#define PCI_COMMAND_STATUS_REG 0x04
+#define PCI_COMMAND_SHIFT 0
+#define PCI_COMMAND_MASK 0xffff
+#define PCI_STATUS_SHIFT 16
+#define PCI_STATUS_MASK 0xffff
+
+#define PCI_COMMAND_STATUS_CODE(cmd,stat) \
+ ((((cmd) & PCI_COMMAND_MASK) >> PCI_COMMAND_SHIFT) | \
+ (((stat) & PCI_STATUS_MASK) >> PCI_STATUS_SHIFT)) \
+
+#define PCI_COMMAND_IO_ENABLE 0x00000001
+#define PCI_COMMAND_MEM_ENABLE 0x00000002
+#define PCI_COMMAND_MASTER_ENABLE 0x00000004
+#define PCI_COMMAND_SPECIAL_ENABLE 0x00000008
+#define PCI_COMMAND_INVALIDATE_ENABLE 0x00000010
+#define PCI_COMMAND_PALETTE_ENABLE 0x00000020
+#define PCI_COMMAND_PARITY_ENABLE 0x00000040
+#define PCI_COMMAND_STEPPING_ENABLE 0x00000080
+#define PCI_COMMAND_SERR_ENABLE 0x00000100
+#define PCI_COMMAND_BACKTOBACK_ENABLE 0x00000200
+
+#define PCI_STATUS_CAPLIST_SUPPORT 0x00100000
+#define PCI_STATUS_66MHZ_SUPPORT 0x00200000
+#define PCI_STATUS_UDF_SUPPORT 0x00400000
+#define PCI_STATUS_BACKTOBACK_SUPPORT 0x00800000
+#define PCI_STATUS_PARITY_ERROR 0x01000000
+#define PCI_STATUS_DEVSEL_FAST 0x00000000
+#define PCI_STATUS_DEVSEL_MEDIUM 0x02000000
+#define PCI_STATUS_DEVSEL_SLOW 0x04000000
+#define PCI_STATUS_DEVSEL_MASK 0x06000000
+#define PCI_STATUS_TARGET_TARGET_ABORT 0x08000000
+#define PCI_STATUS_MASTER_TARGET_ABORT 0x10000000
+#define PCI_STATUS_MASTER_ABORT 0x20000000
+#define PCI_STATUS_SPECIAL_ERROR 0x40000000
+#define PCI_STATUS_PARITY_DETECT 0x80000000
+
+/*
+ * PCI Class and Revision Register; defines type and revision of device.
+ */
+#define PCI_CLASS_REG 0x08
+
+typedef uint8_t pci_class_t;
+typedef uint8_t pci_subclass_t;
+typedef uint8_t pci_interface_t;
+typedef uint8_t pci_revision_t;
+
+#define PCI_CLASS_SHIFT 24
+#define PCI_CLASS_MASK 0xff
+#define PCI_CLASS(cr) \
+ (((cr) >> PCI_CLASS_SHIFT) & PCI_CLASS_MASK)
+
+#define PCI_SUBCLASS_SHIFT 16
+#define PCI_SUBCLASS_MASK 0xff
+#define PCI_SUBCLASS(cr) \
+ (((cr) >> PCI_SUBCLASS_SHIFT) & PCI_SUBCLASS_MASK)
+
+#define PCI_INTERFACE_SHIFT 8
+#define PCI_INTERFACE_MASK 0xff
+#define PCI_INTERFACE(cr) \
+ (((cr) >> PCI_INTERFACE_SHIFT) & PCI_INTERFACE_MASK)
+
+#define PCI_REVISION_SHIFT 0
+#define PCI_REVISION_MASK 0xff
+#define PCI_REVISION(cr) \
+ (((cr) >> PCI_REVISION_SHIFT) & PCI_REVISION_MASK)
+
+#define PCI_CLASS_CODE(mainclass, subclass, interface) \
+ ((((mainclass) & PCI_CLASS_MASK) << PCI_CLASS_SHIFT) | \
+ (((subclass) & PCI_SUBCLASS_MASK) << PCI_SUBCLASS_SHIFT) | \
+ (((interface) & PCI_INTERFACE_MASK) << PCI_INTERFACE_SHIFT))
+
+/* base classes */
+#define PCI_CLASS_PREHISTORIC 0x00
+#define PCI_CLASS_MASS_STORAGE 0x01
+#define PCI_CLASS_NETWORK 0x02
+#define PCI_CLASS_DISPLAY 0x03
+#define PCI_CLASS_MULTIMEDIA 0x04
+#define PCI_CLASS_MEMORY 0x05
+#define PCI_CLASS_BRIDGE 0x06
+#define PCI_CLASS_COMMUNICATIONS 0x07
+#define PCI_CLASS_SYSTEM 0x08
+#define PCI_CLASS_INPUT 0x09
+#define PCI_CLASS_DOCK 0x0a
+#define PCI_CLASS_PROCESSOR 0x0b
+#define PCI_CLASS_SERIALBUS 0x0c
+#define PCI_CLASS_WIRELESS 0x0d
+#define PCI_CLASS_I2O 0x0e
+#define PCI_CLASS_SATCOM 0x0f
+#define PCI_CLASS_CRYPTO 0x10
+#define PCI_CLASS_DASP 0x11
+#define PCI_CLASS_UNDEFINED 0xff
+
+/* 0x00 prehistoric subclasses */
+#define PCI_SUBCLASS_PREHISTORIC_MISC 0x00
+#define PCI_SUBCLASS_PREHISTORIC_VGA 0x01
+
+/* 0x01 mass storage subclasses */
+#define PCI_SUBCLASS_MASS_STORAGE_SCSI 0x00
+#define PCI_SUBCLASS_MASS_STORAGE_IDE 0x01
+#define PCI_SUBCLASS_MASS_STORAGE_FLOPPY 0x02
+#define PCI_SUBCLASS_MASS_STORAGE_IPI 0x03
+#define PCI_SUBCLASS_MASS_STORAGE_RAID 0x04
+#define PCI_SUBCLASS_MASS_STORAGE_ATA 0x05
+#define PCI_SUBCLASS_MASS_STORAGE_SATA 0x06
+#define PCI_SUBCLASS_MASS_STORAGE_MISC 0x80
+
+/* 0x02 network subclasses */
+#define PCI_SUBCLASS_NETWORK_ETHERNET 0x00
+#define PCI_SUBCLASS_NETWORK_TOKENRING 0x01
+#define PCI_SUBCLASS_NETWORK_FDDI 0x02
+#define PCI_SUBCLASS_NETWORK_ATM 0x03
+#define PCI_SUBCLASS_NETWORK_ISDN 0x04
+#define PCI_SUBCLASS_NETWORK_WORLDFIP 0x05
+#define PCI_SUBCLASS_NETWORK_PCIMGMULTICOMP 0x06
+#define PCI_SUBCLASS_NETWORK_MISC 0x80
+
+/* 0x03 display subclasses */
+#define PCI_SUBCLASS_DISPLAY_VGA 0x00
+#define PCI_SUBCLASS_DISPLAY_XGA 0x01
+#define PCI_SUBCLASS_DISPLAY_3D 0x02
+#define PCI_SUBCLASS_DISPLAY_MISC 0x80
+
+/* 0x04 multimedia subclasses */
+#define PCI_SUBCLASS_MULTIMEDIA_VIDEO 0x00
+#define PCI_SUBCLASS_MULTIMEDIA_AUDIO 0x01
+#define PCI_SUBCLASS_MULTIMEDIA_TELEPHONY 0x02
+#define PCI_SUBCLASS_MULTIMEDIA_MISC 0x80
+
+/* 0x05 memory subclasses */
+#define PCI_SUBCLASS_MEMORY_RAM 0x00
+#define PCI_SUBCLASS_MEMORY_FLASH 0x01
+#define PCI_SUBCLASS_MEMORY_MISC 0x80
+
+/* 0x06 bridge subclasses */
+#define PCI_SUBCLASS_BRIDGE_HOST 0x00
+#define PCI_SUBCLASS_BRIDGE_ISA 0x01
+#define PCI_SUBCLASS_BRIDGE_EISA 0x02
+#define PCI_SUBCLASS_BRIDGE_MC 0x03 /* XXX _MCA? */
+#define PCI_SUBCLASS_BRIDGE_PCI 0x04
+#define PCI_SUBCLASS_BRIDGE_PCMCIA 0x05
+#define PCI_SUBCLASS_BRIDGE_NUBUS 0x06
+#define PCI_SUBCLASS_BRIDGE_CARDBUS 0x07
+#define PCI_SUBCLASS_BRIDGE_RACEWAY 0x08
+#define PCI_SUBCLASS_BRIDGE_STPCI 0x09
+#define PCI_SUBCLASS_BRIDGE_INFINIBAND 0x0a
+#define PCI_SUBCLASS_BRIDGE_MISC 0x80
+
+/* 0x07 communications subclasses */
+#define PCI_SUBCLASS_COMMUNICATIONS_SERIAL 0x00
+#define PCI_SUBCLASS_COMMUNICATIONS_PARALLEL 0x01
+#define PCI_SUBCLASS_COMMUNICATIONS_MPSERIAL 0x02
+#define PCI_SUBCLASS_COMMUNICATIONS_MODEM 0x03
+#define PCI_SUBCLASS_COMMUNICATIONS_GPIB 0x04
+#define PCI_SUBCLASS_COMMUNICATIONS_SMARTCARD 0x05
+#define PCI_SUBCLASS_COMMUNICATIONS_MISC 0x80
+
+/* 0x08 system subclasses */
+#define PCI_SUBCLASS_SYSTEM_PIC 0x00
+#define PCI_SUBCLASS_SYSTEM_DMA 0x01
+#define PCI_SUBCLASS_SYSTEM_TIMER 0x02
+#define PCI_SUBCLASS_SYSTEM_RTC 0x03
+#define PCI_SUBCLASS_SYSTEM_PCIHOTPLUG 0x04
+#define PCI_SUBCLASS_SYSTEM_MISC 0x80
+
+/* 0x09 input subclasses */
+#define PCI_SUBCLASS_INPUT_KEYBOARD 0x00
+#define PCI_SUBCLASS_INPUT_DIGITIZER 0x01
+#define PCI_SUBCLASS_INPUT_MOUSE 0x02
+#define PCI_SUBCLASS_INPUT_SCANNER 0x03
+#define PCI_SUBCLASS_INPUT_GAMEPORT 0x04
+#define PCI_SUBCLASS_INPUT_MISC 0x80
+
+/* 0x0a dock subclasses */
+#define PCI_SUBCLASS_DOCK_GENERIC 0x00
+#define PCI_SUBCLASS_DOCK_MISC 0x80
+
+/* 0x0b processor subclasses */
+#define PCI_SUBCLASS_PROCESSOR_386 0x00
+#define PCI_SUBCLASS_PROCESSOR_486 0x01
+#define PCI_SUBCLASS_PROCESSOR_PENTIUM 0x02
+#define PCI_SUBCLASS_PROCESSOR_ALPHA 0x10
+#define PCI_SUBCLASS_PROCESSOR_POWERPC 0x20
+#define PCI_SUBCLASS_PROCESSOR_MIPS 0x30
+#define PCI_SUBCLASS_PROCESSOR_COPROC 0x40
+
+/* 0x0c serial bus subclasses */
+#define PCI_SUBCLASS_SERIALBUS_FIREWIRE 0x00
+#define PCI_SUBCLASS_SERIALBUS_ACCESS 0x01
+#define PCI_SUBCLASS_SERIALBUS_SSA 0x02
+#define PCI_SUBCLASS_SERIALBUS_USB 0x03
+#define PCI_SUBCLASS_SERIALBUS_FIBER 0x04 /* XXX _FIBRECHANNEL */
+#define PCI_SUBCLASS_SERIALBUS_SMBUS 0x05
+#define PCI_SUBCLASS_SERIALBUS_INFINIBAND 0x06
+#define PCI_SUBCLASS_SERIALBUS_IPMI 0x07
+#define PCI_SUBCLASS_SERIALBUS_SERCOS 0x08
+#define PCI_SUBCLASS_SERIALBUS_CANBUS 0x09
+
+/* 0x0d wireless subclasses */
+#define PCI_SUBCLASS_WIRELESS_IRDA 0x00
+#define PCI_SUBCLASS_WIRELESS_CONSUMERIR 0x01
+#define PCI_SUBCLASS_WIRELESS_RF 0x10
+#define PCI_SUBCLASS_WIRELESS_BLUETOOTH 0x11
+#define PCI_SUBCLASS_WIRELESS_BROADBAND 0x12
+#define PCI_SUBCLASS_WIRELESS_802_11A 0x20
+#define PCI_SUBCLASS_WIRELESS_802_11B 0x21
+#define PCI_SUBCLASS_WIRELESS_MISC 0x80
+
+/* 0x0e I2O (Intelligent I/O) subclasses */
+#define PCI_SUBCLASS_I2O_STANDARD 0x00
+
+/* 0x0f satellite communication subclasses */
+/* PCI_SUBCLASS_SATCOM_??? 0x00 / * XXX ??? */
+#define PCI_SUBCLASS_SATCOM_TV 0x01
+#define PCI_SUBCLASS_SATCOM_AUDIO 0x02
+#define PCI_SUBCLASS_SATCOM_VOICE 0x03
+#define PCI_SUBCLASS_SATCOM_DATA 0x04
+
+/* 0x10 encryption/decryption subclasses */
+#define PCI_SUBCLASS_CRYPTO_NETCOMP 0x00
+#define PCI_SUBCLASS_CRYPTO_ENTERTAINMENT 0x10
+#define PCI_SUBCLASS_CRYPTO_MISC 0x80
+
+/* 0x11 data acquisition and signal processing subclasses */
+#define PCI_SUBCLASS_DASP_DPIO 0x00
+#define PCI_SUBCLASS_DASP_TIMEFREQ 0x01
+#define PCI_SUBCLASS_DASP_SYNC 0x10
+#define PCI_SUBCLASS_DASP_MGMT 0x20
+#define PCI_SUBCLASS_DASP_MISC 0x80
+
+/*
+ * PCI BIST/Header Type/Latency Timer/Cache Line Size Register.
+ */
+#define PCI_BHLC_REG 0x0c
+
+#define PCI_BIST_SHIFT 24
+#define PCI_BIST_MASK 0xff
+#define PCI_BIST(bhlcr) \
+ (((bhlcr) >> PCI_BIST_SHIFT) & PCI_BIST_MASK)
+
+#define PCI_HDRTYPE_SHIFT 16
+#define PCI_HDRTYPE_MASK 0xff
+#define PCI_HDRTYPE(bhlcr) \
+ (((bhlcr) >> PCI_HDRTYPE_SHIFT) & PCI_HDRTYPE_MASK)
+
+#define PCI_HDRTYPE_TYPE(bhlcr) \
+ (PCI_HDRTYPE(bhlcr) & 0x7f)
+#define PCI_HDRTYPE_MULTIFN(bhlcr) \
+ ((PCI_HDRTYPE(bhlcr) & 0x80) != 0)
+
+#define PCI_LATTIMER_SHIFT 8
+#define PCI_LATTIMER_MASK 0xff
+#define PCI_LATTIMER(bhlcr) \
+ (((bhlcr) >> PCI_LATTIMER_SHIFT) & PCI_LATTIMER_MASK)
+
+#define PCI_CACHELINE_SHIFT 0
+#define PCI_CACHELINE_MASK 0xff
+#define PCI_CACHELINE(bhlcr) \
+ (((bhlcr) >> PCI_CACHELINE_SHIFT) & PCI_CACHELINE_MASK)
+
+#define PCI_BHLC_CODE(bist,type,multi,latency,cacheline) \
+ ((((bist) & PCI_BIST_MASK) << PCI_BIST_SHIFT) | \
+ (((type) & PCI_HDRTYPE_MASK) << PCI_HDRTYPE_SHIFT) | \
+ (((multi)?0x80:0) << PCI_HDRTYPE_SHIFT) | \
+ (((latency) & PCI_LATTIMER_MASK) << PCI_LATTIMER_SHIFT) | \
+ (((cacheline) & PCI_CACHELINE_MASK) << PCI_CACHELINE_SHIFT))
+
+/*
+ * PCI header type
+ */
+#define PCI_HDRTYPE_DEVICE 0
+#define PCI_HDRTYPE_PPB 1
+#define PCI_HDRTYPE_PCB 2
+
+/*
+ * Mapping registers
+ */
+#define PCI_MAPREG_START 0x10
+#define PCI_MAPREG_END 0x28
+#define PCI_MAPREG_ROM 0x30
+#define PCI_MAPREG_PPB_END 0x18
+#define PCI_MAPREG_PCB_END 0x14
+
+#define PCI_MAPREG_TYPE(mr) \
+ ((mr) & PCI_MAPREG_TYPE_MASK)
+#define PCI_MAPREG_TYPE_MASK 0x00000001
+
+#define PCI_MAPREG_TYPE_MEM 0x00000000
+#define PCI_MAPREG_TYPE_IO 0x00000001
+#define PCI_MAPREG_ROM_ENABLE 0x00000001
+
+#define PCI_MAPREG_MEM_TYPE(mr) \
+ ((mr) & PCI_MAPREG_MEM_TYPE_MASK)
+#define PCI_MAPREG_MEM_TYPE_MASK 0x00000006
+
+#define PCI_MAPREG_MEM_TYPE_32BIT 0x00000000
+#define PCI_MAPREG_MEM_TYPE_32BIT_1M 0x00000002
+#define PCI_MAPREG_MEM_TYPE_64BIT 0x00000004
+
+#define PCI_MAPREG_MEM_PREFETCHABLE(mr) \
+ (((mr) & PCI_MAPREG_MEM_PREFETCHABLE_MASK) != 0)
+#define PCI_MAPREG_MEM_PREFETCHABLE_MASK 0x00000008
+
+#define PCI_MAPREG_MEM_ADDR(mr) \
+ ((mr) & PCI_MAPREG_MEM_ADDR_MASK)
+#define PCI_MAPREG_MEM_SIZE(mr) \
+ (PCI_MAPREG_MEM_ADDR(mr) & -PCI_MAPREG_MEM_ADDR(mr))
+#define PCI_MAPREG_MEM_ADDR_MASK 0xfffffff0
+
+#define PCI_MAPREG_MEM64_ADDR(mr) \
+ ((mr) & PCI_MAPREG_MEM64_ADDR_MASK)
+#define PCI_MAPREG_MEM64_SIZE(mr) \
+ (PCI_MAPREG_MEM64_ADDR(mr) & -PCI_MAPREG_MEM64_ADDR(mr))
+#define PCI_MAPREG_MEM64_ADDR_MASK 0xfffffffffffffff0ULL
+
+#define PCI_MAPREG_IO_ADDR(mr) \
+ ((mr) & PCI_MAPREG_IO_ADDR_MASK)
+#define PCI_MAPREG_IO_SIZE(mr) \
+ (PCI_MAPREG_IO_ADDR(mr) & -PCI_MAPREG_IO_ADDR(mr))
+#define PCI_MAPREG_IO_ADDR_MASK 0xfffffffc
+
+#define PCI_MAPREG_SIZE_TO_MASK(size) \
+ (-(size))
+
+#define PCI_MAPREG_NUM(offset) \
+ (((unsigned)(offset)-PCI_MAPREG_START)/4)
+
+
+/*
+ * Cardbus CIS pointer (PCI rev. 2.1)
+ */
+#define PCI_CARDBUS_CIS_REG 0x28
+
+/*
+ * Subsystem identification register; contains a vendor ID and a device ID.
+ * Types/macros for PCI_ID_REG apply.
+ * (PCI rev. 2.1)
+ */
+#define PCI_SUBSYS_ID_REG 0x2c
+
+/*
+ * Capabilities link list (PCI rev. 2.2)
+ */
+#define PCI_CAPLISTPTR_REG 0x34 /* header type 0 */
+#define PCI_CARDBUS_CAPLISTPTR_REG 0x14 /* header type 2 */
+#define PCI_CAPLIST_PTR(cpr) ((cpr) & 0xff)
+#define PCI_CAPLIST_NEXT(cr) (((cr) >> 8) & 0xff)
+#define PCI_CAPLIST_CAP(cr) ((cr) & 0xff)
+
+#define PCI_CAP_RESERVED0 0x00
+#define PCI_CAP_PWRMGMT 0x01
+#define PCI_CAP_AGP 0x02
+#define PCI_CAP_AGP_MAJOR(cr) (((cr) >> 20) & 0xf)
+#define PCI_CAP_AGP_MINOR(cr) (((cr) >> 16) & 0xf)
+#define PCI_CAP_VPD 0x03
+#define PCI_CAP_SLOTID 0x04
+#define PCI_CAP_MSI 0x05
+#define PCI_CAP_CPCI_HOTSWAP 0x06
+#define PCI_CAP_PCIX 0x07
+#define PCI_CAP_LDT 0x08
+#define PCI_CAP_VENDSPEC 0x09
+#define PCI_CAP_DEBUGPORT 0x0a
+#define PCI_CAP_CPCI_RSRCCTL 0x0b
+#define PCI_CAP_HOTPLUG 0x0c
+#define PCI_CAP_AGP8 0x0e
+#define PCI_CAP_SECURE 0x0f
+#define PCI_CAP_PCIEXPRESS 0x10
+#define PCI_CAP_MSIX 0x11
+
+/*
+ * Vital Product Data; access via capability pointer (PCI rev 2.2).
+ */
+#define PCI_VPD_ADDRESS_MASK 0x7fff
+#define PCI_VPD_ADDRESS_SHIFT 16
+#define PCI_VPD_ADDRESS(ofs) \
+ (((ofs) & PCI_VPD_ADDRESS_MASK) << PCI_VPD_ADDRESS_SHIFT)
+#define PCI_VPD_DATAREG(ofs) ((ofs) + 4)
+#define PCI_VPD_OPFLAG 0x80000000
+
+/*
+ * Power Management Capability; access via capability pointer.
+ */
+
+/* Power Management Capability Register */
+#define PCI_PMCR 0x02
+#define PCI_PMCR_D1SUPP 0x0200
+#define PCI_PMCR_D2SUPP 0x0400
+/* Power Management Control Status Register */
+#define PCI_PMCSR 0x04
+#define PCI_PMCSR_STATE_MASK 0x03
+#define PCI_PMCSR_STATE_D0 0x00
+#define PCI_PMCSR_STATE_D1 0x01
+#define PCI_PMCSR_STATE_D2 0x02
+#define PCI_PMCSR_STATE_D3 0x03
+
+/*
+ * PCI-X capability.
+ */
+
+/*
+ * Command. 16 bits at offset 2 (e.g. upper 16 bits of the first 32-bit
+ * word at the capability; the lower 16 bits are the capability ID and
+ * next capability pointer).
+ *
+ * Since we always read PCI config space in 32-bit words, we define these
+ * as 32-bit values, offset and shifted appropriately. Make sure you perform
+ * the appropriate R/M/W cycles!
+ */
+#define PCI_PCIX_CMD 0x00
+#define PCI_PCIX_CMD_PERR_RECOVER 0x00010000
+#define PCI_PCIX_CMD_RELAXED_ORDER 0x00020000
+#define PCI_PCIX_CMD_BYTECNT_MASK 0x000c0000
+#define PCI_PCIX_CMD_BYTECNT_SHIFT 18
+#define PCI_PCIX_CMD_BCNT_512 0x00000000
+#define PCI_PCIX_CMD_BCNT_1024 0x00040000
+#define PCI_PCIX_CMD_BCNT_2048 0x00080000
+#define PCI_PCIX_CMD_BCNT_4096 0x000c0000
+#define PCI_PCIX_CMD_SPLTRANS_MASK 0x00700000
+#define PCI_PCIX_CMD_SPLTRANS_1 0x00000000
+#define PCI_PCIX_CMD_SPLTRANS_2 0x00100000
+#define PCI_PCIX_CMD_SPLTRANS_3 0x00200000
+#define PCI_PCIX_CMD_SPLTRANS_4 0x00300000
+#define PCI_PCIX_CMD_SPLTRANS_8 0x00400000
+#define PCI_PCIX_CMD_SPLTRANS_12 0x00500000
+#define PCI_PCIX_CMD_SPLTRANS_16 0x00600000
+#define PCI_PCIX_CMD_SPLTRANS_32 0x00700000
+
+/*
+ * Status. 32 bits at offset 4.
+ */
+#define PCI_PCIX_STATUS 0x04
+#define PCI_PCIX_STATUS_FN_MASK 0x00000007
+#define PCI_PCIX_STATUS_DEV_MASK 0x000000f8
+#define PCI_PCIX_STATUS_BUS_MASK 0x0000ff00
+#define PCI_PCIX_STATUS_64BIT 0x00010000
+#define PCI_PCIX_STATUS_133 0x00020000
+#define PCI_PCIX_STATUS_SPLDISC 0x00040000
+#define PCI_PCIX_STATUS_SPLUNEX 0x00080000
+#define PCI_PCIX_STATUS_DEVCPLX 0x00100000
+#define PCI_PCIX_STATUS_MAXB_MASK 0x00600000
+#define PCI_PCIX_STATUS_MAXB_SHIFT 21
+#define PCI_PCIX_STATUS_MAXB_512 0x00000000
+#define PCI_PCIX_STATUS_MAXB_1024 0x00200000
+#define PCI_PCIX_STATUS_MAXB_2048 0x00400000
+#define PCI_PCIX_STATUS_MAXB_4096 0x00600000
+#define PCI_PCIX_STATUS_MAXST_MASK 0x03800000
+#define PCI_PCIX_STATUS_MAXST_1 0x00000000
+#define PCI_PCIX_STATUS_MAXST_2 0x00800000
+#define PCI_PCIX_STATUS_MAXST_3 0x01000000
+#define PCI_PCIX_STATUS_MAXST_4 0x01800000
+#define PCI_PCIX_STATUS_MAXST_8 0x02000000
+#define PCI_PCIX_STATUS_MAXST_12 0x02800000
+#define PCI_PCIX_STATUS_MAXST_16 0x03000000
+#define PCI_PCIX_STATUS_MAXST_32 0x03800000
+#define PCI_PCIX_STATUS_MAXRS_MASK 0x1c000000
+#define PCI_PCIX_STATUS_MAXRS_1K 0x00000000
+#define PCI_PCIX_STATUS_MAXRS_2K 0x04000000
+#define PCI_PCIX_STATUS_MAXRS_4K 0x08000000
+#define PCI_PCIX_STATUS_MAXRS_8K 0x0c000000
+#define PCI_PCIX_STATUS_MAXRS_16K 0x10000000
+#define PCI_PCIX_STATUS_MAXRS_32K 0x14000000
+#define PCI_PCIX_STATUS_MAXRS_64K 0x18000000
+#define PCI_PCIX_STATUS_MAXRS_128K 0x1c000000
+#define PCI_PCIX_STATUS_SCERR 0x20000000
+
+
+/*
+ * Interrupt Configuration Register; contains interrupt pin and line.
+ */
+#define PCI_INTERRUPT_REG 0x3c
+
+typedef uint8_t pci_intr_latency_t;
+typedef uint8_t pci_intr_grant_t;
+typedef uint8_t pci_intr_pin_t;
+typedef uint8_t pci_intr_line_t;
+
+#define PCI_MAX_LAT_SHIFT 24
+#define PCI_MAX_LAT_MASK 0xff
+#define PCI_MAX_LAT(icr) \
+ (((icr) >> PCI_MAX_LAT_SHIFT) & PCI_MAX_LAT_MASK)
+
+#define PCI_MIN_GNT_SHIFT 16
+#define PCI_MIN_GNT_MASK 0xff
+#define PCI_MIN_GNT(icr) \
+ (((icr) >> PCI_MIN_GNT_SHIFT) & PCI_MIN_GNT_MASK)
+
+#define PCI_INTERRUPT_GRANT_SHIFT 24
+#define PCI_INTERRUPT_GRANT_MASK 0xff
+#define PCI_INTERRUPT_GRANT(icr) \
+ (((icr) >> PCI_INTERRUPT_GRANT_SHIFT) & PCI_INTERRUPT_GRANT_MASK)
+
+#define PCI_INTERRUPT_LATENCY_SHIFT 16
+#define PCI_INTERRUPT_LATENCY_MASK 0xff
+#define PCI_INTERRUPT_LATENCY(icr) \
+ (((icr) >> PCI_INTERRUPT_LATENCY_SHIFT) & PCI_INTERRUPT_LATENCY_MASK)
+
+#define PCI_INTERRUPT_PIN_SHIFT 8
+#define PCI_INTERRUPT_PIN_MASK 0xff
+#define PCI_INTERRUPT_PIN(icr) \
+ (((icr) >> PCI_INTERRUPT_PIN_SHIFT) & PCI_INTERRUPT_PIN_MASK)
+
+#define PCI_INTERRUPT_LINE_SHIFT 0
+#define PCI_INTERRUPT_LINE_MASK 0xff
+#define PCI_INTERRUPT_LINE(icr) \
+ (((icr) >> PCI_INTERRUPT_LINE_SHIFT) & PCI_INTERRUPT_LINE_MASK)
+
+#define PCI_INTERRUPT_CODE(lat,gnt,pin,line) \
+ ((((lat)&PCI_INTERRUPT_LATENCY_MASK)<<PCI_INTERRUPT_LATENCY_SHIFT)| \
+ (((gnt)&PCI_INTERRUPT_GRANT_MASK) <<PCI_INTERRUPT_GRANT_SHIFT) | \
+ (((pin)&PCI_INTERRUPT_PIN_MASK) <<PCI_INTERRUPT_PIN_SHIFT) | \
+ (((line)&PCI_INTERRUPT_LINE_MASK) <<PCI_INTERRUPT_LINE_SHIFT))
+
+#define PCI_INTERRUPT_PIN_NONE 0x00
+#define PCI_INTERRUPT_PIN_A 0x01
+#define PCI_INTERRUPT_PIN_B 0x02
+#define PCI_INTERRUPT_PIN_C 0x03
+#define PCI_INTERRUPT_PIN_D 0x04
+#define PCI_INTERRUPT_PIN_MAX 0x04
+
+/* Header Type 1 (Bridge) configuration registers */
+#define PCI_BRIDGE_BUS_REG 0x18
+#define PCI_BRIDGE_BUS_PRIMARY_SHIFT 0
+#define PCI_BRIDGE_BUS_SECONDARY_SHIFT 8
+#define PCI_BRIDGE_BUS_SUBORDINATE_SHIFT 16
+
+#define PCI_BRIDGE_STATIO_REG 0x1C
+#define PCI_BRIDGE_STATIO_IOBASE_SHIFT 0
+#define PCI_BRIDGE_STATIO_IOLIMIT_SHIFT 8
+#define PCI_BRIDGE_STATIO_STATUS_SHIFT 16
+#define PCI_BRIDGE_STATIO_IOBASE_MASK 0xf0
+#define PCI_BRIDGE_STATIO_IOLIMIT_MASK 0xf0
+#define PCI_BRIDGE_STATIO_STATUS_MASK 0xffff
+#define PCI_BRIDGE_IO_32BITS(reg) (((reg) & 0xf) == 1)
+
+#define PCI_BRIDGE_MEMORY_REG 0x20
+#define PCI_BRIDGE_MEMORY_BASE_SHIFT 4
+#define PCI_BRIDGE_MEMORY_LIMIT_SHIFT 20
+#define PCI_BRIDGE_MEMORY_BASE_MASK 0xffff
+#define PCI_BRIDGE_MEMORY_LIMIT_MASK 0xffff
+
+#define PCI_BRIDGE_PREFETCHMEM_REG 0x24
+#define PCI_BRIDGE_PREFETCHMEM_BASE_SHIFT 4
+#define PCI_BRIDGE_PREFETCHMEM_LIMIT_SHIFT 20
+#define PCI_BRIDGE_PREFETCHMEM_BASE_MASK 0xffff
+#define PCI_BRIDGE_PREFETCHMEM_LIMIT_MASK 0xffff
+#define PCI_BRIDGE_PREFETCHMEM_64BITS(reg) ((reg) & 0xf)
+
+#define PCI_BRIDGE_PREFETCHBASE32_REG 0x28
+#define PCI_BRIDGE_PREFETCHLIMIT32_REG 0x2C
+
+#define PCI_BRIDGE_IOHIGH_REG 0x30
+#define PCI_BRIDGE_IOHIGH_BASE_SHIFT 0
+#define PCI_BRIDGE_IOHIGH_LIMIT_SHIFT 16
+#define PCI_BRIDGE_IOHIGH_BASE_MASK 0xffff
+#define PCI_BRIDGE_IOHIGH_LIMIT_MASK 0xffff
+
+#define PCI_BRIDGE_CONTROL_REG 0x3C
+#define PCI_BRIDGE_CONTROL_SHIFT 16
+#define PCI_BRIDGE_CONTROL_MASK 0xffff
+#define PCI_BRIDGE_CONTROL_PERE (1 << 0)
+#define PCI_BRIDGE_CONTROL_SERR (1 << 1)
+#define PCI_BRIDGE_CONTROL_ISA (1 << 2)
+#define PCI_BRIDGE_CONTROL_VGA (1 << 3)
+/* Reserved (1 << 4) */
+#define PCI_BRIDGE_CONTROL_MABRT (1 << 5)
+#define PCI_BRIDGE_CONTROL_SECBR (1 << 6)
+#define PCI_BRIDGE_CONTROL_SECFASTB2B (1 << 7)
+#define PCI_BRIDGE_CONTROL_PRI_DISC_TIMER (1 << 8)
+#define PCI_BRIDGE_CONTROL_SEC_DISC_TIMER (1 << 9)
+#define PCI_BRIDGE_CONTROL_DISC_TIMER_STAT (1 << 10)
+#define PCI_BRIDGE_CONTROL_DISC_TIMER_SERR (1 << 11)
+/* Reserved (1 << 12) - (1 << 15) */
+
+/*
+ * Vital Product Data resource tags.
+ */
+struct pci_vpd_smallres {
+ uint8_t vpdres_byte0; /* length of data + tag */
+ /* Actual data. */
+} __attribute__((__packed__));
+
+struct pci_vpd_largeres {
+ uint8_t vpdres_byte0;
+ uint8_t vpdres_len_lsb; /* length of data only */
+ uint8_t vpdres_len_msb;
+ /* Actual data. */
+} __attribute__((__packed__));
+
+#define PCI_VPDRES_ISLARGE(x) ((x) & 0x80)
+
+#define PCI_VPDRES_SMALL_LENGTH(x) ((x) & 0x7)
+#define PCI_VPDRES_SMALL_NAME(x) (((x) >> 3) & 0xf)
+
+#define PCI_VPDRES_LARGE_NAME(x) ((x) & 0x7f)
+
+#define PCI_VPDRES_TYPE_COMPATIBLE_DEVICE_ID 0x3 /* small */
+#define PCI_VPDRES_TYPE_VENDOR_DEFINED 0xe /* small */
+#define PCI_VPDRES_TYPE_END_TAG 0xf /* small */
+
+#define PCI_VPDRES_TYPE_IDENTIFIER_STRING 0x02 /* large */
+#define PCI_VPDRES_TYPE_VPD 0x10 /* large */
+
+struct pci_vpd {
+ uint8_t vpd_key0;
+ uint8_t vpd_key1;
+ uint8_t vpd_len; /* length of data only */
+ /* Actual data. */
+} __attribute__((__packed__));
+
+/*
+ * Recommended VPD fields:
+ *
+ * PN Part number of assembly
+ * FN FRU part number
+ * EC EC level of assembly
+ * MN Manufacture ID
+ * SN Serial Number
+ *
+ * Conditionally recommended VPD fields:
+ *
+ * LI Load ID
+ * RL ROM Level
+ * RM Alterable ROM Level
+ * NA Network Address
+ * DD Device Driver Level
+ * DG Diagnostic Level
+ * LL Loadable Microcode Level
+ * VI Vendor ID/Device ID
+ * FU Function Number
+ * SI Subsystem Vendor ID/Subsystem ID
+ *
+ * Additional VPD fields:
+ *
+ * Z0-ZZ User/Product Specific
+ */
+
+/*
+ * Threshold below which 32bit PCI DMA needs bouncing.
+ */
+#define PCI32_DMA_BOUNCE_THRESHOLD 0x100000000ULL
+
+#endif /* _DEV_PCI_PCIREG_H_ */
View
12 kern/picirq.c
@@ -83,3 +83,15 @@ irq_setmask_8259A(uint16_t mask)
cprintf("\n");
}
+void
+irq_eoi(void)
+{
+ // OCW2: rse00xxx
+ // r: rotate
+ // s: specific
+ // e: end-of-interrupt
+ // xxx: specific interrupt line
+ outb(IO_PIC1, 0x20);
+ outb(IO_PIC2, 0x20);
+}
+
View
2  kern/picirq.h
@@ -24,7 +24,7 @@
extern uint16_t irq_mask_8259A;
void pic_init(void);
void irq_setmask_8259A(uint16_t mask);
-
+void irq_eoi(void);
#endif // !__ASSEMBLER__
#endif // !JOS_KERN_PICIRQ_H
View
10 kern/syscall.c
@@ -11,6 +11,8 @@
#include <kern/syscall.h>
#include <kern/console.h>
#include <kern/sched.h>
+#include <kern/time.h>
+#include <kern/e100.h>
// Print a string to the system console.
// The string is exactly 'len' characters long.
@@ -280,6 +282,14 @@ sys_ipc_recv(void *dstva)
return 0;
}
+// Return the current time.
+static int
+sys_time_msec(void)
+{
+ // LAB 6: Your code here.
+ panic("sys_time_msec not implemented");
+}
+
// Dispatches to the correct kernel function, passing the arguments.
int32_t
View
26 kern/time.c
@@ -0,0 +1,26 @@
+#include <kern/time.h>
+#include <inc/assert.h>
+
+static unsigned int ticks;
+
+void
+time_init(void)
+{
+ ticks = 0;
+}
+
+// this is called once per timer interupt; a timer interupt fires 100 times a
+// second
+void
+time_tick(void)
+{
+ ticks++;
+ if (ticks * 10 < ticks)
+ panic("time_tick: time overflowed");
+}
+
+unsigned int
+time_msec(void)
+{
+ return ticks * 10;
+}
View
11 kern/time.h
@@ -0,0 +1,11 @@
+#ifndef JOS_KERN_TIME_H
+#define JOS_KERN_TIME_H
+#ifndef JOS_KERNEL
+# error "This is a JOS kernel header; user programs should not #include it"
+#endif
+
+void time_init(void);
+void time_tick(void);
+unsigned int time_msec(void);
+
+#endif /* JOS_KERN_TIME_H */
View
5 kern/trap.c
@@ -11,6 +11,8 @@
#include <kern/sched.h>
#include <kern/kclock.h>
#include <kern/picirq.h>
+#include <kern/time.h>
+#include <kern/e100.h>
static struct Taskstate ts;
@@ -120,6 +122,9 @@ trap_dispatch(struct Trapframe *tf)
// Handle clock interrupts.
// LAB 4: Your code here.
+ // Add time tick increment to clock interrupts.
+ // LAB 6: Your code here.
+
// Handle spurious interupts
// The hardware sometimes raises these because of noise on the
// IRQ line or other reasons. We don't care.
View
4 lib/Makefrag
@@ -24,6 +24,10 @@ LIB_SRCFILES := $(LIB_SRCFILES) \
lib/pageref.c \
lib/spawn.c
+LIB_SRCFILES := $(LIB_SRCFILES) \
+ lib/sockets.c \
+ lib/nsipc.c \
+ lib/malloc.c
LIB_OBJFILES := $(patsubst lib/%.c, $(OBJDIR)/lib/%.o, $(LIB_SRCFILES))
LIB_OBJFILES := $(patsubst lib/%.S, $(OBJDIR)/lib/%.o, $(LIB_OBJFILES))
View
4 lib/entry.S
@@ -11,6 +11,10 @@ fsipcbuf:
.globl fdtab
fdtab:
.space PGSIZE
+ .globl nsipcbuf
+ // page-aligned nsipcbuf for nsipc.c
+nsipcbuf:
+ .space PGSIZE
// Define the global symbols 'envs', 'pages', 'vpt', and 'vpd'
View
2  lib/file.c
@@ -173,7 +173,7 @@ fmap(struct Fd* fd, off_t oldsize, off_t newsize)
// Unmap any file pages that no longer represent valid file pages
// when the size of the file as mapped in our address space decreases.
-// Harmlessly does nothing if newsize >= oldsize. Don't do anything
+// Harmlessly does nothing if newsize >= oldsize.
//
// Hint: Remember to call fsipc_dirty if dirty is true and PTE_D bit
// is set in the pagetable entry.
View
140 lib/malloc.c
@@ -0,0 +1,140 @@
+
+#include <inc/lib.h>
+
+/*
+ * Simple malloc/free.
+ *
+ * Uses the address space to do most of the hard work.
+ * The address space from mbegin to mend is scanned
+ * in order. Pages are allocated, used to fill successive
+ * malloc requests, and then left alone. Free decrements
+ * a ref count maintained in the page; the page is freed
+ * when the ref count hits zero.
+ *
+ * If we need to allocate a large amount (more than a page)
+ * we can't put a ref count at the end of each page,
+ * so we mark the pte entry with the bit PTE_CONTINUED.
+ */
+enum
+{
+ MAXMALLOC = 1024*1024 /* max size of one allocated chunk */
+};
+
+#define PTE_CONTINUED 0x400
+
+static uint8_t *mbegin = (uint8_t*) 0x08000000;
+static uint8_t *mend = (uint8_t*) 0x10000000;
+static uint8_t *mptr;
+
+static int
+isfree(void *v, size_t n)
+{
+ uintptr_t va, end_va = (uintptr_t) v + n;
+
+ for (va = (uintptr_t) v; va < end_va; va += PGSIZE)
+ if (va >= (uintptr_t) mend
+ || ((vpd[PDX(va)] & PTE_P) && (vpt[VPN(va)] & PTE_P)))
+ return 0;
+ return 1;
+}
+
+void*
+malloc(size_t n)
+{
+ int i, cont;
+ int nwrap;
+ uint32_t *ref;
+ void *v;
+
+ if (mptr == 0)
+ mptr = mbegin;
+
+ n = ROUNDUP(n, 4);
+
+ if (n >= MAXMALLOC)
+ return 0;
+
+ if ((uintptr_t) mptr % PGSIZE){
+ /*
+ * we're in the middle of a partially
+ * allocated page - can we add this chunk?
+ * the +4 below is for the ref count.
+ */
+ ref = (uint32_t*) (ROUNDUP(mptr, PGSIZE) - 4);
+ if ((uintptr_t) mptr / PGSIZE == (uintptr_t) (mptr + n - 1 + 4) / PGSIZE) {
+ (*ref)++;
+ v = mptr;
+ mptr += n;
+ return v;
+ }
+ /*
+ * stop working on this page and move on.
+ */
+ free(mptr); /* drop reference to this page */
+ mptr = ROUNDDOWN(mptr + PGSIZE, PGSIZE);
+ }
+
+ /*
+ * now we need to find some address space for this chunk.
+ * if it's less than a page we leave it open for allocation.
+ * runs of more than a page can't have ref counts so we
+ * flag the PTE entries instead.
+ */
+ nwrap = 0;
+ while (1) {
+ if (isfree(mptr, n + 4))
+ break;
+ mptr += PGSIZE;
+ if (mptr == mend) {
+ mptr = mbegin;
+ if (++nwrap == 2)
+ return 0; /* out of address space */
+ }
+ }
+
+ /*
+ * allocate at mptr - the +4 makes sure we allocate a ref count.
+ */
+ for (i = 0; i < n + 4; i += PGSIZE){
+ cont = (i + PGSIZE < n + 4) ? PTE_CONTINUED : 0;
+ if (sys_page_alloc(0, mptr + i, PTE_P|PTE_U|PTE_W|cont) < 0){
+ for (; i >= 0; i -= PGSIZE)
+ sys_page_unmap(0, mptr + i);
+ return 0; /* out of physical memory */
+ }
+ }
+
+ ref = (uint32_t*) (mptr + i - 4);
+ *ref = 2; /* reference for mptr, reference for returned block */
+ v = mptr;
+ mptr += n;
+ return v;
+}
+
+void
+free(void *v)
+{
+ uint8_t *c;
+ uint32_t *ref;
+
+ if (v == 0)
+ return;
+ assert(mbegin <= (uint8_t*) v && (uint8_t*) v < mend);
+
+ c = ROUNDDOWN(v, PGSIZE);
+
+ while (vpt[VPN(c)] & PTE_CONTINUED) {
+ sys_page_unmap(0, c);
+ c += PGSIZE;
+ assert(mbegin <= c && c < mend);
+ }
+
+ /*
+ * c is just a piece of this page, so dec the ref count
+ * and maybe free the page.
+ */
+ ref = (uint32_t*) (c + PGSIZE - 4);
+ if (--(*ref) == 0)
+ sys_page_unmap(0, c);
+}
+
View
158 lib/nsipc.c
@@ -0,0 +1,158 @@
+#include <inc/ns.h>
+#include <inc/lib.h>
+#include <lwip/sockets.h>
+
+#define debug 0
+
+// Virtual address at which to receive page mappings containing client requests.
+#define REQVA 0x0ffff000
+extern uint8_t nsipcbuf[PGSIZE]; // page-aligned, declared in entry.S
+
+// Send an IP request to the network server, and wait for a reply.
+// type: request code, passed as the simple integer IPC value.
+// fsreq: page to send containing additional request data, usually fsipcbuf.
+// Can be modified by server to return additional response info.
+// dstva: virtual address at which to receive reply page, 0 if none.
+// *perm: permissions of received page.
+// Returns 0 if successful, < 0 on failure.
+static int
+nsipc(unsigned type, void *fsreq, void *dstva, int *perm)
+{
+ envid_t whom;
+
+ if (debug)
+ cprintf("[%08x] nsipc %d %08x\n", env->env_id, type, nsipcbuf);
+
+ ipc_send(envs[2].env_id, type, fsreq, PTE_P|PTE_W|PTE_U);
+ return ipc_recv(&whom, dstva, perm);
+}
+
+int
+nsipc_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+ int perm, r;
+ struct Nsreq_accept *req;
+ struct Nsret_accept *ret;
+
+ req = (struct Nsreq_accept*)nsipcbuf;
+ req->req_s = s;
+
+ r = nsipc(NSREQ_ACCEPT, req, (void *)REQVA, &perm);
+
+ ret = (struct Nsret_accept*) REQVA;
+ memmove(addr, &ret->ret_addr, ret->ret_addrlen);
+ *addrlen = ret->ret_addrlen;
+
+ return r;
+}
+
+int
+nsipc_bind(int s, struct sockaddr *name, socklen_t namelen)
+{
+ int perm;
+ struct Nsreq_bind *req;
+
+ req = (struct Nsreq_bind*)nsipcbuf;
+ req->req_s = s;
+ memmove(&req->req_name, name, namelen);
+ req->req_namelen = namelen;
+ return nsipc(NSREQ_BIND, req, 0, &perm);
+}
+
+int
+nsipc_shutdown(int s, int how)
+{
+ int perm;
+ struct Nsreq_shutdown *req;
+
+ req = (struct Nsreq_shutdown*)nsipcbuf;
+ req->req_s = s;
+ req->req_how = how;
+ return nsipc(NSREQ_SHUTDOWN, req, 0, &perm);
+}
+
+int
+nsipc_close(int s)
+{
+ int perm;
+ struct Nsreq_close *req;
+
+ req = (struct Nsreq_close*)nsipcbuf;
+ req->req_s = s;
+ return nsipc(NSREQ_CLOSE, req, 0, &perm);
+}
+
+int
+nsipc_connect(int s, const struct sockaddr *name, socklen_t namelen)
+{
+ int perm;
+ struct Nsreq_connect *req;
+
+ req = (struct Nsreq_connect*)nsipcbuf;
+ req->req_s = s;
+ memmove(&req->req_name, name, namelen);
+ req->req_namelen = namelen;
+ return nsipc(NSREQ_CONNECT, req, 0, &perm);
+}
+
+int
+nsipc_listen(int s, int backlog)
+{
+ int perm;
+ struct Nsreq_listen *req;
+
+ req = (struct Nsreq_listen*)nsipcbuf;
+ req->req_s = s;
+ req->req_backlog = backlog;
+ return nsipc(NSREQ_LISTEN, req, 0, &perm);
+}
+
+int
+nsipc_recv(int s, void *mem, int len, unsigned int flags)
+{
+ int perm, r;
+ struct Nsreq_recv *req;
+ void *ret;
+
+ req = (struct Nsreq_recv*)nsipcbuf;
+ req->req_s = s;
+ req->req_len = len;
+ req->req_flags = flags;
+
+ r = nsipc(NSREQ_RECV, req, (void *)REQVA, &perm);
+
+ assert(r < 1600 && r <= len);
+ ret = (void *) REQVA;
+ memmove(mem, ret, r);
+
+ return r;
+}
+
+int
+nsipc_send(int s, const void *dataptr, int size, unsigned int flags)
+{
+ int perm;
+ struct Nsreq_send *req;
+
+ req = (struct Nsreq_send*)nsipcbuf;
+ req->req_s = s;
+ assert(size < 1600);
+ memmove(&req->req_dataptr, dataptr, size);
+ req->req_size = size;
+ req->req_flags = flags;
+ return nsipc(NSREQ_SEND, req, 0, &perm);
+}
+
+int
+nsipc_socket(int domain, int type, int protocol)
+{
+ int perm;
+ struct Nsreq_socket *req;
+
+ req = (struct Nsreq_socket*)nsipcbuf;
+ req->req_domain = domain;
+ req->req_type = type;
+ req->req_protocol = protocol;
+ return nsipc(NSREQ_SOCKET, req, 0, &perm);
+}
+
View
56 lib/sockets.c
@@ -0,0 +1,56 @@
+#include <inc/lib.h>
+#include <lwip/sockets.h>
+
+int
+accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+ return nsipc_accept(s, addr, addrlen);
+}
+
+int
+bind(int s, struct sockaddr *name, socklen_t namelen)
+{
+ return nsipc_bind(s, name, namelen);
+}
+
+int
+shutdown(int s, int how)
+{
+ return nsipc_shutdown(s, how);
+}
+
+int
+closesocket(int s)
+{
+ return nsipc_close(s);
+}
+
+int
+connect(int s, const struct sockaddr *name, socklen_t namelen)
+{
+ return nsipc_connect(s, name, namelen);
+}
+
+int
+listen(int s, int backlog)
+{
+ return nsipc_listen(s, backlog);
+}
+
+int
+recv(int s, void *mem, int len, unsigned int flags)
+{
+ return nsipc_recv(s, mem, len, flags);
+}
+
+int
+send(int s, const void *dataptr, int size, unsigned int flags)
+{
+ return nsipc_send(s, dataptr, size, flags);
+}
+
+int
+socket(int domain, int type, int protocol)
+{
+ return nsipc_socket(domain, type, protocol);
+}
View
6 lib/syscall.c
@@ -117,3 +117,9 @@ sys_ipc_recv(void *dstva)
return syscall(SYS_ipc_recv, 1, (uint32_t)dstva, 0, 0, 0, 0);
}
+unsigned int
+sys_time_msec(void)
+{
+ return (unsigned int) syscall(SYS_time_msec, 0, 0, 0, 0, 0, 0);
+}
+
View
21 net/Makefrag
@@ -0,0 +1,21 @@
+
+include net/lwip/Makefrag
+
+NET_SRCFILES := net/serv.c \
+ net/timer.c \
+ net/input.c \
+ net/output.c
+
+NET_OBJFILES := $(patsubst net/%.c, $(OBJDIR)/net/%.o, $(NET_SRCFILES))
+
+$(OBJDIR)/net/%.o: net/%.c net/ns.h
+ @echo + cc[USER] $<
+ @mkdir -p $(@D)
+ $(V)$(CC) -nostdinc $(USER_CFLAGS) -c -o $@ $<
+
+$(OBJDIR)/net/ns: $(NET_OBJFILES) $(OBJDIR)/lib/entry.o $(OBJDIR)/lib/libjos.a $(OBJDIR)/lib/liblwip.a user/user.ld
+ @echo + ld $@
+ $(V)$(LD) -o $@ $(ULDFLAGS) $(LDFLAGS) -nostdlib \
+ $(OBJDIR)/lib/entry.o $(NET_OBJFILES) \
+ -L$(OBJDIR)/lib -ljos -llwip $(GCC_LIB)
+ $(V)$(OBJDUMP) -S $@ >$@.asm
View
11 net/input.c
@@ -0,0 +1,11 @@
+#include "ns.h"
+
+void
+input(envid_t ns_envid)
+{
+ binaryname = "ns_input";
+
+ // LAB 6: Your code here:
+ // - read a packet from the device driver
+ // - send it to the network server
+}
View
13 net/lwip/FILES
@@ -0,0 +1,13 @@
+api/ - The code for the high-level wrapper API. Not needed if
+ you use the lowel-level call-back/raw API.
+
+core/ - The core of the TPC/IP stack; protocol implementations,
+ memory and buffer management, and the low-level raw API.
+
+include/ - lwIP include files.
+
+netif/ - Generic network interface device drivers are kept here,
+ as well as the ARP module.
+
+For more information on the various subdirectories, check the FILES
+file in each directory.
View
72 net/lwip/Makefrag
@@ -0,0 +1,72 @@
+LWIP_INCLUDES := \
+ -I$(TOP)/net/lwip/include \
+ -I$(TOP)/net/lwip/include/ipv4 \
+ -I$(TOP)/net/lwip/ext \
+ -I$(TOP)/net/lwip/jos \
+ -I$(TOP)/inc/
+
+OBJDIRS += \
+ net/lwip \
+ net/lwip/api \
+ net/lwip/core \
+ net/lwip/core/ipv4 \
+ net/lwip/netif \
+ net/lwip/jos/arch \
+ net/lwip/jos/jif \
+ net/lwip/jos/api
+
+USER_INC += $(LWIP_INCLUDES)
+
+LWIP_SRCFILES += \
+ net/lwip/api/api_lib.c \
+ net/lwip/api/api_msg.c \
+ net/lwip/api/err.c \
+ net/lwip/api/sockets.c \
+ net/lwip/api/tcpip.c \
+ net/lwip/api/netbuf.c \
+ net/lwip/core/init.c \
+ net/lwip/core/tcp_in.c \
+ net/lwip/core/dhcp.c \
+ net/lwip/core/mem.c \
+ net/lwip/core/memp.c \
+ net/lwip/core/netif.c \
+ net/lwip/core/pbuf.c \
+ net/lwip/core/raw.c \
+ net/lwip/core/stats.c \
+ net/lwip/core/sys.c \
+ net/lwip/core/tcp.c \
+ net/lwip/core/ipv4/ip_addr.c \
+ net/lwip/core/ipv4/icmp.c \
+ net/lwip/core/ipv4/ip.c \
+ net/lwip/core/ipv4/ip_frag.c \
+ net/lwip/core/ipv4/inet_chksum.c \
+ net/lwip/core/ipv4/inet.c \
+ net/lwip/core/tcp_out.c \
+ net/lwip/core/udp.c \
+ net/lwip/netif/etharp.c \
+ net/lwip/netif/loopif.c \
+ net/lwip/jos/arch/sys_arch.c \
+ net/lwip/jos/arch/thread.c \
+ net/lwip/jos/arch/longjmp.S \
+ net/lwip/jos/arch/perror.c \
+ net/lwip/jos/jif/jif.c \
+# net/lwip/jos/jif/tun.c \
+ net/lwip/jos/api/lsocket.c \
+ net/lwip/jos/api/lwipinit.c
+
+LWIP_OBJFILES := $(patsubst %.c, $(OBJDIR)/%.o, $(LWIP_SRCFILES))
+LWIP_OBJFILES := $(patsubst %.S, $(OBJDIR)/%.o, $(LWIP_OBJFILES))
+
+$(OBJDIR)/net/lwip/%.o: net/lwip/%.c
+ @echo + cc[USER] $<
+ $(V)mkdir -p $(@D)
+ $(V)$(CC) -nostdinc $(USER_CFLAGS) $(USER_INC) -c -o $@ $<
+
+$(OBJDIR)/net/lwip/%.o: net/lwip/%.S
+ @echo + as[USER] $<
+ @mkdir -p $(@D)
+ $(V)$(CC) -nostdinc $(USER_CFLAGS) -c -o $@ $<
+
+$(OBJDIR)/lib/liblwip.a: $(LWIP_OBJFILES)
+ $(V)mkdir -p $(@D)
+ $(V)$(AR) r $@ $(LWIP_OBJFILES)
View
571 net/lwip/api/api_lib.c
@@ -0,0 +1,571 @@
+/**
+ * @file
+ * Sequential API External module
+ *
+ */
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+/* This is the part of the API that is linked with
+ the application */
+
+#include "lwip/opt.h"
+
+#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
+
+#include "lwip/api.h"
+#include "lwip/tcpip.h"
+#include "lwip/memp.h"
+
+#include "lwip/ip.h"
+#include "lwip/raw.h"
+#include "lwip/udp.h"
+#include "lwip/tcp.h"
+
+#include <string.h>
+
+/**
+ * Create a new netconn (of a specific type) that has a callback function.
+ * The corresponding pcb is also created.
+ *
+ * @param t the type of 'connection' to create (@see enum netconn_type)
+ * @param proto the IP protocol for RAW IP pcbs
+ * @param callback a function to call on status changes (RX available, TX'ed)
+ * @return a newly allocated struct netconn or
+ * NULL on memory error
+ */
+struct netconn*
+netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
+{
+ struct netconn *conn;
+ struct api_msg msg;
+
+ conn = netconn_alloc(t, callback);
+
+ if (conn != NULL ) {
+ msg.function = do_newconn;
+ msg.msg.msg.n.proto = proto;
+ msg.msg.conn = conn;
+ TCPIP_APIMSG(&msg);
+
+ if (conn->err != ERR_OK) {
+ LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
+ LWIP_ASSERT("conn has no op_completed", conn->op_completed != SYS_SEM_NULL);
+ LWIP_ASSERT("conn has no recvmbox", conn->recvmbox != SYS_MBOX_NULL);
+ LWIP_ASSERT("conn->acceptmbox shouldn't exist", conn->acceptmbox == SYS_MBOX_NULL);
+ sys_sem_free(conn->op_completed);
+ sys_mbox_free(conn->recvmbox);
+ memp_free(MEMP_NETCONN, conn);
+ return NULL;
+ }
+ }
+ return conn;
+}
+
+/**
+ * Close a netconn 'connection' and free its resources.
+ * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate
+ * after this returns.
+ *
+ * @param conn the netconn to delete
+ * @return ERR_OK if the connection was deleted
+ */
+err_t
+netconn_delete(struct netconn *conn)
+{
+ struct api_msg msg;
+
+ /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */
+ if (conn == NULL) {
+ return ERR_OK;
+ }
+
+ msg.function = do_delconn;
+ msg.msg.conn = conn;
+ tcpip_apimsg(&msg);
+
+ conn->pcb.tcp = NULL;
+ netconn_free(conn);
+
+ return ERR_OK;
+}
+
+/**
+ * Get the type of a netconn (as enum netconn_type).
+ *
+ * @param conn the netconn of which to get the type
+ * @return the netconn_type of conn
+ */
+enum netconn_type
+netconn_type(struct netconn *conn)
+{
+ LWIP_ERROR("netconn_type: invalid conn", (conn != NULL), return NETCONN_INVALID;);
+ return conn->type;
+}
+
+/**
+ * Get the local or remote IP address and port of a netconn.
+ * For RAW netconns, this returns the protocol instead of a port!
+ *
+ * @param conn the netconn to query
+ * @param addr a pointer to which to save the IP address
+ * @param port a pointer to which to save the port (or protocol for RAW)
+ * @param local 1 to get the local IP address, 0 to get the remote one
+ * @return ERR_CONN for invalid connections
+ * ERR_OK if the information was retrieved
+ */
+err_t
+netconn_getaddr(struct netconn *conn, struct ip_addr *addr, u16_t *port, u8_t local)
+{
+ struct api_msg msg;
+
+ LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;);
+ LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;);
+ LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;);
+
+ msg.function = do_getaddr;
+ msg.msg.conn = conn;
+ msg.msg.msg.ad.ipaddr = addr;
+ msg.msg.msg.ad.port = port;
+ msg.msg.msg.ad.local = local;
+ TCPIP_APIMSG(&msg);
+
+ return conn->err;
+}
+
+/**
+ * Bind a netconn to a specific local IP address and port.
+ * Binding one netconn twice might not always be checked correctly!
+ *
+ * @param conn the netconn to bind
+ * @param addr the local IP address to bind the netconn to (use IP_ADDR_ANY
+ * to bind to all addresses)
+ * @param port the local port to bind the netconn to (not used for RAW)
+ * @return ERR_OK if bound, any other err_t on failure
+ */
+err_t
+netconn_bind(struct netconn *conn, struct ip_addr *addr, u16_t port)
+{
+ struct api_msg msg;
+
+ LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
+
+ msg.function = do_bind;
+ msg.msg.conn = conn;
+ msg.msg.msg.bc.ipaddr = addr;
+ msg.msg.msg.bc.port = port;
+ TCPIP_APIMSG(&msg);
+ return conn->err;
+}
+
+/**
+ * Connect a netconn to a specific remote IP address and port.
+ *
+ * @param conn the netconn to connect
+ * @param addr the remote IP address to connect to
+ * @param port the remote port to connect to (no used for RAW)
+ * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise
+ */
+err_t
+netconn_connect(struct netconn *conn, struct ip_addr *addr, u16_t port)
+{
+ struct api_msg msg;
+
+ LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
+
+ msg.function = do_connect;
+ msg.msg.conn = conn;
+ msg.msg.msg.bc.ipaddr = addr;
+ msg.msg.msg.bc.port = port;
+ /* This is the only function which need to not block tcpip_thread */
+ tcpip_apimsg(&msg);
+ return conn->err;
+}
+
+/**
+ * Disconnect a netconn from its current peer (only valid for UDP netconns).
+ *
+ * @param conn the netconn to disconnect
+ * @return TODO: return value is not set here...
+ */
+err_t
+netconn_disconnect(struct netconn *conn)
+{
+ struct api_msg msg;
+
+ LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;);
+
+ msg.function = do_disconnect;
+ msg.msg.conn = conn;
+ TCPIP_APIMSG(&msg);
+ return conn->err;
+}
+
+/**
+ * Set a TCP netconn into listen mode
+ *
+ * @param conn the tcp netconn to set to listen mode
+ * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1
+ * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns
+ * don't return any error (yet?))
+ */
+err_t
+netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
+{
+ struct api_msg msg;
+
+ /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */
+ LWIP_UNUSED_ARG(backlog);
+
+ LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;);
+
+ msg.function = do_listen;
+ msg.msg.conn = conn;
+#if TCP_LISTEN_BACKLOG
+ msg.msg.msg.lb.backlog = backlog;
+#endif /* TCP_LISTEN_BACKLOG */
+ TCPIP_APIMSG(&msg);
+ return conn->err;
+}
+
+/**
+ * Accept a new connection on a TCP listening netconn.
+ *
+ * @param conn the TCP listen netconn
+ * @return the newly accepted netconn or NULL on timeout
+ */
+struct netconn *
+netconn_accept(struct netconn *conn)
+{
+ struct netconn *newconn;
+
+ LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return NULL;);
+ LWIP_ERROR("netconn_accept: invalid acceptmbox", (conn->acceptmbox != SYS_MBOX_NULL), return NULL;);
+
+#if LWIP_SO_RCVTIMEO
+ if (sys_arch_mbox_fetch(conn->acceptmbox, (void *)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
+ newconn = NULL;
+ } else
+#else
+ sys_arch_mbox_fetch(conn->acceptmbox, (void *)&newconn, 0);
+#endif /* LWIP_SO_RCVTIMEO*/
+ {
+ /* Register event with callback */
+ API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
+
+#if TCP_LISTEN_BACKLOG
+ if (newconn != NULL) {
+ /* Let the stack know that we have accepted the connection. */
+ struct api_msg msg;
+ msg.function = do_recv;
+ msg.msg.conn = conn;
+ TCPIP_APIMSG(&msg);
+ }
+#endif /* TCP_LISTEN_BACKLOG */
+ }
+
+ return newconn;
+}
+
+/**
+ * Receive data (in form of a netbuf containing a packet buffer) from a netconn
+ *
+ * @param conn the netconn from which to receive data
+ * @return a new netbuf containing received data or NULL on memory error or timeout
+ */
+struct netbuf *
+netconn_recv(struct netconn *conn)
+{
+ struct api_msg msg;
+ struct netbuf *buf = NULL;
+ struct pbuf *p;
+ u16_t len;
+
+ LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return NULL;);
+
+ if (conn->recvmbox == SYS_MBOX_NULL) {
+ /* @todo: should calling netconn_recv on a TCP listen conn be fatal (ERR_CONN)?? */
+ /* TCP listen conns don't have a recvmbox! */
+ conn->err = ERR_CONN;
+ return NULL;
+ }
+
+ if (ERR_IS_FATAL(conn->err)) {
+ return NULL;
+ }