diff --git a/.gitignore b/.gitignore index 8a3e4dab..9dc503a9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +#backup files +*.back +*~ + # Object files *.o @@ -8,6 +12,9 @@ *.lib *.a +# Memory maps +*.map + # Shared objects (inc. Windows DLLs) *.dll *.so @@ -24,6 +31,16 @@ *.boot *.bin +# Temporary swap files (from open Vim windows) +[._]*.s[a-v][a-z] +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + # Xinu build files compile/config/config compile/config/y.tab.h @@ -31,4 +48,6 @@ compile/config/parse.c compile/version compile/vn include/conf.h +include/version.h system/conf.c + diff --git a/README.md b/README.md index a94dd7db..c689fb89 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,22 @@ -# Embedded Xinu # +# Embedded Xinu Embedded Xinu, Copyright (C) 2008, 2009, 2010. All rights reserved. Version: 2.01 - 1. What is Embedded Xinu? - 2. Directory Structure - 3. Prerequisites - 4. Installation Instructions - 1. Build Embedded Xinu - 2. Make serial and network connections - 3. Enter Common Firmware Environment prompt - 4. Set IP address - 5. Load image over TFTP - 5. Links +1. What is Embedded Xinu? +2. Directory Structure +3. Prerequisites +4. Installation Instructions + 1. Build Embedded Xinu + 2. Make serial and network connections + 3. Enter Common Firmware Environment prompt + 4. Set IP address + 5. Load image over TFTP +5. Supported Platforms +6. Links - -## 1. What is Embedded Xinu? ## +## 1. What is Embedded Xinu? Xinu ("Xinu is not unix", a recursive acronym) is a UNIX-like operating system originally developed by Douglas Comer for instructional purposes at @@ -27,82 +27,82 @@ on the MIPS processor which is able to run on inexpensive wireless routers and is suitable for courses and research in the areas of Operating Systems, Hardware Systems, Embedded Systems, Networking, and Compilers. -## 2. Directory Structure ## +## 2. Directory Structure Once you have downloaded and extracted the xinu tarball, you will see a basic directory structure: - AUTHORS device/ lib/ mem/ loader/ README system/ - compile/ include/ LICENSE mailbox/ network/ shell/ test/ - - * `AUTHORS` a brief history of contributors to the Xinu operating system - in it's varying iterations. - * `compile/` contains the Makefile and other necessities for building the - Xinu system once you have a cross-compiler. - * `device/` contains directories with source for all device drivers in Xinu. - * `include/` contains all the header files used by Xinu. - * `lib/` contains library folders (e.g., `libxc/`) with a Makefile and - source for the library - * `LICENSE` the license under which this project falls. - * `loader/` contains assembly files and is where the bootloader will begin - execution of O/S code. - * `mailbox/` contains source for the mailbox message queuing system. - * `mem/` contains source for page-based memory protection. - * `network/` contains code for the TCP/IP networking stack. - * `README` this document. - * `RELEASE` release notes for the current version. - * `shell/` contains the source for all Xinu shell related functions. - * `system/` contains the source for all Xinu system functions such as the - nulluser process (`initialize.c`) as well as code to set up a C - environment (`startup.S`). - * `test/` contains a number of testcases (which can be run using the shell - command `testsuite`). - -## 3. Prerequisites ## - -### 3.1 Supported platform with hardware modification ### + AUTHORS device/ lib/ mem/ loader/ README system/ + compile/ include/ LICENSE mailbox/ network/ shell/ test/ + +- `AUTHORS` a brief history of contributors to the Xinu operating system + in it's varying iterations. +- `compile/` contains the Makefile and other necessities for building the + Xinu system once you have a cross-compiler. +- `device/` contains directories with source for all device drivers in Xinu. +- `include/` contains all the header files used by Xinu. +- `lib/` contains library folders (e.g., `libxc/`) with a Makefile and + source for the library +- `LICENSE` the license under which this project falls. +- `loader/` contains assembly files and is where the bootloader will begin + execution of O/S code. +- `mailbox/` contains source for the mailbox message queuing system. +- `mem/` contains source for page-based memory protection. +- `network/` contains code for the TCP/IP networking stack. +- `README` this document. +- `RELEASE` release notes for the current version. +- `shell/` contains the source for all Xinu shell related functions. +- `system/` contains the source for all Xinu system functions such as the + nulluser process (`initialize.c`) as well as code to set up a C + environment (`startup.S`). +- `test/` contains a number of testcases (which can be run using the shell + command `testsuite`). + +## 3. Prerequisites + +### 3.1 Supported platform with hardware modification To run Embedded Xinu you need a supported router or virtual machine. Currently, Embedded Xinu supports Linksys WRT54GL, Linksys WRT160NL, and the Qemu-mipsel virtual machine. For an updated list of supported platforms, visit: -http://xinu.mscs.mu.edu/List_of_supported_platforms + In order to communicate with the router, you need to perform a hardware modification that will expose the serial port that exists on the PCB. For more information on this process, see: -http://xinu.mscs.mu.edu/Modify_the_Linksys_hardware + -### 3.2 Cross-compiler ### +### 3.2 Cross-compiler To build Embedded Xinu you will need a cross-compiler from your host computer's architecture to MIPSEL (little endian MIPS for the 54GL router) or MIPS (big endian for the 160NL router). Instructions on how to do this can be found here: -http://xinu.mscs.mu.edu/Build_Xinu#Cross-Compiler + -### 3.3 Serial communication software ### +### 3.3 Serial communication software Any serial communication software will do. The Xinu Console Tools include -a program called tty-connect which can serve the purpose for a UNIX -environment. More information about the Xinu Console Tools can be found +a program called tty-connect which can serve the purpose for a UNIX +environment. More information about the Xinu Console Tools can be found at: -http://xinu.mscs.mu.edu/Console_Tools#Xinu_Console_Tools + -### 3.4 TFTP server software ### +### 3.4 TFTP server software A TFTP server will provide the router with the ability to download and run the compiled Embedded Xinu image. -## 4. Installation Instructions ## +## 4. Installation Instructions -### 4.1 Build Embedded Xinu ### +### 4.1 Build Embedded Xinu -Update the `MIPS_ROOT` and `MIPS_PREFIX` variables in compile/mipsVars to +Update the `MIPS_ROOT` and `MIPS_PREFIX` variables in compile/mipsVars to correctly point to the cross-compiler on your machine. Then, from the compile directory, simply run make, which should leave you @@ -111,16 +111,16 @@ your router for it to run Embedded Xinu. The default build is for the WRT54GL router; change the compile/Makefile `PLATFORM` variable for other builds. See the compile/platforms directory for supported configurations. -### 4.2 Make serial and network connections ### +### 4.2 Make serial and network connections After creating the `xinu.boot` image you can connect the router's serial port to your computer and open up a connection using the following settings: - - 8 data bits, no parity bit, and 1 stop bit (8N1) - - 115200 bps +- 8 data bits, no parity bit, and 1 stop bit (8N1) +- 115200 bps -### 4.3 Enter Common Firmware Environment prompt ### +### 4.3 Enter Common Firmware Environment prompt With the serial connection open, power on the router and immediately start sending breaks (Control-C) to the device, if your luck holds you will be @@ -130,16 +130,16 @@ greeted with a CFE prompt. If the router seems to start booting up, you can powercycle and try again. -### 4.4 Set IP address ### +### 4.4 Set IP address By default, the router will have a static IP address of 192.168.1.1. If you need to set a different address for your network, run one of the following commands: - ifconfig eth0 -auto if you are using a DHCP server + ifconfig eth0 -auto if you are using a DHCP server ifconfig eth0 -addr=*.*.*.* for a static IP address -### 4.5 Load image over TFTP ### +### 4.5 Load image over TFTP On a computer that is network accessible from the router, start your TFTP server and place the xinu.boot image in the root directory that the server @@ -150,19 +150,37 @@ Then, on the router type the command: CFE> boot -elf [TFTP server IP]:xinu.boot If all has gone correctly the router you will be greeted with the Xinu Shell -(`xsh$ `), which means you are now running Embedded Xinu! +(`xsh$`), which means you are now running Embedded Xinu! + +## 5. [Supported Platforms](http://xinu.mscs.mu.edu/List_of_supported_platforms) + +| Platforms | Status | Comments | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Linksys WRT54G v8](http://www.linksys.com/servlet/Satellite?c=L_Product_C2&childpagename=US%2FLayout&cid=1149562300349&pagename=Linksys%2FCommon%2FVisitorWrapper) | Supported | Tested and running at the Embedded Xinu Lab. | +| [Linksys WRT54GL](http://www.linksys.com/servlet/Satellite?c=L_Product_C2&childpagename=US%2FLayout&cid=1133202177241&pagename=Linksys%2FCommon%2FVisitorWrapper) | Supported | This is our primary development platform, on which Xinu has been tested thoroughly. | +| [Linksys WRT54G v4 ](http://www.linksys.com/servlet/Satellite?c=L_Product_C2&childpagename=US%2FLayout&cid=1149562300349&pagename=Linksys%2FCommon%2FVisitorWrapper) | Probably Supported | The v4 is apparently the version on which WRT54GL is based, and so although the Embedded Xinu Lab has not explicitly tested it, it probably works. | +| [Linksys WRT350N](http://www.linksys.com/servlet/satellite?c=l_product_c2&childpagename=us%2flayout&cid=1162354643512&pagename=linksys%2fcommon%2fvisitorwrapper) | Under Development | Currently the synchronous UART Driver works. | +| [Linksys WRT160NL](http://www.linksys.com/servlet/satellite?c=l_product_c2&childpagename=us%2flayout&cid=1149562300349&pagename=linksys%2fcommon%2fvisitorwrapper) | Supported | Newer model of router. Full O/S teaching core functioning, including wired network interface. | +| [mipsel-qemu](http://www.qemu.org/) | Supported | Full O/S teaching core functioning, network support in progress. | +| [Raspberry Pi](http://www.raspberrypi.org) | Under Development | Core operating system including wired networking is functional. Some new features are still being worked on, and the full documentation (e.g. for a laboratory setup) hasn't been completed yet. | +| [Raspberry Pi 3](http://www.raspberrypi.org) | Under development | Work has been started remaking the low level systems to operate on the aarch64 architecture. | + +## 6. Links -## 5. Links ## +### Embedded Xinu documentation. -### The Embedded Xinu Wiki ### +Home of the most up to date documentation about new and upcoming projects. + +http://embedded-xinu.readthedocs.io/en/latest/ + +### The Embedded Xinu Wiki The home of the Embedded Xinu project - http://xinu.mscs.mu.edu/ +http://xinu.mscs.mu.edu/ -### Dr. Brylow's Embedded Xinu Lab Infrastructure Page ### +### Dr. Brylow's Embedded Xinu Lab Infrastructure Page More information about the Embedded Xinu Lab at Marquette University - http://www.mscs.mu.edu/~brylow/xinu/ - +http://www.mscs.mu.edu/~brylow/xinu/ diff --git a/compile/Doxygen.PROJECT_NUMBER b/compile/Doxygen.PROJECT_NUMBER new file mode 100644 index 00000000..7ed6ff82 --- /dev/null +++ b/compile/Doxygen.PROJECT_NUMBER @@ -0,0 +1 @@ +5 diff --git a/compile/Makefile b/compile/Makefile index c2df4f91..e619f16b 100644 --- a/compile/Makefile +++ b/compile/Makefile @@ -14,7 +14,7 @@ # # $ make PLATFORM=arm-rpi # -PLATFORM := x86 +PLATFORM := arm-rpi3 # Filename of boot image to create (platform can override it if really needed) BOOTIMAGE := xinu.boot @@ -24,7 +24,7 @@ TOPDIR := .. # Set the C compilation flags common to all Embedded Xinu platforms. # platformVars can add more flags if desired. -CFLAGS := +CFLAGS := # Do not perform linking until the end. CFLAGS += -c @@ -169,7 +169,7 @@ COMPILER_ROOT := $(ARCH_ROOT)$(ARCH_PREFIX) # Set the actual compiler and several binutils programs. CC := $(COMPILER_ROOT)gcc AR := $(COMPILER_ROOT)ar -LD := $(COMPILER_ROOT)ld +LD := $(COMPILER_ROOT)ld# -Map test.map STRIP := $(COMPILER_ROOT)strip OBJCOPY := $(COMPILER_ROOT)objcopy @@ -247,7 +247,7 @@ LIB_ARC := $(LIBS:%=$(LIBDIR)/%.a) MAIN_OBJ := $(MAIN_SRC:%.c=%.o) # Data is relative to the compile directory -DATA := data +DATA ?= data DATA_SRC := include $(DATA:%=%/Makerules) diff --git a/compile/TMP.c b/compile/TMP.c new file mode 100644 index 00000000..347f4348 --- /dev/null +++ b/compile/TMP.c @@ -0,0 +1,204 @@ +/** + * @file xsh_test.c + * + */ +/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../device/lan7800/lan7800.h" +#include +#include + +#define MAX_PAYLOAD 1516 +#define ETH_TYPE_ARP 0x0806 +#define hs2net(x) (unsigned) ((((x)>>8) &0xff) | (((x) & 0xff)<<8)) +#define failif(cond, failmsg) \ + if ( cond ) { testFail(verbose, failmsg); printf("\t%s:%d\r\n", __FILE__, __LINE__); passed = FALSE; } \ + else { testPass(verbose, ""); } + +extern struct usb_device usb_devices[]; + +/** + * @ingroup shell + * + * Shell command (test) provides a mechanism for testing Xinu features. The + * action and output varies depending on the feature currently being tested. + * This is not meant to serve as a permanent shell command for a particular + * action. + * @param nargs number of arguments + * @param args array of arguments + * @return non-zero value on error + */ + +/* Simple ethernet packet structure */ +struct etherGram +{ + char dst[ETH_ADDR_LEN]; /* Destination MAC */ + char src[ETH_ADDR_LEN]; /* Source MAC */ + ushort type_len; /* EthernetII type/Ethernet length */ + char payload[1]; /* Payload data */ +}; + +static int ethtest(void); +shellcmd xsh_test(int nargs, char *args[]) +{ + bool passed = TRUE; + + passed &= ethtest(); + + if(passed) + testPass(TRUE, ""); + + else + testFail(TRUE, ""); + + return 0; +} + +static int ethtest() +{ + bool verbose = TRUE; + bool passed = TRUE; + bool subpass; + uint memsize; + int i, value, len; + struct etherGram *inpkt; + struct etherGram *outpkt; + char *payload; + char mymac[ETH_ADDR_LEN]; + char str[80]; + struct ether *peth = ðertab[0]; + int dev = peth->dev->num; + + /* memget */ + memsize = sizeof(struct etherGram) + MAX_PAYLOAD - 1; + inpkt = memget(memsize); + outpkt = memget(memsize); + payload = &(outpkt->payload[0]); + + control(dev, ETH_CTRL_GET_MAC, (long)mymac, 0); + memcpy(outpkt->dst, mymac, ETH_ADDR_LEN); + memcpy(outpkt->src, mymac, ETH_ADDR_LEN); + outpkt->type_len = hs2net(ETH_TYPE_ARP); + + /* generate payload content */ + for (i = 0; i < MAX_PAYLOAD; i++) + { + /* Cycle through 0x20 to 0x7d (range of 0x5e) */ + value = (i % 0x5e) + 0x20; + payload[i] = value; + } + + /* place ether in loopback mode */ + control(dev, ETH_CTRL_SET_LOOPBK, TRUE, 0); + + /* flush any packets already received */ + while (peth->icount > 0) + { + read(dev, inpkt, memsize); + } + + /* oversized packet (paylod 1502 bytes + 14 byte header) + * should result in s SYSERR */ + sprintf(str, "%s 1516 OVERSIZED byte packet (write)", peth->dev->name); + testPrint(verbose, str); + len = write(dev, outpkt, 1516); + failif((SYSERR != len), ""); + + sprintf(str, "%s 1514 MAX byte packet (write)", peth->dev->name); + testPrint(verbose, str); + len = write(dev, outpkt, 1514); + failif((len < 1514), ""); + + sprintf(str, "%s 700 NORMAL byte packet (write)", peth->dev->name); + testPrint(verbose, str); + len = write(dev, outpkt, 700); + failif((len < 700), ""); + + /* Too small of a packet, should end in SYSERR. */ + sprintf(str, "%s 12 MICRO byte packet (write)", peth->dev->name); + testPrint(verbose, str); + len = write(dev, outpkt, 12); + failif((SYSERR != len), ""); + + sprintf(str, "%s 512 random-sized packets (write)", peth->dev->name); + testPrint(verbose, str); + subpass = TRUE; + + for(i = 0; i < 512; i++) + { + len = 32 + (rand() % 1200); + value = write(dev, outpkt, len); + + if(value < len){ + kprintf("\r\nsubpass = false, value < len... \r\n"); + subpass = FALSE; + } + + bzero(inpkt, memsize); + value = read(dev, inpkt, len); + if (0 != memcmp(outpkt, inpkt, 30)) + subpass = FALSE; + } + failif((TRUE != subpass), ""); + + /* + sprintf(str, "%s 700 byte packet (read)", peth->dev->name); + testPrint(verbose, str); + bzero(inpkt, memsize); + printf("\r\nbefore attempt to read...\r\n"); + len = read(dev, inpkt, 700); + printf("Before fail check...\r\n"); + failif((0 != memcmp(outpkt, inpkt, 700)), ""); + printf("After fail statement...\r\n"); + return 0; + */ + /* ether out of loopback mode */ + control(dev, ETH_CTRL_SET_LOOPBK, FALSE, 0); + + memfree(outpkt, memsize); + memfree(inpkt, memsize); + + return passed; +} + +void testPass(bool verbose, const char *msg) +{ + if (TRUE == verbose) + { + kprintf("\033[60G[\033[1;32mPASS\033[0;39m] %s\n", msg); + } +} + +void testFail(bool verbose, const char *msg) +{ + if (TRUE == verbose) + { + kprintf("\033[60G[\033[1;31mFAIL\033[0;39m] %s\n", msg); + } +} + +void testSkip(bool verbose, const char *msg) +{ + if (TRUE == verbose) + { + kprintf("\033[60G[\033[1;33mSKIP\033[0;39m] %s\n", msg); + } +} + +void testPrint(bool verbose, const char *msg) +{ + if (TRUE == verbose) + { + kprintf(" %s", msg); + } +} diff --git a/compile/arch/arm/platformVars b/compile/arch/arm/platformVars index d37bed69..2dcc4255 100644 --- a/compile/arch/arm/platformVars +++ b/compile/arch/arm/platformVars @@ -1,6 +1,5 @@ # -# Makefile definitions for Embedded Xinu shared between all supported ARM -# platforms. +# Makefile definitions for Embedded Xinu shared between single-core ARM platforms. # TEMPLATE_ARCH := arm diff --git a/compile/arch/armv8/platformVars b/compile/arch/armv8/platformVars new file mode 100644 index 00000000..c1531d7a --- /dev/null +++ b/compile/arch/armv8/platformVars @@ -0,0 +1,28 @@ +# +# Makefile definitions for Embedded Xinu shared between all supported ARM +# Platforms. +# + +TEMPLATE_ARCH := arm + +# Architecture root and prefix (ignored if user overrides COMPILER_ROOT from the +# toplevel Makefile). +ARCH_ROOT := +ARCH_PREFIX := arm-none-eabi- + +# Flaf for producing GDB debug informations. +BUGFLAG := -gstabs+ + +# Add a way to test for any ARM platform in C code. +DEFS += -D_XINU_ARCH_ARM_ + +# Default build target. For ARM we just translate the kernel into a raw binary. +$(BOOTIMAGE): xinu.elf + $(OBJCOPY) -O binary $^ $@ +# +# Makefile definitions for Embedded Xinu shared between single-core ARM platforms. +# + +# Objcopy flags, used for including data files in the resulting binary. +OCFLAGS := -I binary -O elf32-littlearm -B arm + diff --git a/compile/arch/mips/ld.script b/compile/arch/mips/ld.script deleted file mode 100644 index 45de1914..00000000 --- a/compile/arch/mips/ld.script +++ /dev/null @@ -1,32 +0,0 @@ -OUTPUT_ARCH(mips) -ENTRY(_start) -SECTIONS { - . = 0x80001000; /* Image starts here */ - .text : - { - *(.text .text.*) /* asm text, then C text */ - *(.rodata .rodata.*) /* asm and C read-only data */ - _etext = . ; /* provide _etext constant */ - } - - .data : - { - *(.data .data.*) /* asm and C data */ - _edata = . ; /* end of data constant */ - } - - .bss : - { - _bss = . ; /* beginning of bss segment */ - *(.bss .bss.*) /* asm and C bss */ - *(COMMON) /* extra sections that are common */ - _end = . ; /* end of image constant */ - } - - /* Discard comment and note (but not debugging) sections. Some - * versions of GNU ld would otherwise automatically place the - * ".note.gnu.build-id" section before _start! */ - /DISCARD/ : { - *(.comment .comment.* .note .note.*) - } -} diff --git a/compile/arch/mips/platformVars b/compile/arch/mips/platformVars deleted file mode 100644 index 1e3267c0..00000000 --- a/compile/arch/mips/platformVars +++ /dev/null @@ -1,80 +0,0 @@ -# -# Makefile definitions for Embedded Xinu shared between all supported MIPS -# platforms. -# -# Before including this file, define the following variables: -# -# MIPS_ENDIANNESS := little -# -# or -# -# MIPS_ENDIANNESS := big -# -# as well as -# -# MIPS_RELEASE := 1 -# -# or -# -# MIPS_RELEASE := 2 -# -# Default is little endian, release 1. -# -# You can also set -# -# MIPS_PLATFORM_DEFINES_DEFAULT_TARGET := yes -# -# to override the default rule to build the final boot image. -# - -TEMPLATE_ARCH := mips -MIPS_ENDIANNESS ?= little -MIPS_RELEASE ?= 1 - -# Architecture root and prefix (ignored if user overrides COMPILER_ROOT from the -# toplevel Makefile). -ifeq ($(MIPS_ENDIANNESS),little) - ARCH_PREFIX := mipsel- -else - ARCH_PREFIX := mips- -endif -ARCH_ROOT := - -# Flag to pass to compiler and assembler for the specific MIPS Instruction Set -# Architecture Level -ifeq ($(MIPS_RELEASE),1) - MIPS_ISA_FLAG := mips32 -else - MIPS_ISA_FLAG := mips32r2 -endif - -# Flag for producing GDB debug information -BUGFLAG := -gstabs+ - -# Additional platform-specific compiler and assembler flags. -CFLAGS += -march=$(MIPS_ISA_FLAG) -Wa,-march=$(MIPS_ISA_FLAG) \ - -Wa,-$(MIPS_ISA_FLAG) \ - -fomit-frame-pointer -G 0 -mlong-calls \ - -mno-abicalls -mabi=32 -Wa,--trap -Wa,-32 -ASFLAGS += -march=$(MIPS_ISA_FLAG) -$(MIPS_ISA_FLAG) - -# Add a way to test for any MIPS or MIPSel platform from C code. -DEFS += -D_XINU_ARCH_MIPS_ -ifeq ($(MIPS_ENDIANNESS),little) - DEFS += -D_XINU_ARCH_MIPSEL_ -endif - -# Objcopy flags, used for including data files in the resulting binary. -ifeq ($(MIPS_ENDIANNESS),little) - MIPS_BFDARCH := elf32-littlemips -else - MIPS_BFDARCH := elf32-bigmips -endif -OCFLAGS := -I binary -O $(MIPS_BFDARCH) -B mips - -# Use the ELF-format kernel as the final build target, unless the specific -# MIPS platform requires something different. -ifneq ($(MIPS_PLATFORM_DEFINES_DEFAULT_TARGET),yes) -$(BOOTIMAGE): xinu.elf - cp $^ $@ -endif diff --git a/compile/arch/x86/platformVars b/compile/arch/x86/platformVars deleted file mode 100644 index 619076d6..00000000 --- a/compile/arch/x86/platformVars +++ /dev/null @@ -1,23 +0,0 @@ -# -# Makefile definitions for Embedded Xinu shared between all supported x86 -# platforms. -# - -TEMPLATE_ARCH := x86 - -# Architecture root and prefix (ignored if user overrides COMPILER_ROOT from the -# toplevel Makefile). -ARCH_ROOT := -ARCH_PREFIX := - -# Flag for producing GDB debug information. -BUGFLAG := -gstabs+ - -# Objcopy flags, used for including data files in the resulting binary. -OCFLAGS := -I binary -O elf32-i386 -B i386 - -# Add a way to test for any x86 platform in C code. -DEFS += -D_XINU_ARCH_X86_ - -$(BOOTIMAGE): xinu.elf - $(OBJCOPY) -O binary $^ $@ diff --git a/compile/config/config.c b/compile/config/config.c index 15ce66a1..837fe69b 100644 --- a/compile/config/config.c +++ b/compile/config/config.c @@ -46,6 +46,8 @@ int linectr = 1; char *doing = "device type declaration"; char *s; +// TODO: figure out how this is typedef'd to "device" +// typedef struct dev_ent device struct dev_ent { char *name; /* device name (not used in types) */ diff --git a/compile/platforms/arm-qemu/ld.script b/compile/platforms/arm-qemu/ld.script deleted file mode 100644 index 9b99d438..00000000 --- a/compile/platforms/arm-qemu/ld.script +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @file ld.script - * - * This is the linker script for the Xinu kernel on the arm-qemu platform, where - * QEMU simulates an ARM Versatile Platform/Application Baseboard. QEMU loads - * the kernel at address 0x10000 by default (see hw/arm/boot.c in the QEMU - * source), and the ARM processor starts executing instructions at that address. - * We place _start, the entry point for Xinu, in a special .init section to - * ensure it is placed first in the kernel image. - * - * Because of this direct jump to address 0x10000, the "ENTRY(_start)" line - * below does nothing to set the real entry point of the kernel; however, it - * _is_ needed to specify the entry point to the linker when it is executed with - * the --gc-sections option, which removes all sections not reachable from the - * program's entry point. - * - * To be safe, we ensure that every section is aligned on a 64-byte (cache line) - * boundary. - */ -/* Embedded Xinu, Copyright (C) 2014. All rights reserved. */ - -ENTRY(_start) - -SECTIONS { - . = 0x10000; - .init : { - *(.init .init.*) - } - - . = ALIGN(64); - - .text : { - *(.text .text.*) - *(.rodata .rodata.*) - } - - . = ALIGN(64); - - .data : { - *(.data .data.*) - } - - . = ALIGN(64); - - _bss = . ; - .bss : { - *(.bss .bss.*) - } - - . = ALIGN(64); - _end = .; - - /* Discard comment and note (but not debugging) sections. Some - * versions of GNU ld would otherwise automatically place the - * ".note.gnu.build-id" section before _start! */ - /DISCARD/ : { - *(.comment .comment.* .note .note.*) - } -} diff --git a/compile/platforms/arm-qemu/platformVars b/compile/platforms/arm-qemu/platformVars deleted file mode 100644 index 61c06961..00000000 --- a/compile/platforms/arm-qemu/platformVars +++ /dev/null @@ -1,27 +0,0 @@ -# -# Platform-specific Makefile definitions for the ARM QEMU (emulating an ARM -# Versatile Platform Baseboard) port of Embedded Xinu. -# - -# Include default ARM definitions -include arch/arm/platformVars - -PLATFORM_NAME := ARM QEMU - -# Set extra compiler and assembler flags to specifically target ARM1176 CPUs. -# -# Note: When running the resulting kernel With qemu-system-arm, use the option -# '-cpu arm1176'. Although QEMU can emulate many different ARM CPUs, ARM1176 is -# chosen here because it is the same core used on the Raspberry Pi (Embedded -# Xinu platform "arm-rpi"). -CFLAGS += -mcpu=arm1176jz-s -ASFLAGS += -mcpu=arm1176jz-s - -# Add a define so we can test for ARM QEMU in C code if absolutely needed -DEFS += -D_XINU_PLATFORM_ARM_QEMU_ - -# Embedded Xinu components to build into the kernel image -APPCOMPS := apps mailbox shell test - -# Embedded Xinu device drivers to build into the kernel image -DEVICES := loopback tty uart-pl011 diff --git a/compile/platforms/arm-qemu/xinu.conf b/compile/platforms/arm-qemu/xinu.conf deleted file mode 100644 index 89979386..00000000 --- a/compile/platforms/arm-qemu/xinu.conf +++ /dev/null @@ -1,81 +0,0 @@ -/* Configuration - (device configuration specifications) */ -/* Unspecified switches default to ioerr */ -/* -i init -o open -c close */ -/* -r read -g getc -p putc */ -/* -w write -s seek -n control */ -/* -intr interrupt -csr csr -irq irq */ - -/* "type" declarations for both real- and pseudo- devices */ - -/* simple loopback device */ -loopback: - on LOOPBACK -i loopbackInit -o loopbackOpen -c loopbackClose - -r loopbackRead -g loopbackGetc -p loopbackPutc - -w loopbackWrite -n loopbackControl - -/* null device */ -null: - on NOTHING -i ionull -o ionull -c ionull - -r ionull -g ionull -p ionull - -w ionull - -/* physical uart (PL011) device */ -uart: - on HARDWARE -i uartInit -o ionull -c ionull - -r uartRead -g uartGetc -p uartPutc - -w uartWrite -n uartControl - -intr uartInterrupt - - -/* tty pseudo-devices */ -tty: - on SOFTWARE -i ttyInit -o ttyOpen -c ttyClose - -r ttyRead -g ttyGetc -p ttyPutc - -w ttyWrite -n ttyControl - -%% - -/* PL011 UARTS on the ARM Versatile PB. See QEMU: hw/arm/versatilepb.c */ -SERIAL0 is uart on HARDWARE csr 0x101F1000 irq 12 -/* SERIAL1 is uart on HARDWARE csr 0x101F2000 irq 13 */ -/* SERIAL2 is uart on HARDWARE csr 0x101F3000 irq 14 */ -/* Since the third UART uses the secondary interrupt controller, which is not - * yet supported by Embedded Xinu, it can't yet be enabled here. */ -/* SERIAL3 is uart on HARDWARE csr 0x10009000 */ - -DEVNULL is null on NOTHING - -/* Loopback device */ -LOOP0 is loopback on LOOPBACK - -/* TTY for SERIAL0 */ -CONSOLE is tty on SOFTWARE - -/* TTY for LOOP0 (needed in testsuite) */ -TTYLOOP is tty on SOFTWARE - -%% - -/* Interrupt line for the SP804 timer located at address 0x101E2000 */ -#define IRQ_TIMER 4 - -/* Configuration and Size Constants */ - -#define LITTLE_ENDIAN 0x1234 -#define BIG_ENDIAN 0x4321 - -#define BYTE_ORDER LITTLE_ENDIAN - -#define NTHREAD 100 /* number of user threads */ -#define NSEM 100 /* number of semaphores */ -#define NMAILBOX 15 /* number of mailboxes */ -#define RTCLOCK TRUE /* timer support */ -#define NETEMU FALSE /* Network Emulator support */ -#define NVRAM FALSE /* nvram support */ -#define SB_BUS FALSE /* Silicon Backplane support */ -#define USE_TLB FALSE /* make use of TLB */ -#define USE_TAR FALSE /* enable data archives */ -#define NPOOL 8 /* number of buffer pools available */ -#define POOL_MAX_BUFSIZE 2048 /* max size of a buffer in a pool */ -#define POOL_MIN_BUFSIZE 8 /* min size of a buffer in a pool */ -#define POOL_MAX_NBUFS 8192 /* max number of buffers in a pool */ diff --git a/compile/platforms/arm-rpi/platformVars b/compile/platforms/arm-rpi/platformVars deleted file mode 100644 index 5b049363..00000000 --- a/compile/platforms/arm-rpi/platformVars +++ /dev/null @@ -1,39 +0,0 @@ -# -# Platform-specific Makefile definitions for the Raspberry Pi port of Embedded -# Xinu. -# - - -# Include default ARM definitions -include arch/arm/platformVars - -PLATFORM_NAME := Raspberry Pi - -# Extra compiler and assembler flags to specifically target the ARM1176JZF-S CPU -# used on the BCM2835 (used by the Raspberry Pi). -CFLAGS += -mcpu=arm1176jzf-s -ASFLAGS += -mcpu=arm1176jzf-s - -# Add a define so we can test for Raspberry Pi in C code if absolutely needed -DEFS += -D_XINU_PLATFORM_ARM_RPI_ - -# Embedded Xinu components to build into the kernel image -APPCOMPS := apps \ - mailbox \ - network \ - shell \ - test - -# Embedded Xinu device drivers to build into the kernel image -DEVICES := ethloop \ - raw \ - smsc9512 \ - tcp \ - telnet \ - uart-pl011 \ - framebuffer_rpi \ - udp \ - usb \ - usbkbd \ - loopback \ - tty diff --git a/compile/platforms/arm-rpi/ld.script b/compile/platforms/arm-rpi3/ld.script similarity index 82% rename from compile/platforms/arm-rpi/ld.script rename to compile/platforms/arm-rpi3/ld.script index 3d6503c1..76ce5c06 100644 --- a/compile/platforms/arm-rpi/ld.script +++ b/compile/platforms/arm-rpi3/ld.script @@ -1,8 +1,9 @@ /** * @file ld.script * - * This is the linker script for the Xinu kernel on the Raspberry Pi. The GPU - * loads the kernel at address 0x8000 by default, and the ARM processor starts + * This is the linker script for the Xinu kernel on the Raspberry Pi3. The GPU + * loads the kernel at address 0x8000 by default (in 32-bit mode, although the Pi 3 + * does support 64-bit mode at 0x80000), and the ARM processor starts * executing instructions at that address. We place _start, the entry point for * Xinu, in a special .init section to ensure it is placed first in the kernel * image. @@ -21,15 +22,15 @@ ENTRY(_start) SECTIONS { - . = 0x8000; - .init : { - *(.init .init.*) - } + . = 0x8000; + .init : { + *(.init .init.*) + } - . = ALIGN(64); - - .text : { - *(.text .text.*) + . = ALIGN(64); + + .text : { + *(.txt .text.*) *(.rodata .rodata.*) } @@ -44,7 +45,7 @@ SECTIONS { _bss = . ; .bss : { *(.bss .bss.*) - } + } . = ALIGN(64); _end = .; @@ -56,3 +57,4 @@ SECTIONS { *(.comment .comment.* .note .note.*) } } + diff --git a/compile/platforms/arm-rpi3/platformVars b/compile/platforms/arm-rpi3/platformVars new file mode 100644 index 00000000..d956bbbf --- /dev/null +++ b/compile/platforms/arm-rpi3/platformVars @@ -0,0 +1,53 @@ +# +# Platform-specific Makefile definitions for the Raspberry Pi 3 B+ port of Embedded +# Xinu (BCM2837B0) +# + +# Include default ARMv8A definitions +include arch/armv8/platformVars + +PLATFORM_NAME := Raspberry Pi 3 + +# Extra compiler and assembler flags to specifically target the cortex-a53 CPU +# used on the BCM2837 (used by the Raspberry Pi). +CFLAGS += -mcpu=cortex-a53 +ASFLAGS += -mcpu=cortex-a53 + +# Extra compiler flag that disables gcc from generating unaligned memory accesses +# This is used as an alternative to doing this in the assembly code in start.S +CFLAGS += -mno-unaligned-access + +# Extra compiler flag for using FPU (see start.S for enable) +CFLAGS += -mfpu=vfpv4 +ASFLAGS += -mfpu=vfpv4 + +# Extra compiler flag for selecting ARM ABI +CFLAGS += -mfloat-abi=softfp +ASFLAGS += -mfloat-abi=softfp + +# Add a define so we can test for Raspberry Pi in C code if absolutely needed +DEFS += -D_XINU_PLATFORM_ARM_RPI_3_ + +# Embedded Xinu components to build into the kernel image +APPCOMPS := apps \ + mailbox \ + shell \ + network \ + test \ + +# Embedded Xinu device drivers to build into the kernel image +DEVICES := uart-pl011 \ + tty \ + usb \ + lan7800 \ + tcp \ + udp \ + framebuffer_rpi \ + usbkbd \ + usbfs \ +# smsc9512 \ +# ethloop \ +# raw \ +# loopback \ +# telnet \ + diff --git a/compile/platforms/arm-rpi/xinu.conf b/compile/platforms/arm-rpi3/xinu.conf similarity index 93% rename from compile/platforms/arm-rpi/xinu.conf rename to compile/platforms/arm-rpi3/xinu.conf index b0a3d642..5faac36e 100644 --- a/compile/platforms/arm-rpi/xinu.conf +++ b/compile/platforms/arm-rpi3/xinu.conf @@ -7,7 +7,7 @@ /* "type" declarations for both real- and pseudo- devices */ -/* simple loopback device */ +/* Simple loopback device */ loopback: on LOOPBACK -i loopbackInit -o loopbackOpen -c loopbackClose -r loopbackRead -g loopbackGetc -p loopbackPutc @@ -19,6 +19,7 @@ null: -r ionull -g ionull -p ionull -w ionull + /* physical uart (PL011) device */ uart: on HARDWARE -i uartInit -o ionull -c ionull @@ -53,17 +54,20 @@ raw: on SOFTWARE -i rawInit -o rawOpen -c rawClose -r rawRead -w rawWrite -n rawControl + /* udp devices */ udp: on NET -i udpInit -o udpOpen -c udpClose -r udpRead -w udpWrite -n udpControl + /* tcp devices */ tcp: on SOFTWARE -i tcpInit -o tcpOpen -c tcpClose -r tcpRead -g tcpGetc -w tcpWrite -p tcpPutc -n tcpControl + /* telnet devices */ telnet: on TCP -i telnetInit -o telnetOpen -c telnetClose @@ -76,6 +80,13 @@ usbkbd: -r usbKbdRead -g usbKbdGetc -w ioerr -p ioerr -n usbKbdControl +/* USB filesystem devices */ +usbfs: + on SOFTWARE -i usbFsInit -o ionull -c ionull + -r usbFsRead -g usbFsGetc -w usbFsWrite + -p usbFsPutc -n usbFsControl -intr usbFsInterrupt + + /* HACK: a device that reads from the keyboard but writes to the framebuffer. * This only works if the generated minor number(s) are consistent with the * keyboard and framebuffer device minor number(s), and no open, close, or @@ -94,10 +105,12 @@ kbdmon: * (BCM2835-ARM-Peripherals.pdf). IRQ number is on page 113; registers address * is on page 177 (must be translated from bus address to physical address as * per page 6 first). */ -SERIAL0 is uart on HARDWARE csr 0x20201000 irq 57 +SERIAL0 is uart on HARDWARE csr 0x3F201000 irq 57 USBKBD0 is usbkbd on USB +USBFS0 is usbfs on SOFTWARE + KBDMON0 is kbdmon on OTHERDEVS FRAMEBUF is framebuffer on HARDWARE @@ -123,16 +136,21 @@ ETH0 is ether on HARDWARE ELOOP is ethloop on ETHLOOP /* Raw sockets */ + RAW0 is raw on SOFTWARE RAW1 is raw on SOFTWARE + /* UDP devices */ + UDP0 is udp on NET UDP1 is udp on NET UDP2 is udp on NET UDP3 is udp on NET + /* TCP devices */ + TCP0 is tcp on SOFTWARE TCP1 is tcp on SOFTWARE TCP2 is tcp on SOFTWARE @@ -141,6 +159,7 @@ TCP4 is tcp on SOFTWARE TCP5 is tcp on SOFTWARE TCP6 is tcp on SOFTWARE + /* TELNET */ TELNET0 is telnet on TCP TELNET1 is telnet on TCP @@ -170,3 +189,4 @@ TELNET2 is telnet on TCP #define POOL_MAX_NBUFS 8192 /* max number of buffers in a pool */ #define WITH_USB /* USB support */ #define WITH_DHCPC /* DHCP client support */ +#define NCORES 4 /* number of cpu cores */ diff --git a/compile/platforms/e2100l/ld.script b/compile/platforms/e2100l/ld.script deleted file mode 100644 index f111e439..00000000 --- a/compile/platforms/e2100l/ld.script +++ /dev/null @@ -1,32 +0,0 @@ -OUTPUT_ARCH(mips) -ENTRY(_start) -SECTIONS { - . = 0x80010000; /* Image starts here */ - .text : - { - *(.text .text.*) /* asm text, then C text */ - *(.rodata .rodata.*) /* asm and C read-only data */ - _etext = . ; /* provide _etext constant */ - } - - .data : - { - *(.data .data.*) /* asm and C data */ - _edata = . ; /* end of data constant */ - } - - .bss : - { - _bss = . ; /* beginning of bss segment */ - *(.bss .bss.*) /* asm and C bss */ - *(COMMON) /* extra sections that are common */ - _end = . ; /* end of image constant */ - } - - /* Discard comment and note (but not debugging) sections. Some - * versions of GNU ld would otherwise automatically place the - * ".note.gnu.build-id" section before _start! */ - /DISCARD/ : { - *(.comment .comment.* .note .note.*) - } -} diff --git a/compile/platforms/e2100l/platformVars b/compile/platforms/e2100l/platformVars deleted file mode 100644 index edf99ba6..00000000 --- a/compile/platforms/e2100l/platformVars +++ /dev/null @@ -1,50 +0,0 @@ -# -# Platform-specific Makefile definitions for the Cisco Linksys E2100L port of -# Embedded Xinu. -# - -PLATFORM_NAME := Cisco Linksys E2100L - -# Include default mips definitions, but override some details about the -# specific sub-architecture -MIPS_RELEASE := 2 -MIPS_ENDIANNESS := big -MIPS_PLATFORM_DEFINES_DEFAULT_TARGET := yes -include arch/mips/platformVars - -# Embedded Xinu components to build into kernel image -APPCOMPS := apps \ - mailbox \ - network \ - shell \ - test - -# Embedded Xinu device drivers to build into the kernel image -DEVICES := ag71xx \ - ethloop \ - flash \ - loopback \ - raw \ - tcp \ - telnet \ - tty \ - uart-ns16550 \ - udp - -# On this platform, generating the final boot image requires an external tool. - -MKIMAGE := uboot-tool/mkimage -UBOOTOPTS := -A mips -O linux -T kernel -a 0x80010000 \ - -C none -e 0x80010000 -n 'Xinu' - -# Default build target -$(BOOTIMAGE): xinu.bin $(MKIMAGE) - $(MKIMAGE) $(UBOOTOPTS) -d xinu.bin $@ - -$(MKIMAGE): - @echo "ERROR: The U-Boot utilities are not part of Xinu." - @echo "ERROR: Please acquire the mkimage utility separately." - exit 1 - -xinu.bin: xinu.elf - $(OBJCOPY) -O binary $^ $@ diff --git a/compile/platforms/e2100l/xinu.conf b/compile/platforms/e2100l/xinu.conf deleted file mode 100644 index 1d40fd46..00000000 --- a/compile/platforms/e2100l/xinu.conf +++ /dev/null @@ -1,148 +0,0 @@ -/* Configuration - (device configuration specifications) */ -/* Unspecified switches default to ioerr */ -/* -i init -o open -c close */ -/* -r read -g getc -p putc */ -/* -w write -s seek -n control */ -/* -intr interrupt -csr csr -irq irq */ - -/* "type" declarations for both real- and pseudo- devices */ - -/* simple loopback device */ -loopback: - on LOOPBACK -i loopbackInit -o loopbackOpen -c loopbackClose - -r loopbackRead -g loopbackGetc -p loopbackPutc - -w loopbackWrite -n loopbackControl - -/* null device */ -null: - on NOTHING -i ionull -o ionull -c ionull - -r ionull -g ionull -p ionull - -w ionull - -/* physical uart (NS16550) device */ -uart: - on HARDWARE -i uartInit -o ionull -c ionull - -r uartRead -g uartGetc -p uartPutc - -w uartWrite -n uartControl - -intr uartInterrupt - -/* tty pseudo-devices */ -tty: - on SOFTWARE -i ttyInit -o ttyOpen -c ttyClose - -r ttyRead -g ttyGetc -p ttyPutc - -w ttyWrite -n ttyControl - -/* FLASH for each flash device */ -flash: - on HARDWARE -i flashInit -o flashOpen -c flashClose - -r flashRead -w flashWrite -n flashControl - -/* physical Ethernet device */ -ether: - on HARDWARE -i etherInit -o etherOpen -c etherClose - -r etherRead -w etherWrite -n etherControl - -intr etherInterrupt - -/* simple Ethernet loopback device */ -ethloop: - on ETHLOOP -i ethloopInit -o ethloopOpen -c ethloopClose - -r ethloopRead -w ethloopWrite -n ethloopControl - -/* raw sockets */ -raw: - on SOFTWARE -i rawInit -o rawOpen -c rawClose - -r rawRead -w rawWrite -n rawControl - -/* udp devices */ -udp: - on NET -i udpInit -o udpOpen -c udpClose - -r udpRead -w udpWrite -n udpControl - -/* tcp devices */ -tcp: - on SOFTWARE -i tcpInit -o tcpOpen -c tcpClose - -r tcpRead -g tcpGetc -w tcpWrite - -p tcpPutc -n tcpControl - -/* http pseudo-devices */ -http: - on TCP -i httpInit -o httpOpen -c httpClose - -r httpRead -g httpGetc -p httpPutc - -w httpWrite -n httpControl - -/* telnet devices */ -telnet: - on TCP -i telnetInit -o telnetOpen -c telnetClose - -r telnetRead -g telnetGetc -w telnetWrite - -p telnetPutc -n telnetControl -%% - -/* Two uart ports on WRT54GL */ -SERIAL0 is uart on HARDWARE csr 0xB8020000 irq 11 - -DEVNULL is null on NOTHING - -/* Loopback device */ -LOOP0 is loopback on LOOPBACK - -/* TTYs for each uart */ -TTYLOOP is tty on SOFTWARE -CONSOLE is tty on SOFTWARE - -/* Flash device */ -FLASH is flash on HARDWARE csr 0xBD000000 - -/* Physical ethernet raw packet interface */ -ETH0 is ether on HARDWARE csr 0xB9000000 irq 4 - -/* A Ethernet Loopback device */ -ELOOP is ethloop on ETHLOOP - -/* Raw sockets */ -RAW0 is raw on SOFTWARE -RAW1 is raw on SOFTWARE - -/* Two UDP devices */ -UDP0 is udp on NET -UDP1 is udp on NET - -/* TCP devices */ -TCP0 is tcp on SOFTWARE -TCP1 is tcp on SOFTWARE -TCP2 is tcp on SOFTWARE -TCP3 is tcp on SOFTWARE -TCP4 is tcp on SOFTWARE -TCP5 is tcp on SOFTWARE -TCP6 is tcp on SOFTWARE - -/* TELNET */ -TELNET0 is telnet on TCP -TELNET1 is telnet on TCP -TELNET2 is telnet on TCP - -%% - -/* Configuration and Size Constants */ - -#define LITTLE_ENDIAN 0x1234 -#define BIG_ENDIAN 0x4321 -#define BYTE_ORDER BIG_ENDIAN - -#define NTHREAD 100 /* number of user threads */ -#define NSEM 100 /* number of semaphores */ -#define NMAILBOX 15 /* number of mailboxes */ -#define RTCLOCK TRUE /* now have RTC support */ -#define NETEMU FALSE /* Network Emulator support */ -#define NVRAM TRUE /* now have nvram support */ -#define SB_BUS FALSE /* Silicon Backplane support */ -#define GPIO FALSE /* General-purpose I/O (leds) */ -#define IRQ_TIMER IRQ_HW5 /* timer IRQ is wired to hardware 5 */ -#define IRQ_ATH_MISC IRQ_HW4 /* Misc IRQ is wired to hardware 4 */ -#define UART_FIFO_LEN 16 /* Seems to be 16 bytes on the 160NL*/ -#define UART_CSR_SPACED TRUE /* Atheros CSRs at 4 byte intervals */ -#define USE_TLB FALSE /* make use of TLB */ -#define USE_TAR FALSE /* enable data archives */ -#define NPOOL 8 /* number of buffer pools available */ -#define POOL_MAX_BUFSIZE 2048 /* max size of a buffer in a pool */ -#define POOL_MIN_BUFSIZE 8 /* min size of a buffer in a pool */ -#define POOL_MAX_NBUFS 8192 /* max number of buffers in a pool */ diff --git a/compile/platforms/mipsel-qemu/platformVars b/compile/platforms/mipsel-qemu/platformVars deleted file mode 100644 index 1ee42104..00000000 --- a/compile/platforms/mipsel-qemu/platformVars +++ /dev/null @@ -1,22 +0,0 @@ -# -# Platform-specific Makefile definitions for the Mipsel QEMU port of Embedded -# Xinu. -# - -PLATFORM_NAME := MIPSel QEMU - -# Include default mipsel definitions -MIPS_ENDIANNESS := little -MIPS_REVISION := 1 -include arch/mips/platformVars - -# Embedded Xinu components to build into kernel image -APPCOMPS := apps \ - mailbox \ - shell \ - test - -# Embedded Xinu device drivers to build into the kernel image -DEVICES := loopback \ - tty \ - uart-ns16550 diff --git a/compile/platforms/mipsel-qemu/xinu.conf b/compile/platforms/mipsel-qemu/xinu.conf deleted file mode 100644 index 74d6f375..00000000 --- a/compile/platforms/mipsel-qemu/xinu.conf +++ /dev/null @@ -1,73 +0,0 @@ -/* Configuration - (device configuration specifications) */ -/* Unspecified switches default to ioerr */ -/* -i init -o open -c close */ -/* -r read -g getc -p putc */ -/* -w write -s seek -n control */ -/* -intr interrupt -csr csr -irq irq */ - -/* "type" declarations for both real- and pseudo- devices */ - -/* simple loopback device */ -loopback: - on LOOPBACK -i loopbackInit -o loopbackOpen -c loopbackClose - -r loopbackRead -g loopbackGetc -p loopbackPutc - -w loopbackWrite -n loopbackControl - -/* null device */ -null: - on NOTHING -i ionull -o ionull -c ionull - -r ionull -g ionull -p ionull - -w ionull - -/* physical uart (NS16550) device */ -uart: - on HARDWARE -i uartInit -o ionull -c ionull - -r uartRead -g uartGetc -p uartPutc - -w uartWrite -n uartControl - -intr uartInterrupt - -/* tty pseudo-devices */ -tty: - on SOFTWARE -i ttyInit -o ttyOpen -c ttyClose - -r ttyRead -g ttyGetc -p ttyPutc - -w ttyWrite -n ttyControl - -%% - -/* Two uart ports on WRT54GL */ -SERIAL0 is uart on HARDWARE csr 0xB40003F8 irq 12 - -DEVNULL is null on NOTHING - -/* Loopback device */ -LOOP0 is loopback on LOOPBACK - -/* TTYs for each uart */ -TTYLOOP is tty on SOFTWARE -CONSOLE is tty on SOFTWARE - -%% - -/* Configuration and Size Constants */ - -#define LITTLE_ENDIAN 0x1234 -#define BIG_ENDIAN 0x4321 - -#define BYTE_ORDER LITTLE_ENDIAN - -#define NTHREAD 100 /* number of user threads */ -#define NSEM 100 /* number of semaphores */ -#define NMAILBOX 15 /* number of mailboxes */ -#define RTCLOCK TRUE /* now have RTC support */ -#define NETEMU FALSE /* Network Emulator support */ -#define NVRAM FALSE /* now have nvram support */ -#define SB_BUS FALSE /* Silicon Backplane support */ -#define PIC8259 0xB4000020 /* Programmable interrupt controller*/ -#define IRQ_TIMER IRQ_HW5 /* timer IRQ is wired to hardware 5 */ -#define UART_FIFO_LEN 16 /* Hardware FIFO varies by platform */ -#define USE_TLB FALSE /* make use of TLB */ -#define USE_TAR FALSE /* enable data archives */ -#define NPOOL 8 /* number of buffer pools available */ -#define POOL_MAX_BUFSIZE 2048 /* max size of a buffer in a pool */ -#define POOL_MIN_BUFSIZE 8 /* min size of a buffer in a pool */ -#define POOL_MAX_NBUFS 8192 /* max number of buffers in a pool */ diff --git a/compile/platforms/wl330ge/platformVars b/compile/platforms/wl330ge/platformVars deleted file mode 100644 index 27c24451..00000000 --- a/compile/platforms/wl330ge/platformVars +++ /dev/null @@ -1,35 +0,0 @@ -# -# Platform-specific Makefile definitions for the ASUS WL-330gE port of Embedded -# Xinu. -# - -PLATFORM_NAME := ASUS WL-330gE - -# Include default mipsel definitions -MIPS_ENDIANNESS := little -MIPS_REVISION := 1 -include arch/mips/platformVars - -# Embedded Xinu components to build into kernel image -APPCOMPS := apps \ - mailbox \ - network \ - shell \ - test - -# Embedded Xinu device drivers to build into the kernel image -DEVICES := bcm4713 \ - bcmbus \ - ethloop \ - flash \ - http \ - loopback \ - raw \ - tcp \ - telnet \ - tty \ - uart-ns16550 \ - udp - -# Extra defines -DEFS += -DFLASH_ASUS diff --git a/compile/platforms/wl330ge/xinu.conf b/compile/platforms/wl330ge/xinu.conf deleted file mode 100644 index 9f321b41..00000000 --- a/compile/platforms/wl330ge/xinu.conf +++ /dev/null @@ -1,161 +0,0 @@ -/* Configuration - (device configuration specifications) */ -/* Unspecified switches default to ioerr */ -/* -i init -o open -c close */ -/* -r read -g getc -p putc */ -/* -w write -s seek -n control */ -/* -intr interrupt -csr csr -irq irq */ - -/* "type" declarations for both real- and pseudo- devices */ - -/* simple loopback device */ -loopback: - on LOOPBACK -i loopbackInit -o loopbackOpen -c loopbackClose - -r loopbackRead -g loopbackGetc -p loopbackPutc - -w loopbackWrite -n loopbackControl - -/* null device */ -null: - on NOTHING -i ionull -o ionull -c ionull - -r ionull -g ionull -p ionull - -w ionull - -/* physical uart (NS16550) device */ -uart: - on HARDWARE -i uartInit -o ionull -c ionull - -r uartRead -g uartGetc -p uartPutc - -w uartWrite -n uartControl - -intr uartInterrupt - -/* tty pseudo-devices */ -tty: - on SOFTWARE -i ttyInit -o ttyOpen -c ttyClose - -r ttyRead -g ttyGetc -p ttyPutc - -w ttyWrite -n ttyControl - -/* FLASH for each flash device */ -flash: - on HARDWARE -i flashInit -o flashOpen -c flashClose - -r flashRead -w flashWrite -n flashControl - -/* physical Ethernet device */ -ether: - on HARDWARE -i etherInit -o etherOpen -c etherClose - -r etherRead -w etherWrite -n etherControl - -intr etherInterrupt - on SOFTWARE -i vlanInit -o vlanOpen -c vlanClose - -r etherRead -w etherWrite -n etherControl - -intr etherInterrupt - -/* simple Ethernet loopback device */ -ethloop: - on ETHLOOP -i ethloopInit -o ethloopOpen -c ethloopClose - -r ethloopRead -w ethloopWrite -n ethloopControl - -/* raw sockets */ -raw: - on SOFTWARE -i rawInit -o rawOpen -c rawClose - -r rawRead -w rawWrite -n rawControl - -/* udp devices */ -udp: - on NET -i udpInit -o udpOpen -c udpClose - -r udpRead -w udpWrite -n udpControl - -/* tcp devices */ -tcp: - on SOFTWARE -i tcpInit -o tcpOpen -c tcpClose - -r tcpRead -g tcpGetc -w tcpWrite - -p tcpPutc -n tcpControl - -/* http pseudo-devices */ -http: - on TCP -i httpInit -o httpOpen -c httpClose - -r httpRead -g httpGetc -p httpPutc - -w httpWrite -n httpControl - -/* telnet devices */ -telnet: - on TCP -i telnetInit -o telnetOpen -c telnetClose - -r telnetRead -g telnetGetc -w telnetWrite - -p telnetPutc -n telnetControl - -%% - -/* Two uart ports on WRT54GL */ -SERIAL0 is uart on HARDWARE csr 0xB8000300 irq 3 -SERIAL1 is uart on HARDWARE csr 0xB8000400 irq 3 - -DEVNULL is null on NOTHING - -/* Loopback device */ -LOOP0 is loopback on LOOPBACK - -/* TTYs for each uart */ -TTYLOOP is tty on SOFTWARE -CONSOLE is tty on SOFTWARE -TTY1 is tty on SOFTWARE - -/* Flash device */ -FLASH is flash on HARDWARE csr 0xBC000000 - -/* Physical ethernet raw packet interface */ -ETH0 is ether on HARDWARE csr 0xB8001000 irq 4 - -/* A Ethernet Loopback device */ -ELOOP is ethloop on ETHLOOP - -/* Raw sockets */ -RAW0 is raw on SOFTWARE -RAW1 is raw on SOFTWARE - -/* UDP devices */ -UDP0 is udp on NET -UDP1 is udp on NET -UDP2 is udp on NET -UDP3 is udp on NET - -/* TCP devices */ -TCP0 is tcp on SOFTWARE -TCP1 is tcp on SOFTWARE -TCP2 is tcp on SOFTWARE -TCP3 is tcp on SOFTWARE -TCP4 is tcp on SOFTWARE -TCP5 is tcp on SOFTWARE -TCP6 is tcp on SOFTWARE - -/* HTTP */ -HTTP0 is http on TCP -HTTP1 is http on TCP -HTTP2 is http on TCP - -/* TELNET */ -TELNET0 is telnet on TCP -TELNET1 is telnet on TCP -TELNET2 is telnet on TCP - -%% - -/* Configuration and Size Constants */ - -#define LITTLE_ENDIAN 0x1234 -#define BIG_ENDIAN 0x4321 - -#define BYTE_ORDER LITTLE_ENDIAN - -#define NTHREAD 100 /* number of user threads */ -#define NSEM 100 /* number of semaphores */ -#define NMAILBOX 15 /* number of mailboxes */ -#define RTCLOCK TRUE /* now have RTC support */ -#define NETEMU FALSE /* Network Emulator support */ -#define NVRAM TRUE /* now have nvram support */ -#define SB_BUS FALSE /* Silicon Backplane support */ -#define GPIO TRUE /* General-purpose I/O (leds) */ -#define IRQ_TIMER IRQ_HW5 /* timer IRQ is wired to hardware 5 */ -#define UART_FIFO_LEN 64 /* At least 64 bytes on WRT54GL. */ -#define USE_TLB FALSE /* make use of TLB */ -#define USE_TAR TRUE /* enable data archives */ -#define GPIO_BASE 0xB8000060 /* General-purpose I/O lines */ -#define NPOOL 8 /* number of buffer pools available */ -#define POOL_MAX_BUFSIZE 2048 /* max size of a buffer in a pool */ -#define POOL_MIN_BUFSIZE 8 /* min size of a buffer in a pool */ -#define POOL_MAX_NBUFS 8192 /* max number of buffers in a pool */ diff --git a/compile/platforms/wrt160nl/platformVars b/compile/platforms/wrt160nl/platformVars deleted file mode 100644 index edd0a7e7..00000000 --- a/compile/platforms/wrt160nl/platformVars +++ /dev/null @@ -1,49 +0,0 @@ -# -# Platform-specific Makefile definitions for the WRT160NL port of Embedded Xinu. -# - -PLATFORM_NAME := Linksys WRT160NL - -# Include default mips definitions, but override some details about the -# specific sub-architecture -MIPS_RELEASE := 2 -MIPS_ENDIANNESS := big -MIPS_PLATFORM_DEFINES_DEFAULT_TARGET := yes -include arch/mips/platformVars - -# Embedded Xinu components to build into kernel image -APPCOMPS := apps \ - mailbox \ - network \ - shell \ - test - -# Embedded Xinu device drivers to build into the kernel image -DEVICES := ag71xx \ - ethloop \ - flash \ - loopback \ - raw \ - tcp \ - telnet \ - tty \ - uart-ns16550 \ - udp - -# On this platform, generating the final boot image requires an external tool. - -MKIMAGE := uboot-tool/mkimage -UBOOTOPTS := -A mips -O linux -T kernel -a 0x80010000 \ - -C none -e 0x80010000 -n 'Xinu' - -# Default build target -$(BOOTIMAGE): xinu.bin $(MKIMAGE) - $(MKIMAGE) $(UBOOTOPTS) -d xinu.bin $@ - -$(MKIMAGE): - @echo "ERROR: The U-Boot utilities are not part of Xinu." - @echo "ERROR: Please acquire the mkimage utility separately." - exit 1 - -xinu.bin: xinu.elf - $(OBJCOPY) -O binary $^ $@ diff --git a/compile/platforms/wrt160nl/xinu.conf b/compile/platforms/wrt160nl/xinu.conf deleted file mode 100644 index a91eed91..00000000 --- a/compile/platforms/wrt160nl/xinu.conf +++ /dev/null @@ -1,138 +0,0 @@ -/* Configuration - (device configuration specifications) */ -/* Unspecified switches default to ioerr */ -/* -i init -o open -c close */ -/* -r read -g getc -p putc */ -/* -w write -s seek -n control */ -/* -intr interrupt -csr csr -irq irq */ - -/* "type" declarations for both real- and pseudo- devices */ - -/* simple loopback device */ -loopback: - on LOOPBACK -i loopbackInit -o loopbackOpen -c loopbackClose - -r loopbackRead -g loopbackGetc -p loopbackPutc - -w loopbackWrite -n loopbackControl - -/* null device */ -null: - on NOTHING -i ionull -o ionull -c ionull - -r ionull -g ionull -p ionull - -w ionull - -/* physical uart (NS16550) device */ -uart: - on HARDWARE -i uartInit -o ionull -c ionull - -r uartRead -g uartGetc -p uartPutc - -w uartWrite -n uartControl - -intr uartInterrupt - -/* tty pseudo-devices */ -tty: - on SOFTWARE -i ttyInit -o ttyOpen -c ttyClose - -r ttyRead -g ttyGetc -p ttyPutc - -w ttyWrite -n ttyControl - -/* physical Ethernet device */ -ether: - on HARDWARE -i etherInit -o etherOpen -c etherClose - -r etherRead -w etherWrite -n etherControl - -intr etherInterrupt - -/* simple Ethernet loopback device */ -ethloop: - on ETHLOOP -i ethloopInit -o ethloopOpen -c ethloopClose - -r ethloopRead -w ethloopWrite -n ethloopControl - -/* raw sockets */ -raw: - on SOFTWARE -i rawInit -o rawOpen -c rawClose - -r rawRead -w rawWrite -n rawControl - -/* udp devices */ -udp: - on NET -i udpInit -o udpOpen -c udpClose - -r udpRead -w udpWrite -n udpControl - -/* tcp devices */ -tcp: - on SOFTWARE -i tcpInit -o tcpOpen -c tcpClose - -r tcpRead -g tcpGetc -w tcpWrite - -p tcpPutc -n tcpControl - -/* http pseudo-devices */ -http: - on TCP -i httpInit -o httpOpen -c httpClose - -r httpRead -g httpGetc -p httpPutc - -w httpWrite -n httpControl - -/* telnet devices */ -telnet: - on TCP -i telnetInit -o telnetOpen -c telnetClose - -r telnetRead -g telnetGetc -w telnetWrite - -p telnetPutc -n telnetControl -%% - -/* Two uart ports on WRT54GL */ -SERIAL0 is uart on HARDWARE csr 0xB8020000 irq 11 - -DEVNULL is null on NOTHING - -/* Loopback device */ -LOOP0 is loopback on LOOPBACK - -/* TTYs for each uart */ -TTYLOOP is tty on SOFTWARE -CONSOLE is tty on SOFTWARE - -/* Physical ethernet raw packet interface */ -ETH0 is ether on HARDWARE csr 0xB9000000 irq 4 - -/* A Ethernet Loopback device */ -ELOOP is ethloop on ETHLOOP - -/* Raw sockets */ -RAW0 is raw on SOFTWARE -RAW1 is raw on SOFTWARE - -/* Two UDP devices */ -UDP0 is udp on NET -UDP1 is udp on NET - -/* TCP devices */ -TCP0 is tcp on SOFTWARE -TCP1 is tcp on SOFTWARE -TCP2 is tcp on SOFTWARE -TCP3 is tcp on SOFTWARE -TCP4 is tcp on SOFTWARE -TCP5 is tcp on SOFTWARE -TCP6 is tcp on SOFTWARE - -/* TELNET */ -TELNET0 is telnet on TCP -TELNET1 is telnet on TCP -TELNET2 is telnet on TCP - -%% - -/* Configuration and Size Constants */ - -#define LITTLE_ENDIAN 0x1234 -#define BIG_ENDIAN 0x4321 - -#define BYTE_ORDER BIG_ENDIAN - -#define NTHREAD 100 /* number of user threads */ -#define NSEM 100 /* number of semaphores */ -#define NMAILBOX 15 /* number of mailboxes */ -#define NPOOL 0 /* number of buffer pools */ -#define RTCLOCK TRUE /* now have RTC support */ -#define NETEMU FALSE /* Network Emulator support */ -#define NVRAM FALSE /* now have nvram support */ -#define SB_BUS FALSE /* Silicon Backplane support */ -#define GPIO FALSE /* General-purpose I/O (leds) */ -#define IRQ_TIMER IRQ_HW5 /* timer IRQ is wired to hardware 5 */ -#define IRQ_ATH_MISC IRQ_HW4 /* Misc IRQ is wired to hardware 4 */ -#define USE_TLB FALSE /* make use of TLB */ -#define USE_TAR FALSE /* enable data archives */ -#define UART_FIFO_LEN 16 /* NS16550 UART fifo length */ -#define UART_CSR_SPACED TRUE /* NS16550 UART registers are word-sized */ diff --git a/compile/platforms/wrt54gl/platformVars b/compile/platforms/wrt54gl/platformVars deleted file mode 100644 index 3031b5c4..00000000 --- a/compile/platforms/wrt54gl/platformVars +++ /dev/null @@ -1,32 +0,0 @@ -# -# Platform-specific Makefile definitions for the Linksys WRT54GL port of -# Embedded Xinu. -# - -PLATFORM_NAME := Linksys WRT54GL Wireless Router - -# Include default mipsel definitions -MIPS_ENDIANNESS := little -MIPS_REVISION := 1 -include arch/mips/platformVars - -# Embedded Xinu components to build into kernel image -APPCOMPS := apps \ - mailbox \ - network \ - shell \ - test - -# Embedded Xinu device drivers to build into the kernel image -DEVICES := bcm4713 \ - bcmbus \ - ethloop \ - flash \ - http \ - loopback \ - raw \ - tcp \ - telnet \ - tty \ - uart-ns16550 \ - udp diff --git a/compile/platforms/wrt54gl/xinu.conf b/compile/platforms/wrt54gl/xinu.conf deleted file mode 100644 index e89d4b79..00000000 --- a/compile/platforms/wrt54gl/xinu.conf +++ /dev/null @@ -1,167 +0,0 @@ -/* Configuration - (device configuration specifications) */ -/* Unspecified switches default to ioerr */ -/* -i init -o open -c close */ -/* -r read -g getc -p putc */ -/* -w write -s seek -n control */ -/* -intr interrupt -csr csr -irq irq */ - -/* "type" declarations for both real- and pseudo- devices */ - -/* simple loopback device */ -loopback: - on LOOPBACK -i loopbackInit -o loopbackOpen -c loopbackClose - -r loopbackRead -g loopbackGetc -p loopbackPutc - -w loopbackWrite -n loopbackControl - -/* null device */ -null: - on NOTHING -i ionull -o ionull -c ionull - -r ionull -g ionull -p ionull - -w ionull - -/* physical uart (NS16550) device */ -uart: - on HARDWARE -i uartInit -o ionull -c ionull - -r uartRead -g uartGetc -p uartPutc - -w uartWrite -n uartControl - -intr uartInterrupt - -/* tty pseudo-devices */ -tty: - on SOFTWARE -i ttyInit -o ttyOpen -c ttyClose - -r ttyRead -g ttyGetc -p ttyPutc - -w ttyWrite -n ttyControl - -/* FLASH for each flash device */ -flash: - on HARDWARE -i flashInit -o flashOpen -c flashClose - -r flashRead -w flashWrite -n flashControl - -/* physical Ethernet device */ -ether: - on HARDWARE -i etherInit -o etherOpen -c etherClose - -r etherRead -w etherWrite -n etherControl - -intr etherInterrupt - on SOFTWARE -i vlanInit -o vlanOpen -c vlanClose - -r etherRead -w etherWrite -n etherControl - -intr etherInterrupt - -/* simple Ethernet loopback device */ -ethloop: - on ETHLOOP -i ethloopInit -o ethloopOpen -c ethloopClose - -r ethloopRead -w ethloopWrite -n ethloopControl - -/* raw sockets */ -raw: - on SOFTWARE -i rawInit -o rawOpen -c rawClose - -r rawRead -w rawWrite -n rawControl - -/* udp devices */ -udp: - on NET -i udpInit -o udpOpen -c udpClose - -r udpRead -w udpWrite -n udpControl - -/* tcp devices */ -tcp: - on SOFTWARE -i tcpInit -o tcpOpen -c tcpClose - -r tcpRead -g tcpGetc -w tcpWrite - -p tcpPutc -n tcpControl - -/* http pseudo-devices */ -http: - on TCP -i httpInit -o httpOpen -c httpClose - -r httpRead -g httpGetc -p httpPutc - -w httpWrite -n httpControl - -/* telnet devices */ -telnet: - on TCP -i telnetInit -o telnetOpen -c telnetClose - -r telnetRead -g telnetGetc -w telnetWrite - -p telnetPutc -n telnetControl - -%% - -/* Two uart ports on WRT54GL */ -SERIAL0 is uart on HARDWARE csr 0xB8000300 irq 3 -SERIAL1 is uart on HARDWARE csr 0xB8000400 irq 3 - -DEVNULL is null on NOTHING - -/* Loopback device */ -LOOP0 is loopback on LOOPBACK - -/* TTYs for each uart */ -TTYLOOP is tty on SOFTWARE -CONSOLE is tty on SOFTWARE -TTY1 is tty on SOFTWARE - -/* Flash device */ -FLASH is flash on HARDWARE csr 0xBC000000 - -/* Physical ethernet raw packet interface */ -ETH0 is ether on HARDWARE csr 0xB8001000 irq 4 -ETH1 is ether on SOFTWARE csr 0xB8001000 irq 4 -ETH2 is ether on SOFTWARE csr 0xB8001000 irq 4 -ETH3 is ether on SOFTWARE csr 0xB8001000 irq 4 -ETH4 is ether on SOFTWARE csr 0xB8001000 irq 4 - -/* A Ethernet Loopback device */ -ELOOP is ethloop on ETHLOOP - -/* Raw sockets */ -RAW0 is raw on SOFTWARE -RAW1 is raw on SOFTWARE - -/* UDP devices */ -UDP0 is udp on NET -UDP1 is udp on NET -UDP2 is udp on NET -UDP3 is udp on NET - -/* TCP devices */ -TCP0 is tcp on SOFTWARE -TCP1 is tcp on SOFTWARE -TCP2 is tcp on SOFTWARE -TCP3 is tcp on SOFTWARE -TCP4 is tcp on SOFTWARE -TCP5 is tcp on SOFTWARE -TCP6 is tcp on SOFTWARE - -/* HTTP */ -HTTP0 is http on TCP -HTTP1 is http on TCP -HTTP2 is http on TCP - -/* TELNET */ -TELNET0 is telnet on TCP -TELNET1 is telnet on TCP -TELNET2 is telnet on TCP - -%% - -/* Configuration and Size Constants */ - -#define LITTLE_ENDIAN 0x1234 -#define BIG_ENDIAN 0x4321 - -#define BYTE_ORDER LITTLE_ENDIAN - -#define NTHREAD 100 /* number of user threads */ -#define NMON 100 /* number of monitors */ -#define NSEM (NMON + 100) /* number of semaphores */ -#define NMAILBOX 15 /* number of mailboxes */ -#define RTCLOCK TRUE /* now have RTC support */ -#define NETEMU FALSE /* Network Emulator support */ -#define NVRAM TRUE /* now have nvram support */ -#define SB_BUS FALSE /* Silicon Backplane support */ -#define GPIO TRUE /* General-purpose I/O (leds) */ -#define IRQ_TIMER IRQ_HW5 /* timer IRQ is wired to hardware 5 */ -#define UART_FIFO_LEN 64 /* At least 64 bytes on WRT54GL. */ -//#define UHEAP_SIZE 8*1024*1024 /* size of memory for user threads */ -#define USE_TLB FALSE /* make use of TLB */ -#define USE_TAR TRUE /* enable data archives */ -#define GPIO_BASE 0xB8000060 /* General-purpose I/O lines */ -#define NPOOL 8 /* number of buffer pools available */ -#define POOL_MAX_BUFSIZE 2048 /* max size of a buffer in a pool */ -#define POOL_MIN_BUFSIZE 8 /* min size of a buffer in a pool */ -#define POOL_MAX_NBUFS 8192 /* max number of buffers in a pool */ diff --git a/compile/platforms/x86/ld.script b/compile/platforms/x86/ld.script deleted file mode 100644 index 235e7ec4..00000000 --- a/compile/platforms/x86/ld.script +++ /dev/null @@ -1,36 +0,0 @@ -OUTPUT_ARCH(i386) -ENTRY(_start) -SECTIONS { - . = 0x00100000; - .text : - { - *(.text .text.*) /* S text, then C text */ - *(.rodata .rodata.*) /* S and C read-only data */ - _etext = . ; /* provide _etext constant */ - } - - .data : - { - *(.data .data.*) /* S and C data */ - *(.tdata .tdata.*) /* S and C thread data */ - _edata = . ; /* end of data constant */ - } - PROVIDE (edata = .) ; - - .bss : - { - _bss = . ; /* beginning of bss segment */ - *(.bss .bss.*) /* S and C bss */ - *(.tbss .tbss.*) /* S and C thread bss */ - *(COMMON) /* extra sections that are common */ - _end = . ; /* end of image constant */ - } - PROVIDE (end = .) ; - - /* Discard comment and note (but not debugging) sections. Some - * versions of GNU ld would otherwise automatically place the - * ".note.gnu.build-id" section before _start! */ - /DISCARD/ : { - *(.comment .comment.* .note .note.*) - } -} diff --git a/compile/platforms/x86/platformVars b/compile/platforms/x86/platformVars deleted file mode 100644 index 02b6b997..00000000 --- a/compile/platforms/x86/platformVars +++ /dev/null @@ -1,21 +0,0 @@ -# -# Platform-specific Makefile definitions for the x86 port of Embedded Xinu. -# - -# Include default x86 definitions -include arch/x86/platformVars - -PLATFORM_NAME := Intel x86 - -# Add flags to compile 32 bit code -CFLAGS += -m32 -ASFLAGS += --32 - -# Add a define so we can test for x86 in C code if absolutely needed -DEFS += -D_XINU_PLATFORM_X86_ - -# Embedded Xinu components to build into the kernel image -APPCOMPS := apps mailbox shell test - -# Embedded Xinu device drivers to build into the kernel image -DEVICES := loopback tty uart-x86 diff --git a/compile/platforms/x86/xinu.conf b/compile/platforms/x86/xinu.conf deleted file mode 100644 index 42325fc5..00000000 --- a/compile/platforms/x86/xinu.conf +++ /dev/null @@ -1,135 +0,0 @@ -/* Configuration - (device configuration specifications) */ -/* Unspecified switches default to ioerr */ -/* -i init -o open -c close */ -/* -r read -g getc -p putc */ -/* -w write -s seek -n control */ -/* -intr interrupt -csr csr -irq irq */ - -/* "type" declarations for both real- and pseudo- devices */ - -/* simple loopback device */ -loopback: - on LOOPBACK -i loopbackInit -o loopbackOpen -c loopbackClose - -r loopbackRead -g loopbackGetc -p loopbackPutc - -w loopbackWrite -n loopbackControl - -/* null device */ -null: - on NOTHING -i ionull -o ionull -c ionull - -r ionull -g ionull -p ionull - -w ionull - -/* physical uart (NS16550) device */ -uart: - on HARDWARE -i uartInit -o ionull -c ionull - -r uartRead -g uartGetc -p uartPutc - -w uartWrite -n uartControl - -intr uartInterrupt - -/* tty pseudo-devices */ -tty: - on SOFTWARE -i ttyInit -o ttyOpen -c ttyClose - -r ttyRead -g ttyGetc -p ttyPutc - -w ttyWrite -n ttyControl - -/* FLASH for each flash device */ -flash: - on HARDWARE -i flashInit -o flashOpen -c flashClose - -r flashRead -w flashWrite -n flashControl - -/* physical Ethernet device */ -ether: - on HARDWARE -i etherInit -o etherOpen -c etherClose - -r etherRead -w etherWrite -n etherControl - -intr etherInterrupt - on SOFTWARE -i vlanInit -o vlanOpen -c vlanClose - -r etherRead -w etherWrite -n etherControl - -intr etherInterrupt - -/* simple Ethernet loopback device */ -ethloop: - on ETHLOOP -i ethloopInit -o ethloopOpen -c ethloopClose - -r ethloopRead -w ethloopWrite -n ethloopControl - -/* raw sockets */ -raw: - on SOFTWARE -i rawInit -o rawOpen -c rawClose - -r rawRead -w rawWrite -n rawControl - -/* udp devices */ -udp: - on NET -i udpInit -o udpOpen -c udpClose - -r udpRead -w udpWrite -n udpControl - -/* tcp devices */ -tcp: - on SOFTWARE -i tcpInit -o tcpOpen -c tcpClose - -r tcpRead -g tcpGetc -w tcpWrite - -p tcpPutc -n tcpControl - -/* http pseudo-devices */ -http: - on TCP -i httpInit -o httpOpen -c httpClose - -r httpRead -g httpGetc -p httpPutc - -w httpWrite -n httpControl - -/* telnet devices */ -telnet: - on TCP -i telnetInit -o telnetOpen -c telnetClose - -r telnetRead -g telnetGetc -w telnetWrite - -p telnetPutc -n telnetControl - -%% - -/* One uart (that Mike Z knows of) on Intel */ -/* Also, irq 1 is a guess. Hope it's right! */ -SERIAL0 is uart on HARDWARE csr 0x3f8 irq 4 - -DEVNULL is null on NOTHING - -/* Loopback device */ -LOOP0 is loopback on LOOPBACK - -/* TTYs for each uart */ -TTYLOOP is tty on SOFTWARE -CONSOLE is tty on SOFTWARE - -/* Physical ethernet raw packet interface */ -/* TODO: Figure out this csr and irq!!! */ -/* ETH0 is ether on HARDWARE csr 0xB8001000 irq 4 */ - -%% - -/* Configuration and Size Constants */ -/* Mike Z took lots of guesses here. */ - -extern short inb(long); -extern short outb(long, long); - -#define LITTLE_ENDIAN 0x1234 -#define BIG_ENDIAN 0x4321 - -#define BYTE_ORDER LITTLE_ENDIAN - -#define NTHREAD 100 /* number of user threads */ -#define NSEM 100 /* number of semaphores */ -#define NMAILBOX 15 /* number of mailboxes */ -#define RTCLOCK TRUE /* now have RTC support */ -#define NETEMU FALSE /* Network Emulator support */ -#define NVRAM FALSE /* now have nvram support */ -#define SB_BUS FALSE /* Silicon Backplane support */ -#define PCI_BUS FALSE /* PCI Bus for x86 support */ -#define GPIO TRUE /* General-purpose I/O (leds) */ -#define IRQ_TIMER IRQ_HW5 /* timer IRQ is wired to hardware 5 */ -#define IRQ_UART IRQ_HW1 -#define IRQ_ETH0 IRQ_HW2 -#define IRQ_ETH1 IRQ_HW0 -#define UART_FIFO_LEN 16 /* Size of hardware FIFO buffer on x86 */ -//#define UHEAP_SIZE 8*1024*1024 /* size of memory for user threads */ -#define USE_TLB FALSE /* make use of TLB */ -#define USE_TAR TRUE /* enable data archives */ -#define POOL_MAX_BUFSIZE 2048 /* max size of a buffer in a pool */ -#define POOL_MIN_BUFSIZE 8 /* min size of a buffer in a pool */ -#define POOL_MAX_NBUFS 8192 /* max number of buffers in a pool */ -#define NPOOL 8 /* number of buffer pools available */ -#define GPIO_BASE 0xB8000060 /* General-purpose I/O lines */ diff --git a/device/ag71xx/Doxygroup.c b/device/ag71xx/Doxygroup.c deleted file mode 100644 index 56ada525..00000000 --- a/device/ag71xx/Doxygroup.c +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @defgroup etherdriver Ethernet - * @ingroup devices - * @brief Ethernet driver for ag71xx devices - * - * @defgroup ether Ethernet Standard Functions - * @ingroup etherdriver - * - * @defgroup etherspecific Ethernet Device-Specific Functions - * @ingroup etherdriver - */ diff --git a/device/ag71xx/Makerules b/device/ag71xx/Makerules deleted file mode 100644 index ab000998..00000000 --- a/device/ag71xx/Makerules +++ /dev/null @@ -1,12 +0,0 @@ -# This Makefile contains rules to build this directory. - -# Name of this component (the directory this file is stored in) -COMP = device/ag71xx - -# Source files for this component -C_FILES = etherInit.c etherOpen.c etherClose.c etherRead.c etherWrite.c etherControl.c etherInterrupt.c allocRxBuffer.c etherStat.c vlanStat.c colon2mac.c -S_FILES = - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/device/ag71xx/ag71xx.h b/device/ag71xx/ag71xx.h deleted file mode 100644 index 7738f66f..00000000 --- a/device/ag71xx/ag71xx.h +++ /dev/null @@ -1,149 +0,0 @@ -/** - * @file ag71xx.h - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#ifndef _AG71XX_H_ -#define _AG71XX_H_ - -#include -#include - -/* Tracing macros */ -// #define TRACE_ETH CONSOLE -#ifdef TRACE_ETH -#include -#include -#define ETH_TRACE(...) { \ - fprintf(TRACE_ETH, "%s:%d (%d) ", __FILE__, __LINE__, gettid()); \ - fprintf(TRACE_ETH, __VA_ARGS__); \ - fprintf(TRACE_ETH, "\n"); } -#else -#define ETH_TRACE(...) -#endif - -/* Ring buffer sizes */ -#define ETH_RX_RING_ENTRIES 64 /**< Number of buffers on Rx Ring */ -#define ETH_TX_RING_ENTRIES 128 /**< Number of buffers on Tx Ring */ - -#define ETH_PKT_RESERVE 64 - -/** - * Control and Status register layout for the Atheros ag71xx Ethernet - * device. - */ -struct ag71xx -{ - volatile uint macConfig1; /**< 0x000 MAC configuration 1 */ -#define MAC_CFG1_TX (1 << 0) /* Enable Transmitter */ -#define MAC_CFG1_SYNC_TX (1 << 1) /* Syncronize Transmitter */ -#define MAC_CFG1_RX (1 << 2) /* Enable Receiver */ -#define MAC_CFG1_SYNC_RX (1 << 3) /* Syncronize Receiver */ -#define MAC_CFG1_LOOPBACK (1 << 8) /* Enable Loopback */ -#define MAC_CFG1_SOFTRESET (1 << 31) /* Software Reset */ - - volatile uint macConfig2; /**< 0x004 MAC configuration 2 */ -#define MAC_CFG2_FDX (1 << 0) /* Enable Full Duplex */ -#define MAC_CFG2_CRC (1 << 1) /* Enable CRC appending */ -#define MAC_CFG2_PAD (1 << 2) /* Enable padding of short pkts */ -#define MAC_CFG2_LEN_CHECK (1 << 4) /* Enable length field checking */ -#define MAC_CFG2_HUGE (1 << 5) /* Enable frames longer than max */ -#define MAC_CFG2_IMNIBBLE (1 << 8) /* "nibble mode" interface type */ -#define MAC_CFG2_IMBYTE (2 << 8) /* "byte mode" interface type */ - - - volatile uint pad00[2]; - volatile uint pad01[4]; - volatile uint pad02[4]; - volatile uint pad03[4]; - - volatile uint macAddr1; /**< 0x040 MAC Address part 1 */ - volatile uint macAddr2; /**< 0x044 MAC Address part 2 */ - - volatile uint fifoConfig0; /**< 0x048 MAC configuration 0 */ -#define FIFO_CFG0_WTMENREQ (1 << 8) /* Enable FIFO watermark module */ -#define FIFO_CFG0_SRFENREQ (1 << 9) /* Enable FIFO system Rx module */ -#define FIFO_CFG0_FRFENREQ (1 << 10) /* Enable FIFO fabric Rx module */ -#define FIFO_CFG0_STFENREQ (1 << 11) /* Enable FIFO system Tx module */ -#define FIFO_CFG0_FTFENREQ (1 << 12) /* Enable FIFO fabric Tx module */ - - volatile uint fifoConfig1; /**< 0x04C MAC configuration 1 */ - volatile uint fifoConfig2; /**< 0x050 MAC configuration 2 */ - volatile uint fifoConfig3; /**< 0x054 MAC configuration 3 */ - volatile uint fifoConfig4; /**< 0x058 MAC configuration 4 */ - volatile uint fifoConfig5; /**< 0x05C MAC configuration 5 */ - - volatile uint pad06[72]; - - volatile uint txControl; /**< 0x180 Tx Control */ -#define TX_CTRL_ENABLE (1 << 0) /* Enable Tx */ - volatile uint txDMA; /**< 0x184 Tx DMA Descriptor */ - volatile uint txStatus; /**< 0x188 Tx Status */ -#define TX_STAT_SENT (1 << 0) /* Packet Sent */ -#define TX_STAT_UNDER (1 << 1) /* Tx Underrun */ - - volatile uint rxControl; /**< 0x18C Rx Control */ -#define RX_CTRL_RXE (1 << 0) /* Enable receiver */ - - volatile uint rxDMA; /**< 0x190 Rx DMA Descriptor */ - volatile uint rxStatus; /**< 0x194 Rx Status */ -#define RX_STAT_RECVD (1 << 0) /* Packet Received */ -#define RX_STAT_OVERFLOW (1 << 2) /* DMA Rx overflow */ -#define RX_STAT_COUNT (0xFF << 16) /* Count of packets received */ - - volatile uint interruptMask; /**< 0x198 Interrupt Mask */ -#define IRQ_TX_PKTSENT (1 << 0) /* Packet Sent */ -#define IRQ_TX_UNDERFLOW (1 << 1) /* Tx packet underflow */ -#define IRQ_TX_BUSERR (1 << 3) /* Tx Bus Error */ -#define IRQ_RX_PKTRECV (1 << 4) /* Rx Packet received */ -#define IRQ_RX_OVERFLOW (1 << 6) /* Rx Overflow */ -#define IRQ_RX_BUSERR (1 << 7) /* Rx Bus Error */ - - volatile uint interruptStatus; /**< 0x19C Interrupt Status */ -}; - -/* Reciever Header struct and constants */ -#define ETH_RX_FLAG_OFIFO 0x0001 /**< FIFO Overflow */ -#define ETH_RX_FLAG_CRCERR 0x0002 /**< CRC Error */ -#define ETH_RX_FLAG_SERR 0x0004 /**< Receive Symbol Error */ -#define ETH_RX_FLAG_ODD 0x0008 /**< Frame has odd number nibbles */ -#define ETH_RX_FLAG_LARGE 0x0010 /**< Frame is > RX MAX Length */ -#define ETH_RX_FLAG_MCAST 0x0020 /**< Dest is Multicast Address */ -#define ETH_RX_FLAG_BCAST 0x0040 /**< Dest is Broadcast Address */ -#define ETH_RX_FLAG_MISS 0x0080 /**< Received due to promisc mode */ -#define ETH_RX_FLAG_LAST 0x0800 /**< Last buffer in frame */ -#define ETH_RX_FLAG_ERRORS ( ETH_RX_FLAG_ODD | ETH_RX_FLAG_SERR | \ - ETH_RX_FLAG_CRCERR | ETH_RX_FLAG_OFIFO ) - -/** - * Header on a received packet. - */ -struct rxHeader -{ - ushort length; /**< Length of packet data */ - ushort flags; /**< Receive flags */ - ushort pad[12]; /**< Padding */ -}; - -/* Ethernet DMA descriptor */ -#define ETH_DESC_CTRL_LEN 0x00001fff /**< Mask for length field */ -#define ETH_DESC_CTRL_MORE 0x10000000 /**< More fragments */ -#define ETH_DESC_CTRL_EMPTY 0x80000000 /**< Empty descriptor */ - -/** - * Descriptor for the DMA engine to determine where to find a packet - * buffer. - */ -struct dmaDescriptor -{ - ulong address; /**< Stored as physical address */ - ulong control; /**< DMA control bits */ - ulong next; /**< Next descriptor in the ring */ -}; - -#define RESET_CORE 0xB806001C /* Atheros bus reset core reset reg */ -#define RESET_E0_MAC (1 << 9) /* Reset Ethernet zero MAC */ -#define RESET_E1_MAC (1 << 13) /* Reset Ethernet one MAC */ - -#endif /* _AG71XX_H_ */ diff --git a/device/ag71xx/allocRxBuffer.c b/device/ag71xx/allocRxBuffer.c deleted file mode 100644 index ce580e30..00000000 --- a/device/ag71xx/allocRxBuffer.c +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @file allocRxBuffer.c - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#include -#include -#include -#include "ag71xx.h" -#include -#include -#include - -/** - * @ingroup etherspecific - * - * Allocate an ethernet packet buffer structure - * @param ethptr ethernet table entry - * @param destIndex destination index in ethernet reciever ring - * @return bytes allocated - */ -int allocRxBuffer(struct ether *ethptr, int destIndex) -{ - struct ethPktBuffer *pkt = NULL; - struct dmaDescriptor *dmaptr = NULL; - - destIndex %= ethptr->rxRingSize; - pkt = bufget(ethptr->inPool); - if (SYSERR == (ulong)pkt) - { -#ifdef DETAIL - kprintf("eth0 allocRxBuffer() error\r\n"); -#endif /* DETAIL */ - return SYSERR; - } - pkt->length = ETH_RX_BUF_SIZE; - pkt->buf = (uchar *)(pkt + 1); - - /* Data region offset by size of rx header. */ - pkt->data = pkt->buf + ethptr->rxOffset; - - ethptr->rxBufs[destIndex] = pkt; - - /* Fill in DMA descriptor fields */ - dmaptr = ethptr->rxRing + destIndex; - dmaptr->control = ETH_DESC_CTRL_EMPTY; - dmaptr->address = (ulong)(pkt->buf) & PMEM_MASK; - -#ifdef DETAIL - kprintf("eth0 rxBufs[%d] = 0x%08X\r\n", - destIndex, ethptr->rxBufs[destIndex]); - - kprintf - (" control 0x%08X address 0x%08X buffer 0x%08X\r\n", - dmaptr->control, dmaptr->address, pkt); - - if (pkt) - { - kprintf - (" epb buf 0x%08X epb dat 0x%08X epb len %8d\r\n", - pkt->buf, pkt->data, pkt->length); - struct rxHeader *rh; - - rh = (struct rxHeader *)pkt->buf; - kprintf - (" rxHead 0x%08X length 0x%08X flags 0x%08X\r\n", - rh, rh ? rh->length : 0, rh ? rh->flags : 0); - } -#endif /* DETAIL */ - - return OK; -} diff --git a/device/ag71xx/colon2mac.c b/device/ag71xx/colon2mac.c deleted file mode 100644 index f7bcdeda..00000000 --- a/device/ag71xx/colon2mac.c +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @file colon2mac.c - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#include -#include -#include - -#include - -/** - * Convert a colon-separated string representation of a MAC into - * the equivalent byte array. - * @param src pointer to colon-separated MAC string - * @param dst pointer to byte array - * @return number of octets converted. - */ -int colon2mac(char *src, uchar *dst) -{ - uchar count = 0, digit = 0, c = 0; - - if (NULL == src || NULL == dst) - { - return SYSERR; - } - - while ((count < ETH_ADDR_LEN) && ('\0' != *src)) - { - c = *src++; - if (isdigit(c)) - { - digit = c - '0'; - } - else if (isxdigit(c)) - { - digit = 10 + c - (isupper(c) ? 'A' : 'a'); - } - else - { - digit = 0; - } - dst[count] = digit * 16; - - c = *src++; - if (isdigit(c)) - { - digit = c - '0'; - } - else if (isxdigit(c)) - { - digit = 10 + c - (isupper(c) ? 'A' : 'a'); - } - else - { - digit = 0; - } - dst[count] += digit; - - count++; - if (':' != *src++) - { - break; - } - } - - return count; -} diff --git a/device/ag71xx/etherClose.c b/device/ag71xx/etherClose.c deleted file mode 100644 index 55e95fab..00000000 --- a/device/ag71xx/etherClose.c +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @file etherClose.c - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#include -#include -#include "ag71xx.h" -#include -#include -#include -#include -#include -#include - -/* Implementation of etherClose() for the ag71xx; see the documentation for this - * function in ether.h. */ -devcall etherClose(device *devptr) -{ - irqmask im; - struct ether *ethptr = NULL; - struct ag71xx *nicptr = NULL; - - ethptr = ðertab[devptr->minor]; - nicptr = ethptr->csr; - - /* flag interface as down */ - ethptr->state = ETH_STATE_DOWN; - - im = disable(); - - /* disable ether interrupt source */ - nicptr->interruptMask = ethptr->interruptMask = 0x0; - nicptr->interruptStatus = 0x0; - - restore(im); - - etherControl(devptr, ETH_CTRL_RESET, 0, 0); - - bfpfree(ethptr->inPool); - bfpfree(ethptr->outPool); - - return OK; -} diff --git a/device/ag71xx/etherControl.c b/device/ag71xx/etherControl.c deleted file mode 100644 index 4868dc7e..00000000 --- a/device/ag71xx/etherControl.c +++ /dev/null @@ -1,172 +0,0 @@ -/** - * @file etherControl.c - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#include -#include -#include "ag71xx.h" -#include -#include -#include - -/* Implementation of etherControl() for the ag71xx; see the documentation for - * this function in ether.h. */ -devcall etherControl(device *devptr, int func, long arg1, long arg2) -{ - struct ether *ethptr; - struct ag71xx *nicptr; - struct netaddr *addr; - uchar *macptr; - ulong temp = 0; - - ethptr = ðertab[devptr->minor]; - if (NULL == ethptr->csr) - { - return SYSERR; - } - nicptr = ethptr->csr; - - switch (func) - { -/* /\* Clear stats counters on ethernet device. *\/ */ -/* case ETH_CTRL_CLEAR_STATS: */ -/* nicptr->mibControl = MIB_CTRL_CLR_ON_READ; */ - -/* preg = &nicptr->txGoodOctets; */ -/* while (preg <= &nicptr->txPause) */ -/* { */ -/* temp = *preg++; */ -/* } */ - -/* preg = &nicptr->rxGoodOctets; */ -/* while (preg <= &nicptr->rxNonPause) */ -/* { */ -/* temp = *preg++; */ -/* } */ - -/* temp = nicptr->mibControl & ~MIB_CTRL_CLR_ON_READ; */ -/* nicptr->mibControl = temp; */ -/* break; */ - -/* Program MAC address into card. */ - case ETH_CTRL_SET_MAC: - macptr = (uchar *)arg1; - - temp = ((uint)macptr[0]) << 24; - temp |= ((uint)macptr[1]) << 16; - temp |= ((uint)macptr[2]) << 8; - temp |= ((uint)macptr[3]) << 0; - nicptr->macAddr1 = temp; - - temp = 0; - temp = ((uint)macptr[4]) << 24; - temp |= ((uint)macptr[5]) << 16; - nicptr->macAddr2 = temp; - break; - -/* Get MAC address from card. */ - case ETH_CTRL_GET_MAC: - macptr = (uchar *)arg1; - - temp = nicptr->macAddr1; - macptr[0] = temp >> 24; - macptr[1] = temp >> 16; - macptr[2] = temp >> 8; - macptr[3] = temp >> 0; - - temp = nicptr->macAddr2; - macptr[4] = temp >> 24; - macptr[5] = temp >> 16; - break; - -/* Set receiver mode. */ - case ETH_CTRL_SET_LOOPBK: - if (TRUE == (uint)arg1) - { - nicptr->macConfig1 |= MAC_CFG1_LOOPBACK; - } - else - { - nicptr->macConfig1 &= ~MAC_CFG1_LOOPBACK; - } - break; - -/* /\* Reset Ethernet device. *\/ */ -/* case ETH_CTRL_RESET: */ -/* /\* Idle the network card if the backplane core is up *\/ */ -/* if (backplaneCoreUp(&(nicptr->bpConfig))) */ -/* { */ -/* etherControl(devptr, ETH_CTRL_DISABLE, 0, 0); */ -/* } */ - -/* /\* Reset the target core. *\/ */ -/* backplaneReset(&(nicptr->bpConfig)); */ - -/* etherControl(devptr, ETH_CTRL_CLEAR_STATS, 0, 0); */ - -/* /\* Make PHY accessible and set frequency *\/ */ -/* nicptr->mdioControl = (MDIO_CTRL_PREAMBLE | MDIO_CTRL_FREQ); */ - -/* /\* Select external PHY, this model does not have internal. *\/ */ -/* nicptr->enetControl = ENET_CTRL_EPSEL; */ -/* break; */ - -/* /\* Disable ethernet core *\/ */ -/* case ETH_CTRL_DISABLE: */ -/* nicptr->rcvLazy = 0; /\* Turn off lazy reception. *\/ */ -/* nicptr->enetControl; /\* Read control register. *\/ */ - -/* /\* Wait for controller *\/ */ -/* waitOnBit(&nicptr->enetControl, ENET_CTRL_DISABLE, 0, 100); */ -/* /\* Reset transmitter settings and transmitter queue. *\/ */ -/* nicptr->dmaTxControl = 0; */ -/* ethptr->txHead = 0; */ -/* ethptr->txTail = 0; */ -/* if (nicptr->dmaRxStatus & DMARX_STAT_EMASK) */ -/* { */ -/* /\* Wait for receiver to idle. *\/ */ -/* waitOnBit(&nicptr->dmaRxStatus, DMARX_STAT_SIDLE, 1, 100); */ -/* } */ - -/* /\* Reset receiver settings and receiver queue. *\/ */ -/* nicptr->dmaRxControl = 0; */ -/* ethptr->rxHead = 0; */ -/* ethptr->rxTail = 0; */ -/* break; */ - -/* Get link header length. */ - case NET_GET_LINKHDRLEN: - return ETH_HDR_LEN; - -/* Get MTU. */ - case NET_GET_MTU: - return ETH_MTU; - - case NET_GET_HWADDR: - addr = (struct netaddr *)arg1; - addr->type = NETADDR_ETHERNET; - addr->len = ETH_ADDR_LEN; - etherControl(devptr, ETH_CTRL_GET_MAC, (int)addr->addr, NULL); - break; - -/* Get broadcast MAC address. */ - case NET_GET_HWBRC: - addr = (struct netaddr *)arg1; - addr->type = NETADDR_ETHERNET; - addr->len = ETH_ADDR_LEN; - addr->addr[0] = 0xFF; - addr->addr[1] = 0xFF; - addr->addr[2] = 0xFF; - addr->addr[3] = 0xFF; - addr->addr[4] = 0xFF; - addr->addr[5] = 0xFF; - break; - - default: - return SYSERR; - } - - return OK; -} diff --git a/device/ag71xx/etherInit.c b/device/ag71xx/etherInit.c deleted file mode 100644 index c640e322..00000000 --- a/device/ag71xx/etherInit.c +++ /dev/null @@ -1,149 +0,0 @@ -/** - * @file etherInit.c - * - * Initialization for the Atheros ag71xx series of ethernet devices. - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include "ag71xx.h" -#include -#include -#include -#include -#include -#include -#include - -/* Global table of ethernet devices */ -struct ether ethertab[NETHER]; - -/* Implementation of etherInit() for the ag71xx; see the documentation for this - * function in ether.h. */ -devcall etherInit(device *devptr) -{ - struct ether *ethptr; - struct ag71xx *nicptr; - uint *rstptr; - uint rstbit; - - /* Initialize structure pointers */ - ethptr = ðertab[devptr->minor]; - bzero(ethptr, sizeof(struct ether)); - ethptr->dev = devptr; - ethptr->csr = devptr->csr; - nicptr = (struct ag71xx *)devptr->csr; - rstptr = (uint *)RESET_CORE; - if (0 == devptr->minor) - { - rstbit = RESET_E0_MAC; - } - else - { - rstbit = RESET_E1_MAC; - } - - ethptr->state = ETH_STATE_DOWN; - ethptr->rxRingSize = ETH_RX_RING_ENTRIES; - ethptr->txRingSize = ETH_TX_RING_ENTRIES; - ethptr->mtu = ETH_MTU; - ethptr->interruptMask = IRQ_TX_PKTSENT | IRQ_TX_BUSERR - | IRQ_RX_PKTRECV | IRQ_RX_OVERFLOW | IRQ_RX_BUSERR; - - ethptr->errors = 0; - ethptr->isema = semcreate(0); - ethptr->istart = 0; - ethptr->icount = 0; - ethptr->ovrrun = 0; - ethptr->rxOffset = ETH_PKT_RESERVE; - - /* Lookup canonical MAC in NVRAM, and store in ether struct */ - colon2mac(nvramGet("et0macaddr"), ethptr->devAddress); - ethptr->addressLength = ETH_ADDR_LEN; - - // Reset the device. - nicptr->macConfig1 |= MAC_CFG1_SOFTRESET; - udelay(20); - *rstptr |= rstbit; - mdelay(100); - *rstptr &= ~rstbit; - mdelay(100); - - // Enable Tx and Rx. - nicptr->macConfig1 = MAC_CFG1_TX | MAC_CFG1_SYNC_TX | - MAC_CFG1_RX | MAC_CFG1_SYNC_RX; - // Configure full duplex, auto padding CRC, and interface mode. - nicptr->macConfig2 |= - MAC_CFG2_FDX | MAC_CFG2_PAD | MAC_CFG2_LEN_CHECK | - MAC_CFG2_IMNIBBLE; - - // Enable FIFO modules. - nicptr->fifoConfig0 = FIFO_CFG0_WTMENREQ | FIFO_CFG0_SRFENREQ | - FIFO_CFG0_FRFENREQ | FIFO_CFG0_STFENREQ | FIFO_CFG0_FTFENREQ; - - // FIXME - // -> ag71xx_mii_ctrl_set_if(ag, pdata->mii_if); - // Stores a '1' in 0x18070000 (MII mode) - // Stores a '1' in 0x18070004 (RMII mode) - - // FRRD may be asserted only after the completion of the input frame. - nicptr->fifoConfig1 = 0x0FFF0000; - // Max out number of words to store in Rx RAM; - nicptr->fifoConfig2 = 0x00001FFF; - // Drop anything with errors in the Rx stats vector. - nicptr->fifoConfig4 = 0x0003FFFF; - // Drop short packets, set "don't care" on Rx stats vector bits. - nicptr->fifoConfig5 = 0x0003FFFF; - - /* NOTE: because device initialization runs early in the system, */ - /* we are assured that this stkget() call will return */ - /* page-aligned (and cache-aligned) boundaries. */ - ethptr->rxBufs = stkget(PAGE_SIZE); - ethptr->txBufs = stkget(PAGE_SIZE); - ethptr->rxRing = stkget(PAGE_SIZE); - ethptr->txRing = stkget(PAGE_SIZE); - - if ((SYSERR == (int)ethptr->rxBufs) - || (SYSERR == (int)ethptr->txBufs) - || (SYSERR == (int)ethptr->rxRing) - || (SYSERR == (int)ethptr->txRing)) - { -#ifdef DETAIL - kprintf("eth%d ring buffer allocation error.\r\n", devptr->minor); -#endif /* DETAIL */ - return SYSERR; - } - - /* bump buffer pointers/rings to KSEG1 */ - ethptr->rxBufs = - (struct ethPktBuffer - **)(((ulong)ethptr->rxBufs - PAGE_SIZE + - sizeof(int)) | KSEG1_BASE); - ethptr->txBufs = - (struct ethPktBuffer - **)(((ulong)ethptr->txBufs - PAGE_SIZE + - sizeof(int)) | KSEG1_BASE); - ethptr->rxRing = - (struct dmaDescriptor - *)(((ulong)ethptr->rxRing - PAGE_SIZE + - sizeof(int)) | KSEG1_BASE); - ethptr->txRing = - (struct dmaDescriptor - *)(((ulong)ethptr->txRing - PAGE_SIZE + - sizeof(int)) | KSEG1_BASE); - - /* Zero out the buffer pointers and rings */ - bzero(ethptr->rxBufs, PAGE_SIZE); - bzero(ethptr->txBufs, PAGE_SIZE); - bzero(ethptr->rxRing, PAGE_SIZE); - bzero(ethptr->txRing, PAGE_SIZE); - - interruptVector[devptr->irq] = devptr->intr; - enable_irq(devptr->irq); - - return OK; -} diff --git a/device/ag71xx/etherInterrupt.c b/device/ag71xx/etherInterrupt.c deleted file mode 100644 index 5f77f830..00000000 --- a/device/ag71xx/etherInterrupt.c +++ /dev/null @@ -1,185 +0,0 @@ -/** - * @file etherInterrupt.c - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#include -#include -#include -#include -#include "ag71xx.h" -#include -#include -#include -#include -#include -#include - -extern int resdefer; - -/** - * @ingroup etherspecific - * - * Receive packet interrupt handler. - */ -void rxPackets(struct ether *ethptr, struct ag71xx *nicptr) -{ - struct dmaDescriptor *dmaptr; - struct ethPktBuffer *pkt = NULL; - int head = 0; - - while (1) - { - head = ethptr->rxHead % ETH_RX_RING_ENTRIES; - dmaptr = ðptr->rxRing[head]; - if (dmaptr->control & ETH_DESC_CTRL_EMPTY) - { - nicptr->rxStatus = RX_STAT_RECVD; - break; - } - - pkt = ethptr->rxBufs[head]; - pkt->length = dmaptr->control & ETH_DESC_CTRL_LEN; - - if (ethptr->icount < ETH_IBLEN) - { - allocRxBuffer(ethptr, head); - ethptr->in[(ethptr->istart + ethptr->icount) % ETH_IBLEN] = - pkt; - ethptr->icount++; - signaln(ethptr->isema, 1); - } - else - { - ethptr->ovrrun++; - bzero(pkt->buf, pkt->length); - } - - ethptr->rxHead++; - // Clear Rx interrupt. - nicptr->rxStatus = RX_STAT_RECVD; - // FIXME - break; - } -} - -/** - * @ingroup etherspecific - * - * Transmit packet interrupt handler - */ -void txPackets(struct ether *ethptr, struct ag71xx *nicptr) -{ - struct dmaDescriptor *dmaptr; - struct ethPktBuffer **epb = NULL; - struct ethPktBuffer *pkt = NULL; - ulong head = 0; - - // kprintf("txS=0x%08X\r\n", nicptr->txStatus); - if (ethptr->txHead == ethptr->txTail) - { - nicptr->txStatus = TX_STAT_SENT; - return; - } - - while (ethptr->txHead != ethptr->txTail) - { - head = ethptr->txHead % ETH_TX_RING_ENTRIES; - dmaptr = ðptr->txRing[head]; - if (!(dmaptr->control & ETH_DESC_CTRL_EMPTY)) - { - break; - } - - epb = ðptr->txBufs[head]; - - // Clear Tx interrupt. - nicptr->txStatus = TX_STAT_SENT; - - ethptr->txHead++; - pkt = *epb; - if (NULL == pkt) - { - continue; - } - buffree((void *)((ulong)pkt & (PMEM_MASK | KSEG0_BASE))); - *epb = NULL; - } -} - -/** - * @ingroup etherspecific - * - * Decode and handle hardware interrupt request from ethernet device. - */ -interrupt etherInterrupt(void) -{ -// int ethnum; - struct ether *ethptr; - struct ag71xx *nicptr; - uint status, mask; - - /* Initialize structure pointers */ - ethptr = ðertab[0]; /* default physical ethernet for WRT54GL */ - if (!ethptr) - { - return; - } - nicptr = ethptr->csr; - if (!nicptr) - { - return; - } - - mask = nicptr->interruptMask; - status = nicptr->interruptStatus & mask; - - /* remember interrupt status in ether struct */ - ethptr->interruptStatus = status; - - if (!status) - { - return; - } - - resdefer = 1; /* defer rescheduling */ - - if (status & IRQ_TX_PKTSENT) - { - ethptr->txirq++; - txPackets(ethptr, nicptr); - } - - if (status & IRQ_RX_PKTRECV) - { - ethptr->rxirq++; - rxPackets(ethptr, nicptr); - } - - if (status & IRQ_RX_OVERFLOW) - { - // Clear interrupt, restart processing. - nicptr->rxStatus = RX_STAT_OVERFLOW; - nicptr->rxControl = RX_CTRL_RXE; - ethptr->errors++; - } - - if ((status & IRQ_TX_UNDERFLOW) || - (status & IRQ_TX_BUSERR) || (status & IRQ_RX_BUSERR)) - { - kprintf("Ethernet ERROR 0x%08X\r\n", status); - while (1) - ; - ethptr->errors++; - // etherClose(ethptr->dev); - } - - if (--resdefer > 0) - { - resdefer = 0; - resched(); - } - - return; -} diff --git a/device/ag71xx/etherOpen.c b/device/ag71xx/etherOpen.c deleted file mode 100644 index dff3672f..00000000 --- a/device/ag71xx/etherOpen.c +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @file etherOpen.c - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#include -#include -#include "ag71xx.h" -#include -#include -#include -#include -#include -#include - -/* Implementation of etherOpen() for the ag71xx; see the documentation for this - * function in ether.h. */ -devcall etherOpen(device *devptr) -{ - int i; - irqmask im; - struct ether *ethptr; - struct ag71xx *nicptr; - - /* Initialize structure pointers */ - ethptr = ðertab[devptr->minor]; - nicptr = ethptr->csr; - - im = disable(); - - // Clear the Rx Counter. - while (nicptr->rxStatus & RX_STAT_COUNT) - { - nicptr->rxStatus = RX_STAT_RECVD; - } - - /* Initialize Tx ring */ - for (i = 0; i < ETH_TX_RING_ENTRIES; i++) - { - ethptr->txRing[i].next = - (ulong)(ethptr->txRing + ((i + 1) % ETH_TX_RING_ENTRIES)) - & PMEM_MASK; - ethptr->txRing[i].control = ETH_DESC_CTRL_EMPTY; - ethptr->txBufs[i] = NULL; - } - /* Point NIC to start of Tx ring */ - nicptr->txDMA = ((ulong)ethptr->txRing) & PMEM_MASK; - - /* Allocate buffer pool for Tx DMA engine */ - ethptr->outPool = - bfpalloc(ETH_TX_BUF_SIZE + ETH_PKT_RESERVE - + sizeof(struct ethPktBuffer), ETH_TX_RING_ENTRIES); - if (SYSERR == ethptr->outPool) - { - ETH_TRACE("eth%d outPool buffer error.\r\n", devptr->minor); - restore(im); - return SYSERR; - } - - /* Allocate buffer pool for Rx DMA engine */ - ethptr->inPool = - bfpalloc(ETH_RX_BUF_SIZE + ETH_PKT_RESERVE - + sizeof(struct ethPktBuffer), - ETH_RX_RING_ENTRIES + ETH_IBLEN); - if (SYSERR == ethptr->inPool) - { - ETH_TRACE("eth%d inPool buffer error.\r\n", devptr->minor); - restore(im); - return SYSERR; - } - - /* Initialize Rx ring */ - for (i = 0; i < ETH_RX_RING_ENTRIES; i++) - { - ethptr->rxRing[i].next = - (ulong)(ethptr->rxRing + ((i + 1) % ETH_RX_RING_ENTRIES)) - & PMEM_MASK; - } - - /* Fill up Rx ring with available buffers */ - for (i = 0; i < ethptr->rxRingSize; i++) - { - allocRxBuffer(ethptr, i); - } - /* Point NIC to start of Rx ring */ - nicptr->rxDMA = ((ulong)ethptr->rxRing) & PMEM_MASK; - - // FIXME: Need to start up PHY here? - etherControl(devptr, ETH_CTRL_SET_MAC, (long)ethptr->devAddress, 0); - - /* start Rx engine */ - nicptr->rxControl = RX_CTRL_RXE; - - ethptr->state = ETH_STATE_UP; - /* enable interrupts */ - nicptr->interruptMask = ethptr->interruptMask; - - restore(im); - - return OK; -} diff --git a/device/ag71xx/etherRead.c b/device/ag71xx/etherRead.c deleted file mode 100644 index 77ccbe84..00000000 --- a/device/ag71xx/etherRead.c +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @file etherRead.c - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#include -#include -#include -#include "ag71xx.h" -#include -#include -#include -#include -#include -#include -#include - -/* Implementation of etherRead() for the ag71xx; see the documentation for this - * function in ether.h. */ -devcall etherRead(device *devptr, void *buf, uint len) -{ - irqmask im; - struct ether *ethptr; - struct ethPktBuffer *pkt; - uint length; -/* struct rxHeader *rh; */ -/* struct vlanPkt *pvlan; */ - - ethptr = ðertab[devptr->minor]; - - im = disable(); - if (ETH_STATE_UP != ethptr->state) - { - restore(im); - return SYSERR; - } - - /* make sure buffer is large enough to store packet */ - if (len < ETH_HEADER_LEN) - { - restore(im); - return SYSERR; - } - - wait(ethptr->isema); - - pkt = ethptr->in[ethptr->istart]; - ethptr->in[ethptr->istart] = NULL; - ethptr->istart = (ethptr->istart + 1) % ETH_IBLEN; - ethptr->icount--; - restore(im); - - if (NULL == pkt) - { - return 0; - } -/* rh = (struct rxHeader *)pkt->buf; */ -/* pvlan = (struct vlanPkt *)pkt->data; */ - -/* /\* slice off CRC *\/ */ -/* rh->length -= ETH_CRC_LEN; */ - -/* if (ETH_TYPE_VLAN == net2hs(pvlan->tpi)) */ -/* { */ -/* rh->length -= 4; /\* Account for vlan tag removal *\/ */ -/* } */ - -/* /\* compute size of packet *\/ */ -/* length = (rh->length < len) ? rh->length : len; */ - -/* if (ETH_TYPE_VLAN == net2hs(pvlan->tpi)) */ -/* { */ -/* /\* strip vlan tag *\/ */ -/* memcpy(buffer, pkt->data, 12); */ -/* memcpy(buffer + 12, pkt->data + 16, length - 12); */ -/* } */ -/* else */ -/* { */ - /* no vlan tagging */ - length = pkt->length; - memcpy(buf, (uchar *)(((ulong)pkt->buf) | KSEG1_BASE), length); -/* } */ - - buffree(pkt); - - return length; -} diff --git a/device/ag71xx/etherStat.c b/device/ag71xx/etherStat.c deleted file mode 100644 index 6711a4cc..00000000 --- a/device/ag71xx/etherStat.c +++ /dev/null @@ -1,225 +0,0 @@ -/** - * @file etherStat.c - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#include -#include -#include -#include "ag71xx.h" -#include -#include -#include -#include -#include - -#ifdef NETHER -void etherStat(ushort minor) -{ - struct ether *ethptr = NULL; /* pointer to ether entry */ - struct ag71xx *nicptr = NULL; /* pointer to ether device registers */ - ulong tmp; - uchar mac[6]; - - /* Initialize pointers */ - ethptr = ðertab[minor]; - nicptr = ethptr->csr; - - fprintf(stdout, "eth%d:\n", minor); - control(ethptr->dev->num, ETH_CTRL_GET_MAC, (long)mac, 0); - fprintf(stdout, - " MAC Address %02X:%02X:%02X:%02X:%02X:%02X", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - - fprintf(stdout, " %8d MTU", ethptr->mtu); - - tmp = ethptr->state; - fprintf(stdout, " Device "); - if (ETH_STATE_FREE == tmp) - { - fprintf(stdout, "FREE\n"); - } - if (ETH_STATE_UP == tmp) - { - fprintf(stdout, "UP \n"); - } - if (ETH_STATE_DOWN == tmp) - { - fprintf(stdout, "DOWN\n"); - } - - fprintf(stdout, " Errors %d\n", ethptr->errors); - - /* Ether statistics */ - tmp = ethptr->interruptStatus; - fprintf(stdout, " IRQ Status 0x%08X [", tmp); - if (tmp & IRQ_TX_PKTSENT) - { - fprintf(stdout, " TX"); - } - if (tmp & IRQ_TX_UNDERFLOW) - { - fprintf(stdout, " UF"); - } - if (tmp & IRQ_TX_BUSERR) - { - fprintf(stdout, " TE"); - } - if (tmp & IRQ_RX_PKTRECV) - { - fprintf(stdout, " RX"); - } - if (tmp & IRQ_RX_BUSERR) - { - fprintf(stdout, " RE"); - } - fprintf(stdout, " ]\n"); - - tmp = ethptr->interruptMask; - fprintf(stdout, " IRQ Mask 0x%08X [", tmp); - if (tmp & IRQ_TX_PKTSENT) - { - fprintf(stdout, " TX"); - } - if (tmp & IRQ_TX_UNDERFLOW) - { - fprintf(stdout, " UF"); - } - if (tmp & IRQ_TX_BUSERR) - { - fprintf(stdout, " TE"); - } - if (tmp & IRQ_RX_PKTRECV) - { - fprintf(stdout, " RX"); - } - if (tmp & IRQ_RX_BUSERR) - { - fprintf(stdout, " RE"); - } - fprintf(stdout, " ]\n"); - - tmp = nicptr->macConfig1; - fprintf(stdout, " MAC Config 1 0x%08X [", tmp); - if (tmp & MAC_CFG1_TX) - { - fprintf(stdout, " TX"); - } - if (tmp & MAC_CFG1_SYNC_TX) - { - fprintf(stdout, " ST"); - } - if (tmp & MAC_CFG1_RX) - { - fprintf(stdout, " RX"); - } - if (tmp & MAC_CFG1_SYNC_RX) - { - fprintf(stdout, " SR"); - } - if (tmp & MAC_CFG1_LOOPBACK) - { - fprintf(stdout, " LB"); - } - if (tmp & MAC_CFG1_SOFTRESET) - { - fprintf(stdout, " RS"); - } - fprintf(stdout, " ]\n"); - - tmp = nicptr->macConfig2; - fprintf(stdout, " MAC Config 2 0x%08X [", tmp); - if (tmp & MAC_CFG2_FDX) - { - fprintf(stdout, " FDX"); - } - if (tmp & MAC_CFG2_CRC) - { - fprintf(stdout, " CRC"); - } - if (tmp & MAC_CFG2_PAD) - { - fprintf(stdout, " PAD"); - } - if (tmp & MAC_CFG2_LEN_CHECK) - { - fprintf(stdout, " LEN"); - } - fprintf(stdout, " ]\n"); - - fprintf(stdout, " FIFO Config0 0x%08X", nicptr->fifoConfig0); - fprintf(stdout, " FIFO Config1 0x%08X", nicptr->fifoConfig1); - fprintf(stdout, " FIFO Config2 0x%08X\n", nicptr->fifoConfig2); - fprintf(stdout, " FIFO Config3 0x%08X", nicptr->fifoConfig3); - fprintf(stdout, " FIFO Config4 0x%08X", nicptr->fifoConfig4); - fprintf(stdout, " FIFO Config5 0x%08X\n", nicptr->fifoConfig5); - fprintf(stdout, "\n"); - - fprintf(stdout, " Tx Ring 0x%08X", ethptr->txRing); - fprintf(stdout, " Tx Bufs 0x%08X", ethptr->txBufs); - fprintf(stdout, " Tx Ring Size %8d\n", ethptr->txRingSize); - fprintf(stdout, " Tx IRQ Count %8d", ethptr->txirq); - fprintf(stdout, " Tx Head %8d", ethptr->txHead); - fprintf(stdout, " Tx Tail %8d\n", ethptr->txTail); - fprintf(stdout, " Tx Control 0x%08X", nicptr->txControl); - fprintf(stdout, " Tx DMA 0x%08X", nicptr->txDMA); - fprintf(stdout, " Tx Status 0x%08X\n", nicptr->txStatus); - fprintf(stdout, "\n"); - fprintf(stdout, " Rx Ring 0x%08X", ethptr->rxRing); - fprintf(stdout, " Rx Bufs 0x%08X", ethptr->rxBufs); - fprintf(stdout, " Rx Ring Size %8d\n", ethptr->rxRingSize); - fprintf(stdout, " Rx IRQ Count %8d", ethptr->rxirq); - fprintf(stdout, " Rx Head %8d", ethptr->rxHead); - fprintf(stdout, " Rx Errors %8d\n", ethptr->rxErrors); - fprintf(stdout, " Rx Control 0x%08X", nicptr->rxControl); - fprintf(stdout, " Rx DMA 0x%08X", nicptr->rxDMA); - fprintf(stdout, " Rx Status 0x%08X\n", nicptr->rxStatus); - - fprintf(stdout, "\n"); -} - -/** - * @ingroup etherspecific - */ -void ethStat2(void) -{ - struct ether *ethptr = NULL; /* pointer to ether entry */ - int i = 0; - - /* Initialize pointers */ - ethptr = ðertab[0]; - - kprintf("ethStat2()\r\n"); - struct dmaDescriptor *dmaptr; - for (i = 0; i < ETH_RX_RING_ENTRIES; i++) - { - dmaptr = ðptr->rxRing[i]; - if (0 == dmaptr->control) - { - kprintf("[%08X]Rx Addr 0x%08X", (ulong)dmaptr, - dmaptr->address); - kprintf(" Rx Cntl 0x%08X", dmaptr->control); - kprintf(" Rx Next 0x%08X\r\n", dmaptr->next); - } - } -} - -void etherThroughput(ushort minor) -{ - struct ether *ethptr = NULL; /* pointer to ether entry */ - struct ag71xx *nicptr = NULL; /* pointer to ether device registers */ - - /* Initialize pointers */ - ethptr = ðertab[minor]; - nicptr = ethptr->csr; - - if (ethptr->dev != ethptr->phy) - { - return; - } - - printf("Throughput monitoring not implemented for AG71xx Ethernet\n"); -} - -#endif diff --git a/device/ag71xx/etherWrite.c b/device/ag71xx/etherWrite.c deleted file mode 100644 index 796726e1..00000000 --- a/device/ag71xx/etherWrite.c +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @file etherWrite.c - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#include -#include -#include -#include -#include "ag71xx.h" -#include -#include -#include -#include -#include - -/* Implementation of etherWrite() for the ag71xx; see the documentation for this - * function in ether.h. */ -devcall etherWrite(device *devptr, const void *buf, uint len) -{ - struct ether *ethptr = NULL; - struct ag71xx *nicptr = NULL; - struct ethPktBuffer *pkt = NULL; - struct dmaDescriptor *dmaptr = NULL; - irqmask im; - ulong tail = 0; - const uchar *buffer = buf; -/* ulong *flushControl = (ulong *)0xB800007C; */ - - ethptr = ðertab[devptr->minor]; - nicptr = ethptr->csr; - - im = disable(); - if ((ETH_STATE_UP != ethptr->state) - || (len < ETH_HEADER_LEN) - || (len > (ETH_TX_BUF_SIZE - ETH_VLAN_LEN))) - { - restore(im); - return SYSERR; - } - - tail = ethptr->txTail % ETH_TX_RING_ENTRIES; - dmaptr = ðptr->txRing[tail]; - - if (!(dmaptr->control & ETH_DESC_CTRL_EMPTY)) - { - ETH_TRACE("dmaptr 0x%08X not empty.\r\n", dmaptr); - ethptr->errors++; - restore(im); - return SYSERR; - } - - pkt = (struct ethPktBuffer *)bufget(ethptr->outPool); - if (SYSERR == (ulong)pkt) - { - ETH_TRACE("etherWrite() couldn't get a buffer!\r\n"); - ethptr->errors++; - restore(im); - return SYSERR; - } - - /* Translate pkt pointer into uncached memory space */ - pkt = (struct ethPktBuffer *)((int)pkt | KSEG1_BASE); - pkt->buf = (uchar *)(pkt + 1); - pkt->data = pkt->buf; - memcpy(pkt->data, buffer, len); - - /* Place filled buffer in outgoing queue */ - ethptr->txBufs[tail] = pkt; - - /* Add this buffer to the Tx ring. */ - /* Address on ring should be physical (USEG) for DMA engine */ - ethptr->txRing[tail].address = (ulong)pkt->data & PMEM_MASK; - /* Clear empty flag and write the length */ - ethptr->txRing[tail].control = len & ETH_DESC_CTRL_LEN; - - ethptr->txTail++; - - if (nicptr->txStatus & TX_STAT_UNDER) - { - nicptr->txDMA = ((ulong)(ethptr->txRing + tail)) & PMEM_MASK; - nicptr->txStatus = TX_STAT_UNDER; - } - nicptr->txControl = TX_CTRL_ENABLE; - restore(im); - - return len; -} diff --git a/device/ag71xx/vlanStat.c b/device/ag71xx/vlanStat.c deleted file mode 100644 index a9a85e79..00000000 --- a/device/ag71xx/vlanStat.c +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @file vlanStat.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include "ag71xx.h" -#include -#include - -int vlanStat(void) -{ - fprintf(stderr, "Switch Core not found!\n"); - return SYSERR; -} diff --git a/device/ag71xx/waitOnBit.c b/device/ag71xx/waitOnBit.c deleted file mode 100644 index c696329a..00000000 --- a/device/ag71xx/waitOnBit.c +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @file waitOnBit.c - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#include - -/** - * @ingroup etherspecific - * - * Wait on a bit in a device's control and status register. - * @param reg pointer to device status register - * @param mask bit to wait on - * @param value bit value desired - * @param tries number of retries before giving up - * @return OK or SYSERR - */ -int waitOnBit(volatile uint *reg, uint mask, const int value, int tries) -{ - int i = 0; - volatile int j = 0; - - for (i = 0; i < tries; i++) - { - /* break on the following conditions: - * - if expected value is non-zero, check if the register & mask has - * a non-zero value - * - if expected value is zero, check if the register & mask has - * a zero value - */ - if (((0 != value) && (*reg & mask)) - || ((0 == value) && !(*reg & mask))) - { - break; - } - - for (j = 100; j; j--) - { /* spin wait */ - } - } - - if (tries == i) - { -#ifdef DETAIL - kprintf("etherInit() TIMEOUT waiting for register "); - kprintf("0x%08X bit 0x%08X to %s\r\n", reg, - mask, (value ? "set" : "clear")); -#endif /* DETAIL */ - return SYSERR; - } - - return OK; -} diff --git a/device/bcm4713/Doxygroup.c b/device/bcm4713/Doxygroup.c deleted file mode 100644 index 4a9ed475..00000000 --- a/device/bcm4713/Doxygroup.c +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @defgroup etherdriver Ethernet - * @ingroup devices - * @brief Ethernet driver for bcm4713 devices - * - * @defgroup ether Ethernet Standard Functions - * @ingroup etherdriver - * - * @defgroup etherspecific Ethernet Device-Specific Functions - * @ingroup etherdriver - */ diff --git a/device/bcm4713/Makerules b/device/bcm4713/Makerules deleted file mode 100644 index a00b59ed..00000000 --- a/device/bcm4713/Makerules +++ /dev/null @@ -1,12 +0,0 @@ -# This Makefile contains rules to build this directory. - -# Name of this component (the directory this file is stored in) -COMP = device/bcm4713 - -# Source files for this component -C_FILES = etherInit.c etherOpen.c etherClose.c etherRead.c etherWrite.c etherControl.c etherInterrupt.c etherStat.c colon2mac.c allocRxBuffer.c waitOnBit.c switchInit.c vlanInit.c vlanOpen.c vlanClose.c vlanStat.c -S_FILES = - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/device/bcm4713/allocRxBuffer.c b/device/bcm4713/allocRxBuffer.c deleted file mode 100644 index 246aed80..00000000 --- a/device/bcm4713/allocRxBuffer.c +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @file allocRxBuffer.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include "bcm4713.h" -#include -#include -#include - -/** - * @ingroup etherspecific - * - * Allocate an ethernet packet buffer structure - * @param ethptr ethernet table entry - * @param destIndex destination index in ethernet reciever ring - * @return bytes allocated - */ -int allocRxBuffer(struct ether *ethptr, int destIndex) -{ - struct ethPktBuffer *pkt = NULL; - struct dmaDescriptor *dmaptr = NULL; - - destIndex %= ethptr->rxRingSize; - pkt = bufget(ethptr->inPool); - if (SYSERR == (ulong)pkt) - { -#ifdef DETAIL - kprintf("eth0 allocRxBuffer() error\r\n"); -#endif /* DETAIL */ - return SYSERR; - } - pkt->length = ETH_RX_BUF_SIZE; - pkt->buf = (uchar *)(pkt + 1); - - /* Data region offset by size of rx header. */ - pkt->data = pkt->buf + ethptr->rxOffset; - - ethptr->rxBufs[destIndex] = pkt; - - /* Fill in DMA descriptor fields */ - dmaptr = ethptr->rxRing + destIndex; - dmaptr->control = ETH_DESC_CTRL_LEN & pkt->length; - if ((ethptr->rxRingSize - 1) == destIndex) - { - dmaptr->control |= ETH_DESC_CTRL_EOT; - } - dmaptr->address = (ulong)(pkt->buf) & PMEM_MASK; - -#ifdef DETAIL - kprintf("eth0 rxBufs[%d] = 0x%08X\r\n", - destIndex, ethptr->rxBufs[destIndex]); - - kprintf - (" control 0x%08X address 0x%08X buffer 0x%08X\r\n", - dmaptr->control, dmaptr->address, pkt); - - if (pkt) - { - kprintf - (" epb buf 0x%08X epb dat 0x%08X epb len %8d\r\n", - pkt->buf, pkt->data, pkt->length); - struct rxHeader *rh; - - rh = (struct rxHeader *)pkt->buf; - kprintf - (" rxHead 0x%08X length 0x%08X flags 0x%08X\r\n", - rh, rh ? rh->length : 0, rh ? rh->flags : 0); - } -#endif /* DETAIL */ - - return OK; -} diff --git a/device/bcm4713/bcm4713.h b/device/bcm4713/bcm4713.h deleted file mode 100644 index b4a01063..00000000 --- a/device/bcm4713/bcm4713.h +++ /dev/null @@ -1,274 +0,0 @@ -/** - * @file bcm4713.h - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#ifndef _BCM4713_H_ -#define _BCM4713_H_ - -#include -#include - -#include - -/* Ring buffer sizes */ -#define ETH_RX_RING_ENTRIES 511 /**< Number of buffers on Rx Ring */ -#define ETH_TX_RING_ENTRIES 511 /**< Number of buffers on Tx Ring */ - -/** - * Control and Status register layout for the Broadcom 4713 Ethernet - * device. - */ -struct bcm4713 -{ - volatile uint devControl; /**< 0x000 Device control */ -#define DEVCTRL_PFE 0x00000080 /* Pattern Filtering Enable */ -#define DEVCTRL_IPP 0x00000400 /* Internal EPHY Present */ -#define DEVCTRL_EPR 0x00008000 /* EPHY Reset */ -#define DEVCTRL_PME 0x00001000 /* PHY Mode Enable */ -#define DEVCTRL_PMCE 0x00002000 /* PHY Mode Clocks Enable */ -#define DEVCTRL_PADDR 0x0007c000 /* PHY Address */ - - volatile uint pad0[7]; - - volatile uint interruptStatus; /**< 0x020 Interrupt Status */ -#define ISTAT_PME 0x00000040 /* Power Management Event */ -#define ISTAT_TO 0x00000080 /* General Purpose Timeout */ -#define ISTAT_DSCE 0x00000400 /* Descriptor Error */ -#define ISTAT_DATAE 0x00000800 /* Data Error */ -#define ISTAT_DPE 0x00001000 /* Descr. Protocol Error */ -#define ISTAT_RDU 0x00002000 /* Receive Descr. Underflow */ -#define ISTAT_RFO 0x00004000 /* Receive FIFO Overflow */ -#define ISTAT_TFU 0x00008000 /* Transmit FIFO Underflow */ -#define ISTAT_RX 0x00010000 /* RX Interrupt */ -#define ISTAT_TX 0x01000000 /* TX Interrupt */ -#define ISTAT_EMAC 0x04000000 /* EMAC Interrupt */ -#define ISTAT_MII_WRITE 0x08000000 /* MII Write Interrupt */ -#define ISTAT_MII_READ 0x10000000 /* MII Read Interrupt */ -#define ISTAT_ERRORS (ISTAT_DSCE | ISTAT_DATAE | ISTAT_DPE | ISTAT_RDU \ - | ISTAT_RFO | ISTAT_TFU) - - volatile uint interruptMask; /**< Interrupt Mask */ -#define IMASK_DEF (ISTAT_ERRORS | ISTAT_RX | ISTAT_TO | ISTAT_TX) - - volatile uint gpTimer; /**< General Purpose Timer */ - volatile uint pad1[31]; - - volatile uint macControl; /**< 0x0A8 MAC Control */ -#define MAC_CTRL_CRC32_ENAB 0x0000001 /* CRC32 Generation Enable */ -#define MAC_CTRL_PHY_PDOWN 0x00000004 /* Onchip EPHY Powerdown */ -#define MAC_CTRL_PHY_EDET 0x00000008 /* Onchip EPHY Energy Detected */ -#define MAC_CTRL_PHY_LEDCTRL 0x0000e0 /* Onchip EPHY LED Control */ - - volatile uint pad2[21]; - - volatile uint rcvLazy; /**< 0x100 Lazy Interrupt Control */ -#define RCV_LAZY_TO_MASK 0x00ffffff /* Timeout */ -#define RCV_LAZY_FC_MASK 0xff000000 /* Frame Count */ -#define RCV_LAZY_FC_SHIFT 24 - - volatile uint pad3[63]; - - /* Direct Memory Access (DMA) features 0x200 - 0x2FF */ - volatile uint dmaTxControl; /**< DMA Tx Control Register */ -#define DMATX_CTRL_ENABLE 0x00000001 /* Enable */ -#define DMATX_CTRL_SUSPEND 0x00000002 /* Suspend Request */ -#define DMATX_CTRL_LPBACK 0x00000004 /* Loopback Enable */ -#define DMATX_CTRL_FAIRPRIO 0x00000008 /* Fair Priority */ -#define DMATX_CTRL_FLUSH 0x00000010 /* Flush Request */ - - volatile uint dmaTxAddress; /**< DMA Tx Descriptor Ring */ - volatile uint dmaTxLast; /**< DMA Tx Last Posted Desc */ - volatile uint dmaTxStatus; /**< DMA Tx Current & Status */ -#define DMATX_STAT_CDMASK 0x00000fff /* Current Descriptor Mask */ -#define DMATX_STAT_SMASK 0x0000f000 /* State Mask */ -#define DMATX_STAT_SDISABLED 0x00000000 /* State Disabled */ -#define DMATX_STAT_SACTIVE 0x00001000 /* State Active */ -#define DMATX_STAT_SIDLE 0x00002000 /* State Idle Wait */ -#define DMATX_STAT_SSTOPPED 0x00003000 /* State Stopped */ -#define DMATX_STAT_SSUSP 0x00004000 /* State Suspend Pending */ -#define DMATX_STAT_EMASK 0x000f0000 /* Error Mask */ -#define DMATX_STAT_ENONE 0x00000000 /* Error None */ -#define DMATX_STAT_EDPE 0x00010000 /* Error Desc. Protocol Error */ -#define DMATX_STAT_EDFU 0x00020000 /* Error Data FIFO Underrun */ -#define DMATX_STAT_EBEBR 0x00030000 /* Bus Error on Buffer Read */ -#define DMATX_STAT_EBEDA 0x00040000 /* Bus Error on Desc Access */ -#define DMATX_STAT_FLUSHED 0x00100000 /* Flushed */ - - volatile uint dmaRxControl; /**< DMA Rx Control Register */ -#define DMARX_CTRL_ENABLE 0x00000001 /* Enable */ -#define DMARX_CTRL_ROMASK 0x000000fe /* Receive Offset Mask */ -#define DMARX_CTRL_ROSHIFT 1 /* Receive Offset Shift */ - - volatile uint dmaRxAddress; /**< DMA Rx Descriptor Ring */ - volatile uint dmaRxLast; /**< DMA Rx Last Posted Desc */ - - volatile uint dmaRxStatus; /**< DMA Rx Current & Status */ -#define DMARX_STAT_CDMASK 0x00000fff /* Current Descriptor Mask */ -#define DMARX_STAT_SMASK 0x0000f000 /* State Mask */ -#define DMARX_STAT_SDISABLED 0x00000000 /* State Disabled */ -#define DMARX_STAT_SACTIVE 0x00001000 /* State Active */ -#define DMARX_STAT_SIDLE 0x00002000 /* State Idle Wait */ -#define DMARX_STAT_SSTOPPED 0x00003000 /* State Stopped */ -#define DMARX_STAT_EMASK 0x000f0000 /* Error Mask */ -#define DMARX_STAT_ENONE 0x00000000 /* Error None */ -#define DMARX_STAT_EDPE 0x00010000 /* Error Desc. Protocol Error */ -#define DMARX_STAT_EDFO 0x00020000 /* Error Data FIFO Overflow */ -#define DMARX_STAT_EBEBW 0x00030000 /* Bus Error - Buffer Write */ -#define DMARX_STAT_EBEDA 0x00040000 /* Bus Error - Desc. Access */ - - volatile uint pad4[56]; - - /* Don't know what's in blocks 0x300 - 0x3FF */ - volatile uint pad5[64]; - - /* EMAC features in block 0x400 - 0x4FF */ - volatile uint rxConfig; /**< 0x400 EMAC Rx config */ -#define RXCONFIG_NONE 0x00000000 /* No Receive configuration */ -#define RXCONFIG_DBCAST 0x00000001 /* Disable Broadcast */ -#define RXCONFIG_ALLMULTI 0x00000002 /* Accept All Multicast */ -#define RXCONFIG_NORX_W_TX 0x00000004 /* Receive Disable While Tx */ -#define RXCONFIG_PROMISC 0x00000008 /* Promiscuous Enable */ -#define RXCONFIG_LPBACK 0x00000010 /* Loopback Enable */ -#define RXCONFIG_FLOW 0x00000020 /* Flow Control Enable */ -#define RXCONFIG_FLOW_ACCEPT 0x00000040 /* Accept Unicast Flow Control */ -#define RXCONFIG_RFILT 0x00000080 /* Reject Filter */ - - volatile uint rxMaxLength; /**< EMAC Rx Max Packet Length */ - volatile uint txMaxLength; /**< EMAC Tx Max Packet Length */ - volatile uint pad6; - volatile uint mdioControl; /**< EMAC MDIO Control */ -#define MDIO_CTRL_FREQ 0x0d /* MDC Frequency */ -#define MDIO_CTRL_FREQ_MSK 0x0000007f /* MDC Frequency Mask */ -#define MDIO_CTRL_PREAMBLE 0x00000080 /* MII Preamble Enable */ - volatile uint mdioData; - volatile uint emacIntmask; - volatile uint emacIntstatus; - volatile uint camDataLo; /**< EMAC CAM Data Low */ - volatile uint camDataHi; /**< EMAC CAM Data High */ -#define CAM_DATA_HI_VALID 0x00010000 /* Valid Bit */ - - volatile uint camControl; /**< EMAC CAM Control */ -#define CAM_CTRL_ENABLE 0x00000001 /* CAM Enable */ -#define CAM_CTRL_MSEL 0x00000002 /* Mask Select */ -#define CAM_CTRL_READ 0x00000004 /* Read */ -#define CAM_CTRL_WRITE 0x00000008 /* Read */ -#define CAM_CTRL_INDEX_MASK 0x03f0000 /* Index Mask */ -#define CAM_CTRL_INDEX_SHIFT 16 -#define CAM_CTRL_BUSY 0x80000000 /* CAM Busy */ - - volatile uint enetControl; /**< EMAC ENET Control */ -#define ENET_CTRL_ENABLE 0x00000001 /* EMAC Enable */ -#define ENET_CTRL_DISABLE 0x00000002 /* EMAC Disable */ -#define ENET_CTRL_SRST 0x00000004 /* EMAC Soft Reset */ -#define ENET_CTRL_EPSEL 0x00000008 /* External PHY Select */ - - volatile uint pad7; - volatile uint txWatermark; /**< EMAC Tx Watermark */ -#define TX_WATERMARK 48 /* Sane value for watermark */ - volatile uint mibControl; /**< EMAC MIB Control */ -#define MIB_CTRL_CLR_ON_READ 0x000001 /* Autoclear on Read */ - - volatile uint pad8[49]; - - /* MIB statistics in block 0x500 - 0x5FF */ - volatile uint txGoodOctets; /**< MIB Tx Good Octets */ - volatile uint txGoodPackets; /**< MIB Tx Good Packets */ - volatile uint txOctets; /**< MIB Tx Octets */ - volatile uint txPackets; /**< MIB Tx Packets */ - volatile uint txBroadcast; /**< MIB Tx Broadcast Packets */ - volatile uint txMulticast; /**< MIB Tx Multicast Packets */ - volatile uint tx_64; /**< MIB Tx <= 64 byte Packets */ - volatile uint tx_65_127; /**< MIB Tx 65 to 127 bytes */ - volatile uint tx_128_255; /**< MIB Tx 128 to 255 bytes */ - volatile uint tx_256_511; /**< MIB Tx 256 to 511 bytes */ - volatile uint tx_512_1023; /**< MIB Tx 512 to 1023 bytes */ - volatile uint tx_1024_max; /**< MIB Tx 1024 to max bytes */ - volatile uint txJabber; /**< MIB Tx Jabber Packets */ - volatile uint txOversize; /**< MIB Tx Oversize Packets */ - volatile uint txFragment; /**< MIB Tx Fragment Packets */ - volatile uint txUnderruns; /**< MIB Tx Underruns */ - volatile uint txCollisions; /**< MIB Tx Total Collisions */ - volatile uint txCollSingle; /**< MIB Tx Single Collisions */ - volatile uint txCollMultiple; /**< MIB Tx Multiple Collision */ - volatile uint txCollExcess; /**< MIB Tx Excessive Collision */ - volatile uint txCollLate; /**< MIB Tx Late Collisions */ - volatile uint txDeferred; /**< MIB Tx Deferred Packets */ - volatile uint txLostCarrier; /**< MIB Tx Carrier Lost */ - volatile uint txPause; /**< MIB Tx Pause Packets */ - volatile uint pad9[8]; - volatile uint rxGoodOctets; /**< MIB Rx Good Octets */ - volatile uint rxGoodPackets; /**< MIB Rx Good Packets */ - volatile uint rxOctets; /**< MIB Rx Octets */ - volatile uint rxPackets; /**< MIB Rx Packets */ - volatile uint rxBroadcast; /**< MIB Rx Broadcast Packets */ - volatile uint rxMulticast; /**< MIB Rx Multicast Packets */ - volatile uint rx_64; /**< MIB Rx <= 64 byte Packets */ - volatile uint rx_65_127; /**< MIB Rx 65 to 127 bytes */ - volatile uint rx_128_255; /**< MIB Rx 128 to 255 bytes */ - volatile uint rx_256_511; /**< MIB Rx 256 to 511 bytes */ - volatile uint rx_512_1023; /**< MIB Rx 512 to 1023 bytes */ - volatile uint rx_1024_max; /**< MIB Rx 1024 to max bytes */ - volatile uint rxJabber; /**< MIB Rx Jabber Packets */ - volatile uint rxOversize; /**< MIB Rx Oversize Packets */ - volatile uint rxFragment; /**< MIB Rx Fragment Packets */ - volatile uint rxMissed; /**< MIB Rx Missed Packets */ - volatile uint rxCrcAlign; /**< MIB Rx CRC Align Errors */ - volatile uint rxUndersize; /**< MIB Rx Undersize Packets */ - volatile uint rxCrc; /**< MIB Rx CRC Errors */ - volatile uint rxAlign; /**< MIB Rx Align Errors */ - volatile uint rxSymbol; /**< MIB Rx Symbol Errors */ - volatile uint rxPause; /**< MIB Rx Pause Packets */ - volatile uint rxNonPause; /**< MIB Rx Non-Pause Packets */ - volatile uint pad10[9]; - - /* Don't know what's in blocks 0x600 - 0xEFF */ - volatile uchar pad11[256 * 9]; - - /* Silicon Backplane configuration space in 0xF00 - 0xFFF */ - volatile struct backplaneConfig bpConfig; /**< configuration space */ -}; - -/* Reciever Header struct and constants */ -#define ETH_RX_FLAG_OFIFO 0x0001 /**< FIFO Overflow */ -#define ETH_RX_FLAG_CRCERR 0x0002 /**< CRC Error */ -#define ETH_RX_FLAG_SERR 0x0004 /**< Receive Symbol Error */ -#define ETH_RX_FLAG_ODD 0x0008 /**< Frame has odd number nibbles */ -#define ETH_RX_FLAG_LARGE 0x0010 /**< Frame is > RX MAX Length */ -#define ETH_RX_FLAG_MCAST 0x0020 /**< Dest is Multicast Address */ -#define ETH_RX_FLAG_BCAST 0x0040 /**< Dest is Broadcast Address */ -#define ETH_RX_FLAG_MISS 0x0080 /**< Received due to promisc mode */ -#define ETH_RX_FLAG_LAST 0x0800 /**< Last buffer in frame */ -#define ETH_RX_FLAG_ERRORS ( ETH_RX_FLAG_ODD | ETH_RX_FLAG_SERR | \ - ETH_RX_FLAG_CRCERR | ETH_RX_FLAG_OFIFO ) - -/** - * Header on a received packet. - */ -struct rxHeader -{ - ushort length; /**< Length of packet data */ - ushort flags; /**< Receive flags */ - ushort pad[12]; /**< Padding */ -}; - -/* Ethernet DMA descriptor */ -#define ETH_DESC_CTRL_LEN 0x00001fff /**< Mask for length field */ -#define ETH_DESC_CTRL_CMASK 0x0ff00000 /**< Core specific bits */ -#define ETH_DESC_CTRL_EOT 0x10000000 /**< End of Table */ -#define ETH_DESC_CTRL_IOC 0x20000000 /**< Interrupt On Completion */ -#define ETH_DESC_CTRL_EOF 0x40000000 /**< End of Frame */ -#define ETH_DESC_CTRL_SOF 0x80000000 /**< Start of Frame */ - -/** - * Descriptor for the DMA engine to determine where to find a packet - * buffer. - */ -struct dmaDescriptor -{ - ulong control; /**< DMA control bits */ - ulong address; /**< Stored as physical address */ -}; - -#endif /* _BCM4713_H_ */ diff --git a/device/bcm4713/bcmswitch.h b/device/bcm4713/bcmswitch.h deleted file mode 100644 index cc0f84ce..00000000 --- a/device/bcm4713/bcmswitch.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * @file bcmswitch.h - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#define SWT_PORTS 6 -#define SWT_CPUPORT (SWT_PORTS - 1) - -struct mdioregs -{ - ulong mdioControl; /**< 0x410 EMAC MDIO Control */ - ulong mdioData; - ulong emacIntmask; - ulong emacIntstatus; -}; - -struct swtstate -{ - struct mdioregs *mdio; - uchar page; -}; - -extern struct swtstate swtregs; - -#define SWT_CONTROL_ENABLE 0x0001 - -#define SWT_ADDRESS_MASK 0xFFFF -#define SWT_ADDRESS_SHIFT 0 -#define SWT_ADDRESS_REG 0x00FF -#define SWT_ADDRESS_PAGE 0xFF00 -#define SWT_ADDRESS_PSHIFT 8 - -#define SWT_SIZE_MASK 0xFF -#define SWT_SIZE_SHIFT 16 -#define SWT_SIZE_8BIT 0x01 -#define SWT_SIZE_16BIT 0x03 -#define SWT_SIZE_32BIT 0x0F -#define SWT_SIZE_64BIT 0x3F - -#define SWT_COMMAND_MASK 0xFF -#define SWT_COMMAND_SHIFT 24 -#define SWT_COMMAND_WRITE 0x01 -#define SWT_COMMAND_READ 0x02 -#define SWT_COMMAND_BUSY 0xC0 - -/* Switch control space pages and registers */ -#define SWT_PAGE_VLAN 0x34 -#define SWT_REG_VLAN_CONTROL0 0x00 -#define SWT_REG_VLAN_CONTROL1 0x01 -#define SWT_REG_VLAN_CONTROL2 0x02 -#define SWT_REG_VLAN_CONTROL3 0x03 -#define SWT_REG_VLAN_CONTROL4 0x04 -#define SWT_REG_VLAN_CONTROL5 0x05 -#define SWT_REG_VLAN_TABACC 0x06 -#define SWT_REG_VLAN_WRITE 0x08 -#define SWT_REG_VLAN_READ 0x0C -#define SWT_REG_VLAN_TAGPORT0 0x10 -#define SWT_REG_VLAN_TAGPORT1 0x12 -#define SWT_REG_VLAN_TAGPORT2 0x14 -#define SWT_REG_VLAN_TAGPORT3 0x16 -#define SWT_REG_VLAN_TAGPORT4 0x18 -#define SWT_REG_VLAN_TAGMII 0x1A - -#define SWT_VLAN_TABACC_WRITE (1 << 12) -#define SWT_VLAN_TABACC_ENABLE (1 << 13) - -#define SWT_VLAN_WRITE_VALID (1 << 20) - -#define SWT_VLAN_GROUPMASK 0x003F -#define SWT_VLAN_UNTAGMASK 0x0FC0 - -#define SWT_VLAN_TABLEMAX 16 - -int switchInit(struct bcm4713 *); -int switchWriteReg(struct mdioregs *, uchar, uchar, void *); -int switchReadReg(struct mdioregs *, uchar, uchar, void *); diff --git a/device/bcm4713/colon2mac.c b/device/bcm4713/colon2mac.c deleted file mode 100644 index 87d1cd8c..00000000 --- a/device/bcm4713/colon2mac.c +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @file colon2mac.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include - -#include - -/** - * @ingroup ether - * - * Convert a colon-separated string representation of a MAC into - * the equivalent byte array. - * @param src pointer to colon-separated MAC string - * @param dst pointer to byte array - * @return number of octets converted. - */ -int colon2mac(char *src, uchar *dst) -{ - uchar count = 0, digit = 0, c = 0; - - if (NULL == src || NULL == dst) - { - return SYSERR; - } - - while ((count < ETH_ADDR_LEN) && ('\0' != *src)) - { - c = *src++; - if (isdigit(c)) - { - digit = c - '0'; - } - else if (isxdigit(c)) - { - digit = 10 + c - (isupper(c) ? 'A' : 'a'); - } - else - { - digit = 0; - } - dst[count] = digit * 16; - - c = *src++; - if (isdigit(c)) - { - digit = c - '0'; - } - else if (isxdigit(c)) - { - digit = 10 + c - (isupper(c) ? 'A' : 'a'); - } - else - { - digit = 0; - } - dst[count] += digit; - - count++; - if (':' != *src++) - { - break; - } - } - - return count; -} diff --git a/device/bcm4713/etherClose.c b/device/bcm4713/etherClose.c deleted file mode 100644 index de66c659..00000000 --- a/device/bcm4713/etherClose.c +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @file etherClose.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include "bcm4713.h" -#include -#include -#include -#include -#include - -/* Implementation of etherClose() for the bcm4713; see the documentation for - * this function in ether.h. */ -devcall etherClose(device *devptr) -{ - irqmask im; - struct ether *ethptr = NULL; - struct bcm4713 *nicptr = NULL; - - ethptr = ðertab[devptr->minor]; - nicptr = ethptr->csr; - - /* flag interface as down */ - ethptr->state = ETH_STATE_DOWN; - - im = disable(); - - /* disable ether interrupt source */ - nicptr->interruptMask = ethptr->interruptMask = 0x0; - nicptr->interruptStatus = 0x0; - - restore(im); - - etherControl(devptr, ETH_CTRL_RESET, 0, 0); - - bfpfree(ethptr->inPool); - bfpfree(ethptr->outPool); - - return OK; -} diff --git a/device/bcm4713/etherControl.c b/device/bcm4713/etherControl.c deleted file mode 100644 index 2b506d43..00000000 --- a/device/bcm4713/etherControl.c +++ /dev/null @@ -1,187 +0,0 @@ -/** - * @file etherControl.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include "bcm4713.h" -#include -#include -#include -#include - -/* Implementation of etherControl() for the bcm4713; see the documentation for - * this function in ether.h. */ -devcall etherControl(device *devptr, int func, long arg1, long arg2) -{ - struct ether *ethptr; - struct bcm4713 *nicptr; - volatile uint *regptr; - uchar *macptr; - ulong temp = 0; - struct netaddr *addr; - - ethptr = ðertab[devptr->minor]; - if (NULL == ethptr->csr) - { - return SYSERR; - } - nicptr = ethptr->csr; - - switch (func) - { -/* Clear stats counters on ethernet device. */ - case ETH_CTRL_CLEAR_STATS: - nicptr->mibControl = MIB_CTRL_CLR_ON_READ; - - regptr = &nicptr->txGoodOctets; - while (regptr <= &nicptr->txPause) - { - temp = *regptr++; - } - - regptr = &nicptr->rxGoodOctets; - while (regptr <= &nicptr->rxNonPause) - { - temp = *regptr++; - } - - temp = nicptr->mibControl & ~MIB_CTRL_CLR_ON_READ; - nicptr->mibControl = temp; - break; - -/* Get link header length. */ - case NET_GET_LINKHDRLEN: - return ETH_HDR_LEN; - -/* Program MAC address into card. */ - case ETH_CTRL_SET_MAC: - macptr = (uchar *)arg1; - /* b44 cam write */ - nicptr->camControl = 0; - temp = ((uint)macptr[2]) << 24; - temp |= ((uint)macptr[3]) << 16; - temp |= ((uint)macptr[4]) << 8; - temp |= ((uint)macptr[5]) << 0; - nicptr->camDataLo = temp; - - temp = (CAM_DATA_HI_VALID - | (((uint)macptr[0]) << 8) | (((uint)macptr[1]) << 0)); - nicptr->camDataHi = temp; - nicptr->camControl = - (devptr->minor << CAM_CTRL_INDEX_SHIFT) | CAM_CTRL_WRITE; - - waitOnBit(&nicptr->camControl, CAM_CTRL_BUSY, 0, 100); - - /* Re-enable CAM control */ - nicptr->camControl |= CAM_CTRL_ENABLE; - break; - -/* Get MAC address from card. */ - case ETH_CTRL_GET_MAC: - macptr = (uchar *)arg1; - nicptr->camControl = - (devptr->minor << CAM_CTRL_INDEX_SHIFT) | CAM_CTRL_READ; - waitOnBit(&nicptr->camControl, CAM_CTRL_BUSY, 0, 100); - - temp = nicptr->camDataLo; - macptr[2] = temp >> 24; - macptr[3] = temp >> 16; - macptr[4] = temp >> 8; - macptr[5] = temp >> 0; - - temp = nicptr->camDataHi; - macptr[0] = temp >> 8; - macptr[1] = temp >> 0; - - /* Re-enable CAM control */ - nicptr->camControl = CAM_CTRL_ENABLE; - break; - - case NET_GET_HWADDR: - addr = (struct netaddr *)arg1; - addr->type = NETADDR_ETHERNET; - addr->len = ETH_ADDR_LEN; - etherControl(devptr, ETH_CTRL_GET_MAC, (int)addr->addr, NULL); - break; - -/* Get broadcast MAC address. */ - case NET_GET_HWBRC: - addr = (struct netaddr *)arg1; - addr->type = NETADDR_ETHERNET; - addr->len = ETH_ADDR_LEN; - addr->addr[0] = 0xFF; - addr->addr[1] = 0xFF; - addr->addr[2] = 0xFF; - addr->addr[3] = 0xFF; - addr->addr[4] = 0xFF; - addr->addr[5] = 0xFF; - break; - -/* Set receiver mode. */ - case ETH_CTRL_SET_LOOPBK: - if (TRUE == (uint)arg1) - { - nicptr->rxConfig = RXCONFIG_LPBACK; - } - else - { - nicptr->rxConfig = 0; - } - break; - -/* Reset Ethernet device. */ - case ETH_CTRL_RESET: - /* Idle the network card if the backplane core is up */ - if (backplaneCoreUp(&(nicptr->bpConfig))) - { - etherControl(devptr, ETH_CTRL_DISABLE, 0, 0); - } - - /* Reset the target core. */ - backplaneReset(&(nicptr->bpConfig)); - - etherControl(devptr, ETH_CTRL_CLEAR_STATS, 0, 0); - - /* Make PHY accessible and set frequency */ - nicptr->mdioControl = (MDIO_CTRL_PREAMBLE | MDIO_CTRL_FREQ); - - /* Select external PHY, this model does not have internal. */ - nicptr->enetControl = ENET_CTRL_EPSEL; - break; - -/* Disable ethernet core */ - case ETH_CTRL_DISABLE: - nicptr->rcvLazy = 0; /* Turn off lazy reception. */ - nicptr->enetControl; /* Read control register. */ - - /* Wait for controller */ - waitOnBit(&nicptr->enetControl, ENET_CTRL_DISABLE, 0, 100); - /* Reset transmitter settings and transmitter queue. */ - nicptr->dmaTxControl = 0; - ethptr->txHead = 0; - ethptr->txTail = 0; - if (nicptr->dmaRxStatus & DMARX_STAT_EMASK) - { - /* Wait for receiver to idle. */ - waitOnBit(&nicptr->dmaRxStatus, DMARX_STAT_SIDLE, 1, 100); - } - - /* Reset receiver settings and receiver queue. */ - nicptr->dmaRxControl = 0; - ethptr->rxHead = 0; - ethptr->rxTail = 0; - break; - -/* Get MTU. */ - case NET_GET_MTU: - return ETH_MTU; - - default: - return SYSERR; - } - - return OK; -} diff --git a/device/bcm4713/etherInit.c b/device/bcm4713/etherInit.c deleted file mode 100644 index 7dad7cd4..00000000 --- a/device/bcm4713/etherInit.c +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @file etherInit.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include -#include -#include "bcm4713.h" -#include -#include "bcmswitch.h" -#include -#include - -/* Global table of ethernet devices */ -struct ether ethertab[NETHER]; - -/* Implementation of etherInit() for the bcm4713; see the documentation for this - * function in ether.h. */ -devcall etherInit(device *devptr) -{ - struct ether *ethptr; - - /* Initialize structure pointers */ - ethptr = ðertab[devptr->minor]; - bzero(ethptr, sizeof(struct ether)); - ethptr->dev = devptr; - ethptr->csr = devptr->csr; - ethptr->phy = devptr; - - ethptr->state = ETH_STATE_DOWN; - ethptr->rxRingSize = ETH_RX_RING_ENTRIES; - ethptr->txRingSize = ETH_TX_RING_ENTRIES; - ethptr->mtu = ETH_MTU; - ethptr->interruptMask = IMASK_DEF; - - ethptr->errors = 0; - ethptr->isema = semcreate(0); - ethptr->istart = 0; - ethptr->icount = 0; - ethptr->ovrrun = 0; - ethptr->rxOffset = sizeof(struct rxHeader); - - /* Lookup canonical MAC in NVRAM, and store in ether struct */ - colon2mac(nvramGet("et0macaddr"), ethptr->devAddress); - - /* NOTE: because device initialization runs early in the system, */ - /* we are assured that this stkget() call will return */ - /* page-aligned (and cache-aligned) boundaries. */ - ethptr->rxBufs = stkget(PAGE_SIZE); - ethptr->txBufs = stkget(PAGE_SIZE); - ethptr->rxRing = stkget(PAGE_SIZE); - ethptr->txRing = stkget(PAGE_SIZE); - - if ((SYSERR == (int)ethptr->rxBufs) - || (SYSERR == (int)ethptr->txBufs) - || (SYSERR == (int)ethptr->rxRing) - || (SYSERR == (int)ethptr->txRing)) - { -#ifdef DETAIL - kprintf("eth%d ring buffer allocation error.\r\n", devptr->minor); -#endif /* DETAIL */ - return SYSERR; - } - - /* bump buffers/rings to KSEG1 */ - ethptr->rxBufs = - (struct ethPktBuffer - **)(((ulong)ethptr->rxBufs - PAGE_SIZE + - sizeof(int)) | KSEG1_BASE); - ethptr->txBufs = - (struct ethPktBuffer - **)(((ulong)ethptr->txBufs - PAGE_SIZE + - sizeof(int)) | KSEG1_BASE); - ethptr->rxRing = - (struct dmaDescriptor - *)(((ulong)ethptr->rxRing - PAGE_SIZE + - sizeof(int)) | KSEG1_BASE); - ethptr->txRing = - (struct dmaDescriptor - *)(((ulong)ethptr->txRing - PAGE_SIZE + - sizeof(int)) | KSEG1_BASE); - - /* Make sure nothing erroneous is in buffers/rings */ - bzero(ethptr->rxBufs, PAGE_SIZE); - bzero(ethptr->txBufs, PAGE_SIZE); - bzero(ethptr->rxRing, PAGE_SIZE); - bzero(ethptr->txRing, PAGE_SIZE); - - /* Reset ethernet device to known state. */ - etherControl(devptr, ETH_CTRL_RESET, 0, 0); - - /* Initialize the network switch */ - switchInit((struct bcm4713 *)ethptr->csr); - - interruptVector[devptr->irq] = devptr->intr; - enable_irq(devptr->irq); - - return OK; -} diff --git a/device/bcm4713/etherInterrupt.c b/device/bcm4713/etherInterrupt.c deleted file mode 100644 index 6df3d496..00000000 --- a/device/bcm4713/etherInterrupt.c +++ /dev/null @@ -1,190 +0,0 @@ -/** - * @file etherInterrupt.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include "bcm4713.h" -#include -#include -#include -#include -#include -#include - -extern int resdefer; - -/** - * @ingroup etherspecific - */ -void rxPackets(struct ether *ethptr, struct bcm4713 *nicptr) -{ - ulong head = 0, tail = 0; - struct ethPktBuffer *pkt = NULL; - struct rxHeader *rh = NULL; - struct vlanPkt *lanptr = NULL; - struct ether *phyptr = 0; - - /* 12-bit descriptor indicates where card is currently placing */ - /* received packets into the ring. */ - tail = (nicptr->dmaRxStatus & DMARX_STAT_CDMASK) - / sizeof(struct dmaDescriptor); - /* rxHead indicates where we last left off pulling received */ - /* packets off of the ring. */ - head = ethptr->rxHead; - while (head != tail) - { - pkt = ethptr->rxBufs[head]; - rh = (struct rxHeader *)pkt->buf; - lanptr = (struct vlanPkt *)pkt->data; - - if (ETH_TYPE_VLAN == net2hs(lanptr->tpi)) - { - phyptr = ðertab[net2hs(lanptr->vlanId) & ETH_VLAN_IDMASK]; - } - else - { - phyptr = ethptr; - } - - if ((rh->length > - ETH_MAX_PKT_LEN + ETH_CRC_LEN) - || (rh->flags & ETH_RX_FLAG_ERRORS)) - { - phyptr->rxErrors++; - bzero(pkt->buf, pkt->length); - } - else - { - if (phyptr->icount < ETH_IBLEN) - { - allocRxBuffer(ethptr, head); - phyptr->in[(phyptr->istart + phyptr->icount) % - ETH_IBLEN] = pkt; - phyptr->icount++; - signaln(phyptr->isema, 1); - } - else - { - phyptr->ovrrun++; - bzero(pkt->buf, pkt->length); - } - } - ethptr->rxTail = (ethptr->rxTail + 1) % ethptr->rxRingSize; - nicptr->dmaRxLast = ethptr->rxTail * sizeof(struct dmaDescriptor); - head = (head + 1) % ethptr->rxRingSize; - } - ethptr->rxHead = head; -} - -/** - * @ingroup etherspecific - */ -void txPackets(struct ether *ethptr, struct bcm4713 *nicptr) -{ - struct ethPktBuffer **epb = NULL; - struct ethPktBuffer *pkt = NULL; - ulong current = 0, head = 0; - - current = (nicptr->dmaTxStatus & DMATX_STAT_CDMASK) - / sizeof(struct dmaDescriptor); - - for (head = ethptr->txHead; head != current; - head = (head + 1) % ethptr->txRingSize) - { - epb = ðptr->txBufs[head]; - pkt = *epb; - if (NULL == pkt) - { - continue; - } - buffree((void *)((ulong)pkt & (PMEM_MASK | KSEG0_BASE))); - *epb = NULL; - } - ethptr->txHead = head; - nicptr->gpTimer = 0; -} - -/** - * @ingroup etherspecific - * - * Decode and handle hardware interrupt request from ethernet device. - */ -interrupt etherInterrupt(void) -{ - int ethnum; - struct ether *ethptr; - struct bcm4713 *nicptr; - uint status, mask; - - /* Initialize structure pointers */ - ethptr = ðertab[0]; /* default physical ethernet for WRT54GL */ - if (!ethptr) - { - return; - } - nicptr = ethptr->csr; - if (!nicptr) - { - return; - } - - mask = nicptr->interruptMask; - status = nicptr->interruptStatus & mask; - - /* remember interrupt status in ether struct */ - ethptr->interruptStatus = status; - - if (!status) - { - return; - } - - resdefer = 1; /* defer rescheduling */ - - if (status & ISTAT_TX) - { - ethptr->txirq++; - txPackets(ethptr, nicptr); - /* Set Rx timeout to 2 seconds after last Tx */ - nicptr->gpTimer = 2 * platform.clkfreq; - } - - if (status & ISTAT_RX) - { - ethptr->rxirq++; - rxPackets(ethptr, nicptr); - /* Set Rx timeout to 0 */ - nicptr->gpTimer = 0; - } - - if (status & ISTAT_ERRORS) - { - /* Error closes physical NIC as well as vlans */ - for (ethnum = 0; ethnum < NETHER; ethnum++) - { - ethptr = ðertab[ethnum]; - if (!ethptr) - { - continue; - } - ethptr->errors++; - etherClose(ethptr->dev); - } - } - - /* signal the card with the interrupts we handled */ - nicptr->interruptStatus = status; - - if (--resdefer > 0) - { - resdefer = 0; - resched(); - } - - return; -} diff --git a/device/bcm4713/etherOpen.c b/device/bcm4713/etherOpen.c deleted file mode 100644 index ec8b0c69..00000000 --- a/device/bcm4713/etherOpen.c +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file etherOpen.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include "bcm4713.h" -#include -#include -#include -#include -#include -#include - -/* Implementation of etherOpen() for the bcm4713; see the documentation for this - * function in ether.h. */ -devcall etherOpen(device *devptr) -{ - int i; - irqmask im; - struct ether *ethptr; - struct bcm4713 *nicptr; - - /* Initialize structure pointers */ - ethptr = ðertab[devptr->minor]; - nicptr = ethptr->csr; - - /* Request memory buffer pool for Rx DMA and intermediate buffers of - all ethernet devices--both real and virtual */ - ethptr->inPool = - bfpalloc(ETH_RX_BUF_SIZE + sizeof(struct ethPktBuffer), - ETH_RX_RING_ENTRIES + ETH_IBLEN * NETHER); - ETHER_TRACE("eth%d inPool has been assigned pool ID %d.\r\n", - devptr->minor, ethptr->inPool); - if (SYSERR == ethptr->inPool) - { -#ifdef DETAIL - kprintf("eth%d inPool buffer error.\r\n", devptr->minor); -#endif /* DETAIL */ - return SYSERR; - } - - /* Request memory buffer pool for Tx DMA */ - ethptr->outPool = - bfpalloc(ETH_TX_BUF_SIZE + sizeof(struct ethPktBuffer), - ETH_TX_RING_ENTRIES - 1); - ETHER_TRACE("eth%d outPool has been assigned pool ID %d.\r\n", - devptr->minor, ethptr->outPool); - if (SYSERR == ethptr->outPool) - { -#ifdef DETAIL - kprintf("eth%d outPool buffer error.\r\n", devptr->minor); -#endif /* DETAIL */ - return SYSERR; - } - - im = disable(); - - /* Initialize DMA descriptor processor */ - nicptr->dmaTxControl = DMATX_CTRL_ENABLE; - nicptr->dmaTxAddress = (ulong)ethptr->txRing & PMEM_MASK; - - nicptr->dmaRxControl = DMARX_CTRL_ENABLE | - (ethptr->rxOffset << DMARX_CTRL_ROSHIFT); - nicptr->dmaRxAddress = (ulong)ethptr->rxRing & PMEM_MASK; - - for (i = 0; i < ethptr->rxRingSize; i++) - { - allocRxBuffer(ethptr, i); - } - - nicptr->dmaRxLast = ethptr->rxRingSize * sizeof(struct dmaDescriptor); - ethptr->rxTail = ethptr->rxRingSize; // Producer goes to tail. - - /* Configure NIC */ - nicptr->macControl |= MAC_CTRL_CRC32_ENAB; /* enable crc32 */ - nicptr->rcvLazy = (1 << RCV_LAZY_FC_SHIFT); /* enable lazy Rx intr */ - - etherControl(devptr, ETH_CTRL_SET_MAC, (long)ethptr->devAddress, 0); - etherControl(devptr, ETH_CTRL_SET_LOOPBK, FALSE, 0); - - /* Set maximum incoming and outgoing packet length */ - nicptr->rxMaxLength = ETH_HEADER_LEN + ETH_VLAN_LEN - + ethptr->mtu + ETH_CRC_LEN; - nicptr->txMaxLength = ETH_HEADER_LEN + ETH_VLAN_LEN - + ethptr->mtu + ETH_CRC_LEN; - - nicptr->txWatermark = TX_WATERMARK; - - nicptr->enetControl |= ENET_CTRL_ENABLE; - - ethptr->state = ETH_STATE_UP; - nicptr->interruptMask = ethptr->interruptMask; - - restore(im); - - return OK; -} diff --git a/device/bcm4713/etherRead.c b/device/bcm4713/etherRead.c deleted file mode 100644 index 91a64ee4..00000000 --- a/device/bcm4713/etherRead.c +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file etherRead.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include "bcm4713.h" -#include -#include -#include -#include -#include -#include - -/* Implementation of etherRead() for the bcm4713; see the documentation for this - * function in ether.h. */ -devcall etherRead(device *devptr, void *buf, uint len) -{ - irqmask im; - struct ether *ethptr; - struct ethPktBuffer *pkt; - struct rxHeader *rh; - struct vlanPkt *lanptr; - uint length; - char *buffer = buf; - - ethptr = ðertab[devptr->minor]; - - im = disable(); - if (ETH_STATE_UP != ethptr->state) - { - restore(im); - return SYSERR; - } - - /* make sure buffer is large enough to store packet */ - if (len < ETH_HEADER_LEN) - { - restore(im); - return SYSERR; - } - - wait(ethptr->isema); - - pkt = ethptr->in[ethptr->istart]; - ethptr->in[ethptr->istart] = NULL; - ethptr->istart = (ethptr->istart + 1) % ETH_IBLEN; - ethptr->icount--; - restore(im); - - if (NULL == pkt) - { - return 0; - } - rh = (struct rxHeader *)pkt->buf; - lanptr = (struct vlanPkt *)pkt->data; - - /* slice off CRC */ - rh->length -= ETH_CRC_LEN; - - if (ETH_TYPE_VLAN == net2hs(lanptr->tpi)) - { - rh->length -= 4; /* Account for vlan tag removal */ - } - - /* compute size of packet */ - length = (rh->length < len) ? rh->length : len; - - if (ETH_TYPE_VLAN == net2hs(lanptr->tpi)) - { - /* strip vlan tag */ - memcpy(buffer, pkt->data, 12); - memcpy(buffer + 12, pkt->data + 16, length - 12); - } - else - { - /* no vlan tagging */ - memcpy(buffer, pkt->data, length); - } - - buffree(pkt); - - return length; -} diff --git a/device/bcm4713/etherStat.c b/device/bcm4713/etherStat.c deleted file mode 100644 index a3812cd5..00000000 --- a/device/bcm4713/etherStat.c +++ /dev/null @@ -1,273 +0,0 @@ -/** - * @file etherStat.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include "bcm4713.h" -#include -#include -#include -#include - -static void vethStat(ushort); - -void etherStat(ushort minor) -{ - struct ether *ethptr = NULL; /* pointer to ether entry */ - struct bcm4713 *nicptr = NULL; /* pointer to ether device registers */ - ulong tmp; - uchar mac[6]; - - /* Initialize pointers */ - ethptr = ðertab[minor]; - nicptr = ethptr->csr; - - printf("%s:\n", (ethptr->dev)->name); - control(ethptr->dev->num, ETH_CTRL_GET_MAC, (long)mac, 0); - printf(" MAC Address %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], - mac[2], mac[3], mac[4], mac[5]); - - if (ethptr->dev != ethptr->phy) - { - vethStat(minor); - return; - } - - printf(" %8d MTU\n", ethptr->mtu); - - tmp = ethptr->state; - printf(" Device "); - if (ETH_STATE_FREE == tmp) - { - printf("FREE"); - } - if (ETH_STATE_UP == tmp) - { - printf("UP "); - } - if (ETH_STATE_DOWN == tmp) - { - printf("DOWN"); - } - - printf(" RxErrors %lu ", ethptr->rxErrors); - printf(" Errors %lu\n", ethptr->errors); - - /* Ether statistics */ - tmp = ethptr->interruptStatus; - printf(" IRQ Status 0x%08lX [", tmp); - if (tmp & ISTAT_PME) - { - printf(" PME"); - } - if (tmp & ISTAT_TO) - { - printf(" TO"); - } - if (tmp & ISTAT_DSCE) - { - printf(" DSCE"); - } - if (tmp & ISTAT_DATAE) - { - printf(" DATAE"); - } - if (tmp & ISTAT_DPE) - { - printf(" DPE"); - } - if (tmp & ISTAT_RDU) - { - printf(" RDU"); - } - if (tmp & ISTAT_RFO) - { - printf(" RFO"); - } - if (tmp & ISTAT_TFU) - { - printf(" TFU"); - } - if (tmp & ISTAT_RX) - { - printf(" RX"); - } - if (tmp & ISTAT_TX) - { - printf(" TX"); - } - if (tmp & ISTAT_EMAC) - { - printf(" EMAC"); - } - if (tmp & ISTAT_MII_WRITE) - { - printf(" MII_WRITE"); - } - if (tmp & ISTAT_MII_READ) - { - printf(" MII_READ"); - } - printf(" ]\n"); - - tmp = ethptr->interruptMask; - printf(" IRQ Mask 0x%08lX [", tmp); - if (tmp & ISTAT_PME) - { - printf(" PME"); - } - if (tmp & ISTAT_TO) - { - printf(" TO"); - } - if (tmp & ISTAT_DSCE) - { - printf(" DSCE"); - } - if (tmp & ISTAT_DATAE) - { - printf(" DATAE"); - } - if (tmp & ISTAT_DPE) - { - printf(" DPE"); - } - if (tmp & ISTAT_RDU) - { - printf(" RDU"); - } - if (tmp & ISTAT_RFO) - { - printf(" RFO"); - } - if (tmp & ISTAT_TFU) - { - printf(" TFU"); - } - if (tmp & ISTAT_RX) - { - printf(" RX"); - } - if (tmp & ISTAT_TX) - { - printf(" TX"); - } - if (tmp & ISTAT_EMAC) - { - printf(" EMAC"); - } - if (tmp & ISTAT_MII_WRITE) - { - printf(" MII_WRITE"); - } - if (tmp & ISTAT_MII_READ) - { - printf(" MII_READ"); - } - printf(" ]\n"); - - printf(" Tx IRQ Count %8lu", ethptr->txirq); - printf(" Tx Octets %8u", nicptr->txGoodOctets); - printf(" Tx Packets %8u\n", nicptr->txGoodPackets); - printf(" Tx < 65 octets %8u", nicptr->tx_64); - printf(" Tx < 128 %8u", nicptr->tx_65_127); - printf(" Tx < 256 %8u\n", nicptr->tx_128_255); - printf(" Tx < 512 %8u", nicptr->tx_256_511); - printf(" Tx < 1024 %8u", nicptr->tx_512_1023); - printf(" Tx >= 1024 %8u\n", nicptr->tx_1024_max); - printf(" Tx Broadcast %8u", nicptr->txBroadcast); - printf(" Tx Multicast %8u", nicptr->txMulticast); - printf(" Tx Jabber %8u\n", nicptr->txJabber); - printf(" Tx Oversize %8d", nicptr->txOversize); - printf(" Tx Fragment %8u", nicptr->txFragment); - printf(" Tx Underruns %8u\n", nicptr->txUnderruns); - printf(" Tx Collisions %8u", nicptr->txCollisions); - printf(" Tx Status 0x%08X\n", nicptr->dmaTxStatus); - printf("\n"); - printf(" Rx IRQ Count %8lu", ethptr->rxirq); - printf(" Rx Octets %8u", nicptr->rxGoodOctets); - printf(" Rx Packets %8u\n", nicptr->rxGoodPackets); - printf(" Rx < 65 octets %8u", nicptr->rx_64); - printf(" Rx < 128 %8u", nicptr->rx_65_127); - printf(" Rx < 256 %8u\n", nicptr->rx_128_255); - printf(" Rx < 512 %8u", nicptr->rx_256_511); - printf(" Rx < 1024 %8u", nicptr->rx_512_1023); - printf(" Rx >= 1024 %8u\n", nicptr->rx_1024_max); - printf(" Rx Broadcast %8u", nicptr->rxBroadcast); - printf(" Rx Multicast %8u", nicptr->rxMulticast); - printf(" Rx Jabber %8u\n", nicptr->rxJabber); - printf(" Rx Oversize %8u", nicptr->rxOversize); - printf(" Rx Fragment %8u", nicptr->rxFragment); - printf(" Rx Missed %8u\n", nicptr->rxMissed); - printf(" Rx CRC Align %8u", nicptr->rxCrcAlign); - printf(" Rx Undersize %8u", nicptr->rxUndersize); - printf(" Rx CRC Error %8u\n", nicptr->rxCrc); - printf(" Rx Alignment %8u", nicptr->rxAlign); - printf(" Rx Symbol Err %8u", nicptr->rxSymbol); - printf(" Rx Pause %8u\n", nicptr->rxPause); - printf(" Rx Non-Pause %8u", nicptr->rxNonPause); - - tmp = nicptr->dmaRxLast / sizeof(struct dmaDescriptor); - printf(" Rx DMA Last %8lu", tmp); - - tmp = (nicptr->dmaRxStatus & DMARX_STAT_CDMASK) - / sizeof(struct dmaDescriptor); - printf(" Rx DMA Stat %8lu\n", tmp); - - printf("\n"); -} - -void etherThroughput(ushort minor) -{ - int tx, rx; - - struct ether *ethptr = NULL; /* pointer to ether entry */ - struct bcm4713 *nicptr = NULL; /* pointer to ether device registers */ - - /* Initialize pointers */ - ethptr = ðertab[minor]; - nicptr = ethptr->csr; - - if (ethptr->dev != ethptr->phy) - { - return; - } - - while (TRUE) - { - tx = nicptr->txGoodOctets; - rx = nicptr->rxGoodOctets; - sleep(1000); /* sleep for 1 second */ - printf("Tx: %4d bytes/sec, ", nicptr->txGoodOctets - tx); - printf("Rx: %4d bytes/sec\n", nicptr->rxGoodOctets - rx); - } -} - -static void vethStat(ushort minor) -{ - struct ether *ethptr = NULL; /* pointer to ether entry */ - ulong tmp; - - /* Initialize pointers */ - ethptr = ðertab[minor]; - - tmp = ethptr->state; - printf("\n Device "); - if (ETH_STATE_FREE == tmp) - { - printf("FREE"); - } - if (ETH_STATE_UP == tmp) - { - printf("UP "); - } - if (ETH_STATE_DOWN == tmp) - { - printf("DOWN"); - } - - printf(" RxErrors %lu\n\n", ethptr->rxErrors); -} diff --git a/device/bcm4713/etherWrite.c b/device/bcm4713/etherWrite.c deleted file mode 100644 index 454ab9f0..00000000 --- a/device/bcm4713/etherWrite.c +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file etherWrite.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include "bcm4713.h" -#include -#include -#include -#include -#include -#include -#include - -/* Implementation of etherWrite() for the bcm4713; see the documentation for - * this function in ether.h. */ -devcall etherWrite(device *devptr, const void *buf, uint len) -{ - struct ether *ethptr; - struct bcm4713 *nicptr; - struct ethPktBuffer *pkt = NULL; - struct vlanPkt *lanptr; - struct ether *phyptr; - irqmask im; - ulong entry = 0, control = 0; - const uchar *buffer = buf; - uint outlen; - - ethptr = ðertab[devptr->minor]; - nicptr = ethptr->csr; - - if (ETH_STATE_UP != ethptr->state) - { - return SYSERR; - } - phyptr = ðertab[ethptr->phy->minor]; - if (ETH_STATE_UP != phyptr->state) - { - return SYSERR; - } - - /* make sure packet is not too small */ - if (len < ETH_HEADER_LEN) - { - return SYSERR; - } - - /* make sure packet is not too big */ - if (len > (ETH_TX_BUF_SIZE - ETH_VLAN_LEN)) - { - return SYSERR; - } - - pkt = (struct ethPktBuffer *)bufget(phyptr->outPool); - if (SYSERR == (ulong)pkt) - { - return SYSERR; - } - - /* set outbound packet length to currently buffer length */ - outlen = len; - - pkt = (struct ethPktBuffer *)((int)pkt | KSEG1_BASE); - pkt->buf = (uchar *)(pkt + 1); - pkt->data = pkt->buf; - lanptr = (struct vlanPkt *)pkt->data; - - /* Copy packet to DMA buffer with added vlan tag */ - memcpy(pkt->data, buffer, 12); - lanptr->tpi = hs2net(ETH_TYPE_VLAN); - lanptr->vlanId = hs2net(devptr->minor); - memcpy(pkt->data + 16, buffer + 12, outlen - 12); - outlen += ETH_VLAN_LEN; /* account for vlan tag addition */ - pkt->length = outlen; - - /* Place filled buffer in outgoing queue */ - im = disable(); - entry = phyptr->txTail; - phyptr->txBufs[entry] = pkt; - - control = outlen & ETH_DESC_CTRL_LEN; - /* Mark as start and end of frame, interrupt on completion. */ - control |= ETH_DESC_CTRL_IOC | ETH_DESC_CTRL_SOF | ETH_DESC_CTRL_EOF; - if (phyptr->txRingSize - 1 == entry) - { - control |= ETH_DESC_CTRL_EOT; - } - - /* Add this buffer to the Tx ring. */ - phyptr->txRing[entry].control = control; - phyptr->txRing[entry].address = (ulong)pkt->data & PMEM_MASK; - - phyptr->txTail = (entry + 1) % phyptr->txRingSize; - entry = phyptr->txTail; - - nicptr->dmaTxLast = entry * sizeof(struct dmaDescriptor); - - restore(im); - - return len; -} diff --git a/device/bcm4713/switchInit.c b/device/bcm4713/switchInit.c deleted file mode 100644 index 007953ea..00000000 --- a/device/bcm4713/switchInit.c +++ /dev/null @@ -1,208 +0,0 @@ -/** - * @file switchInit.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include "bcm4713.h" -#include "bcmswitch.h" - -int waitOnBit(volatile uint *reg, uint mask, const int value, int tries); - -struct swtstate swtregs; - -int switchInit(struct bcm4713 *nicptr) -{ - int result = 0, members = 0, untag = 0, vlan = 0, port = 0; - struct mdioregs *mdio = NULL; - ushort deftags[SWT_PORTS]; - - swtregs.mdio = NULL; - swtregs.page = -1; - - if (NULL == nicptr) - { - return SYSERR; - } - mdio = (struct mdioregs *)&nicptr->mdioControl; - swtregs.mdio = mdio; - - for (port = 0; port < (SWT_PORTS - NETHER); port++) - { - /* Initialize default VLAN */ - members |= (1 << port); - untag |= (1 << port); - deftags[port] = vlan; - } - members |= (1 << SWT_CPUPORT); /* Always include CPU interface */ - result = ((members | (untag << SWT_PORTS)) - & (SWT_VLAN_GROUPMASK | SWT_VLAN_UNTAGMASK)); - - result |= SWT_VLAN_WRITE_VALID; - switchWriteReg(mdio, SWT_PAGE_VLAN, SWT_REG_VLAN_WRITE, &result); - result = SWT_VLAN_TABACC_ENABLE | SWT_VLAN_TABACC_WRITE | vlan; - switchWriteReg(mdio, SWT_PAGE_VLAN, SWT_REG_VLAN_TABACC, &result); - - deftags[SWT_CPUPORT] = vlan; - - for (port = (SWT_PORTS - NETHER); port < SWT_CPUPORT; port++) - { - /* Initialize optional LANs */ - vlan++; - members = (1 << port) | (1 << SWT_CPUPORT); - untag = (1 << port); - result = ((members | (untag << SWT_PORTS)) - & (SWT_VLAN_GROUPMASK | SWT_VLAN_UNTAGMASK)); - - result |= SWT_VLAN_WRITE_VALID; - switchWriteReg(mdio, SWT_PAGE_VLAN, SWT_REG_VLAN_WRITE, &result); - result = SWT_VLAN_TABACC_ENABLE | SWT_VLAN_TABACC_WRITE | vlan; - switchWriteReg(mdio, SWT_PAGE_VLAN, SWT_REG_VLAN_TABACC, &result); - deftags[port] = vlan; - } - for (port = SWT_CPUPORT; port < SWT_VLAN_TABLEMAX; port++) - { - /* Clear remaining table entries */ - vlan++; - result = SWT_VLAN_WRITE_VALID; - switchWriteReg(mdio, SWT_PAGE_VLAN, SWT_REG_VLAN_WRITE, &result); - result = SWT_VLAN_TABACC_ENABLE | SWT_VLAN_TABACC_WRITE | vlan; - switchWriteReg(mdio, SWT_PAGE_VLAN, SWT_REG_VLAN_TABACC, &result); - } - - for (port = 0; port < SWT_PORTS; port++) - { - /* Program default port tags */ - result = deftags[port]; - switchWriteReg(mdio, SWT_PAGE_VLAN, - SWT_REG_VLAN_TAGPORT0 + 2 * port, &result); - } - - return OK; -} - -#define MII_MAX_RETRY 100 -#define PSEUDO_PHYAD 0x1E /* MII Pseudo PHY address */ - -/* MII registers */ -#define REG_MII_PAGE 0x10 /* MII Page register */ -#define REG_MII_ADDR 0x11 /* MII Address register */ -#define REG_MII_DATA0 0x18 /* MII Data register 0 */ -#define REG_MII_DATA1 0x19 /* MII Data register 1 */ - -/* emac mdio data */ -#define MD_DATA_MASK 0xffff /* r/w data */ -#define MD_TA_MASK 0x30000 /* turnaround value */ -#define MD_TA_SHIFT 16 -#define MD_TA_VALID (2 << MD_TA_SHIFT) /* valid ta */ -#define MD_RA_MASK 0x7c0000 /* register address */ -#define MD_RA_SHIFT 18 -#define MD_PMD_MASK 0xf800000 /* physical media device */ -#define MD_PMD_SHIFT 23 -#define MD_OP_MASK 0x30000000 /* opcode */ -#define MD_OP_SHIFT 28 -#define MD_OP_WRITE (1 << MD_OP_SHIFT) /* write op */ -#define MD_OP_READ (2 << MD_OP_SHIFT) /* read op */ -#define MD_SB_MASK 0xc0000000 /* start bits */ -#define MD_SB_SHIFT 30 -#define MD_SB_START (0x1 << MD_SB_SHIFT) /* start of frame */ - -#define EI_MII ((ulong)1 << 0) /* mii mdio interrupt */ -#define EI_MIB ((ulong)1 << 1) /* mib interrupt */ -#define EI_FLOW ((ulong)1 << 2) /* flow control interrupt */ - -static ushort mdioRead(struct mdioregs *mdio, ulong phyaddr, ulong reg) -{ - /* clear mii_int */ - mdio->emacIntstatus = EI_MII; - - mdio->mdioData = - (MD_SB_START | MD_OP_READ | (phyaddr << MD_PMD_SHIFT) | - (reg << MD_RA_SHIFT) | MD_TA_VALID); - - /* wait for it to complete */ - waitOnBit((uint *)&mdio->emacIntstatus, EI_MII, 1, 100); - - return (mdio->mdioData & MD_DATA_MASK); -} - -static void mdioWrite(struct mdioregs *mdio, ulong phyaddr, ulong reg, - ushort v) -{ - /* clear mii_int */ - mdio->emacIntstatus = EI_MII; - - /* issue the write */ - mdio->mdioData = - (MD_SB_START | MD_OP_WRITE | (phyaddr << MD_PMD_SHIFT) - | (reg << MD_RA_SHIFT) | MD_TA_VALID | v); - - /* wait for it to complete */ - waitOnBit((uint *)&mdio->emacIntstatus, EI_MII, 1, 100); -} - -/* Write register thru MDC/MDIO */ -int switchWriteReg(struct mdioregs *mdio, uchar page, uchar reg, - void *val) -{ - ushort cmd16, val16; - int i; - - cmd16 = (page << 8) /* page number */ - | 1 /* mdc/mdio access enable */ - ; - mdioWrite(mdio, PSEUDO_PHYAD, REG_MII_PAGE, cmd16); - - /* write data - MII register 0x18-0x1B */ - val16 = (ushort)*(ushort *)val; - mdioWrite(mdio, PSEUDO_PHYAD, REG_MII_DATA0, val16); - val16 = (ulong)(*(ulong *)val >> 16); - mdioWrite(mdio, PSEUDO_PHYAD, REG_MII_DATA1, val16); - - /* set register address - MII register 0x11 */ - cmd16 = (reg << 8) /* register address */ - | 1 /* opcode write */ - ; - mdioWrite(mdio, PSEUDO_PHYAD, REG_MII_ADDR, cmd16); - /* is operation finished? */ - for (i = MII_MAX_RETRY; i > 0; i--) - { - val16 = mdioRead(mdio, PSEUDO_PHYAD, REG_MII_ADDR); - if ((val16 & 3) == 0) - break; - } - return 0; -} - -/* Read register thru MDC/MDIO */ -int switchReadReg(struct mdioregs *mdio, uchar page, uchar reg, void *val) -{ - ushort cmd16, val16; - int i; - - cmd16 = (page << 8) /* page number */ - | 1 /* mdc/mdio access enable */ - ; - mdioWrite(mdio, PSEUDO_PHYAD, REG_MII_PAGE, cmd16); - - /* set register address - MII register 0x11 */ - cmd16 = (reg << 8) /* register address */ - | 2 /* opcode read */ - ; - mdioWrite(mdio, PSEUDO_PHYAD, REG_MII_ADDR, cmd16); - /* is operation finished? */ - for (i = MII_MAX_RETRY; i > 0; i--) - { - val16 = mdioRead(mdio, PSEUDO_PHYAD, REG_MII_ADDR); - if ((val16 & 3) == 0) - break; - } - /* read data - MII register 0x18-0x1B */ - val16 = mdioRead(mdio, PSEUDO_PHYAD, REG_MII_DATA0); - *(ulong *)val = val16; - val16 = mdioRead(mdio, PSEUDO_PHYAD, REG_MII_DATA1); - *(ulong *)val += val16 << 16; - return 0; -} diff --git a/device/bcm4713/vlanClose.c b/device/bcm4713/vlanClose.c deleted file mode 100644 index 7d47232b..00000000 --- a/device/bcm4713/vlanClose.c +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @file vlanClose.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include - -/** - * @ingroup etherspecific - * - * Close a virtual ethernet device. - * @param devptr ether device table entry - * @return OK if device is closed properly - */ -devcall vlanClose(device *devptr) -{ - struct ether *ethptr = NULL; - - ethptr = ðertab[devptr->minor]; - - /* flag interface as down */ - ethptr->state = ETH_STATE_DOWN; - - return OK; -} diff --git a/device/bcm4713/vlanInit.c b/device/bcm4713/vlanInit.c deleted file mode 100644 index 41e2f410..00000000 --- a/device/bcm4713/vlanInit.c +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @file vlanInit.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include "bcm4713.h" -#include -#include -#include -#include -#include - -/** - * @ingroup etherspecific - * - * Initialize virtual ethernet device structures. - * @param devptr TTY device table entry - * @return OK if device is intialized successfully - */ -devcall vlanInit(device *devptr) -{ - struct ether *ethptr; - - /* Initialize structure pointers */ - ethptr = ðertab[devptr->minor]; - bzero(ethptr, sizeof(struct ether)); - ethptr->dev = devptr; - ethptr->csr = (struct bcm4713 *)devptr->csr; - /* Physical ethernet device to which the VLAN attaches */ - ethptr->phy = (device *)&devtab[ETH0]; - - ethptr->errors = 0; - ethptr->state = ETH_STATE_DOWN; - ethptr->rxRingSize = ETH_RX_RING_ENTRIES; - ethptr->txRingSize = ETH_TX_RING_ENTRIES; - ethptr->mtu = ETH_MTU; - - ethptr->isema = semcreate(0); - ethptr->istart = 0; - ethptr->icount = 0; - ethptr->ovrrun = 0; - ethptr->rxOffset = sizeof(struct rxHeader); - - /* Lookup MAC in NVRAM, and store it in ether dev struct. */ - /* Modify first octet with device minor and set local admin bit */ - colon2mac(nvramGet("et0macaddr"), ethptr->devAddress); - ethptr->devAddress[0] |= ((uchar)devptr->minor << 2) | ETH_LOCAL_MAC; - - ethptr->interruptMask = IMASK_DEF; - - /* As there is only one DMA ring for the physical ethernet, and - * none for virtual interfaces, certain values in the ether struct - * are set to invalid - */ - ethptr->rxBufs = (struct ethPktBuffer **)ETH_INVALID; - ethptr->txBufs = (struct ethPktBuffer **)ETH_INVALID; - ethptr->rxRing = (struct dmaDescriptor *)ETH_INVALID; - ethptr->txRing = (struct dmaDescriptor *)ETH_INVALID; - - return OK; -} diff --git a/device/bcm4713/vlanOpen.c b/device/bcm4713/vlanOpen.c deleted file mode 100644 index 08d98954..00000000 --- a/device/bcm4713/vlanOpen.c +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @file vlanOpen.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include -#include -#include - -/** - * @ingroup etherspecific - * - * Open a virtual ethernet device for use - * @param devptr ethernet device table entry - * @return OK if opened properly, otherwise SYSERR - */ -devcall vlanOpen(device *devptr) -{ - struct ether *ethptr; - - /* Initialize structure pointers */ - ethptr = ðertab[devptr->minor]; - - /* Rx and Tx buffers associated with hardware device */ - ethptr->inPool = ETH_INVALID; - ethptr->outPool = ETH_INVALID; - ethptr->state = ETH_STATE_UP; - - etherControl(devptr, ETH_CTRL_SET_MAC, (ulong)ethptr->devAddress, 0); - - return OK; -} diff --git a/device/bcm4713/vlanStat.c b/device/bcm4713/vlanStat.c deleted file mode 100644 index 7fced274..00000000 --- a/device/bcm4713/vlanStat.c +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @file vlanStat.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include "bcm4713.h" -#include "bcmswitch.h" -#include -#include - -/** - * @ingroup etherspecific - */ -int vlanStat(void) -{ - struct mdioregs *mdio = NULL; - ulong result = 0; - int table = 0, port = 0; - ushort deftags[SWT_PORTS]; - - if (NULL == swtregs.mdio) - { - fprintf(stderr, "Switch Core not found!\n"); - return 1; - } - mdio = swtregs.mdio; - - printf("VLAN Switch Status:\n"); - - switchReadReg(mdio, SWT_PAGE_VLAN, SWT_REG_VLAN_CONTROL0, &result); - printf("\tControl %d : %02lX, ", SWT_REG_VLAN_CONTROL0, result); - switchReadReg(mdio, SWT_PAGE_VLAN, SWT_REG_VLAN_CONTROL1, &result); - printf("%d : %02lX, ", SWT_REG_VLAN_CONTROL1, result); - switchReadReg(mdio, SWT_PAGE_VLAN, SWT_REG_VLAN_CONTROL2, &result); - printf("%d : %02lX, ", SWT_REG_VLAN_CONTROL2, result); - switchReadReg(mdio, SWT_PAGE_VLAN, SWT_REG_VLAN_CONTROL3, &result); - printf("%d : %02lX, ", SWT_REG_VLAN_CONTROL3, result); - switchReadReg(mdio, SWT_PAGE_VLAN, SWT_REG_VLAN_CONTROL4, &result); - printf("%d : %02lX, ", SWT_REG_VLAN_CONTROL4, result); - switchReadReg(mdio, SWT_PAGE_VLAN, SWT_REG_VLAN_CONTROL5, &result); - printf("%d : %02lX\n", SWT_REG_VLAN_CONTROL5, result); - - printf("\tVLAN Table\n"); - for (table = 0; table < SWT_VLAN_TABLEMAX; table++) - { - result = 0x2000 | table; - switchWriteReg(mdio, SWT_PAGE_VLAN, SWT_REG_VLAN_TABACC, &result); - switchReadReg(mdio, SWT_PAGE_VLAN, SWT_REG_VLAN_READ, &result); - if (result & SWT_VLAN_GROUPMASK) - { - printf("\t VID %2d:", table); - for (port = 0; port < SWT_PORTS; port++) - { - if (result & (1 << port)) - { - printf(" %d", port); - if (!(result & (1 << (port + SWT_PORTS)))) - { - if (port == SWT_CPUPORT) - { - printf("*"); - } - else - { - printf("t"); - } - } - } - } - printf("\n"); - } - } - - for (port = 0; port < SWT_PORTS; port++) - { - switchReadReg(mdio, - SWT_PAGE_VLAN, - SWT_REG_VLAN_TAGPORT0 + 2 * port, &result); - deftags[port] = result; - printf("\tDefault Port %d tag: 0x%04X\r\n", port, deftags[port]); - } - - printf("\n"); - - return 0; -} diff --git a/device/bcm4713/waitOnBit.c b/device/bcm4713/waitOnBit.c deleted file mode 100644 index acb662b8..00000000 --- a/device/bcm4713/waitOnBit.c +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @file waitOnBit.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include - -/** - * @ingroup etherspecific - * - * Wait on a bit in a device's control and status register. - * @param reg pointer to device status register - * @param mask bit to wait on - * @param value bit value desired - * @param tries number of retries before giving up - * @return OK or SYSERR - */ -int waitOnBit(volatile uint *reg, uint mask, const int value, int tries) -{ - int i = 0; - volatile int j = 0; - - for (i = 0; i < tries; i++) - { - /* break on the following conditions: - * - if expected value is non-zero, check if the register & mask has - * a non-zero value - * - if expected value is zero, check if the register & mask has - * a zero value - */ - if (((0 != value) && (*reg & mask)) - || ((0 == value) && !(*reg & mask))) - { - break; - } - - for (j = 100; j; j--) - { /* spin wait */ - } - } - - if (tries == i) - { -#ifdef DETAIL - kprintf("etherInit() TIMEOUT waiting for register "); - kprintf("0x%08X bit 0x%08X to %s\r\n", reg, - mask, (value ? "set" : "clear")); -#endif /* DETAIL */ - return SYSERR; - } - - return OK; -} diff --git a/device/bcmbus/Makerules b/device/bcmbus/Makerules deleted file mode 100644 index ab79284f..00000000 --- a/device/bcmbus/Makerules +++ /dev/null @@ -1,12 +0,0 @@ -# This Makefile contains rules to build this directory. - -# Name of this component (the directory this file is stored in) -COMP = device/bcmbus - -# Source files for this component -C_FILES = backplaneInit.c backplaneCoreDisable.c backplaneCoreReset.c backplaneCoreUp.c -S_FILES = - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/device/bcmbus/backplaneCoreDisable.c b/device/bcmbus/backplaneCoreDisable.c deleted file mode 100644 index 9ea743c6..00000000 --- a/device/bcmbus/backplaneCoreDisable.c +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @file backplaneCoreDisable.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include - -#define SBTML_RESET 0x1 /* reset */ -#define SBTML_REJ 0x2 /* reject */ -#define SBTML_CLK 0x10000 /* clock enable */ -#define SBTML_FGC 0x20000 /* force gated clocks on */ -#define SBTML_FL_MASK 0x3ffc0000 /* core-specific flags */ -#define SBTML_PE 0x40000000 /* pme enable */ -#define SBTML_BE 0x80000000 /* bist enable */ - -int waitOnBit(volatile ulong *, ulong, const ulong, ulong); - -/** - * Disable a Silicon Backplane core. - * @param bpConfig pointer to device Silicon Backplane configuration space - * @return OK if all goes well - */ -int backplaneCoreDisable(volatile struct backplaneConfig *bpConfig) -{ - volatile int i = 0; - - if (NULL == bpConfig) - { - return SYSERR; - } - - /* Check if core is already disabled. */ - if (bpConfig->tmStateLow & SBTML_RESET) - { - return OK; - } - - bpConfig->tmStateLow = (SBTML_REJ | SBTML_CLK); - waitOnBit(&bpConfig->tmStateLow, SBTML_REJ, 1, 100000); - waitOnBit(&bpConfig->tmStateHigh, SBTMH_BUSY, 0, 100000); - bpConfig->tmStateLow = - (SBTML_FGC | SBTML_CLK | SBTML_REJ | SBTML_RESET); - bpConfig->tmStateLow; - for (i = 100; i; i--) - ; - bpConfig->tmStateLow = (SBTML_REJ | SBTML_RESET); - bpConfig->tmStateLow; - for (i = 100; i; i--) - ; - return OK; -} diff --git a/device/bcmbus/backplaneCoreReset.c b/device/bcmbus/backplaneCoreReset.c deleted file mode 100644 index d5187ddc..00000000 --- a/device/bcmbus/backplaneCoreReset.c +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @file backplaneCoreReset.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include - -int backplaneReset(volatile struct backplaneConfig *bpConfig) -{ - volatile int i = 0; - - /* Reset the target core. */ - backplaneCoreDisable(bpConfig); - bpConfig->tmStateLow = (SBTML_RESET | SBTML_CLK | SBTML_FGC); - bpConfig->tmStateLow; - for (i = 10; i; i--) - ; - /* Clear SERR if set, this is a hw bug workaround. */ - if (bpConfig->tmStateHigh & SBTMH_SERR) - { - bpConfig->tmStateHigh = 0; - } - /* Clear any state errors. */ - i = bpConfig->imState; - if (i & (SBIM_IBE | SBIM_TO)) - { - bpConfig->imState = i & ~(SBIM_IBE | SBIM_TO); - } - bpConfig->tmStateLow = (SBTML_CLK | SBTML_FGC); - bpConfig->tmStateLow; - for (i = 10; i; i--) - ; - bpConfig->tmStateLow = SBTML_CLK; - bpConfig->tmStateLow; - for (i = 10; i; i--) - ; - return OK; -} diff --git a/device/bcmbus/backplaneCoreUp.c b/device/bcmbus/backplaneCoreUp.c deleted file mode 100644 index a4720138..00000000 --- a/device/bcmbus/backplaneCoreUp.c +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @file backplaneCoreUp.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include - -/** - * Query Silicon Backplane status to determine if a core is "up". - * @param bpConfig pointer to device Silicon Backplane configuration space - * @return True if device core is up - */ -int backplaneCoreUp(volatile struct backplaneConfig *bpConfig) -{ - /* Core status can be determined by checking the target state */ - /* low register's Reset, Reject and Clock bits. */ - /* Only 'Clock' should be set. */ - if (NULL == bpConfig) - { - return SYSERR; - } - return (SBTML_CLK == - (bpConfig->tmStateLow & - (SBTML_RESET | SBTML_REJ | SBTML_CLK))); -} diff --git a/device/bcmbus/backplaneInit.c b/device/bcmbus/backplaneInit.c deleted file mode 100644 index 2b755921..00000000 --- a/device/bcmbus/backplaneInit.c +++ /dev/null @@ -1,158 +0,0 @@ -/** - * @file backplaneInit.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include - -struct chipcregs *sbCore; - -/** - * Initialize Silicon Backplane bus interface. - * @param devptr pointer to an sb-bus device - */ -devcall backplaneInit(device *devptr) -{ -#if SB_BUS - int numcores = 0; - ushort vendor = 0; - ushort coreid = 0; - uchar *scanptr = NULL; - char *vendStr = NULL; - char *devcStr = NULL; - - sbCore = (struct chipcregs *)SB_ENUM_BASE; - - numcores = (sbCore->chipid & CID_CC_MASK) >> CID_CC_SHIFT; - -#ifdef DETAIL - kprintf - ("Silicon Backplane Chip ID %04X, rev %d. Number of cores = %d\r\n", - sbCore->chipid & CID_ID_MASK, - (sbCore->chipid & CID_REV_MASK) >> CID_REV_SHIFT, numcores); -#endif /* DETAIL */ - - for (scanptr = (uchar *)SB_ENUM_BASE; - (long)scanptr < - SB_ENUM_BASE + numcores * SB_CORE_SIZE; scanptr += SB_CORE_SIZE) - { - vendor = - (*(ulong *) - (scanptr + SBCONFIGOFF + - SBIDHIGH) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT; - coreid = - (*(ulong *) - (scanptr + SBCONFIGOFF + - SBIDHIGH) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT; - - if (SB_VEND_BCM == vendor) - { - vendStr = "Broadcom"; - } - else - { - vendStr = "Unknown Vendor"; - } - switch (coreid) - { - case SB_CC: - devcStr = "Chip Common"; - break; - case SB_ILINE20: - devcStr = "Iline20"; - break; - case SB_SDRAM: - devcStr = "SDRAM"; - break; - case SB_PCI: - devcStr = "PCI"; - break; - case SB_MIPS: - devcStr = "MIPS"; - break; - case SB_ENET: - devcStr = "Ethernet MAC"; - break; - case SB_CODEC: - devcStr = "v90 Codec"; - break; - case SB_USB: - devcStr = "USB 1.1 Host/Device"; - break; - case SB_ADSL: - devcStr = "ADSL"; - break; - case SB_ILINE100: - devcStr = "Iline 100"; - break; - case SB_IPSEC: - devcStr = "IPSec"; - break; - case SB_PCMCIA: - devcStr = "PCMCIA"; - break; - case SB_SOCRAM: - devcStr = "Internal Memory"; - break; - case SB_MEMC: - devcStr = "Memc SDRAM"; - break; - case SB_EXTIF: - devcStr = "External Interface"; - break; - case SB_D11: - devcStr = "802.11 MAC"; - break; - case SB_MIPS33: - devcStr = "MIPS 3302"; - break; - case SB_USB11H: - devcStr = "USB 1.1 Host"; - break; - case SB_USB11D: - devcStr = "USB 1.1 Device"; - break; - case SB_USB20H: - devcStr = "USB 2.0 Host"; - break; - case SB_USB20D: - devcStr = "USB 2.0 Device"; - break; - case SB_SDIOH: - devcStr = "SDIO Host"; - break; - case SB_ROBO: - devcStr = "RoboSwitch"; - break; - case SB_ATA100: - devcStr = "Parallel ATA"; - break; - case SB_SATAXOR: - devcStr = "Serial ATA & XOR DMA"; - break; - case SB_GIGETH: - devcStr = "Gigabit Ethernet"; - break; - - default: - devcStr = "Unknown"; - } - -#ifdef DETAIL - kprintf(" Found %s %20s Core (%03X) at 0x%08X\r\n", - vendStr, devcStr, coreid, scanptr); -#endif /* DETAIL */ - } - -#ifdef DETAIL - kprintf("\r\n"); -#endif /* DETAIL */ - -#endif /* SB_BUS */ - return OK; -} diff --git a/device/framebuffer_rpi/Makerules b/device/framebuffer_rpi/Makerules index 98534858..0e00f784 100644 --- a/device/framebuffer_rpi/Makerules +++ b/device/framebuffer_rpi/Makerules @@ -5,7 +5,8 @@ COMP = device/framebuffer_rpi # Source files for this component S_FILES = -C_FILES = screenInit.c mailbox.c drawChar.c drawShapes.c fbPutc.c fbWrite.c fbprintf.c trig.c font.c +C_FILES = drawChar.c drawShapes.c fbPutc.c fbWrite.c fbprintf.c trig.c font.c screenInit.c +#XXX mailbox.c # Add the files to the compile source path DIR = ${TOPDIR}/${COMP} diff --git a/device/framebuffer_rpi/drawShapes.c b/device/framebuffer_rpi/drawShapes.c index b49996d2..ee7a80d5 100644 --- a/device/framebuffer_rpi/drawShapes.c +++ b/device/framebuffer_rpi/drawShapes.c @@ -8,7 +8,15 @@ #include #include #include + +#if defined(_XINU_PLATFORM_ARM_RPI_3_) +#include +#elif defined (_XINU_PLATFORM_ARM_RPI_) #include +#endif + +extern void _inval_area(void *); +extern void _flush_area(void *); /* Draws a colored pixel at given (x, y) coordinates. */ @@ -24,9 +32,11 @@ void drawPixel(int x, int y, ulong color) volatile ulong *address = (volatile ulong *)(framebufferAddress + (y * pitch) + (x * (BIT_DEPTH/8))); - *address = color; - - post_peripheral_write_mb(); + dmb(); + *address = color; + dmb(); + _inval_area(address); + dmb(); } } diff --git a/device/framebuffer_rpi/mailbox.c b/device/framebuffer_rpi/mailbox.c index 4ec2deab..96b82b21 100644 --- a/device/framebuffer_rpi/mailbox.c +++ b/device/framebuffer_rpi/mailbox.c @@ -7,7 +7,7 @@ #include #include -#include +#include "../../system/platforms/arm-rpi3/bcm2837_mbox.h" /* Read from mailbox one on channel one (GPU mailbox) */ /* Note: Data: first 28 bits. Channel: last 4 bits. */ @@ -27,19 +27,17 @@ void mailboxWrite(ulong data) { while (readMMIO(MAILBOX_BASE, MAILBOX_STATUS) & MAILBOX_FULL) ; //wait for space writeMMIO(MAILBOX_BASE, MAILBOX_WRITE, toWrite); - } /* To omit illegible lines of code, a helper function that reads from * memory mapped IO registers. */ ulong readMMIO(ulong base, ulong reg) { - ulong n; - + ulong n; pre_peripheral_read_mb(); n = *(volatile ulong *)(MMIO_BASE + base + reg); - post_peripheral_read_mb(); - return n; + post_peripheral_read_mb(); + return n; } /* The opposite of above. Write to MMIO. */ @@ -47,10 +45,9 @@ void writeMMIO(ulong base, ulong reg, ulong val) { pre_peripheral_write_mb(); *(volatile ulong *)(MMIO_BASE + base + reg) = val; - post_peripheral_write_mb(); + //post_peripheral_write_mb(); } - /* Converts ARM physical addresses to ARM bus addresses. * Separate function for legibility's sake. * Rev 1 board GPU required bus addresses. Now deprecated. */ diff --git a/device/framebuffer_rpi/screenInit.c b/device/framebuffer_rpi/screenInit.c index 89107d3e..6f9e90ba 100644 --- a/device/framebuffer_rpi/screenInit.c +++ b/device/framebuffer_rpi/screenInit.c @@ -10,7 +10,12 @@ #include #include /* for banner */ #include -#include +#include +#include "../../system/platforms/arm-rpi3/bcm2837_mbox.h" +#include +#include + +extern void _inval_area(void *); int rows; int cols; @@ -23,88 +28,163 @@ bool minishell; ulong framebufferAddress; int pitch; bool screen_initialized; +volatile unsigned int __attribute__((aligned(16))) mbox[36]; + +/* Make a mailbox call. Returns 0 on failure, non-zero on success */ +int mbox_call(unsigned char ch) +{ + unsigned int r = (((unsigned int)((unsigned long)&mbox)&~0xF) | (ch&0xF)); + /* wait until we can write to the mailbox */ + do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_FULL); + /* write the address of our message to the mailbox with channel identifier */ + *MBOX_WRITE = r; + /* now wait for the response */ + while(1) { + // LED on here... there is a response... + /* Is there a response? */ + do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_EMPTY); + /* Is it a response to our message? */ + if(r == *MBOX_READ){ + /* Is it a valid successful response? */ + // LED on... apparently the response is successful + return mbox[1]==MBOX_RESPONSE; + } + } + return 0; +} /* screenInit(): Calls framebufferInit() several times to ensure we successfully initialize, just in case. */ void screenInit() { int i = 0; - while (framebufferInit() == SYSERR) { - if ( (i++) == MAXRETRIES) { - screen_initialized = FALSE; - return; - } - } + + while (framebufferInit() == SYSERR) { + if ( (i++) == MAXRETRIES) { + screen_initialized = FALSE; + return; + } + } + // clear the screen to the background color. screenClear(background); - initlinemap(); - screen_initialized = TRUE; + initlinemap(); + screen_initialized = TRUE; } /* Initializes the framebuffer used by the GPU. Returns OK on success; SYSERR on failure. */ int framebufferInit() { - //GPU expects this struct to be 16 byte aligned - struct framebuffer frame __attribute__((aligned (16))); - frame.width_p = DEFAULT_WIDTH; //must be less than 4096 - frame.height_p = DEFAULT_HEIGHT; //must be less than 4096 - frame.width_v = DEFAULT_WIDTH; //must be less than 4096 - frame.height_v = DEFAULT_HEIGHT; //must be less than 4096 - frame.pitch = 0; //no space between rows - frame.depth = BIT_DEPTH; //must be equal to or less than 32 - frame.x = 0; //no x offset - frame.y = 0; //no y offset - frame.address = 0; //always initializes to 0x48006000 - frame.size = 0; + // LED turns on here... - mailboxWrite((ulong)&frame); + //XXXbcm2837_mailbox_write(MAILBOX_CH_PROPERTY, (uint)&frame); - ulong result = mailboxRead(); + //XXXulong result = bcm2837_mailbox_read(MAILBOX_CH_PROPERTY); + + mbox[0] = 35*4; + mbox[1] = MBOX_REQUEST; - /* Error checking */ - if (result) { //if anything but zero - return SYSERR; - } - if (!frame.address) { //if address remains zero + mbox[2] = 0x48003; //set phy wh + mbox[3] = 8; + mbox[4] = 8; + mbox[5] = 1024; //FrameBufferInfo.width + mbox[6] = 768; //FrameBufferInfo.height + + mbox[7] = 0x48004; //set virt wh + mbox[8] = 8; + mbox[9] = 8; + mbox[10] = 1024; //FrameBufferInfo.virtual_width + mbox[11] = 768; //FrameBufferInfo.virtual_height + + mbox[12] = 0x48009; //set virt offset + mbox[13] = 8; + mbox[14] = 8; + mbox[15] = 0; //FrameBufferInfo.x_offset + mbox[16] = 0; //FrameBufferInfo.y.offset + + mbox[17] = 0x48005; //set depth + mbox[18] = 4; + mbox[19] = 4; + mbox[20] = 32; //FrameBufferInfo.depth + + mbox[21] = 0x48006; //set pixel order + mbox[22] = 4; + mbox[23] = 4; + mbox[24] = 1; //RGB, not BGR preferably + + mbox[25] = 0x40001; //get framebuffer, gets alignment on request + mbox[26] = 8; + mbox[27] = 8; + mbox[28] = 4096; //FrameBufferInfo.pointer + mbox[29] = 0; //FrameBufferInfo.size + + mbox[30] = 0x40008; //get pitch + mbox[31] = 4; + mbox[34] = MBOX_TAG_LAST; + + // LED turns on here... + + if(mbox_call(MAILBOX_CH_PROPERTY) && mbox[20]==32 && mbox[28]!=0) { + + led_init(); + led_on(); + + mbox[28]&=0x3FFFFFFF; + cols=mbox[5]; + rows=mbox[6]; + pitch=mbox[33]; + framebufferAddress=(ulong)((unsigned long)mbox[28]); + } else { // If mailbox call ends in error, return return SYSERR; } + + /* Error checking */ + /*if (result) { //if anything but zero + return SYSERR; + } + if (!frame.address) { //if address remains zero + return SYSERR; + }*/ - /* Initialize global variables */ - framebufferAddress = frame.address; - rows = frame.height_p / CHAR_HEIGHT; - cols = frame.width_p / CHAR_WIDTH; - pitch = frame.pitch; - cursor_row = 0; - cursor_col = 0; - background = BLACK; - foreground = WHITE; - minishell = FALSE; + /* Initialize global variables */ + //framebufferAddress = frame.address; + //rows = frame.height_p / CHAR_HEIGHT; + //cols = frame.width_p / CHAR_WIDTH; + //pitch = frame.pitch; + cursor_row = 0; + cursor_col = 0; + background = RED; + foreground = CYAN; + minishell = FALSE; return OK; } /* Very heavy handed clearing of the screen to a single color. */ void screenClear(ulong color) { ulong *address = (ulong *)(framebufferAddress); - ulong *maxaddress = (ulong *)(framebufferAddress + (DEFAULT_HEIGHT * pitch) + (DEFAULT_WIDTH * (BIT_DEPTH / 8))); - while (address != maxaddress) { - *address = color; - address++; - } + ulong *maxaddress = (ulong *)(framebufferAddress + (DEFAULT_HEIGHT * pitch) + (DEFAULT_WIDTH * (BIT_DEPTH / 8))); + while (address != maxaddress) { + *address = color; + _inval_area(address); + address++; + } + _inval_area((void *)framebufferAddress); } /* Clear the minishell window */ void minishellClear(ulong color) { - ulong *address = (ulong *)(framebufferAddress + (pitch * (DEFAULT_HEIGHT - (MINISHELLMINROW * CHAR_HEIGHT))) + (DEFAULT_WIDTH * (BIT_DEPTH / 8))); - ulong *maxaddress = (ulong *)(framebufferAddress + (DEFAULT_HEIGHT * pitch) + (DEFAULT_WIDTH * (BIT_DEPTH / 8))); - while (address != maxaddress) { - *address = color; - address++; - } + ulong *address = (ulong *)(framebufferAddress + (pitch * (DEFAULT_HEIGHT - (MINISHELLMINROW * CHAR_HEIGHT))) + (DEFAULT_WIDTH * (BIT_DEPTH / 8))); + ulong *maxaddress = (ulong *)(framebufferAddress + (DEFAULT_HEIGHT * pitch) + (DEFAULT_WIDTH * (BIT_DEPTH / 8))); + while (address != maxaddress) { + *address = color; + address++; + } + _inval_area((void *)framebufferAddress); } /* Clear the "linemapping" array used to keep track of pixels we need to remember */ void initlinemap() { - int i = MAPSIZE; - while (i != 0) { - i--; - linemap[i] = background; - } + int i = MAPSIZE; + while (i != 0) { + i--; + linemap[i] = background; + } } diff --git a/device/lan7800/Makerules b/device/lan7800/Makerules new file mode 100644 index 00000000..95320842 --- /dev/null +++ b/device/lan7800/Makerules @@ -0,0 +1,20 @@ +# This Makefile contains rules to build this directory + +# Name of this component (the directory this file is stored in) +COMP = device/lan7800 + +# Source files for this component +C_FILES = lan7800.c \ + etherInit.c \ + etherOpen.c \ + etherClose.c \ + etherInterrupt.c \ + etherRead.c \ + etherWrite.c \ + etherControl.c \ + +S_FILES = + +# Add the files to the compile source path +DIR = ${TOPDIR}/${COMP} +COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/device/smsc9512/etherClose.c b/device/lan7800/etherClose.c similarity index 62% rename from device/smsc9512/etherClose.c rename to device/lan7800/etherClose.c index 980a654e..44759778 100644 --- a/device/smsc9512/etherClose.c +++ b/device/lan7800/etherClose.c @@ -1,12 +1,17 @@ /** * @file etherClose.c + * + * @authors + * Rade Latinovich + * Patrick J. McGee + * */ -/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ +/* Embedded Xinu, Copyright (C) 2018. All rights reserved. */ #include /* Implementation of etherClose() for the smsc9512; see the documentation for - * this function in ether.h. */ + * * this function in ether.h. */ devcall etherClose(device *devptr) { /* TODO: need to handle canceling all the outstanding USB requests, etc. */ diff --git a/device/smsc9512/etherControl.c b/device/lan7800/etherControl.c similarity index 57% rename from device/smsc9512/etherControl.c rename to device/lan7800/etherControl.c index 50e3ebc8..cee2d98a 100644 --- a/device/smsc9512/etherControl.c +++ b/device/lan7800/etherControl.c @@ -1,14 +1,19 @@ /** * @file etherControl.c + * + * Simple contoller to handle requests of the MicroChip LAN7800 device. + * + * Authors: Patrick J. McGee + * Rade Latinovich */ -/* Embedded Xinu, Copyright (C) 2008, 2013. All rights reserved. */ +/* Embedded Xinu, Copyright (C) 2008, 2013, 2018. All rights reserved. */ #include #include #include -#include "smsc9512.h" +#include "lan7800.h" -/* Implementation of etherControl() for the smsc9512; see the documentation for +/* Implementation of etherControl() for the LAN7800 device; see the documentation for * this function in ether.h. */ devcall etherControl(device *devptr, int req, long arg1, long arg2) { @@ -30,19 +35,39 @@ devcall etherControl(device *devptr, int req, long arg1, long arg2) { /* Program MAC address into device. */ case ETH_CTRL_SET_MAC: - status = smsc9512_set_mac_address(udev, (const uchar*)arg1); + status = lan7800_set_mac_address(udev, (const uchar*)arg1); break; /* Get MAC address from device. */ case ETH_CTRL_GET_MAC: - status = smsc9512_get_mac_address(udev, (uchar*)arg1); + status = lan7800_get_mac_address(udev, (uchar*)arg1); break; /* Enable or disable loopback mode. */ - case ETH_CTRL_SET_LOOPBK: - status = smsc9512_modify_reg(udev, MAC_CR, ~MAC_CR_LOOPBK, - ((bool)arg1 == TRUE) ? MAC_CR_LOOPBK : 0); - break; + case ETH_CTRL_SET_LOOPBK:; + uint32_t buf; + + // disable tx and rx + lan7800_read_reg(udev, LAN7800_MAC_RX, &buf); + buf &= ~(LAN7800_MAC_RX_RXEN); + lan7800_write_reg(udev, LAN7800_MAC_RX, buf); + + lan7800_read_reg(udev, LAN7800_MAC_TX, &buf); + buf &= ~(LAN7800_MAC_TX_TXEN); + lan7800_write_reg(udev, LAN7800_MAC_TX, buf); + + status = lan7800_modify_reg(udev, LAN7800_MAC_CR, ~MAC_CR_LOOPBACK, + ((bool)arg1 == TRUE) ? MAC_CR_LOOPBACK : 0); + // enable tx and rx + lan7800_read_reg(udev, LAN7800_MAC_RX, &buf); + buf |= (LAN7800_MAC_RX_RXEN); + lan7800_write_reg(udev, LAN7800_MAC_RX, buf); + + lan7800_read_reg(udev, LAN7800_MAC_TX, &buf); + buf |= (LAN7800_MAC_TX_TXEN); + lan7800_write_reg(udev, LAN7800_MAC_TX, buf); + + break; /* Get link header length. */ case NET_GET_LINKHDRLEN: diff --git a/device/lan7800/etherInit.c b/device/lan7800/etherInit.c new file mode 100644 index 00000000..ebb977e9 --- /dev/null +++ b/device/lan7800/etherInit.c @@ -0,0 +1,240 @@ +/** + * @file etherInit.c + * + * @authors + * Rade Latinovich + * Patrick J. McGee + * + * Initialization for the LAN7800 USB Ethernet Adapter + */ +/* Embedded Xinu, Copyright (C) 2018. All rights reserved. */ + +#include "lan7800.h" +#include +#include +#include +#include +#include +#include +#include +#include "../../system/platforms/arm-rpi3/bcm2837_mbox.h" +#include +#include +#include "../system/platforms/arm-rpi3/bcm2837.h" + +bool lan7800_isattached = 0; + +/* Global table of Ethernet devices. */ +struct ether ethertab[NETHER]; + +/** + * Semaphores that indicate whether each given Ethernet device is connected to the system + * yet (in our case, attached to USB). + */ +static semaphore lan7800_attached[NETHER]; + +/* Global variable which contains the MAC address after + * getEthAddr() is called. This is later copied to the + * devAddress member of the ether struct using memcpy(). */ +uchar addr[ETH_ADDR_LEN] = {0}; + +/** + * Try to bind the LAN7800 driver to a specific USB device. + */ +static usb_status_t +lan7800_bind_device(struct usb_device *udev) +{ + struct ether *ethptr; + + /* Check if this is actually a LAN7800 by checking the USB device's + * standard device descriptor, which the USB core already read into memory. + * Also check to make sure the expected endpoints for sending/receiving + * packets are present and that the device is operating at high speed. */ + if (udev->descriptor.idVendor != LAN7800_VENDOR_ID || + udev->descriptor.idProduct != LAN7800_PRODUCT_ID || + udev->interfaces[0]->bNumEndpoints < 2 || + (udev->endpoints[0][0]->bmAttributes & 0x3) != USB_TRANSFER_TYPE_BULK || + (udev->endpoints[0][1]->bmAttributes & 0x3) != USB_TRANSFER_TYPE_BULK || + (udev->endpoints[0][0]->bEndpointAddress >> 7) != USB_DIRECTION_IN || + (udev->endpoints[0][1]->bEndpointAddress >> 7) != USB_DIRECTION_OUT || + udev->speed != USB_SPEED_HIGH) + { + return USB_STATUS_DEVICE_UNSUPPORTED; + } + + /* Make sure this driver isn't already bound to a LAN7800. + * * TODO: Support multiple devices of this type concurrently. */ + ethptr = ðertab[0]; + STATIC_ASSERT(NETHER == 1); + if (ethptr->csr != NULL) + { + return USB_STATUS_DEVICE_UNSUPPORTED; + } + + /* The rest of this function is responsible for making the LAN7800 + * ready to use, but not actually enabling Rx and Tx (which is done in + * etherOpen()). This primarily involves writing to the registers on the + * LAN7800. But these are not memory mapped registers, as this is a + * USB Ethernet Adapter that is attached on the USB! Instead, registers are + * read and written using USB control transfers. It's somewhat of a pain, + * and also unlike memory accesses it is possible for USB control transfers + * to fail. However, here we perform lazy error checking where we just do + * all the needed reads and writes, then check at the end if an error + * occurred. */ + udev->last_error = USB_STATUS_SUCCESS; + + /* Check for error and return. */ + if (udev->last_error != USB_STATUS_SUCCESS) + { + return udev->last_error; + } + + ethptr->csr = udev; + udev->driver_private = ethptr; + + signal(lan7800_attached[ethptr - ethertab]); + + return USB_STATUS_SUCCESS; +} + +/** + * Unbinds the LAN7800 driver from the LAN7800 device that has been detached. + */ +static void +lan7800_unbind_device(struct usb_device *udev) +{ + + struct ether *ethptr = udev->driver_private; + + /* Reset attached semaphore to 0. */ + wait(lan7800_attached[ethptr - ethertab]); + + /* Close the device. */ + etherClose(ethptr->dev); + +} + +/** + * Specification of a USB device driver for the LAN7800 device. This is for the USB core subsystem + * and not related to Xinu's primary device and driver model. + */ +static const struct usb_device_driver lan7800_driver = { + .name = "LAN7800 USB Ethernet Adapter Driver", + .bind_device = lan7800_bind_device, + .unbind_device = lan7800_unbind_device, +}; + +/* Get static MAC address from Pi 3 B+ chip, based on the XinuPi + * mailbox technique. + * + * @details + * + * Get the Pi 3 B+'s MAC address using its ARM->VideoCore (VC) mailbox + * and assign corresponding values to a global array containing the MAC. + * This array is then assigned to the devAddress member of the ether structure. + */ +static void +getEthAddr(uint8_t *addr) +{ + /* Initialize the mailbox buffer */ + uint32_t *mailbuffer; + mailbuffer = dma_buf_alloc(MBOX_BUFLEN / 4); + + /* Fill the mailbox buffer with the MAC address. + * This function is defined in system/platforms/arm-rpi3/bcm2837_mbox.c */ + get_mac_mailbox(mailbuffer); + + ushort i; + for (i = 0; i < 2; ++i) { + + /* Access the MAC value within the buffer */ + uint32_t value = mailbuffer[MBOX_HEADER_LENGTH + TAG_HEADER_LENGTH + i]; + + /* Store the low MAC values */ + if(i == 0){ + addr[0] = (value >> 0) & 0xff; + addr[1] = (value >> 8) & 0xff; + addr[2] = (value >> 16) & 0xff; + addr[3] = (value >> 24) & 0xff; + } + + /* Store the remaining high MAC values */ + if(i == 1){ + addr[4] = (value >> 0) & 0xff; + addr[5] = (value >> 8) & 0xff; + } + } +} + +/** + * @ingroup etherspecific + * Wait until the specified Ethernet device has been attached. + * This is necessary because USB is a dynamic bus, but Xinu expects static devices. + * @param minor + * Minor number of the Ethernet device to wait for. + * @return + * Currently ::USB_STATUS_SUCCESS. + */ +usb_status_t +lan7800_wait_device_attached(ushort minor) +{ + wait(lan7800_attached[minor]); + signal(lan7800_attached[minor]); + lan7800_isattached = 1; + return USB_STATUS_SUCCESS; +} + +/* Implementation of etherInit() for lan7800; documentation in ether.h */ +/** + * @details + * LAN7800-specific notes: This function returns ::OK if the Ethernet + * Driver was successfully registered with the USB core, otherwise ::SYSERR. + * This is a work-around to use USB's dynamic device model at the same time as + * Xinu's static device model, and there is no guarantee that the device + * actually exists when the function returns. + */ +devcall etherInit(device *devptr) +{ + struct ether *ethptr; + usb_status_t status; + + /* Initialize static ether struct for this device. */ + ethptr = ðertab[devptr->minor]; + bzero(ethptr, sizeof(struct ether)); + ethptr->dev = devptr; + ethptr->state = ETH_STATE_DOWN; + ethptr->mtu = ETH_MTU; + ethptr->addressLength = ETH_ADDR_LEN; + ethptr->isema = semcreate(0); + if (isbadsem(ethptr->isema)) + { + goto err; + } + + /* Create semaphore for device attachment. */ + lan7800_attached[devptr->minor] = semcreate(0); + + if (isbadsem(lan7800_attached[devptr->minor])) + { + goto err_free_isema; + } + + /* Get the MAC address and store it into addr[] */ + getEthAddr(ethptr->devAddress); + + /* Register this device driver with the USB core and return. */ + status = usb_register_device_driver(&lan7800_driver); + if (status != USB_STATUS_SUCCESS) + { + goto err_free_attached_sema; + } + + return OK; + +err_free_attached_sema: + semfree(lan7800_attached[devptr->minor]); +err_free_isema: + semfree(ethptr->isema); +err: + return SYSERR; +} diff --git a/device/lan7800/etherInterrupt.c b/device/lan7800/etherInterrupt.c new file mode 100644 index 00000000..042c48b6 --- /dev/null +++ b/device/lan7800/etherInterrupt.c @@ -0,0 +1,143 @@ +/** + * @file lan7800_interrupt.c + * + * @authors Patrick J. McGee + * Rade Latinovich + * + * This file provides USB transfer completion callbacks for the + * Microchip LAN7800 USB Ethernet Adapter. + * + */ +/* Embedded Xinu, Copyright (C) 2018. All rights reserved. */ + +#include "lan7800.h" +#include +#include +#include +#include +#include + +/** + * @ingroup etherspecific + * + * Callback function executed with interrupts disabled when an asynchronous USB + * bulk transfer to the Bulk OUT endpoint of the Microchip LAN7800 USB Ethernet + * Adapter for the purpose of sending an Ethernet packet has successfully + * completed or has failed. + * + * Currently all this function has to do is return the buffer to its pool. This + * may wake up a thread in etherWrite() that is waiting for a free buffer. + * + * @param req + * USB bulk OUT transfer request that has completed. + */ +void lan7800_tx_complete(struct usb_xfer_request *req) +{ + struct ether *ethptr = req->private; + + ethptr->txirq++; + usb_dev_debug(req->dev, "\r\n\nLAN7800: Tx complete\r\n"); + buffree(req); +} + +/** + * @ingroup etherspecific + * + * Callback function executed with interrupts disabled when an asynchronous USB + * bulk transfer from the Bulk IN endpoint of the Microchip LAN7800 USB Ethernet + * Adapter for the purpose of receiving one or more Ethernet packets has + * successfully completed or has failed. + * + * This function is responsible for breaking up the raw USB transfer data into + * the constituent Ethernet packet(s), then pushing them onto the incoming + * packets queue (which may wake up threads in etherRead() that are waiting for + * new packets). It then must re-submit the USB bulk transfer request so that + * packets can continue to be received. + * + * @param req + * USB bulk IN transfer request that has completed. + */ +void lan7800_rx_complete(struct usb_xfer_request *req) +{ + struct ether *ethptr = req->private; + + usb_dev_debug(req->dev, "\r\n\nLAN7800: Rx complete\r\n"); + ethptr->rxirq++; + usb_dev_debug(req->dev, "req->status = %d\r\n", req->status); + usb_dev_debug(req->dev, "(req->status == USB_STATUS_SUCCESS) ? = %s\r\n", + (req->status == USB_STATUS_SUCCESS) ? "TRUE" : "FALSE"); + usb_dev_debug(req->dev, "req->recvbuf = 0x%08X\r\n", req->recvbuf); + usb_dev_debug(req->dev, "req->actual_size = %d\r\n", req->actual_size); + if (req->status == USB_STATUS_SUCCESS) + { + const uint8_t *data, *edata; + uint32_t frame_length; + + uint32_t rx_cmd_a; + + /* For each Ethernet frame in the received USB data... */ + for (data = req->recvbuf, edata = req->recvbuf + req->actual_size; + data + RX_OVERHEAD + ETH_HDR_LEN + ETH_CRC_LEN <= edata; + data += RX_OVERHEAD + ((frame_length + 3) & ~3)) + { + /* Get the RxA, RxB, RxC status word, which contains information about the next + * Ethernet frame. */ + rx_cmd_a = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24; + + /* Extract frame_length, which specifies the length of the next + * Ethernet frame from the MAC destination address to end of the CRC + * following the payload. (This does not include the Rx status + * words, which we instead account for in RX_OVERHEAD.) */ + frame_length = (rx_cmd_a & RX_CMD_A_LEN_MASK); + + if ((rx_cmd_a & RX_CMD_A_RED) || + (frame_length + RX_OVERHEAD > edata - data) || + (frame_length > ETH_MAX_PKT_LEN + ETH_CRC_LEN) || + (frame_length < ETH_HDR_LEN + ETH_CRC_LEN)) + { + /* The Ethernet adapter set the error flag to indicate a problem + * or the Ethernet frame size it provided was invalid. */ + //usb_dev_debug(req->dev, "LAN78XX: Tallying rx error " + //"(recv_status=0x%08x, frame_length=%u)\n", + //recv_status, frame_length); + ethptr->errors++; + } + else if (ethptr->icount == ETH_IBLEN) + { + /* No space to buffer another received packet. */ + usb_dev_debug(req->dev, "LAN78XX: Tallying overrun\n"); + ethptr->ovrrun++; + } + else + { + /* Buffer the received packet. */ + struct ethPktBuffer *pkt; + + pkt = bufget(ethptr->inPool); + pkt->buf = pkt->data = (uint8_t*)(pkt + 1); + pkt->length = frame_length - ETH_CRC_LEN; + memcpy(pkt->buf, data + RX_OVERHEAD, pkt->length); + ethptr->in[(ethptr->istart + ethptr->icount) % ETH_IBLEN] = pkt; + ethptr->icount++; + + usb_dev_debug(req->dev, "LAN78XX: Receiving " + "packet (length=%u, icount=%u)\n", + pkt->length, ethptr->icount); + + /* This may wake up a thread in etherRead(). */ + signal(ethptr->isema); + } + } + } + else + { + /* USB transfer failed for some reason. */ + usb_dev_debug(req->dev, "\r\n\nLAN78XX: USB Rx transfer failed\n"); + ethptr->errors++; + } + usb_dev_debug(req->dev, "LAN78XX: Re-submitting USB Rx request\n"); + usb_submit_xfer_request(req); + +} + + diff --git a/device/lan7800/etherOpen.c b/device/lan7800/etherOpen.c new file mode 100644 index 00000000..1398a762 --- /dev/null +++ b/device/lan7800/etherOpen.c @@ -0,0 +1,137 @@ +/** + * @file lan7800_open.c + * + * @authors + * Patrick J. McGee + * Rade Latinovich + * + * Routine for opening a Microchip LAN7800 USB Ethernet Adapter device. + */ +/* Embedded Xinu, Copyright (C) 2018. All rights reserved. */ + +#include +#include +#include +#include +#include +#include "lan7800.h" + +/* Implementation of etherOpen() for the lan7800; see the documentation for + * this function in ether.h. */ +devcall etherOpen(device *devptr) +{ + struct ether *ethptr; + struct usb_device *udev; + irqmask im; + int retval = SYSERR; + + im = disable(); + /* Wait for USB device to actually be attached. */ + if (lan7800_wait_device_attached(devptr->minor) != USB_STATUS_SUCCESS) + { + goto out_restore; + } + + /* Fail if device is not down. */ + ethptr = ðertab[devptr->minor]; + if (ethptr->state != ETH_STATE_DOWN) + { + goto out_restore; + } + + /* Create buffer pool for Tx transfers. */ +#define LAN7800_MAX_TX_REQUESTS 1 + ethptr->outPool = bfpalloc(sizeof(struct usb_xfer_request) + + ETH_MAX_PKT_LEN + + LAN7800_TX_OVERHEAD, + LAN7800_MAX_TX_REQUESTS); + if (ethptr->outPool == SYSERR) + { + goto out_restore; + } + + /* Create buffer pool for Rx packets (not the actual USB transfers, which + * are allocated separately). */ + ethptr->inPool = bfpalloc(sizeof(struct ethPktBuffer) + ETH_MAX_PKT_LEN, + ETH_IBLEN); + if (ethptr->inPool == SYSERR) + { + goto out_free_out_pool; + } + + /* We're abusing the csr field to store a pointer to the USB device + * structure. At least it's somewhat equivalent, since it's what we need to + * actually communicate with the device hardware. */ + udev = ethptr->csr; + + + /* The rest of this function is responsible for making the LAN78xx + * ready to use, but not actually enabling Rx and Tx (which is done in + * etherOpen()). This primarily involves writing to the registers on the + * LAN78xx. But these are not memory mapped registers, as this is a + * USB Ethernet Adapter that is attached on the USB! Instead, registers are + * read and written using USB control transfers. It's somewhat of a pain, + * and also unlike memory accesses it is possible for USB control transfers + * to fail. However, here we perform lazy error checking where we just do + * all the needed reads and writes, then check at the end if an error + * occurred. */ + udev->last_error = USB_STATUS_SUCCESS; + + retval = lan7800_init(udev, ðptr->devAddress[0]); + if (retval < 0) goto out_free_in_pool; + + /* Initialize the Tx requests. */ + { + struct usb_xfer_request *reqs[LAN7800_MAX_TX_REQUESTS]; + for (int i = 0; i < LAN7800_MAX_TX_REQUESTS; i++) + { + struct usb_xfer_request *req; + + req = bufget(ethptr->outPool); + usb_init_xfer_request(req); + req->dev = udev; + /* Assign Tx endpoint, checked in lan78xx_bind_device() */ + req->endpoint_desc = udev->endpoints[0][1]; + req->sendbuf = (uint8_t*)req + sizeof(struct usb_xfer_request); + req->completion_cb_func = lan7800_tx_complete; + req->private = ethptr; + reqs[i] = req; + } + for (int i = 0; i < LAN7800_MAX_TX_REQUESTS; i++) + { + buffree(reqs[i]); + } + } + + /* Allocate and submit the Rx requests. TODO: these aren't freed anywhere. */ +#define LAN7800_MAX_RX_REQUESTS 1 + for (int i = 0; i < LAN7800_MAX_RX_REQUESTS; i++) + { + struct usb_xfer_request *req; + + req = usb_alloc_xfer_request(LAN7800_DEFAULT_BURST_CAP_SIZE); + if (req == NULL) + { + goto out_free_in_pool; + } + req->dev = udev; + /* Assign Rx endpoint, checked in lan78xx_bind_device() */ + req->endpoint_desc = udev->endpoints[0][0]; + req->completion_cb_func = lan7800_rx_complete; + req->private = ethptr; + usb_submit_xfer_request(req); + } + + /* Success! Set the device to ETH_STATE_UP. */ + ethptr->state = ETH_STATE_UP; + retval = OK; + goto out_restore; + +out_free_in_pool: + bfpfree(ethptr->inPool); +out_free_out_pool: + bfpfree(ethptr->outPool); +out_restore: + restore(im); + return retval; +} diff --git a/device/smsc9512/etherRead.c b/device/lan7800/etherRead.c similarity index 69% rename from device/smsc9512/etherRead.c rename to device/lan7800/etherRead.c index c7ace72a..a10bbbc6 100644 --- a/device/smsc9512/etherRead.c +++ b/device/lan7800/etherRead.c @@ -1,14 +1,30 @@ /** * @file etherRead.c + * + * Authors: Patrick J. McGee + * Rade Latinovich + * */ -/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ +/* Embedded Xinu, Copyright (C) 2018. All rights reserved. */ #include #include #include #include -/* Implementation of etherRead() for the smsc9512; see the documentation for +#define ALLOC_CACHE_ALIGN_BUFFER(type, name, size) \ + ALLOC_ALIGN_BUFFER(type, name, size, ARCH_DMA_MINALIGN) + +#define ALLOC_ALIGN_BUFFER(type, name, size, align) \ + ALLOC_ALIGN_BUFFER_PAD(type, name, size, align, 1) + +#define ALLOC_ALIGN_BUFFER_PAD(type, name, size, align, pad) \ + char __##name[ROUND(PAD_SIZE((size) * sizeof(type), pad), align) \ + + (align - 1)]; + +#define PAD_SIZE(s, pad) (PAD_COUNT(s, pad) * pad) + +/* Implementation of etherRead() for the MicroChip LAN7800; see the documentation for * this function in ether.h. */ devcall etherRead(device *devptr, void *buf, uint len) { diff --git a/device/lan7800/etherWrite.c b/device/lan7800/etherWrite.c new file mode 100644 index 00000000..6fea184f --- /dev/null +++ b/device/lan7800/etherWrite.c @@ -0,0 +1,65 @@ +/** + * @file etherWrite.c + */ +/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ + +#include "lan7800.h" +#include +#include +#include +#include +#include + +/* Implementation of etherWrite() for the MicroChip LAN7800; see the documentation + * for this function in ether.h. */ +devcall etherWrite(device *devptr, const void *buf, uint len) +{ + struct ether *ethptr; + struct usb_xfer_request *req; + uint8_t *sendbuf; + uint32_t tx_cmd_a, tx_cmd_b; + + ethptr = ðertab[devptr->minor]; + if (ethptr->state != ETH_STATE_UP || + len < ETH_HEADER_LEN || len > ETH_HDR_LEN + ETH_MTU) + { + return SYSERR; + } + + /* Get a buffer for the packet. (This may block.) */ + req = bufget(ethptr->outPool); + + /* Copy the packet's data into the buffer, but also include two words at the + * beginning that contain device-specific flags. These two fields are + * required, although we essentially just use them to tell the hardware we + * are transmitting one (1) packet with no extra bells and whistles. */ + + sendbuf = req->sendbuf; + tx_cmd_a = (len & TX_CMD_A_LEN_MASK) | TX_CMD_A_FCS; + sendbuf[0] = (tx_cmd_a >> 0) & 0xff; + sendbuf[1] = (tx_cmd_a >> 8) & 0xff; + sendbuf[2] = (tx_cmd_a >> 16) & 0xff; + sendbuf[3] = (tx_cmd_a >> 24) & 0xff; + tx_cmd_b = 0; + sendbuf[4] = (tx_cmd_b >> 0) & 0xff; + sendbuf[5] = (tx_cmd_b >> 8) & 0xff; + sendbuf[6] = (tx_cmd_b >> 16) & 0xff; + sendbuf[7] = (tx_cmd_b >> 24) & 0xff; + STATIC_ASSERT(TX_OVERHEAD == 8); + memcpy(sendbuf + TX_OVERHEAD, buf, len); + + /* Set total size of the data to send over the USB. */ + req->size = len + TX_OVERHEAD; + + /* Submit the data as an asynchronous bulk USB transfer. In other words, + * this tells the USB subsystem to send begin sending the data over the USB + * to the LAN7800 USB Ethernet Adapter. At some later time when all + * the data has been transferred over the USB, lan7800_tx_complete() will + * be called by the USB subsystem. */ + usb_submit_xfer_request(req); + + /* Return the length of the packet written (not including the + * device-specific fields that were added). */ + return len; + +} diff --git a/device/lan7800/lan7800.c b/device/lan7800/lan7800.c new file mode 100644 index 00000000..bdb77f21 --- /dev/null +++ b/device/lan7800/lan7800.c @@ -0,0 +1,475 @@ +/** + * @file lan7800.c + * + * @authors + * Rade Latinovich + * Patrick J. McGee + * + * This file provides various functions needed by the Microchip LAN7800 USB Ethernet Driver, + * equipped on the Raspberry Pi 3 Model B+. + * + * These functions are based on those of the LAN78XX drivers found in: + * - The Linux Kernel + * (https://github.com/torvalds/linux/blob/master/drivers/net/usb/lan78xx.c) + * - U-Boot + * (https://github.com/u-boot/u-boot/blob/af15946aa081dbcd0bec7d507a2b2db4e6b6cda5/drivers/usb/eth/lan78xx.c) + * + * Embedded Xinu, Copyright (C) 2018. All rights reserved. + */ + +#include "lan7800.h" +#include +#include +#include +#include + +/** + * Write to a register on the Microchip LAN7800 USB Ethernet Adapter. + * @param udev + * USB device for the adapter + * @param index + * Index of the register to write + * @param data + * Value to write to the register + * @return + * ::USB_STATUS_SUCCESS on success; otherwise another ::usb_status_t error + * code. + */ + usb_status_t +lan7800_write_reg(struct usb_device *udev, uint32_t index, uint32_t data) +{ + return usb_control_msg(udev, NULL, + LAN7800_VENDOR_REQUEST_WRITE, + USB_BMREQUESTTYPE_DIR_OUT | + USB_BMREQUESTTYPE_TYPE_VENDOR | + USB_BMREQUESTTYPE_RECIPIENT_DEVICE, + 0, index, &data, sizeof(uint32_t)); +} + +/** + * Read from a register on the Microchip LAN7800 USB Ethernet Adapter. + * @param udev + * USB device for the adapter + * @param index + * Index of the register to read + * @param data + * Pointer into which to write the register's value + * @return + * ::USB_STATUS_SUCCESS on success; otherwise another ::usb_status_t error + * code. + */ + usb_status_t +lan7800_read_reg(struct usb_device *udev, uint32_t index, uint32_t *data) +{ + return usb_control_msg(udev, NULL, + LAN7800_VENDOR_REQUEST_READ, + USB_BMREQUESTTYPE_DIR_IN | + USB_BMREQUESTTYPE_TYPE_VENDOR | + USB_BMREQUESTTYPE_RECIPIENT_DEVICE, + 0, index, data, sizeof(uint32_t)); +} + +/** + * Modify the value contained in a register on the Microchip LAN7800 USB Ethernet + * Adapter. + * @param udev + * USB device for the adapter + * @param index + * Index of the register to modify + * @param mask + * Mask that contains 1 for the bits where the old value in the register + * will be kept rather than cleared (unless those bits also appear in @p + * set, in which case they will still be set). + * @param set + * Mask of bits to set in the register. + * @return + * ::USB_STATUS_SUCCESS on success; otherwise another ::usb_status_t error + * code. + */ + usb_status_t +lan7800_modify_reg(struct usb_device *udev, uint32_t index, + uint32_t mask, uint32_t set) +{ + usb_status_t status; + uint32_t val; + + status = lan7800_read_reg(udev, index, &val); + if (status != USB_STATUS_SUCCESS) + { + return status; + } + val &= mask; + val |= set; + return lan7800_write_reg(udev, index, val); +} + +/** + * Set bits in a register on the Microchip LAN7800 USB Ethernet Adapter. + * @param udev + * USB Device for the adapter + * @param index + * Index of the register to modify + * @param set + * Bits to set in the register. At positions where the is a 0, the old value + * in the register will be written. + * @return + * ::USB_STATUS_SUCCESS on success; otherwise another ::usb_status_t error + * code. + */ +usb_status_t lan7800_set_reg_bits(struct usb_device *udev, uint32_t index, uint32_t set) +{ + return lan7800_modify_reg(udev, index, 0xFFFFFFFF, set); +} + +/** + * Change the MAC address of the Microchip LAN7800 USB Ethernet Adapter + * on the actual hardware by writing to its registers. + * @param udev + * USB device for the adapter + * @param macaddr + * New MAC address to set (6 bytes long) + * @return + * ::USB_STATUS_SUCCESS on success; otherwise another ::usb_status_t error + * code. On failure the existing MAC address may have been partially + * modified. + */ +usb_status_t lan7800_set_mac_address(struct usb_device *udev, const uint8_t *macaddr) +{ + usb_status_t status; + uint32_t addrl, addrh; + + addrl = macaddr[0] | macaddr[1] << 8 | macaddr[2] << 16 | macaddr[3] << 24; + addrh = macaddr[4] | macaddr[5] << 8; + + status = lan7800_write_reg(udev, LAN7800_ADDRL, addrl); + if (status != USB_STATUS_SUCCESS) + { + kprintf("\r\nERROR: Failed to write low registers of MAC address\r\n"); + return status; + } + + /* Try to write the MAC until there are nonzero values read back from the mailbox */ + + return lan7800_write_reg(udev, LAN7800_ADDRH, addrh); +} + +/** + * Reads the MAC address of the MICROCHIP LAN7800 USB Ethernet Adapter. + * @param udev + * USB device for the adapter + * @param macaddr + * Pointer into which to write the MAC address (6 bytes long) + * @return + * ::USB_STATUS_SUCCESS on success; otherwise another ::usb_status_t error + * code. + */ +usb_status_t lan7800_get_mac_address(struct usb_device *udev, uint8_t *macaddr) +{ + usb_status_t status; + uint32_t addrl, addrh; + + status = lan7800_read_reg(udev, LAN7800_ADDRL, &addrl); + if (status != USB_STATUS_SUCCESS) + { + return status; + } + status = lan7800_read_reg(udev, LAN7800_ADDRH, &addrh); + if (status != USB_STATUS_SUCCESS) + { + return status; + } + + macaddr[0] = (addrl >> 0) & 0xff; + macaddr[1] = (addrl >> 8) & 0xff; + macaddr[2] = (addrl >> 16) & 0xff; + macaddr[3] = (addrl >> 24) & 0xff; + macaddr[4] = (addrh >> 0) & 0xff; + macaddr[5] = (addrh >> 8) & 0xff; + + return USB_STATUS_SUCCESS; + +} +/** + * Wait for a bit value to change on the Microchip LAN7800 USB Ethernet Adapter. + * @param udev + * USB device for the adapter + * @param reg + * Register to change + * @param mask + * Mask value for register + * @param set + * Value of register bit to apply + * @return + * ::USB_STATUS_SUCCESS after value is applied + */ +usb_status_t lan7800_mdio_wait_for_bit(struct usb_device *udev, const uint32_t reg, + const uint32_t mask, const bool set) +{ + uint32_t val = 0; + while(1){ + lan7800_read_reg(udev, reg, &val); + + if(!set) + val = ~val; + if((val & mask) == mask) + return USB_STATUS_SUCCESS; + udelay(1); + } +} + +/** + * Waits for PHY to be free. + * @param udev + * USB device for the adapter + * @return + * returns ::USB_STATUS_SUCCESS on success. + */ +usb_status_t lan7800_phy_wait_not_busy(struct usb_device *udev) +{ + return lan7800_mdio_wait_for_bit(udev, MII_ACC, MII_ACC_MII_BUSY, USB_STATUS_SUCCESS); +} + +/* Before waiting, confirm that EEPROM is not busy. (Helper function) */ +usb_status_t lan7800_eeprom_confirm_not_busy(struct usb_device *udev) +{ + return lan7800_wait_for_bit(udev, LAN7800_E2P_CMD, LAN7800_E2P_CMD_EPC_BUSY, + USB_STATUS_SUCCESS); +} + +/* Wait for EEPROM. (Helper function) */ +usb_status_t lan7800_wait_eeprom(struct usb_device *udev) +{ + return lan7800_wait_for_bit(udev, LAN7800_E2P_CMD, (LAN7800_E2P_CMD_EPC_BUSY + | LAN7800_E2P_CMD_EPC_TIMEOUT), + USB_STATUS_SUCCESS); +} + +/** + * Read raw EEPROM from the Microchip LAN7800 Ethernet device. + * @param udev + * USB device for the adapter + * @return + * returns ::USB_STATUS_SUCCESS on success. + */ +usb_status_t lan7800_read_raw_eeprom(struct usb_device *udev, uint32_t offset, + uint32_t length, uint8_t *data) +{ + uint32_t val; + uint32_t saved; + int i, ret = 0; + int retval; + + lan7800_read_reg(udev, LAN7800_HW_CFG, &val); + saved = val; + + val &= ~(LAN7800_HW_CFG_LED1_EN | LAN7800_HW_CFG_LED0_EN); + lan7800_write_reg(udev, LAN7800_HW_CFG, val); + + retval = lan7800_eeprom_confirm_not_busy(udev); + if (retval) + return retval; + + for (i = 0; i < length; i++) { + val = LAN7800_E2P_CMD_EPC_BUSY | LAN7800_E2P_CMD_EPC_CMD_READ; + val |= (offset & LAN7800_E2P_CMD_EPC_ADDR_MASK); + lan7800_write_reg(udev, LAN7800_E2P_CMD, val); + if (ret < 0) { + retval = -EIO; + goto exit; + } + + retval = lan7800_wait_eeprom(udev); + if (retval < 0) + goto exit; + + lan7800_read_reg(udev, LAN7800_E2P_DATA, &val); + if (ret < 0) { + retval = -EIO; + goto exit; + } + + data[i] = val & 0xFF; + offset++; + } + retval = USB_STATUS_SUCCESS; +exit: + lan7800_write_reg(udev, LAN7800_HW_CFG, saved); + + return retval; +} + +/** + * Set max RX frame length for the Microchip LAN7800 Ethernet device. + * @param udev + * USB device for the adapter + * @param size + * Size of max RX frame + * @return + * returns ::USB_STATUS_SUCCESS on success. + */ +usb_status_t lan7800_set_rx_max_frame_length(struct usb_device *udev, int size) +{ + uint32_t buf; + bool rxenabled; + + lan7800_read_reg(udev, LAN7800_MAC_RX, &buf); + + rxenabled = ((buf & LAN7800_MAC_RX_RXEN) != 0); + + if (rxenabled) { + buf &= ~LAN7800_MAC_RX_RXEN; + lan7800_write_reg(udev, LAN7800_MAC_RX, buf); + } + + /* To fit FCS, add 4 */ + buf &= ~LAN7800_MAC_RX_MAX_SIZE_MASK; + buf |= (((size + 4) << LAN7800_MAC_RX_MAX_SIZE_SHIFT) & LAN7800_MAC_RX_MAX_SIZE_MASK); + + lan7800_write_reg(udev, LAN7800_MAC_RX, buf); + + if (rxenabled) { + buf |= LAN7800_MAC_RX_RXEN; + lan7800_write_reg(udev, LAN7800_MAC_RX, buf); + } + + return USB_STATUS_SUCCESS; +} + +/** + * Enable or disable Rx checksum offload engine for the Microchip LAN7800 Ethernet device. + * @param udev + * USB device for the adapter + * @param set + * Bit (whether to enable or disable) + * @return + * returns ::USB_STATUS_SUCCESS on success. + */ +usb_status_t lan7800_set_features(struct usb_device *udev, uint32_t set) +{ + uint32_t rfe_ctl; + lan7800_read_reg(udev, LAN7800_RFE_CTL, &rfe_ctl); + + if (set & NETIF_F_RXCSUM) { + rfe_ctl |= RFE_CTL_TCPUDP_COE | RFE_CTL_IP_COE; + rfe_ctl |= RFE_CTL_ICMP_COE | RFE_CTL_IGMP_COE; + } + else { + rfe_ctl &= ~(RFE_CTL_TCPUDP_COE | RFE_CTL_IP_COE); + rfe_ctl &= ~(RFE_CTL_ICMP_COE | RFE_CTL_IGMP_COE); + } + + if (set & NETIF_F_HW_VLAN_CTAG_RX) + rfe_ctl |= RFE_CTL_VLAN_STRIP; + else + rfe_ctl &= ~RFE_CTL_VLAN_STRIP; + + if (set & NETIF_F_HW_VLAN_CTAG_FILTER) + rfe_ctl |= RFE_CTL_VLAN_FILTER; + else + rfe_ctl &= ~RFE_CTL_VLAN_FILTER; + + lan7800_write_reg(udev, LAN7800_RFE_CTL, rfe_ctl); + + return USB_STATUS_SUCCESS; +} + +/** + * Initialize various functions for the Microchip LAN7800 Ethernet device. + * @param udev + * USB device for the adapter + * @param macaddress + * MAC address to be set on the device (obtained from the BCM2837B0 mailbox) + * @return + * returns ::USB_STATUS_SUCCESS on success. + */ +usb_status_t lan7800_init(struct usb_device *udev, uint8_t* macaddress) +{ + uint32_t buf; + + /* Set the MAC address on the device. */ + lan7800_set_mac_address(udev, macaddress); + + /* Respond to the IN token with a NAK */ + lan7800_read_reg(udev, LAN7800_USB_CFG0, &buf); + buf |= LAN7800_USB_CFG_BIR; + lan7800_write_reg(udev, LAN7800_USB_CFG0, buf); + + /* Set burst cap. */ + buf = LAN7800_DEFAULT_BURST_CAP_SIZE / LAN7800_FS_USB_PKT_SIZE; + lan7800_write_reg(udev, LAN7800_BURST_CAP, buf); + lan7800_write_reg(udev, LAN7800_BULK_IN_DLY, LAN7800_DEFAULT_BULK_IN_DELAY); + + /* Enable LED over HW CFG. */ + lan7800_read_reg(udev, LAN7800_HW_CFG, &buf); + buf |= LAN7800_HW_CFG_MEF; + buf |= LAN7800_HW_CFG_LED0_EN; + buf |= LAN7800_HW_CFG_LED1_EN; + lan7800_write_reg(udev, LAN7800_HW_CFG, buf); + + lan7800_read_reg(udev, LAN7800_USB_CFG0, &buf); + buf |= LAN7800_USB_CFG_BCE; + lan7800_write_reg(udev, LAN7800_USB_CFG0, buf); + + /* Set FIFO sizes (similar to SMSC9512) */ + buf = (LAN7800_MAX_RX_FIFO_SIZE - 512) / 512; + lan7800_write_reg(udev, LAN7800_FCT_RX_FIFO_END, buf); + + buf = (LAN7800_MAX_TX_FIFO_SIZE - 512) / 512; + lan7800_write_reg(udev, LAN7800_FCT_TX_FIFO_END, buf); + + lan7800_write_reg(udev, LAN7800_INT_STS, LAN7800_INT_STS_CLEAR_ALL); + lan7800_write_reg(udev, LAN7800_FLOW, 0); + lan7800_write_reg(udev, LAN7800_FCT_FLOW, 0); + + lan7800_read_reg(udev, LAN7800_RFE_CTL, &buf); + buf |= (LAN7800_RFE_CTL_BCAST_EN | LAN7800_RFE_CTL_UCAST_EN | LAN7800_RFE_CTL_MCAST_EN); + lan7800_write_reg(udev, LAN7800_RFE_CTL, buf); + + /* Disable checksum offload engines */ + lan7800_set_features(udev, 0); + + /* Do not filter packets. This is done in the network functions stack. */ + lan7800_read_reg(udev, LAN7800_RFE_CTL, &buf); + buf &= ~(LAN7800_RFE_CTL_DA_PERFECT | LAN7800_RFE_CTL_MCAST_HASH); + lan7800_write_reg(udev, LAN7800_RFE_CTL, buf); + + lan7800_read_reg(udev, LAN7800_MAC_CR, &buf); + + /* Set MAC speed */ + uint8_t sig; + lan7800_read_raw_eeprom(udev, 0, 1, &sig); + if (sig != LAN7800_EEPROM_INDICATOR) { + usb_dev_debug(udev, "No External EEPROM. Setting MAC Speed\n"); + buf |= LAN7800_MAC_CR_AUTO_DUPLEX | LAN7800_MAC_CR_AUTO_SPEED; + } + + buf &= ~(LAN7800_MAC_CR_AUTO_DUPLEX); + lan7800_write_reg(udev, LAN7800_MAC_CR, buf); + + /* Full duplex mode. */ + lan7800_read_reg(udev, LAN7800_MAC_CR, &buf); + buf |= (1 << 3); + lan7800_write_reg(udev, LAN7800_MAC_CR, buf); + + /* Set TX, RX registers for MAC, FCT (similar to SMSC9512) */ + lan7800_read_reg(udev, LAN7800_MAC_TX, &buf); + buf |= LAN7800_MAC_TX_TXEN; + lan7800_write_reg(udev, LAN7800_MAC_TX, buf); + + lan7800_read_reg(udev, LAN7800_FCT_TX_CTL, &buf); + buf |= LAN7800_FCT_TX_CTL_EN; + lan7800_write_reg(udev, LAN7800_FCT_TX_CTL, buf); + + lan7800_set_rx_max_frame_length(udev, LAN7800_ETH_MTU + LAN7800_ETH_VLAN_LEN); + + lan7800_read_reg(udev, LAN7800_MAC_RX, &buf); + buf |= LAN7800_MAC_RX_RXEN; + lan7800_write_reg(udev, LAN7800_MAC_RX, buf); + + lan7800_read_reg(udev, LAN7800_FCT_RX_CTL, &buf); + buf |= LAN7800_FCT_RX_CTL_EN; + lan7800_write_reg(udev, LAN7800_FCT_RX_CTL, buf); + + return USB_STATUS_SUCCESS; +} + diff --git a/device/lan7800/lan7800.h b/device/lan7800/lan7800.h new file mode 100644 index 00000000..e2a9b06a --- /dev/null +++ b/device/lan7800/lan7800.h @@ -0,0 +1,316 @@ +/** + * @file lan7800.h + * + * @authors + * Rade Latinovich + * Patrick J. McGee + * + * This header file provides definitions of the registers of the LAN7800 USB + * Ethernet Adapter. Many of these definitions were borrowed primarily from + * Microchip's LAN78XX Linux Driver + */ + +#ifndef _LAN7800_H_ +#define _LAN7800_H_ + +#include "usb_util.h" +#include /* for udelay() */ + +#define LAN7800_VENDOR_ID 0x424 +#define LAN7800_PRODUCT_ID 0x7800 + +usb_status_t lan7800_write_reg(struct usb_device *udev, uint32_t index, uint32_t data); +usb_status_t lan7800_read_reg(struct usb_device *udev, uint32_t index, uint32_t *data); +usb_status_t lan7800_modify_reg(struct usb_device *udev, uint32_t index, uint32_t mask, uint32_t set); +usb_status_t lan7800_set_reg_bits(struct usb_device *udev, uint32_t index, uint32_t set); +usb_status_t lan7800_wait_device_attached(ushort minor); +usb_status_t lan7800_set_mac_address(struct usb_device *udev, const uint8_t *macaddr); +usb_status_t lan7800_get_mac_address(struct usb_device *udev, uint8_t *macaddr); + +struct usb_xfer_request; + +void lan7800_rx_complete(struct usb_xfer_request *req); +void lan7800_tx_complete(struct usb_xfer_request *req); + +static inline void +__lan7800_dump_reg(struct usb_device *udev, uint32_t index, const char *name) +{ + uint32_t val = 0; + lan7800_read_reg(udev, index, &val); + kprintf("LAN7800: %s = 0x%08X\r\n", name, val); +} + +#define lan7800_dump_reg(udev, index) __lan7800_dump_reg(udev, index, #index) + +/* lan7800_mdio methods */ +usb_status_t lan7800_mdio_read (struct usb_device *udev, int phy_id, int idx); +void lan7800_mdio_write(struct usb_device *udev, int phy_id, int idx, int regval); + +/* LAN7800 function declarations (defined in lan7800.c) */ +usb_status_t lan7800_read_raw_otp(struct usb_device *udev, uint32_t offset, + uint32_t length, uint8_t *data); +int lan7800_read_otp_mac(unsigned char *enetaddr, + struct usb_device *udev); +usb_status_t lan7800_eeprom_confirm_not_busy(struct usb_device *udev); +usb_status_t lan7800_wait_eeprom(struct usb_device *udev); +usb_status_t lan7800_read_raw_eeprom(struct usb_device *dev, uint32_t offset, + uint32_t length, uint8_t *data); +usb_status_t lan7800_read_eeprom(struct usb_device *dev, uint32_t offset, + uint32_t length, uint8_t *data); +usb_status_t lan7800_set_rx_max_frame_length(struct usb_device *dev, int size); + +#define NETIF_F_RXCSUM 4 +#define NETIF_F_HW_VLAN_CTAG_RX 2 +#define NETIF_F_HW_VLAN_CTAG_FILTER 1 +usb_status_t lan7800_set_features(struct usb_device *dev, uint32_t features); +usb_status_t lan7800_init(struct usb_device *dev, uint8_t* macaddress); + +usb_status_t lan7800_mdio_wait_for_bit(struct usb_device *udev, + const uint32_t reg, + const uint32_t mask, + const bool set); + +#define lan7800_wait_for_bit lan7800_mdio_wait_for_bit + +/*************************************************************************** + * The following regsiter set is primarily based on that of Linux's open-source 78xx driver: + * https://github.com/torvalds/linux/blob/8fa3b6f9392bf6d90cb7b908e07bd90166639f0a/drivers/net/usb/lan78xx.h + * and U-Boot: + * https://github.com/trini/u-boot/blob/890e79f2b1c26c5ba1a86d179706348aec7feef7/drivers/usb/eth/lan7x.h + ***************************************************************************/ + +/* TX command word A */ +#define TX_CMD_A_IGE_ 0x20000000 +#define TX_CMD_A_ICE_ 0x10000000 + +/* ??? LSO = Last segment... */ +#define TX_CMD_A_LSO 0x08000000 + +#define TX_CMD_A_IPE_ 0x04000000 +#define TX_CMD_A_TPE_ 0x02000000 +#define TX_CMD_A_IVTG_ 0x01000000 +#define TX_CMD_A_RVTG_ 0x00800000 + +/* TX word A buffer size. */ +#define LAN7800_TX_CMD_A_BUF_SIZE 0x000FFFFF + +/* TX command word B */ +#define TX_CMD_B_MSS_SHIFT_ 16 +#define TX_CMD_B_MSS_MASK_ 0x3FFF0000 +#define TX_CMD_B_MSS_MIN_ (unsigned short)8 +#define TX_CMD_B_VTAG_MASK_ 0x0000FFFF +#define TX_CMD_B_VTAG_PRI_MASK_ 0x0000E000 +#define TX_CMD_B_VTAG_CFI_MASK_ 0x00001000 +#define TX_CMD_B_VTAG_VID_MASK_ 0x00000FFF + + +/* TX/RX Overhead + * Used in sum to allocate for Tx transfer buffer in etherOpen() */ +#define LAN7800_TX_OVERHEAD 8 +#define LAN7800_RX_OVERHEAD 4 + +/* According to U-Boot's LAN78xx driver. */ +#define LAN7800_HS_USB_PKT_SIZE 512 + +/* Read/write regsiters. */ +#define LAN7800_VENDOR_REQUEST_WRITE 0xA0 +#define LAN7800_VENDOR_REQUEST_READ 0xA1 +#define LAN7800_VENDER_REQUEST_GET_STATS 0xA2 + +/* MAC TX/RX */ +#define LAN7800_MAC_RX 0x104 +#define LAN7800_MAC_TX 0x108 + +/* High and low RX register offsets */ +#define LAN7800_ADDRH 0x118 +#define LAN7800_ADDRL 0x11C + +/* Offset of Hardware Configuration Register. */ +#define LAN7800_HW_CFG 0x010 + +/* ??? */ +#define LAN7800_HW_CFG_SRST 0x00000001 +#define LAN7800_HW_CFG_LRST 0x00000002 + +#define LAN7800_BURST_CAP 0x090 +#define LAN7800_BURST_CAP_SIZE 0x000000FF + +/* Loopback mode. */ +#define MAC_CR_LOOPBACK 0x00000400 + +/* Received Ethernet Frame Length */ +#define LAN7800_RX_STS_FL 0x00003FFF + +/* ??? Not entirely sure, appears to be Received Ethernet Error Summary. */ +#define LAN7800_RX_CMD_A_RX_ERR 0xC03F0000 + +/* The following register definitions were pulled from U-Boot's implementation: + * https://github.com/Screenly/u-boot/blob/master/drivers/usb/eth/lan78xx.c + */ + +/* For initializing Tx. */ +#define LAN7800_TX_FLOW 0x0D0 + +/* For initializing Rx. */ +#define LAN7800_RFE_CTL 0x0B0 + +#define LAN7800_MAC_CR 0x100 + +/* Adaptive & Dynamic Polling at MAC layer ??? */ +#define LAN7800_MAC_CR_ADP (1 << 13) + +#define LAN7800_FCT_TX_CTL 0x0C4 + +#define LAN7800_ETH_FRAME_LEN 1514 +#define LAN7800_MAC_RX_MAX_SIZE(mtu) \ + ((mtu) << 16) +#define LAN7800_MAC_RX_MAX_SIZE_DEFAULT LAN7800_MAC_RX_MAX_SIZE(LAN7800_ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */) + +#define LAN7800_MAC_RX_FCS_STRIP (1 << 4) + +#define LAN7800_FCT_RX_CTL 0x0C0 + +/* MAF is where U-Boot writes the hardware address. */ +#define LAN78XX_MAF_BASE 0x400 +#define LAN78XX_MAF_HIX 0x00 +#define LAN78XX_MAF_LOX 0x04 +#define LAN78XX_MAF_HI_BEGIN (LAN78XX_MAF_BASE + LAN78XX_MAF_HIX) +#define LAN78XX_MAF_LO_BEGIN (LAN78XX_MAF_BASE + LAN78XX_MAF_LOX) +#define LAN78XX_MAF_HI(index) (LAN78XX_MAF_BASE + (8 * (index)) + \ + LAN78XX_MAF_HIX) +#define LAN78XX_MAF_LO(index) (LAN78XX_MAF_BASE + (8 * (index)) + \ + LAN78XX_MAF_LOX) +#define LAN78XX_MAF_HI_VALID BIT(31) + + +/* MII_ACC */ +#define MII_ACC 0x120 +#define MII_ACC_MII_READ 0x0 +#define MII_ACC_MII_WRITE 0x2 +#define MII_ACC_MII_BUSY 1 << 0 + +#define MII_DATA 0x124 + +#define TX_OVERHEAD 8 +#define RX_OVERHEAD 10 +#define RX_CMD_A_LEN_MASK 0x00003FFF +#define RX_CMD_A_RED 0x00400000 +#define TX_CMD_A_LEN_MASK 0x000FFFFF +#define TX_CMD_A_FCS 0x00400000 +#define EINVAL 22 + +/* OTP (One-Time Programmable) */ +#define LAN7800_OTP_BASE 0x00001000 +#define LAN7800_OTP_PWR_DN LAN7800_OTP_BASE + 4 * 0x00 +#define LAN7800_OTP_PWR_DN_PWRDN_N 0x01 +#define LAN7800_OTP_ADDR1 LAN7800_OTP_BASE + 4 * 0x01 +#define LAN7800_OTP_ADDR1_15_11 0x1F +#define LAN7800_OTP_ADDR2 LAN7800_OTP_BASE + 4 * 0x02 +#define LAN7800_OTP_ADDR2_10_3 0xFF +#define LAN7800_OTP_FUNC_CMD LAN7800_OTP_BASE + 4 * 0x08 +#define LAN7800_OTP_FUNC_CMD_READ 0x01 +#define LAN7800_OTP_CMD_GO LAN7800_OTP_BASE + 4 * 0x0A +#define LAN7800_OTP_CMD_GO_GO 0x01 +#define LAN7800_OTP_STATUS LAN7800_OTP_BASE + 4 * 0x0C +#define LAN7800_OTP_STATUS_BUSY 0x01 +#define LAN7800_OTP_RD_DATA 0x01 +#define LAN7800_OTP_INDICATOR_1 0xF3 +#define LAN7800_OTP_INDICATOR_2 0xF7 + +#define EIO 5 + +/* EEPROM */ +#define LAN7800_EEPROM_INDICATOR 0xA5 +#define LAN7800_E2P_CMD 0x040 +#define LAN7800_E2P_CMD_EPC_BUSY 0x80000000 +#define LAN7800_EEPROM_MAC_OFFSET 0x01 +#define LAN7800_E2P_CMD_EPC_TIMEOUT 0x00000400 +#define LAN7800_HW_CFG_LED3_EN 0x00800000 +#define LAN7800_HW_CFG_LED2_EN 0x00400000 +#define LAN7800_HW_CFG_LED1_EN 0x00200000 +#define LAN7800_HW_CFG_LED0_EN 0x00100000 +#define LAN7800_E2P_CMD_EPC_CMD_READ 0x00000000 +#define LAN7800_E2P_CMD_EPC_ADDR_MASK 0x000001FF +#define LAN7800_E2P_DATA 0x44 +#define LAN7800_USB_CFG1 0x084 +#define LAN7800_USB_CFG1_LTM_ENABLE 0x00000100 + +/* LTM = LED function mux? */ +#define LAN7800_LTM_BELT_IDLE0 0x0E0 +#define LAN7800_LTM_BELT_IDLE1 0x0E4 +#define LAN7800_LTM_BELT_ACT0 0x0E8 +#define LAN7800_LTM_BELT_ACT1 0x0EC +#define LAN7800_LTM_INACTIVE0 0x0F0 +#define LAN7800_LTM_INACTIVE1 0x0F4 +#define LAN7800_MAC_RX_MAX_SIZE_MASK 0x3FFF0000 +#define LAN7800_MAC_RX_MAX_SIZE_SHIFT 16 + +/* RFE */ +#define RFE_CTL_TCPUDP_COE 0x00001000 +#define RFE_CTL_IP_COE 0x00000800 +#define RFE_CTL_ICMP_COE 0x00002000 +#define RFE_CTL_IGMP_COE 0x00004000 +#define RFE_CTL_TCPUDP_COE 0x00001000 +#define NETIF_F_HW_VLAN_CTAG_RX 2 +#define RFE_CTL_VLAN_STRIP 0x00000080 +#define NETIF_F_HW_VLAN_CTAG_FILTER 1 +#define RFE_CTL_VLAN_FILTER 0x00000020 +#define NETIF_F_RXCSUM 4 + +/* RESET CONTINUE */ +#define LAN7800_USB_CFG0 0x080 +#define LAN7800_USB_CFG_BIR 0x00000040 +#define LAN7800_MAX_TX_FIFO_SIZE 12 * 1024 +#define LAN7800_MAX_RX_FIFO_SIZE 12 * 1024 +#define LAN7800_DEFAULT_BURST_CAP_SIZE LAN7800_MAX_TX_FIFO_SIZE +#define LAN7800_FS_USB_PKT_SIZE 64 +#define LAN7800_HS_USB_PKT_SIZE 512 +#define LAN7800_SS_USB_PKT_SIZE 1024 + +#define LAN7800_BULK_IN_DLY 0x094 +#define LAN7800_DEFAULT_BULK_IN_DELAY 0x0800 + +#define LAN7800_HW_CFG_MEF 0x00000010 +#define LAN7800_USB_CFG_BCE 0x00000020 + +/* FIFO */ +#define LAN7800_INT_STS 0x0C +#define LAN7800_INT_STS_CLEAR_ALL 0xFFFFFFFF +#define LAN7800_FLOW 0x10C +#define LAN7800_FCT_FLOW 0x0D0 +#define LAN7800_FCT_TX_FIFO_END 0x0CC +#define LAN7800_FCT_RX_FIFO_END 0x0C8 + +#define LAN7800_RFE_CTL_BCAST_EN 0x00000400 +#define LAN7800_RFE_CTL_DA_PERFECT 0x00000002 +#define LAN7800_RFE_CTL 0x0B0 +#define LAN7800_RFE_CTL_UCAST_EN 0x00000100 +#define LAN7800_RFE_CTL_MCAST_EN 0x00000200 +#define LAN7800_RFE_CTL_MCAST_HASH 0x00000008 + +/* PMT */ +#define LAN7800_PMT_CTL 0x014 +#define LAN7800_PMT_CTL_PHY_RST 0x00000010 + +/* EEPROM, MAC */ +#define LAN7800_EEPROM_INDICATOR 0xA5 +#define LAN7800_MAC_CR_AUTO_DUPLEX 0x00001000 +#define LAN7800_MAC_CR_AUTO_SPEED 0x00000800 +#define LAN7800_FCT_TX_CTL 0x0C4 + +/* DMA buffer size */ +#define LAN7800_ETH_MTU 1500 + +#define LAN7800_ETH_ALEN 6 + +#define LAN7800_ETH_VLAN_LEN 4 +#define LAN7800_MAC_RX_RXEN 0x00000001 +#define LAN7800_MAC_TX_TXEN 0x00000001 + +/* FCT */ +#define LAN7800_FCT_RX_CTL 0x0C0 +#define LAN7800_FCT_RX_CTL_EN 0x80000000 +#define LAN7800_FCT_TX_CTL 0x0C4 +#define LAN7800_FCT_TX_CTL_EN 0x80000000 + +#endif /* _LAN7800_H_ */ diff --git a/device/lan7800/old.etherinit.c b/device/lan7800/old.etherinit.c new file mode 100644 index 00000000..5527bab0 --- /dev/null +++ b/device/lan7800/old.etherinit.c @@ -0,0 +1,271 @@ +/** + * @file etherInit.c + * + * @authors + * Rade Latinovich + * Patrick J. McGee + * + * Initialization for the LAN7800 USB Ethernet Adapter + */ +/* Embedded Xinu, Copyright (C) 2018. All rights reserved. */ + +#include "lan7800.h" +#include +#include +#include +#include +#include +#include +#include +#include "../../system/platforms/arm-rpi3/bcm2837_mbox.h" +#include +#include +#include + +/* Global table of Ethernet devices. */ +struct ether ethertab[NETHER]; + +/** + * Semaphores that indicate whether each given Ethernet device is connected to the system + * yet (in our case, attached to USB). + */ +static semaphore lan7800_attached[NETHER]; + +/* Global variable which contains the MAC address after + * getEthAddr() is called. This is later copied to the + * devAddress member of the ether struct using memcpy(). */ +uchar addr[ETH_ADDR_LEN] = {0}; + +/** + * Try to bind the LAN7800 driver to a specific USB device. + */ +static usb_status_t +lan7800_bind_device(struct usb_device *udev) +{ + struct ether *ethptr; + + /* Check if this is actually a LAN7800 by checking the USB device's + * standard device descriptor, which the USB core already read into memory. + * Also check to make sure the expected endpoints for sending/receiving + * packets are present and that the device is operating at high speed. */ + if (udev->descriptor.idVendor != LAN7800_VENDOR_ID || + udev->descriptor.idProduct != LAN7800_PRODUCT_ID || + udev->interfaces[0]->bNumEndpoints < 2 || + (udev->endpoints[0][0]->bmAttributes & 0x3) != USB_TRANSFER_TYPE_BULK || + (udev->endpoints[0][1]->bmAttributes & 0x3) != USB_TRANSFER_TYPE_BULK || + (udev->endpoints[0][0]->bEndpointAddress >> 7) != USB_DIRECTION_IN || + (udev->endpoints[0][1]->bEndpointAddress >> 7) != USB_DIRECTION_OUT || + udev->speed != USB_SPEED_HIGH) + { + return USB_STATUS_DEVICE_UNSUPPORTED; + } + + /* Make sure this driver isn't already bound to a LAN7800. */ + ethptr = ðertab[0]; + STATIC_ASSERT(NETHER == 1); + if (ethptr->csr != NULL) + { + return USB_STATUS_DEVICE_UNSUPPORTED; + } + + /* The rest of this function is responsible for making the LAN7800 + * ready to use, but not actually enabling Rx and Tx (which is done in + * etherOpen()). This primarily involves writing to the registers on the + * LAN7800. But these are not memory mapped registers, as this is a + * USB Ethernet Adapter that is attached on the USB! Instead, registers are + * read and written using USB control transfers. It's somewhat of a pain, + * and also unlike memory accesses it is possible for USB control transfers + * to fail. However, here we perform lazy error checking where we just do + * all the needed reads and writes, then check at the end if an error + * occurred. */ + udev->last_error = USB_STATUS_SUCCESS; + + /* Set MAC address within ethernet struct */ + lan7800_set_mac_address(udev, ethptr->devAddress); + + /* Check for error and return. */ + if (udev->last_error != USB_STATUS_SUCCESS) + { + return udev->last_error; + } + + ethptr->csr = udev; + udev->driver_private = ethptr; + + signal(lan7800_attached[ethptr - ethertab]); + kprintf("\r\nReturning from bind device...\r\n"); + + return USB_STATUS_SUCCESS; +} + +/** + * Unbinds the LAN7800 driver from the LAN7800 device that has been detached. + */ +static void +lan7800_unbind_device(struct usb_device *udev) +{ + + struct ether *ethptr = udev->driver_private; + + /* Reset attached semaphore to 0. */ + wait(lan7800_attached[ethptr - ethertab]); + + /* Close the device. */ + etherClose(ethptr->dev); + +} + +/** + * Specification of a USB device driver for the LAN7800 device. This is for the USB core subsystem + * and not related to Xinu's primary device and driver model. + */ +static const struct usb_device_driver lan7800_driver = { + .name = "LAN7800 USB Ethernet Adapter Driver", + .bind_device = lan7800_bind_device, + .unbind_device = lan7800_unbind_device, +}; + +/* Get static MAC address from Pi 3 B+ chip, based on the XinuPi + * mailbox technique. + * + * @details + * + * Get the Pi 3 B+'s MAC address using its ARM->VideoCore (VC) mailbox + * and assign corresponding values to a global array containing the MAC. + * This array is then assigned to the devAddress member of the ether structure. + * + * TODO: + * There exists a quirk in which the address does not get set unless kprintf is + * called at the very end of this function. This quirk is not one that udelay() + * solved, thus, I am led to believe there is some sort of dependency on UART + * communication here. */ +static void +getEthAddr(uint8_t *addr) +{ + /* Initialize and clear the mailbox buffer */ + uint32_t mailbuffer; //[MBOX_BUFLEN]; + //bzero(mailbuffer, 1024); + + mailbuffer = mbox_buf_alloc(MBOX_BUFLEN); + + /* Fill the mailbox buffer with the MAC address. + * This function is defined in system/platforms/arm-rpi3/bcm2837_mbox.c */ + get_mac_mailbox(mailbuffer); + + ushort i; + for (i = 0; i < 2; ++i) { + + /* Access the MAC value within the buffer */ + uint32_t value = mailbuffer[MBOX_HEADER_LENGTH + TAG_HEADER_LENGTH + i]; + + /* Store the low MAC values */ + if(i == 0){ + addr[0] = (value >> 0) & 0xff; + addr[1] = (value >> 8) & 0xff; + addr[2] = (value >> 16) & 0xff; + addr[3] = (value >> 24) & 0xff; + } + + /* Store the remaining high MAC values */ + if(i == 1){ + addr[4] = (value >> 0) & 0xff; + addr[5] = (value >> 8) & 0xff; + } + } + + /* Clear multicast bit and set locally assigned bit */ +// addr[0] &= 0xFE; +// addr[0] |= 0x02; + + /* TODO: Figure out why this function fails if kprintf is not called here. + * Attempted udelay(1000+) instead, still fails. Seems dependent on UART comm. + * However, seems like a timing issue that a delay can fix because if this for + * loop iterates less than five times, the bug appears. + * I discovered this "fix" after noticing that the devAddress values were incorrect, + * 2:0:0:0:0:0, after storing the addr into the devAddress, + * as if the MAC address was never being loaded. Printed them here to debug. + * Go figure, the print statement seemed to fix it. + * --Behavior--: if kprintf is not called here at least six times, then the global + * array @param addr does not contain the MAC address, but rather: 2:0:0:0:0:0. + * When kprintf is called here, then the MAC address is set successfully. */ + ushort j; + for(j = 0; j < 25; j++) + kprintf(""); +} + +/** + * @ingroup etherspecific + * Wait until the specified Ethernet device has been attached. + * This is necessary because USB is a dynamic bus, but Xinu expects static devices. + * @param minor + * Minor number of the Ethernet device to wait for. + * @return + * Currently ::USB_STATUS_SUCCESS. + */ +usb_status_t +lan7800_wait_device_attached(ushort minor) +{ + wait(lan7800_attached[minor]); + signal(lan7800_attached[minor]); + return USB_STATUS_SUCCESS; +} + +/* Implementation of etherInit() for lan7800; documentation in ether.h */ +/** + * @details + * LAN7800-specific notes: This function returns ::OK if the Ethernet + * Driver was successfully registered with the USB core, otherwise ::SYSERR. + * This is a work-around to use USB's dynamic device model at the same time as + * Xinu's static device model, and there is no guarantee that the device + * actually exists when the function returns. + */ +devcall etherInit(device *devptr) +{ + struct ether *ethptr; + usb_status_t status; + + /* Initialize static ether struct for this device. */ + ethptr = ðertab[devptr->minor]; + bzero(ethptr, sizeof(struct ether)); + ethptr->dev = devptr; + ethptr->state = ETH_STATE_DOWN; + ethptr->mtu = ETH_MTU; + ethptr->addressLength = ETH_ADDR_LEN; + ethptr->isema = semcreate(0); + if (isbadsem(ethptr->isema)) + { + goto err; + } + + /* Create semaphore for device attachment. */ + lan7800_attached[devptr->minor] = semcreate(0); + + if (isbadsem(lan7800_attached[devptr->minor])) + { + goto err_free_isema; + } + + /* Get the MAC address and store it */ + getEthAddr(ethptr->devAddress); + + /* Copy the MAC address array into the devAddress member of the + * Ether structure. */ + //memcpy(ethptr->devAddress, addr, sizeof(addr)); + + /* Register this device driver with the USB core and return. */ + status = usb_register_device_driver(&lan7800_driver); + if (status != USB_STATUS_SUCCESS) + { + goto err_free_attached_sema; + } + + kprintf("Ether device initialized\r\n"); + return OK; + +err_free_attached_sema: + semfree(lan7800_attached[devptr->minor]); +err_free_isema: + semfree(ethptr->isema); +err: + return SYSERR; +} diff --git a/device/lan7800/old.etheropen.c b/device/lan7800/old.etheropen.c new file mode 100644 index 00000000..1ce7a3cc --- /dev/null +++ b/device/lan7800/old.etheropen.c @@ -0,0 +1,138 @@ +/** + * @file lan7800_open.c + * + * @authors + * Patrick J. McGee + * Rade Latinovich + * + * Routine for opening a Microchip LAN7800 USB Ethernet Adapter device. + */ +/* Embedded Xinu, Copyright (C) 2018. All rights reserved. */ + +#include +#include +#include +#include +#include +#include "lan7800.h" + +/* Implementation of etherOpen() for the lan7800; see the documentation for + * this function in ether.h. */ +devcall etherOpen(device *devptr) +{ + struct ether *ethptr; + struct usb_device *udev; + irqmask im; + int retval = SYSERR; + + im = disable(); + /* Wait for USB device to actually be attached. */ + if (lan7800_wait_device_attached(devptr->minor) != USB_STATUS_SUCCESS) + { + goto out_restore; + } + + kprintf("Done waiting for attach...\r\n"); + /* Fail if device is not down. */ + ethptr = ðertab[devptr->minor]; + if (ethptr->state != ETH_STATE_DOWN) + { + goto out_restore; + } + + /* Create buffer pool for Tx transfers. */ +#define LAN7800_MAX_TX_REQUESTS 1 + ethptr->outPool = bfpalloc(sizeof(struct usb_xfer_request) + + ETH_MAX_PKT_LEN + + LAN7800_TX_OVERHEAD, + LAN7800_MAX_TX_REQUESTS); + if (ethptr->outPool == SYSERR) + { + goto out_restore; + } + + /* Create buffer pool for Rx packets (not the actual USB transfers, which + * are allocated separately). */ + ethptr->inPool = bfpalloc(sizeof(struct ethPktBuffer) + ETH_MAX_PKT_LEN, + ETH_IBLEN); + if (ethptr->inPool == SYSERR) + { + goto out_free_out_pool; + } + + /* We're abusing the csr field to store a pointer to the USB device + * structure. At least it's somewhat equivalent, since it's what we need to + * actually communicate with the device hardware. */ + udev = ethptr->csr; + + + /* The rest of this function is responsible for making the LAN78xx + * ready to use, but not actually enabling Rx and Tx (which is done in + * etherOpen()). This primarily involves writing to the registers on the + * LAN78xx. But these are not memory mapped registers, as this is a + * USB Ethernet Adapter that is attached on the USB! Instead, registers are + * read and written using USB control transfers. It's somewhat of a pain, + * and also unlike memory accesses it is possible for USB control transfers + * to fail. However, here we perform lazy error checking where we just do + * all the needed reads and writes, then check at the end if an error + * occurred. */ + udev->last_error = USB_STATUS_SUCCESS; + + retval = lan7800_init(udev, ðptr->devAddress[0]); + if (retval < 0) goto out_free_in_pool; + + /* Initialize the Tx requests. */ + { + struct usb_xfer_request *reqs[LAN7800_MAX_TX_REQUESTS]; + for (int i = 0; i < LAN7800_MAX_TX_REQUESTS; i++) + { + struct usb_xfer_request *req; + + req = bufget(ethptr->outPool); + usb_init_xfer_request(req); + req->dev = udev; + /* Assign Tx endpoint, checked in lan78xx_bind_device() */ + req->endpoint_desc = udev->endpoints[0][1]; + req->sendbuf = (uint8_t*)req + sizeof(struct usb_xfer_request); + req->completion_cb_func = lan7800_tx_complete; + req->private = ethptr; + reqs[i] = req; + } + for (int i = 0; i < LAN7800_MAX_TX_REQUESTS; i++) + { + buffree(reqs[i]); + } + } + + /* Allocate and submit the Rx requests. TODO: these aren't freed anywhere. */ +#define LAN7800_MAX_RX_REQUESTS 1 + for (int i = 0; i < LAN7800_MAX_RX_REQUESTS; i++) + { + struct usb_xfer_request *req; + + req = usb_alloc_xfer_request(LAN7800_DEFAULT_BURST_CAP_SIZE); + if (req == NULL) + { + goto out_free_in_pool; + } + req->dev = udev; + /* Assign Rx endpoint, checked in lan78xx_bind_device() */ + req->endpoint_desc = udev->endpoints[0][0]; + req->completion_cb_func = lan7800_rx_complete; + req->private = ethptr; + usb_submit_xfer_request(req); + } + + /* Success! Set the device to ETH_STATE_UP. */ + ethptr->state = ETH_STATE_UP; + retval = OK; + goto out_restore; + +out_free_in_pool: + bfpfree(ethptr->inPool); +out_free_out_pool: + bfpfree(ethptr->outPool); +out_restore: + restore(im); + return retval; +} diff --git a/loader/platforms/arm-qemu/Makerules b/device/rpi_gpio/Makerules similarity index 82% rename from loader/platforms/arm-qemu/Makerules rename to device/rpi_gpio/Makerules index 802f853e..8d002897 100644 --- a/loader/platforms/arm-qemu/Makerules +++ b/device/rpi_gpio/Makerules @@ -1,9 +1,10 @@ # Name of this component (the directory this file is stored in) -COMP = loader/platforms/arm-qemu +COMP = device/rpi_gpio # Source files for this component C_FILES = -S_FILES = start.S + +S_FILES = # Add the files to the compile source path DIR = ${TOPDIR}/${COMP} diff --git a/device/smsc9512/Doxygroup.c b/device/smsc9512/Doxygroup.c deleted file mode 100644 index 7e2ac80e..00000000 --- a/device/smsc9512/Doxygroup.c +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @defgroup etherdriver Ethernet - * @brief Ethernet driver for SMSC LAN9512 devices - * @ingroup devices - * - * @defgroup ether Ethernet Standard Functions - * @ingroup etherdriver - * @brief The functions in this category are also implemented in Xinu's other - * Ethernet drivers; some, such as etherRead() and etherWrite(), are compliant - * with Xinu's main device model and therefore can be accessed through functions - * like read() and write(). - * - * @defgroup etherspecific Ethernet Device-Specific Functions - * @ingroup etherdriver - * @brief The functions in this category are specific to the SMSC LAN9512 and - * not intended to be used outside of the driver itself. - */ diff --git a/device/smsc9512/Makerules b/device/smsc9512/Makerules deleted file mode 100644 index 985167d4..00000000 --- a/device/smsc9512/Makerules +++ /dev/null @@ -1,24 +0,0 @@ -# This Makefile contains rules to build this directory. - -# Name of this component (the directory this file is stored in) -COMP = device/smsc9512 - -# Source files for this component -C_FILES = \ - colon2mac.c \ - etherClose.c \ - etherControl.c \ - etherInit.c \ - etherInterrupt.c \ - etherOpen.c \ - etherRead.c \ - etherStat.c \ - etherWrite.c \ - smsc9512.c \ - vlanStat.c - -S_FILES = - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/device/smsc9512/colon2mac.c b/device/smsc9512/colon2mac.c deleted file mode 100644 index 87d1cd8c..00000000 --- a/device/smsc9512/colon2mac.c +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @file colon2mac.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include - -#include - -/** - * @ingroup ether - * - * Convert a colon-separated string representation of a MAC into - * the equivalent byte array. - * @param src pointer to colon-separated MAC string - * @param dst pointer to byte array - * @return number of octets converted. - */ -int colon2mac(char *src, uchar *dst) -{ - uchar count = 0, digit = 0, c = 0; - - if (NULL == src || NULL == dst) - { - return SYSERR; - } - - while ((count < ETH_ADDR_LEN) && ('\0' != *src)) - { - c = *src++; - if (isdigit(c)) - { - digit = c - '0'; - } - else if (isxdigit(c)) - { - digit = 10 + c - (isupper(c) ? 'A' : 'a'); - } - else - { - digit = 0; - } - dst[count] = digit * 16; - - c = *src++; - if (isdigit(c)) - { - digit = c - '0'; - } - else if (isxdigit(c)) - { - digit = 10 + c - (isupper(c) ? 'A' : 'a'); - } - else - { - digit = 0; - } - dst[count] += digit; - - count++; - if (':' != *src++) - { - break; - } - } - - return count; -} diff --git a/device/smsc9512/etherInit.c b/device/smsc9512/etherInit.c deleted file mode 100644 index a0c29634..00000000 --- a/device/smsc9512/etherInit.c +++ /dev/null @@ -1,254 +0,0 @@ -/** - * @file etherInit.c - * - * Initialization for the SMSC LAN9512 USB Ethernet Adapter. - */ -/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ - -#include "smsc9512.h" -#include -#include -#include -#include -#include -#include -#include - -/* Global table of Ethernet devices. */ -struct ether ethertab[NETHER]; - -/** - * Semaphores that indicate whether each given Ethernet device has actually been - * connected to the system yet (here, attached to the USB). Could be moved into - * struct ::ether if other drivers needed it... - */ -static semaphore smsc9512_attached[NETHER]; - -/** - * Try to bind the SMSC LAN9512 driver to a specific USB device. This the @ref - * usb_device_driver::bind_device "bind_device" implementation for the SMSC - * LAN9512 driver and therefore complies with its documented behavior. - */ -static usb_status_t -smsc9512_bind_device(struct usb_device *udev) -{ - struct ether *ethptr; - - /* Check if this is actually a SMSC LAN9512 by checking the USB device's - * standard device descriptor, which the USB core already read into memory. - * Also check to make sure the expected endpoints for sending/receiving - * packets are present and that the device is operating at high speed. */ - if (udev->descriptor.idVendor != SMSC9512_VENDOR_ID || - udev->descriptor.idProduct != SMSC9512_PRODUCT_ID || - udev->interfaces[0]->bNumEndpoints < 2 || - (udev->endpoints[0][0]->bmAttributes & 0x3) != USB_TRANSFER_TYPE_BULK || - (udev->endpoints[0][1]->bmAttributes & 0x3) != USB_TRANSFER_TYPE_BULK || - (udev->endpoints[0][0]->bEndpointAddress >> 7) != USB_DIRECTION_IN || - (udev->endpoints[0][1]->bEndpointAddress >> 7) != USB_DIRECTION_OUT || - udev->speed != USB_SPEED_HIGH) - { - return USB_STATUS_DEVICE_UNSUPPORTED; - } - - /* Make sure this driver isn't already bound to a SMSC LAN9512. - * TODO: Support multiple devices of this type concurrently. */ - ethptr = ðertab[0]; - STATIC_ASSERT(NETHER == 1); - if (ethptr->csr != NULL) - { - return USB_STATUS_DEVICE_UNSUPPORTED; - } - - /* The rest of this function is responsible for making the SMSC LAN9512 - * ready to use, but not actually enabling Rx and Tx (which is done in - * etherOpen()). This primarily involves writing to the registers on the - * SMSC LAN9512. But these are not memory mapped registers, as this is a - * USB Ethernet Adapter that is attached on the USB! Instead, registers are - * read and written using USB control transfers. It's somewhat of a pain, - * and also unlike memory accesses it is possible for USB control transfers - * to fail. However, here we perform lazy error checking where we just do - * all the needed reads and writes, then check at the end if an error - * occurred. */ - - udev->last_error = USB_STATUS_SUCCESS; - - /* Resetting the SMSC LAN9512 via its registers should not be necessary - * because the USB code already performed a reset on the USB port it's - * attached to. */ - - /* Set MAC address. */ - smsc9512_set_mac_address(udev, ethptr->devAddress); - - /* Allow multiple Ethernet frames to be received in a single USB transfer. - * Also set a couple flags of unknown function. */ - smsc9512_set_reg_bits(udev, HW_CFG, HW_CFG_MEF | HW_CFG_BIR | HW_CFG_BCE); - - /* Set the maximum USB (not networking!) packets per USB Rx transfer. - * Required when HW_CFG_MEF was set. */ - smsc9512_write_reg(udev, BURST_CAP, - SMSC9512_DEFAULT_HS_BURST_CAP_SIZE / SMSC9512_HS_USB_PKT_SIZE); - - /* Check for error and return. */ - if (udev->last_error != USB_STATUS_SUCCESS) - { - return udev->last_error; - } - ethptr->csr = udev; - udev->driver_private = ethptr; - signal(smsc9512_attached[ethptr - ethertab]); - return USB_STATUS_SUCCESS; -} - -/** - * Unbinds the SMSC LAN9512 driver from a SMSC LAN9512 that has been detached. - * This the @ref usb_device_driver::unbind_device "unbind_device" implementation - * for the SMSC LAN9512 driver and therefore complies with its documented - * behavior. - */ -static void -smsc9512_unbind_device(struct usb_device *udev) -{ - struct ether *ethptr = udev->driver_private; - - /* Reset attached semaphore to 0. */ - wait(smsc9512_attached[ethptr - ethertab]); - - /* Close the device. */ - etherClose(ethptr->dev); -} - -/** - * Specification of a USB device driver for the SMSC LAN9512. This is - * specifically for the USB core and is not related to Xinu's primary device and - * driver model, which is static. - */ -static const struct usb_device_driver smsc9512_driver = { - .name = "SMSC LAN9512 USB Ethernet Adapter Driver", - .bind_device = smsc9512_bind_device, - .unbind_device = smsc9512_unbind_device, -}; - -static void -randomEthAddr(uchar addr[ETH_ADDR_LEN]) -{ - uint i; - if (platform.serial_low != 0 && platform.serial_high != 0) - { - /* Use value generated from platform's serial number. The problem here - * is that we must generate a 48-bit MAC address from a 64-bit serial - * number but avoid mapping multiple serial numbers to the same MAC - * address. This is impossible, so we perform an approximation where we - * hash the serial number to remove any obvious non-randomness in the - * way serial numbers are assigned, then extract the low 48 bits. */ - unsigned long long serial_nr, hashval; - - serial_nr = (unsigned long long)platform.serial_low | - ((unsigned long long)platform.serial_high << 32); - hashval = serial_nr * 0x9e37fffffffc0001ULL; - for (i = 0; i < ETH_ADDR_LEN; i++) - { - addr[i] = hashval & 0xff; - hashval >>= 8; - } - } - else - { - /* Generate value using the C library's random number generator, seeded - * on the current system timer tick count. */ - srand(clkcount()); - for (i = 0; i < ETH_ADDR_LEN; i++) - { - addr[i] = rand(); - } - } - /* Clear multicast bit and set locally assigned bit */ - addr[0] &= 0xfe; - addr[0] |= 0x02; -} - -/** - * @ingroup etherspecific - * - * Wait until the specified Ethernet device has actually been attached. - * - * This is necessary because USB is a dynamic bus, but Xinu expects static - * devices. Therefore, code opening a static ethernet device must wait until - * the corresponding USB device has actually been detected and attached. Fun - * fact: the USB standard places no constraints on how long this will actually - * take, even if the device is physically soldered to the board. - * - * TODO: Wait for at most a certain amount of time before returning failure. - * - * @param minor - * Minor number of the Ethernet device to wait for. - * - * @return - * Currently ::USB_STATUS_SUCCESS. TODO: implement timeouts and return - * ::USB_STATUS_TIMEOUT if timed out. - */ -usb_status_t -smsc9512_wait_device_attached(ushort minor) -{ - wait(smsc9512_attached[minor]); - signal(smsc9512_attached[minor]); - return USB_STATUS_SUCCESS; -} - -/* Implementation of etherInit() for the smsc9512; see the documentation for - * this function in ether.h. */ -/** - * @details - * - * SMSC LAN9512-specific notes: This function returns ::OK if the Ethernet - * driver was successfully registered with the USB core, otherwise ::SYSERR. - * This is a work-around to use USB's dynamic device model at the same time as - * Xinu's static device model, and there is no guarantee that the device - * actually exists when this function returns. (If it doesn't, the problem is - * delayed until the device is actually opened with etherOpen()). - */ -devcall etherInit(device *devptr) -{ - struct ether *ethptr; - usb_status_t status; - - /* Initialize the static `struct ether' for this device. */ - ethptr = ðertab[devptr->minor]; - bzero(ethptr, sizeof(struct ether)); - ethptr->dev = devptr; - ethptr->state = ETH_STATE_DOWN; - ethptr->mtu = ETH_MTU; - ethptr->addressLength = ETH_ADDR_LEN; - ethptr->isema = semcreate(0); - if (isbadsem(ethptr->isema)) - { - goto err; - } - - smsc9512_attached[devptr->minor] = semcreate(0); - - if (isbadsem(smsc9512_attached[devptr->minor])) - { - goto err_free_isema; - } - - /* The SMSC LAN9512 on the Raspberry Pi does not have an EEPROM attached. - * The EEPROM is normally used to store the MAC address of the adapter, - * along with some other information. As a result, software needs to set - * the MAC address to a value of its choosing (such as a random number). */ - randomEthAddr(ethptr->devAddress); - - /* Register this device driver with the USB core and return. */ - status = usb_register_device_driver(&smsc9512_driver); - if (status != USB_STATUS_SUCCESS) - { - goto err_free_attached_sema; - } - return OK; - -err_free_attached_sema: - semfree(smsc9512_attached[devptr->minor]); -err_free_isema: - semfree(ethptr->isema); -err: - return SYSERR; -} diff --git a/device/smsc9512/etherInterrupt.c b/device/smsc9512/etherInterrupt.c deleted file mode 100644 index 1bfad0e8..00000000 --- a/device/smsc9512/etherInterrupt.c +++ /dev/null @@ -1,137 +0,0 @@ -/** - * @file etherInterrupt.c - * - * - * This file provides USB transfer completion callbacks for the SMSC LAN9512 USB - * Ethernet Adapter. These are roughly the equivalent of etherInterrupt() as - * implemented in other Xinu Ethernet drivers, hence the filename, but there is - * no actual etherInterrupt() function here because of how USB works. The SMSC - * LAN9512 cannot actually issue an interrupt by itself--- what actually happens - * is that a USB transfer to or from it completes, thereby causing the USB Host - * Controller to interrupt the CPU. This interrupt is handled by the USB Host - * Controller Driver, which will then call the callback function registered for - * the USB transfer. - */ -/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ - -#include "smsc9512.h" -#include -#include -#include -#include - -/** - * @ingroup etherspecific - * - * Callback function executed with interrupts disabled when an asynchronous USB - * bulk transfer to the Bulk OUT endpoint of the SMSC LAN9512 USB Ethernet - * Adapter for the purpose of sending an Ethernet packet has successfully - * completed or has failed. - * - * Currently all this function has to do is return the buffer to its pool. This - * may wake up a thread in etherWrite() that is waiting for a free buffer. - * - * @param req - * USB bulk OUT transfer request that has completed. - */ -void smsc9512_tx_complete(struct usb_xfer_request *req) -{ - struct ether *ethptr = req->private; - - ethptr->txirq++; - usb_dev_debug(req->dev, "SMSC9512: Tx complete\n"); - buffree(req); -} - -/** - * @ingroup etherspecific - * - * Callback function executed with interrupts disabled when an asynchronous USB - * bulk transfer from the Bulk IN endpoint of the SMSC LAN9512 USB Ethernet - * Adapter for the purpose of receiving one or more Ethernet packets has - * successfully completed or has failed. - * - * This function is responsible for breaking up the raw USB transfer data into - * the constituent Ethernet packet(s), then pushing them onto the incoming - * packets queue (which may wake up threads in etherRead() that are waiting for - * new packets). It then must re-submit the USB bulk transfer request so that - * packets can continue to be received. - * - * @param req - * USB bulk IN transfer request that has completed. - */ -void smsc9512_rx_complete(struct usb_xfer_request *req) -{ - struct ether *ethptr = req->private; - - ethptr->rxirq++; - if (req->status == USB_STATUS_SUCCESS) - { - const uint8_t *data, *edata; - uint32_t recv_status; - uint32_t frame_length; - - /* For each Ethernet frame in the received USB data... */ - for (data = req->recvbuf, edata = req->recvbuf + req->actual_size; - data + SMSC9512_RX_OVERHEAD + ETH_HDR_LEN + ETH_CRC_LEN <= edata; - data += SMSC9512_RX_OVERHEAD + ((frame_length + 3) & ~3)) - { - /* Get the Rx status word, which contains information about the next - * Ethernet frame. */ - recv_status = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24; - - /* Extract frame_length, which specifies the length of the next - * Ethernet frame from the MAC destination address to end of the CRC - * following the payload. (This does not include the Rx status - * word, which we instead account for in SMSC9512_RX_OVERHEAD.) */ - frame_length = (recv_status & RX_STS_FL) >> 16; - - if ((recv_status & RX_STS_ES) || - (frame_length + SMSC9512_RX_OVERHEAD > edata - data) || - (frame_length > ETH_MAX_PKT_LEN + ETH_CRC_LEN) || - (frame_length < ETH_HDR_LEN + ETH_CRC_LEN)) - { - /* The Ethernet adapter set the error flag to indicate a problem - * or the Ethernet frame size it provided was invalid. */ - usb_dev_debug(req->dev, "SMSC9512: Tallying rx error " - "(recv_status=0x%08x, frame_length=%u)\n", - recv_status, frame_length); - ethptr->errors++; - } - else if (ethptr->icount == ETH_IBLEN) - { - /* No space to buffer another received packet. */ - usb_dev_debug(req->dev, "SMSC9512: Tallying overrun\n"); - ethptr->ovrrun++; - } - else - { - /* Buffer the received packet. */ - - struct ethPktBuffer *pkt; - - pkt = bufget(ethptr->inPool); - pkt->buf = pkt->data = (uint8_t*)(pkt + 1); - pkt->length = frame_length - ETH_CRC_LEN; - memcpy(pkt->buf, data + SMSC9512_RX_OVERHEAD, pkt->length); - ethptr->in[(ethptr->istart + ethptr->icount) % ETH_IBLEN] = pkt; - ethptr->icount++; - - usb_dev_debug(req->dev, "SMSC9512: Receiving " - "packet (length=%u, icount=%u)\n", - pkt->length, ethptr->icount); - - /* This may wake up a thread in etherRead(). */ - signal(ethptr->isema); - } - } - } - else - { - /* USB transfer failed for some reason. */ - usb_dev_debug(req->dev, "SMSC9512: USB Rx transfer failed\n"); - ethptr->errors++; - } - usb_dev_debug(req->dev, "SMSC9512: Re-submitting USB Rx request\n"); - usb_submit_xfer_request(req); -} diff --git a/device/smsc9512/etherOpen.c b/device/smsc9512/etherOpen.c deleted file mode 100644 index cba4239a..00000000 --- a/device/smsc9512/etherOpen.c +++ /dev/null @@ -1,143 +0,0 @@ -/** - * @file etherOpen.c - * - * Code for opening a SMSC LAN9512 USB Ethernet Adapter device. - */ -/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ - -#include "smsc9512.h" -#include -#include -#include -#include -#include - -/* Implementation of etherOpen() for the smsc9512; see the documentation for - * this function in ether.h. */ -/** - * @details - * - * SMSC LAN9512-specific notes: as a work-around to use USB's dynamic device - * model at the same time as Xinu's static device model, this function will - * block until the corresponding USB device has actually been attached to the - * USB. Strictly speaking, there is no guarantee as to when this will actually - * occur, even if the device is non-removable. - */ -devcall etherOpen(device *devptr) -{ - struct ether *ethptr; - struct usb_device *udev; - irqmask im; - uint i; - int retval = SYSERR; - - im = disable(); - - /* Wait for USB device to actually be attached. */ - if (smsc9512_wait_device_attached(devptr->minor) != USB_STATUS_SUCCESS) - { - goto out_restore; - } - - /* Fail if device is not down. */ - ethptr = ðertab[devptr->minor]; - if (ethptr->state != ETH_STATE_DOWN) - { - goto out_restore; - } - - /* Create buffer pool for Tx transfers. */ - ethptr->outPool = bfpalloc(sizeof(struct usb_xfer_request) + ETH_MAX_PKT_LEN + - SMSC9512_TX_OVERHEAD, - SMSC9512_MAX_TX_REQUESTS); - if (ethptr->outPool == SYSERR) - { - goto out_restore; - } - - /* Create buffer pool for Rx packets (not the actual USB transfers, which - * are allocated separately). */ - ethptr->inPool = bfpalloc(sizeof(struct ethPktBuffer) + ETH_MAX_PKT_LEN, - ETH_IBLEN); - if (ethptr->inPool == SYSERR) - { - goto out_free_out_pool; - } - - /* We're abusing the csr field to store a pointer to the USB device - * structure. At least it's somewhat equivalent, since it's what we need to - * actually communicate with the device hardware. */ - udev = ethptr->csr; - - /* Set MAC address */ - if (smsc9512_set_mac_address(udev, ethptr->devAddress) != USB_STATUS_SUCCESS) - { - goto out_free_in_pool; - } - - /* Initialize the Tx requests. */ - { - struct usb_xfer_request *reqs[SMSC9512_MAX_TX_REQUESTS]; - for (i = 0; i < SMSC9512_MAX_TX_REQUESTS; i++) - { - struct usb_xfer_request *req; - - req = bufget(ethptr->outPool); - usb_init_xfer_request(req); - req->dev = udev; - /* Assign Tx endpoint, checked in smsc9512_bind_device() */ - req->endpoint_desc = udev->endpoints[0][1]; - req->sendbuf = (uint8_t*)req + sizeof(struct usb_xfer_request); - req->completion_cb_func = smsc9512_tx_complete; - req->private = ethptr; - reqs[i] = req; - } - for (i = 0; i < SMSC9512_MAX_TX_REQUESTS; i++) - { - buffree(reqs[i]); - } - } - - /* Allocate and submit the Rx requests. TODO: these aren't freed anywhere. - * */ - for (i = 0; i < SMSC9512_MAX_RX_REQUESTS; i++) - { - struct usb_xfer_request *req; - - req = usb_alloc_xfer_request(SMSC9512_DEFAULT_HS_BURST_CAP_SIZE); - if (req == NULL) - { - goto out_free_in_pool; - } - req->dev = udev; - /* Assign Rx endpoint, checked in smsc9512_bind_device() */ - req->endpoint_desc = udev->endpoints[0][0]; - req->completion_cb_func = smsc9512_rx_complete; - req->private = ethptr; - usb_submit_xfer_request(req); - } - - /* Enable transmit and receive on the actual hardware. After doing this and - * restoring interrupts, the Rx transfers can complete at any time due to - * incoming packets. */ - udev->last_error = USB_STATUS_SUCCESS; - smsc9512_set_reg_bits(udev, MAC_CR, MAC_CR_TXEN | MAC_CR_RXEN); - smsc9512_write_reg(udev, TX_CFG, TX_CFG_ON); - if (udev->last_error != USB_STATUS_SUCCESS) - { - goto out_free_in_pool; - } - - /* Success! Set the device to ETH_STATE_UP. */ - ethptr->state = ETH_STATE_UP; - retval = OK; - goto out_restore; - -out_free_in_pool: - bfpfree(ethptr->inPool); -out_free_out_pool: - bfpfree(ethptr->outPool); -out_restore: - restore(im); - return retval; -} diff --git a/device/smsc9512/etherStat.c b/device/smsc9512/etherStat.c deleted file mode 100644 index 88b2d888..00000000 --- a/device/smsc9512/etherStat.c +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @file etherStat.c - */ -/* Embedded Xinu, Copyright (C) 2008, 2013. All rights reserved. */ - -#include -#include - -void etherStat(ushort minor) -{ - const struct ether *ethptr = ðertab[minor]; - - printf("eth%u:\n", minor); - printf(" MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n", - ethptr->devAddress[0], ethptr->devAddress[1], - ethptr->devAddress[2], ethptr->devAddress[3], - ethptr->devAddress[4], ethptr->devAddress[5]); - - printf(" MTU %u\n", ethptr->mtu); - - printf(" Device state"); - switch (ethptr->state) - { - case ETH_STATE_FREE: - printf(" FREE\n"); - break; - case ETH_STATE_UP: - printf(" UP\n"); - break; - case ETH_STATE_DOWN: - printf(" DOWN\n"); - break; - } - - printf(" Rx packets in queue %u\n", ethptr->icount); - printf(" Rx errors %lu\n", ethptr->errors); - printf(" Rx overruns %u\n", ethptr->ovrrun); - printf(" Rx USB transfers done %lu\n", ethptr->rxirq); - printf(" Tx USB transfers done %lu\n", ethptr->txirq); -} - -void etherThroughput(ushort minor) -{ - printf("Throughput monitoring not implemented for " - "SMSC LAN9512 USB Ethernet Adapter\n"); -} diff --git a/device/smsc9512/etherWrite.c b/device/smsc9512/etherWrite.c deleted file mode 100644 index 9f0d5024..00000000 --- a/device/smsc9512/etherWrite.c +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @file etherWrite.c - */ -/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ - -#include "smsc9512.h" -#include -#include -#include -#include -#include - -/* Implementation of etherWrite() for the SMSC LAN9512; see the documentation - * for this function in ether.h. */ -devcall etherWrite(device *devptr, const void *buf, uint len) -{ - struct ether *ethptr; - struct usb_xfer_request *req; - uint8_t *sendbuf; - uint32_t tx_cmd_a, tx_cmd_b; - - ethptr = ðertab[devptr->minor]; - if (ethptr->state != ETH_STATE_UP || - len < ETH_HEADER_LEN || len > ETH_HDR_LEN + ETH_MTU) - { - return SYSERR; - } - - /* Get a buffer for the packet. (This may block.) */ - req = bufget(ethptr->outPool); - - /* Copy the packet's data into the buffer, but also include two words at the - * beginning that contain device-specific flags. These two fields are - * required, although we essentially just use them to tell the hardware we - * are transmitting one (1) packet with no extra bells and whistles. */ - sendbuf = req->sendbuf; - tx_cmd_a = len | TX_CMD_A_FIRST_SEG | TX_CMD_A_LAST_SEG; - sendbuf[0] = (tx_cmd_a >> 0) & 0xff; - sendbuf[1] = (tx_cmd_a >> 8) & 0xff; - sendbuf[2] = (tx_cmd_a >> 16) & 0xff; - sendbuf[3] = (tx_cmd_a >> 24) & 0xff; - tx_cmd_b = len; - sendbuf[4] = (tx_cmd_b >> 0) & 0xff; - sendbuf[5] = (tx_cmd_b >> 8) & 0xff; - sendbuf[6] = (tx_cmd_b >> 16) & 0xff; - sendbuf[7] = (tx_cmd_b >> 24) & 0xff; - STATIC_ASSERT(SMSC9512_TX_OVERHEAD == 8); - memcpy(sendbuf + SMSC9512_TX_OVERHEAD, buf, len); - - /* Set total size of the data to send over the USB. */ - req->size = len + SMSC9512_TX_OVERHEAD; - - /* Submit the data as an asynchronous bulk USB transfer. In other words, - * this tells the USB subsystem to send begin sending the data over the USB - * to the SMSC LAN9512 USB Ethernet Adapter. At some later time when all - * the data has been transferred over the USB, smsc9512_tx_complete() will - * be called by the USB subsystem. */ - usb_submit_xfer_request(req); - - /* Return the length of the packet written (not including the - * device-specific fields that were added). */ - return len; -} diff --git a/device/smsc9512/smsc9512.c b/device/smsc9512/smsc9512.c deleted file mode 100644 index 469e86c5..00000000 --- a/device/smsc9512/smsc9512.c +++ /dev/null @@ -1,196 +0,0 @@ -/** - * @file smsc9512.c - * - * This file provides various functions needed by the SMSC LAN9512 USB Ethernet - * Driver. - */ -/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ - -#include "smsc9512.h" -#include - -/** - * @ingroup etherspecific - * - * Write to a register on the SMSC LAN9512 USB Ethernet Adapter. - * - * @param udev - * USB device for the adapter - * @param index - * Index of the register to write - * @param data - * Value to write to the register - * - * @return - * ::USB_STATUS_SUCCESS on success; otherwise another ::usb_status_t error - * code. - */ -usb_status_t -smsc9512_write_reg(struct usb_device *udev, uint32_t index, uint32_t data) -{ - return usb_control_msg(udev, NULL, - SMSC9512_VENDOR_REQUEST_WRITE_REGISTER, - USB_BMREQUESTTYPE_DIR_OUT | - USB_BMREQUESTTYPE_TYPE_VENDOR | - USB_BMREQUESTTYPE_RECIPIENT_DEVICE, - 0, index, &data, sizeof(uint32_t)); -} - -/** - * @ingroup etherspecific - * - * Read from a register on the SMSC LAN9512 USB Ethernet Adapter. - * - * @param udev - * USB device for the adapter - * @param index - * Index of the register to read - * @param data - * Pointer into which to write the register's value - * - * @return - * ::USB_STATUS_SUCCESS on success; otherwise another ::usb_status_t error - * code. - */ -usb_status_t -smsc9512_read_reg(struct usb_device *udev, uint32_t index, uint32_t *data) -{ - return usb_control_msg(udev, NULL, - SMSC9512_VENDOR_REQUEST_READ_REGISTER, - USB_BMREQUESTTYPE_DIR_IN | - USB_BMREQUESTTYPE_TYPE_VENDOR | - USB_BMREQUESTTYPE_RECIPIENT_DEVICE, - 0, index, data, sizeof(uint32_t)); -} - -/** - * @ingroup etherspecific - * - * Modify the value contained in a register on the SMSC LAN9512 USB Ethernet - * Adapter. - * - * @param udev - * USB device for the adapter - * @param index - * Index of the register to modify - * @param mask - * Mask that contains 1 for the bits where the old value in the register - * will be kept rather than cleared (unless those bits also appear in @p - * set, in which case they will still be set). - * @param set - * Mask of bits to set in the register. - * - * @return - * ::USB_STATUS_SUCCESS on success; otherwise another ::usb_status_t error - * code. - */ -usb_status_t -smsc9512_modify_reg(struct usb_device *udev, uint32_t index, - uint32_t mask, uint32_t set) -{ - usb_status_t status; - uint32_t val; - - status = smsc9512_read_reg(udev, index, &val); - if (status != USB_STATUS_SUCCESS) - { - return status; - } - val &= mask; - val |= set; - return smsc9512_write_reg(udev, index, val); -} - -/** - * @ingroup etherspecific - * - * Set bits in a register on the SMSC LAN9512 USB Ethernet Adapter. - * - * @param udev - * USB device for the adapter - * @param index - * Index of the register to modify - * @param set - * Bits to set in the register. At positions where there is a 0, the old - * value in the register will be written. - * - * @return - * ::USB_STATUS_SUCCESS on success; otherwise another ::usb_status_t error - * code. - */ -usb_status_t -smsc9512_set_reg_bits(struct usb_device *udev, uint32_t index, uint32_t set) -{ - return smsc9512_modify_reg(udev, index, 0xffffffff, set); -} - -/** - * @ingroup etherspecific - * - * Change the MAC address of the SMSC LAN9512 USB Ethernet Adapter. - * - * @param udev - * USB device for the adapter - * @param macaddr - * New MAC address to set (6 bytes long) - * - * @return - * ::USB_STATUS_SUCCESS on success; otherwise another ::usb_status_t error - * code. On failure the existing MAC address may have been partially - * modified. - */ -usb_status_t -smsc9512_set_mac_address(struct usb_device *udev, const uint8_t *macaddr) -{ - usb_status_t status; - uint32_t addrl, addrh; - - addrl = macaddr[0] | macaddr[1] << 8 | macaddr[2] << 16 | macaddr[3] << 24; - addrh = macaddr[4] | macaddr[5] << 8; - - status = smsc9512_write_reg(udev, ADDRL, addrl); - if (status != USB_STATUS_SUCCESS) - { - return status; - } - return smsc9512_write_reg(udev, ADDRH, addrh); -} - -/** - * @ingroup etherspecific - * - * Reads the MAC address of the SMSC LAN9512 USB Ethernet Adapter. - * - * @param udev - * USB device for the adapter - * @param macaddr - * Pointer into which to write the MAC address (6 bytes long) - * - * @return - * ::USB_STATUS_SUCCESS on success; otherwise another ::usb_status_t error - * code. - */ -usb_status_t -smsc9512_get_mac_address(struct usb_device *udev, uint8_t *macaddr) -{ - usb_status_t status; - uint32_t addrl, addrh; - - status = smsc9512_read_reg(udev, ADDRL, &addrl); - if (status != USB_STATUS_SUCCESS) - { - return status; - } - status = smsc9512_read_reg(udev, ADDRH, &addrh); - if (status != USB_STATUS_SUCCESS) - { - return status; - } - macaddr[0] = (addrl >> 0) & 0xff; - macaddr[1] = (addrl >> 8) & 0xff; - macaddr[2] = (addrl >> 16) & 0xff; - macaddr[3] = (addrl >> 24) & 0xff; - macaddr[4] = (addrh >> 0) & 0xff; - macaddr[5] = (addrh >> 8) & 0xff; - return USB_STATUS_SUCCESS; -} diff --git a/device/smsc9512/smsc9512.h b/device/smsc9512/smsc9512.h deleted file mode 100644 index da071475..00000000 --- a/device/smsc9512/smsc9512.h +++ /dev/null @@ -1,612 +0,0 @@ -/** - * @file smsc9512.h - * - * This header mostly provides definitions of the registers of the SMSC LAN9512 - * USB Ethernet Adapter. Since there is no publicly available documentation for - * this hardware, these definitions were borrowed primarily from SMSC's Linux - * driver. However, based on experiment and educated guesswork, we have also - * added explanations of what various registers and fields actually mean. - */ -#ifndef _SMSC9512_H_ -#define _SMSC9512_H_ - -#include "usb_util.h" - -/* The SMSC LAN9512 has an integrated USB hub and is technically a compound - * device. Here we instead use the vendor ID and product ID of the - * vendor-specific class device attached to the hub that is the device we - * actually need to communicate with. */ - -/** idVendor in the USB device descriptor for this device */ -#define SMSC9512_VENDOR_ID 0x0424 - -/** idProduct in the USB device descriptor for this device */ -#define SMSC9512_PRODUCT_ID 0xEC00 - -/** TODO */ -#define SMSC9512_TX_OVERHEAD 8 - -/** TODO */ -#define SMSC9512_RX_OVERHEAD 4 - -/** TODO */ -#define SMSC9512_HS_USB_PKT_SIZE 512 - -/** TODO */ -#define SMSC9512_DEFAULT_HS_BURST_CAP_SIZE (16 * 1024 + 5 * SMSC9512_HS_USB_PKT_SIZE) - -/** TODO */ -#define SMSC9512_DEFAULT_BULK_IN_DELAY 0x2000 - -#define SMSC9512_MAX_TX_REQUESTS 1 -/* TODO */ -//#define SMSC9512_MAX_RX_REQUESTS (DIV_ROUND_UP(60 * 1518, SMSC9512_DEFAULT_HS_BURST_CAP_SIZE)) -#define SMSC9512_MAX_RX_REQUESTS 1 - -usb_status_t smsc9512_write_reg(struct usb_device *udev, uint32_t index, uint32_t data); - -usb_status_t smsc9512_read_reg(struct usb_device *udev, uint32_t index, uint32_t *data); - -usb_status_t smsc9512_modify_reg(struct usb_device *udev, uint32_t index, - uint32_t mask, uint32_t set); -usb_status_t smsc9512_set_reg_bits(struct usb_device *udev, uint32_t index, uint32_t set); - -usb_status_t smsc9512_wait_device_attached(ushort minor); - -usb_status_t smsc9512_set_mac_address(struct usb_device *udev, const uint8_t *macaddr); -usb_status_t smsc9512_get_mac_address(struct usb_device *udev, uint8_t *macaddr); - -struct usb_xfer_request; - -void smsc9512_rx_complete(struct usb_xfer_request *req); -void smsc9512_tx_complete(struct usb_xfer_request *req); - - -static inline void -__smsc9512_dump_reg(struct usb_device *udev, uint32_t index, const char *name) -{ - uint32_t val = 0; - smsc9512_read_reg(udev, index, &val); - kprintf("SMSC9512: %s = 0x%08x\n", name, val); -} - -#define smsc9512_dump_reg(udev, index) __smsc9512_dump_reg(udev, index, #index) - -/****************************************************************************/ - - -/* - * Transmitted Ethernet frames (as written to the SMSC LAN9512's Bulk OUT - * endpoint) must be prefixed with an 8-byte header containing the "Tx command - * word A" followed by the "Tx command word B". It apparently is possible to - * use these command words to set up the transmission of multiple Ethernet - * frames in a single USB Bulk transfer, although we do not use this - * functionality in this driver. - */ - -/* Tx command word A */ -#define TX_CMD_A_DATA_OFFSET 0x001F0000 -#define TX_CMD_A_FIRST_SEG 0x00002000 -#define TX_CMD_A_LAST_SEG 0x00001000 -#define TX_CMD_A_BUF_SIZE 0x000007FF - -/* Tx command word B */ -#define TX_CMD_B_CSUM_ENABLE 0x00004000 -#define TX_CMD_B_ADD_CRC_DISABLE 0x00002000 -#define TX_CMD_B_DISABLE_PADDING 0x00001000 -#define TX_CMD_B_PKT_BYTE_LENGTH 0x000007FF - -/****************************************************************************/ - -/* - * Received Ethernet frames (as read from the SMSC LAN9512's Bulk IN endpoint) - * are prefixed with a 4-byte Rx Status word containing the flags below. A - * single USB Bulk IN transfer may contain multiple Ethernet frames (provided - * that HW_CFG_MEF is set in HW_CFG), each of which is prepended by a Rx Status - * word and padded to a 4-byte boundary. - */ - -#define RX_STS_FF 0x40000000 /* Filter Fail */ -#define RX_STS_FL 0x3FFF0000 /* Frame Length */ -#define RX_STS_ES 0x00008000 /* Error Summary */ -#define RX_STS_BF 0x00002000 /* Broadcast Frame */ -#define RX_STS_LE 0x00001000 /* Length Error */ -#define RX_STS_RF 0x00000800 /* Runt Frame */ -#define RX_STS_MF 0x00000400 /* Multicast Frame */ -#define RX_STS_TL 0x00000080 /* Frame too long */ -#define RX_STS_CS 0x00000040 /* Collision Seen */ -#define RX_STS_FT 0x00000020 /* Frame Type */ -#define RX_STS_RW 0x00000010 /* Receive Watchdog */ -#define RX_STS_ME 0x00000008 /* Mii Error */ -#define RX_STS_DB 0x00000004 /* Dribbling */ -#define RX_STS_CRC 0x00000002 /* CRC Error */ - -/****************************************************************************/ - -/** - * Offset of Device ID / Revision Register. TODO - */ -#define ID_REV 0x00 -#define ID_REV_CHIP_ID_MASK 0xFFFF0000 -#define ID_REV_CHIP_REV_MASK 0x0000FFFF -#define ID_REV_CHIP_ID_9500 0x9500 -#define ID_REV_CHIP_ID_9500A 0x9E00 -#define ID_REV_CHIP_ID_9512 0xEC00 -#define ID_REV_CHIP_ID_9530 0x9530 -#define ID_REV_CHIP_ID_89530 0x9E08 -#define ID_REV_CHIP_ID_9730 0x9730 - -/****************************************************************************/ - -/** - * Offset of Interrupt Status Register. TODO - */ -#define INT_STS 0x08 -#define INT_STS_TX_STOP 0x00020000 -#define INT_STS_RX_STOP 0x00010000 -#define INT_STS_PHY_INT 0x00008000 -#define INT_STS_TXE 0x00004000 -#define INT_STS_TDFU 0x00002000 -#define INT_STS_TDFO 0x00001000 -#define INT_STS_RXDF 0x00000800 -#define INT_STS_GPIOS 0x000007FF -#define INT_STS_CLEAR_ALL 0xFFFFFFFF - -/****************************************************************************/ - -/** Offset of Receive Configuration Register. */ -#define RX_CFG 0x0C - -/** Most likely, software can write 1 to this flag discard all the Rx packets - * currently buffered by the device. */ -#define RX_FIFO_FLUSH 0x00000001 - -/****************************************************************************/ - -/** Offset of Transmit Configuration Register. */ -#define TX_CFG 0x10 - -/** Transmit On flag. Software can write 1 here to enable transmit - * functionality (at the PHY layer?). Writing 0 is ignored. Reads as current - * on (1) / off (0) state. However, to actually allow packets to be - * transmitted, software also must set the ::MAC_CR_TXEN flag in the ::MAC_CR - * register. */ -#define TX_CFG_ON 0x00000004 - -/** Transmit Stop flag. Software can write 1 here to turn transmit - * functionality off. Writing 0 is ignored. Always reads as 0. */ -#define TX_CFG_STOP 0x00000002 - -/** Most likely, software can write 1 to this flag to discard all the Tx packets - * currently buffered by the device. */ -#define TX_CFG_FIFO_FLUSH 0x00000001 - -/****************************************************************************/ - -/** Offset of Hardware Configuration Register. As implied by the name, this - * contains a number of flags that software can modify to configure the Ethernet - * Adapter. After reset, this register contains all 0's. */ -#define HW_CFG 0x14 - -/** TODO: this is set by SMSC's Linux driver. I don't know what BIR stands for, - * but the BI might stand for Bulk In. The observed behavior is that if you - * don't set this flag, latency for Rx, Tx, or both appears to increase, and - * Bulk IN transfers can complete immediately with 0 length even when no data - * has been received. */ -#define HW_CFG_BIR 0x00001000 - -/** TODO */ -#define HW_CFG_LEDB 0x00000800 - -/** Rx packet offset: Software can modify this 2-bit field to cause Rx packets - * to be offset by the specified number of bytes. This is apparently intended - * to allow software to align the IP header on a 4 byte boundary. */ -#define HW_CFG_RXDOFF 0x00000600 - -/** TODO */ -#define HW_CFG_DRP 0x00000040 - -/** Multiple Ethernet Frames: Software can set this flag in HW_CFG to allow - * multiple Ethernet frames to be received in a single USB Bulk In transfer. - * The default value after reset is 0, meaning that the hardware will by default - * provide each received Ethernet frame in a separate USB Bulk In transfer. */ -#define HW_CFG_MEF 0x00000020 - -/** "Lite" Reset flag. Software can write 1 to this flag in HW_CFG to start a - * "lite" reset on the device, whatever that means. The hardware will - * automatically clear this flag when the device has finished resetting, which - * should take no longer than 1 second. */ -#define HW_CFG_LRST 0x00000008 - -/** TODO */ -#define HW_CFG_PSEL 0x00000004 - -/** TODO: this is set by SMSC's Linux driver at the same time as HW_CFG_MEF. I - * have no idea what it stands for or what it does. */ -#define HW_CFG_BCE 0x00000002 - -/** TODO */ -#define HW_CFG_SRST 0x00000001 - -/****************************************************************************/ - -/** TODO */ -#define RX_FIFO_INF 0x18 - -/****************************************************************************/ - -/** Offset of Power Management Control Register. TODO */ -#define PM_CTRL 0x20 -#define PM_CTL_RES_CLR_WKP_STS 0x00000200 -#define PM_CTL_DEV_RDY 0x00000080 -#define PM_CTL_SUS_MODE 0x00000060 -#define PM_CTL_SUS_MODE_0 0x00000000 -#define PM_CTL_SUS_MODE_1 0x00000020 -#define PM_CTL_SUS_MODE_2 0x00000040 -#define PM_CTL_SUS_MODE_3 0x00000060 - -/** PHY Reset flag: Software can write 1 here to start a PHY reset on the - * device. The hardware will automatically clear this flag when the PHY has - * finished resetting, which should take no longer than 1 second. */ -#define PM_CTL_PHY_RST 0x00000010 -#define PM_CTL_WOL_EN 0x00000008 -#define PM_CTL_ED_EN 0x00000004 -#define PM_CTL_WUPS 0x00000003 -#define PM_CTL_WUPS_NO 0x00000000 -#define PM_CTL_WUPS_ED 0x00000001 -#define PM_CTL_WUPS_WOL 0x00000002 -#define PM_CTL_WUPS_MULTI 0x00000003 - -/****************************************************************************/ - -/** Offset of LED General Purpose I/O Configuration Register. */ -#define LED_GPIO_CFG 0x24 -#define LED_GPIO_CFG_SPD_LED 0x01000000 -#define LED_GPIO_CFG_LNK_LED 0x00100000 -#define LED_GPIO_CFG_FDX_LED 0x00010000 - -/****************************************************************************/ - -/** Offset of General Purpose I/O Configuration Register. */ -#define GPIO_CFG 0x28 - -/****************************************************************************/ - -/** Offset of (Advanced?) Flow Control Configuration Register. - * After reset, this register is 0. */ -#define AFC_CFG 0x2C - -/** - * Value written to AFC_CFG by the Linux driver, with the following explanation: - * - * Hi watermark = 15.5Kb (~10 mtu pkts) - * low watermark = 3k (~2 mtu pkts) - * backpressure duration = ~ 350us - * Apply FC on any frame. - */ -#define AFC_CFG_DEFAULT 0x00F830A1 - -/****************************************************************************/ - -/** TODO */ -#define E2P_CMD 0x30 -#define E2P_CMD_BUSY 0x80000000 -#define E2P_CMD_MASK 0x70000000 -#define E2P_CMD_READ 0x00000000 -#define E2P_CMD_EWDS 0x10000000 -#define E2P_CMD_EWEN 0x20000000 -#define E2P_CMD_WRITE 0x30000000 -#define E2P_CMD_WRAL 0x40000000 -#define E2P_CMD_ERASE 0x50000000 -#define E2P_CMD_ERAL 0x60000000 -#define E2P_CMD_RELOAD 0x70000000 -#define E2P_CMD_TIMEOUT 0x00000400 -#define E2P_CMD_LOADED 0x00000200 -#define E2P_CMD_ADDR 0x000001FF - -#define MAX_EEPROM_SIZE 512 - -/****************************************************************************/ - -/** TODO */ -#define E2P_DATA 0x34 -#define E2P_DATA_MASK 0x000000FF - -/****************************************************************************/ - -/** Offset of Burst Cap Register. - * - * When multiple Ethernet frames per USB bulk transfer are enabled, this - * register must be set by software to specify the maximum number of USB (not - * networking!) packets the hardware will provide in a single Bulk In transfer. - * - * This register is ignored if HW_CFG_MEF is not set. Otherwise, this must be - * set to at least 5, which represents a maximum of 5 * 512 = 2560 bytes of data - * per transfer from the high speed Bulk In endpoint. */ -#define BURST_CAP 0x38 - -/****************************************************************************/ - -/** TODO */ -#define GPIO_WAKE 0x64 - -/****************************************************************************/ - -/** TODO */ -#define INT_EP_CTL 0x68 -#define INT_EP_CTL_INTEP 0x80000000 -#define INT_EP_CTL_MACRTO 0x00080000 -#define INT_EP_CTL_TX_STOP 0x00020000 -#define INT_EP_CTL_RX_STOP 0x00010000 -#define INT_EP_CTL_PHY_INT 0x00008000 -#define INT_EP_CTL_TXE 0x00004000 -#define INT_EP_CTL_TDFU 0x00002000 -#define INT_EP_CTL_TDFO 0x00001000 -#define INT_EP_CTL_RXDF 0x00000800 -#define INT_EP_CTL_GPIOS 0x000007FF - -/****************************************************************************/ - -/** - * Offset of Bulk In Delay Register. - * - * The low 16 bits of this register contain a value that indicates the maximum - * amount of time the hardware waits for additional packets before responding to - * a Bulk In request once a packet has been received. From experiment, the time - * is specified on a linear scale where each unit is approximately 17 - * nanoseconds. The default value in this register after reset is 0x800 which - * indicates a delay of about 34.8 microseconds, assuming that the scale is - * 0-based. SMSC's Linux driver changes this to 0x2000, or a delay of about 139 - * microseconds. - * - * The high 16 bits of this register are ignored, as far as I can tell. - * - * The value in this register no effect if HW_CFG_MEF is not set in the - * HW_CFG register. - */ -#define BULK_IN_DLY 0x6C - -/****************************************************************************/ - -/** Offset of Media Access Control Control Register */ -#define MAC_CR 0x100 - -/** ??? */ -#define MAC_CR_RXALL 0x80000000 - -/** Half duplex mode. */ -#define MAC_CR_RCVOWN 0x00800000 - -/** Loopback mode. */ -#define MAC_CR_LOOPBK 0x00200000 - -/** Full duplex mode. */ -#define MAC_CR_FDPX 0x00100000 - -/** Multicast pass: receive all multicast packets. */ -#define MAC_CR_MCPAS 0x00080000 - -/** Promiscuous mode. */ -#define MAC_CR_PRMS 0x00040000 - -/** Inverse filtering. */ -#define MAC_CR_INVFILT 0x00020000 - -/** Pass on bad frames. */ -#define MAC_CR_PASSBAD 0x00010000 - -/** ??? */ -#define MAC_CR_HFILT 0x00008000 - -/** Filter received multicast packets by the set of addresses specified by HASHH - * and HASHL. */ -#define MAC_CR_HPFILT 0x00002000 - -/** ??? */ -#define MAC_CR_LCOLL 0x00001000 - -/** Receive broadcast packets? */ -#define MAC_CR_BCAST 0x00000800 - -/** ??? */ -#define MAC_CR_DISRTY 0x00000400 - -/** ??? */ -#define MAC_CR_PADSTR 0x00000100 - -/** ??? */ -#define MAC_CR_BOLMT_MASK 0x000000C0 - -/** ??? */ -#define MAC_CR_DFCHK 0x00000020 - -/** Transmit enabled at the MAC layer. Software can write 1 to enable or write - * 0 to disable. However, to actually allow packets to be transmitted, software - * also must set the ::TX_CFG_ON flag in the ::TX_CFG register. */ -#define MAC_CR_TXEN 0x00000008 - -/** Receive enabled. Software can write 1 to enable or write 0 to disable. */ -#define MAC_CR_RXEN 0x00000004 - -/****************************************************************************/ - -/** Offset of Address High Register. This contains the high 2 bytes of the MAC - * address used by the device, stored in little endian order. - * - * As they are not part of the MAC address, the hardware ignores the values - * written to the upper 2 bytes of this register and always reads them as 0. - * - * Software can change the MAC address used by the device by writing to the - * ::ADDRH and ::ADDRL registers, and it can retrieve the current MAC address by - * reading them. On reset, the device will read its MAC address from the EEPROM - * if one is attached; otherwise it will set its MAC address to 0xFFFFFFFFFFFF. - * */ -#define ADDRH 0x104 - -/** Offset of Address Low Register. This contains the low 4 bytes of the MAC - * address used by the device, stored in little endian order. See ::ADDRH. */ -#define ADDRL 0x108 - -/****************************************************************************/ - -/** Offset of Hash High register, used together with HASHL to filter specific - * multicast packets. TODO */ -#define HASHH 0x10C - -/** Offset of Hash Low register, used together with HASHH to filter specific - * multicast packets. TODO */ -#define HASHL 0x110 - -/****************************************************************************/ - -/** TODO */ -#define MII_ADDR 0x114 -#define MII_WRITE 0x02 -#define MII_BUSY 0x01 -#define MII_READ 0x00 /* ~of MII Write bit */ - -/** TODO */ -#define MII_DATA 0x118 - -/****************************************************************************/ - -/** TODO. After reset, this is 0. */ -#define FLOW 0x11C -#define FLOW_FCPT 0xFFFF0000 -#define FLOW_FCPASS 0x00000004 -#define FLOW_FCEN 0x00000002 -#define FLOW_FCBSY 0x00000001 - -/****************************************************************************/ - -/** TODO */ -#define VLAN1 0x120 - -/** TODO */ -#define VLAN2 0x124 - -/****************************************************************************/ - -/** TODO */ -#define WUFF 0x128 -#define LAN9500_WUFF_NUM 4 -#define LAN9500A_WUFF_NUM 8 - -/****************************************************************************/ - -/** TODO */ -#define WUCSR 0x12C -#define WUCSR_WFF_PTR_RST 0x80000000 -#define WUCSR_GUE 0x00000200 -#define WUCSR_WUFR 0x00000040 -#define WUCSR_MPR 0x00000020 -#define WUCSR_WAKE_EN 0x00000004 -#define WUCSR_MPEN 0x00000002 - -/****************************************************************************/ - -/** Offset of Checksum Offload Engine/Enable Control Register. This register - * can be used to enable or disable Tx and Rx checksum offload. These refer - * specifically to the TCP/UDP checksums and not to the CRC32 calculated for - * an Ethernet frame itself, which is controlled separately and is done by - * default, unlike this which must be explicitly enabled. */ -#define COE_CR 0x130 - -/** Transmit checksum offload enabled. Software can write 1 here to enable or - * write 0 here to disable. After reset, this is disabled (0). */ -#define Tx_COE_EN 0x00010000 - -/** TODO. After reset, this is 0. */ -#define Rx_COE_MODE 0x00000002 - -/** Receive checksum offload enabled. Software can write 1 here to enable or - * write 0 here to disable. After reset, this is disabled (0). */ -#define Rx_COE_EN 0x00000001 - -/****************************************************************************/ - -/* Vendor-specific PHY Definitions */ - -/* EDPD NLP / crossover time configuration (LAN9500A only) */ -#define PHY_EDPD_CONFIG 16 -#define PHY_EDPD_CONFIG_TX_NLP_EN ((u16)0x8000) -#define PHY_EDPD_CONFIG_TX_NLP_1000 ((u16)0x0000) -#define PHY_EDPD_CONFIG_TX_NLP_768 ((u16)0x2000) -#define PHY_EDPD_CONFIG_TX_NLP_512 ((u16)0x4000) -#define PHY_EDPD_CONFIG_TX_NLP_256 ((u16)0x6000) -#define PHY_EDPD_CONFIG_RX_1_NLP ((u16)0x1000) -#define PHY_EDPD_CONFIG_RX_NLP_64 ((u16)0x0000) -#define PHY_EDPD_CONFIG_RX_NLP_256 ((u16)0x0400) -#define PHY_EDPD_CONFIG_RX_NLP_512 ((u16)0x0800) -#define PHY_EDPD_CONFIG_RX_NLP_1000 ((u16)0x0C00) -#define PHY_EDPD_CONFIG_EXT_CROSSOVER ((u16)0x0001) -#define PHY_EDPD_CONFIG_DEFAULT (PHY_EDPD_CONFIG_TX_NLP_EN | \ - PHY_EDPD_CONFIG_TX_NLP_768 | \ - PHY_EDPD_CONFIG_RX_1_NLP) - -/* Mode Control/Status Register */ -#define PHY_MODE_CTRL_STS 17 -#define MODE_CTRL_STS_EDPWRDOWN ((u16)0x2000) -#define MODE_CTRL_STS_ENERGYON ((u16)0x0002) - -#define SPECIAL_CTRL_STS 27 -#define SPECIAL_CTRL_STS_OVRRD_AMDIX ((u16)0x8000) -#define SPECIAL_CTRL_STS_AMDIX_ENABLE ((u16)0x4000) -#define SPECIAL_CTRL_STS_AMDIX_STATE ((u16)0x2000) - -#define PHY_INT_SRC 29 -#define PHY_INT_SRC_ENERGY_ON ((u16)0x0080) -#define PHY_INT_SRC_ANEG_COMP ((u16)0x0040) -#define PHY_INT_SRC_REMOTE_FAULT ((u16)0x0020) -#define PHY_INT_SRC_LINK_DOWN ((u16)0x0010) - -#define PHY_INT_MASK 30 -#define PHY_INT_MASK_ENERGY_ON ((u16)0x0080) -#define PHY_INT_MASK_ANEG_COMP ((u16)0x0040) -#define PHY_INT_MASK_REMOTE_FAULT ((u16)0x0020) -#define PHY_INT_MASK_LINK_DOWN ((u16)0x0010) -#define PHY_INT_MASK_DEFAULT (PHY_INT_MASK_ANEG_COMP | \ - PHY_INT_MASK_LINK_DOWN) - -#define PHY_SPECIAL 31 -#define PHY_SPECIAL_SPD ((u16)0x001C) -#define PHY_SPECIAL_SPD_10HALF ((u16)0x0004) -#define PHY_SPECIAL_SPD_10FULL ((u16)0x0014) -#define PHY_SPECIAL_SPD_100HALF ((u16)0x0008) -#define PHY_SPECIAL_SPD_100FULL ((u16)0x0018) - -/****************************************************************************/ - -/* SMSC LAN9512 USB Vendor Requests */ - -/** Write Register: Specify as bRequest of a USB control message to write a - * register on the SMSC LAN9512. bmRequestType must specify a vendor-specific - * request in the host-to-device direction, wIndex must specify the offset of - * the register, and the transfer data must be 4 bytes containing the value to - * write. */ -#define SMSC9512_VENDOR_REQUEST_WRITE_REGISTER 0xA0 - -/** Read Register: Specify as bRequest of a USB control message to read a - * register from the SMSC LAN9512. bmRequestType must specify a vendor-specific - * request in the device-to-host direction, wIndex must specify the offset of - * the register, and the transfer data must be a 4-byte location in which to - * store the register's contents. */ -#define SMSC9512_VENDOR_REQUEST_READ_REGISTER 0xA1 - -/** TODO */ -#define SMSC9512_VENDOR_REQUEST_GET_STATS 0xA2 - -/****************************************************************************/ - -/* Interrupt Endpoint status word bitfields */ -#define INT_ENP_TX_STOP ((uint32_t)BIT(17)) -#define INT_ENP_RX_STOP ((uint32_t)BIT(16)) -#define INT_ENP_PHY_INT ((uint32_t)BIT(15)) -#define INT_ENP_TXE ((uint32_t)BIT(14)) -#define INT_ENP_TDFU ((uint32_t)BIT(13)) -#define INT_ENP_TDFO ((uint32_t)BIT(12)) -#define INT_ENP_RXDF ((uint32_t)BIT(11)) - -/***********************************/ - -#endif /* _SMSC9512_H_ */ diff --git a/device/smsc9512/vlanStat.c b/device/smsc9512/vlanStat.c deleted file mode 100644 index de1184db..00000000 --- a/device/smsc9512/vlanStat.c +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @file vlanStat.c - */ -/* Embedded Xinu, Copyright (C) 2009, 2013. All rights reserved. */ - -#include -#include - -int vlanStat(void) -{ - fprintf(stderr, "ERROR: VLANs not supported by this driver.\n"); - return SYSERR; -} diff --git a/device/tcp/tcpRecvValid.c b/device/tcp/tcpRecvValid.c index 91e40cc7..73ee7697 100644 --- a/device/tcp/tcpRecvValid.c +++ b/device/tcp/tcpRecvValid.c @@ -22,7 +22,7 @@ bool tcpRecvValid(struct packet *pkt, struct tcb *tcbptr) struct tcpPkt *tcp; ushort tcplen; tcpseq temp; - bool result; + bool result = 0; bool resultB; ushort seglen; uint availwnd; diff --git a/device/tcp/tcpSend.c b/device/tcp/tcpSend.c index 7a971a19..6b01e0c4 100644 --- a/device/tcp/tcpSend.c +++ b/device/tcp/tcpSend.c @@ -31,8 +31,8 @@ int tcpSend(struct tcb *tcbptr, uchar ctrl, uint seqnum, int result; uchar *data; uint i = 0; - ushort window = 0; ushort msslen = 0; + ushort window = 0; ushort tcplen; /* If SYN is set, then don't include in datalen, but include MSS */ @@ -75,8 +75,8 @@ int tcpSend(struct tcb *tcbptr, uchar ctrl, uint seqnum, tcp->acknum = acknum; tcp->offset = octets2offset(TCP_HDR_LEN + msslen); tcp->control = ctrl; - tcp->window = tcpSendWindow(tcbptr); - window = tcp->window; + window = tcpSendWindow(tcbptr); + tcp->window = window; data = tcp->data; /* Add options */ diff --git a/device/telnet/telnetRead.c b/device/telnet/telnetRead.c index 1786534a..62691d3a 100644 --- a/device/telnet/telnetRead.c +++ b/device/telnet/telnetRead.c @@ -277,10 +277,15 @@ devcall telnetRead(device *devptr, void *buf, uint len) TELNET_TRACE("Recv Interrupt"); /* Terminate the currently running thread... */ /* unless the current thread name begins with "SHELL" */ - if (strncmp(thrtab[thrcurrent].name, "SHELL", 5) != 0) + + uint cpuid; + cpuid = getcpuid(); + thrtab_acquire(thrcurrent[cpuid]); + if (strncmp(thrtab[thrcurrent[cpuid]].name, "SHELL", 5) != 0) { kill(thrcurrent); } + thrtab_release(thrcurrent[cpuid]); break; case TELNET_AO: TELNET_TRACE("Recv Abort Output"); diff --git a/device/telnet/telnetServer.c b/device/telnet/telnetServer.c index 96a284d9..2d2a6bdb 100644 --- a/device/telnet/telnetServer.c +++ b/device/telnet/telnetServer.c @@ -11,6 +11,7 @@ #include #include #include +#include thread telnetServerKiller(ushort, ushort); @@ -58,7 +59,7 @@ thread telnetServer(int ethdev, int port, ushort telnetdev, sprintf(thrname, "telnetSvrKill_%d", (devtab[telnetdev].minor)); killtid = create((void *)telnetServerKiller, INITSTK, INITPRIO, thrname, 2, telnetdev, tcpdev); - ready(killtid, RESCHED_YES); + ready(killtid, RESCHED_YES, CORE_ZERO); if (open(tcpdev, host, NULL, port, NULL, TCP_PASSIVE) < 0) { @@ -111,7 +112,7 @@ thread telnetServer(int ethdev, int port, ushort telnetdev, /* Clear any pending messages */ recvclr(); TELNET_TRACE("telnetServer() spawning shell thread %d\n", tid); - ready(tid, RESCHED_YES); + ready(tid, RESCHED_YES, CORE_ZERO); // loop until child process dies while (recvclr() != tid) diff --git a/device/uart-ns16550/Makerules b/device/uart-ns16550/Makerules deleted file mode 100644 index e0cf394d..00000000 --- a/device/uart-ns16550/Makerules +++ /dev/null @@ -1,25 +0,0 @@ - -# Name of this component (the directory this file is stored in) -COMP = device/uart-ns16550 - -# Source files for this component -C_FILES = kgetc.c \ - kputc.c \ - ../uart/uartControl.c \ - ../uart/uartGetc.c \ - uartHwInit.c \ - uartHwPutc.c \ - uartHwStat.c \ - ../uart/uartInit.c \ - uartInterrupt.c \ - ../uart/uartPutc.c \ - ../uart/uartRead.c \ - ../uart/uartWrite.c \ - ../uart/uartStat.c \ - ../uart/kprintf.c \ - ../uart/kvprintf.c -S_FILES = - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/device/uart-ns16550/kgetc.c b/device/uart-ns16550/kgetc.c deleted file mode 100644 index 5a6a416b..00000000 --- a/device/uart-ns16550/kgetc.c +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @file kgetc.c - */ -/* Embedded Xinu, Copyright (C) 2009, 2013. All rights reserved. */ - -#include -#include "ns16550.h" - -/** - * @ingroup uarthardware - * - * Synchronously read a character from a UART. This blocks until a character is - * available. The interrupt handler is not used. - * - * @param devptr - * Pointer to the device table entry for a UART. - * - * @return - * The character read from the UART as an unsigned char cast - * to an int. - */ -syscall kgetc(device *devptr) -{ - volatile struct ns16550_uart_csreg *regptr; - struct uart *uartptr; - uint uart_im; - uchar c; - - /* Get pointers to the UART and to its registers. */ - uartptr = &uarttab[devptr->minor]; - regptr = devptr->csr; - - /* Save the UART's interrupt state and disable the UART's interrupts. Note: - * we do not need to disable global interrupts here; only UART interrupts - * must be disabled, to prevent race conditions with the UART interrupt - * handler. */ - uart_im = regptr->ier; - regptr->ier = 0; - - /* Wait until a character is ready to be received. */ - while (!(regptr->lsr & UART_LSR_DR)) - { - /* Do nothing */ - } - - /* Get the next character from the UART by reading it from the Receiving - * Holding Register. */ - c = regptr->rbr; - - /* Tally one character received. */ - uartptr->cin++; - - /* Restore UART interrupts and return the read character. */ - regptr->ier = uart_im; - return c; -} diff --git a/device/uart-ns16550/kputc.c b/device/uart-ns16550/kputc.c deleted file mode 100644 index 8c74df07..00000000 --- a/device/uart-ns16550/kputc.c +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @file kputc.c - */ -/* Embedded Xinu, Copyright (C) 2009, 2013. All rights reserved. */ - -#include -#include "ns16550.h" - -/** - * @ingroup uarthardware - * - * Synchronously write a character to a UART. This blocks until the character - * has been written to the hardware. The interrupt handler is not used. - * - * @param c - * The character to write. - * @param devptr - * Pointer to the device table entry for a UART. - * - * @return - * The character written to the UART as an unsigned char cast - * to an int. - */ -syscall kputc(uchar c, device *devptr) -{ - struct uart *uartptr; - volatile struct ns16550_uart_csreg *regptr; - uint uart_im; - - /* Get pointers to the UART and to its registers. */ - uartptr = &uarttab[devptr->minor]; - regptr = devptr->csr; - - /* Save the UART's interrupt state and disable the UART's interrupts. Note: - * we do not need to disable global interrupts here; only UART interrupts - * must be disabled, to prevent race conditions with the UART interrupt - * handler. */ - uart_im = regptr->ier; - regptr->ier = 0; - - /* Wait until UART is ready for another character */ - while ((regptr->lsr & UART_LSR_TEMT) != UART_LSR_TEMT) - { - /* Do nothing */ - } - - /* Send character. */ - regptr->thr = c; - - /* Tally one character sent. */ - uartptr->cout++; - - /* Restore UART interrupts and return the put character. */ - regptr->ier = uart_im; - return c; -} diff --git a/device/uart-ns16550/ns16550.h b/device/uart-ns16550/ns16550.h deleted file mode 100644 index 52bff547..00000000 --- a/device/uart-ns16550/ns16550.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file ns16550.h - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#ifndef _NS16550_H_ -#define _NS16550_H_ - -#include -#include - -/** - * Control and status registers for the 16550 UART. This structure is - * mapped directly to the base address for the CSR. - */ -struct ns16550_uart_csreg -{ -#if UART_CSR_SPACED - volatile ulong buffer; /**< receive buffer (read only) */ - /**< OR transmit hold (write only) */ - volatile ulong ier; /**< interrupt enable */ - volatile ulong iir; /**< interrupt ident (read only) */ - /**< OR FIFO control (write only) */ - volatile ulong lcr; /**< line control */ - volatile ulong mcr; /**< modem control */ - volatile ulong lsr; /**< line status */ - volatile ulong msr; /**< modem status */ - volatile ulong scr; /**< scratch */ -#else - - volatile uchar buffer; /**< receive buffer (read only) */ - /**< OR transmit hold (write only) */ - volatile uchar ier; /**< interrupt enable */ - volatile uchar iir; /**< interrupt ident (read only) */ - /**< OR FIFO control (write only) */ - volatile uchar lcr; /**< line control */ - volatile uchar mcr; /**< modem control */ - volatile uchar lsr; /**< line status */ - volatile uchar msr; /**< modem status */ - volatile uchar scr; /**< scratch */ -#endif -}; - -/* Alternative names for control and status registers */ -#define rbr buffer /**< receive buffer (read only) */ -#define thr buffer /**< transmit hold (write only) */ -#define fcr iir /**< FIFO control (write only) */ -#define dll buffer /**< divisor latch low byte */ -#define dlm ier /**< divisor latch high byte */ - -/* UART Bit flags for control and status registers */ -/* Interrupt enable bits */ -#define UART_IER_ERBFI 0x01 /**< Received data interrupt mask */ -#define UART_IER_ETBEI 0x02 /**< Transmitter buffer empty interrupt */ -#define UART_IER_ELSI 0x04 /**< Recv line status interrupt mask */ -#define UART_IER_EMSI 0x08 /**< Modem status interrupt mask */ - -/* Interrupt identification masks */ -#define UART_IIR_IRQ 0x01 /**< Interrupt pending bit */ -#define UART_IIR_IDMASK 0x0E /**< 3-bit field for interrupt ID */ -#define UART_IIR_MSC 0x00 /**< Modem status change */ -#define UART_IIR_THRE 0x02 /**< Transmitter holding register empty */ -#define UART_IIR_RDA 0x04 /**< Receiver data available */ -#define UART_IIR_RLSI 0x06 /**< Receiver line status interrupt */ -#define UART_IIR_RTO 0x0C /**< Receiver timed out */ - -/* FIFO control bits */ -#define UART_FCR_EFIFO 0x01 /**< Enable in and out hardware FIFOs */ -#define UART_FCR_RRESET 0x02 /**< Reset receiver FIFO */ -#define UART_FCR_TRESET 0x04 /**< Reset transmit FIFO */ -#define UART_FCR_TRIG0 0x00 /**< RCVR FIFO trigger level one char */ -#define UART_FCR_TRIG1 0x40 /**< RCVR FIFO trigger level 1/4 */ -#define UART_FCR_TRIG2 0x80 /**< RCVR FIFO trigger level 2/4 */ -#define UART_FCR_TRIG3 0xC0 /**< RCVR FIFO trigger level 3/4 */ - -/* Line control bits */ -#define UART_LCR_DLAB 0x80 /**< Divisor latch access bit */ -#define UART_LCR_8N1 0x03 /**< 8 bits, no parity, 1 stop */ - -/* Modem control bits */ -#define UART_MCR_OUT2 0x08 /**< User-defined OUT2. */ -#define UART_MCR_LOOP 0x10 /**< Enable loopback test mode */ - -/* Line status bits */ -#define UART_LSR_DR 0x01 /**< Data ready */ -#define UART_LSR_THRE 0x20 /**< Transmit-hold-register empty */ -#define UART_LSR_TEMT 0x40 /**< Transmitter empty */ - -#endif /* _NS16550_H_ */ diff --git a/device/uart-ns16550/uartHwInit.c b/device/uart-ns16550/uartHwInit.c deleted file mode 100644 index 903bb9a7..00000000 --- a/device/uart-ns16550/uartHwInit.c +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @file uartHwInit.c - */ -/* Embedded Xinu, Copyright (C) 2009, 2013. All rights reserved. */ - -#include -#include -#include -#include "ns16550.h" - -devcall uartHwInit(device *devptr) -{ - volatile struct ns16550_uart_csreg *regptr = devptr->csr; - - /* Set baud rate */ - regptr->lcr = UART_LCR_DLAB; /* Set Divisor Latch Access Bit */ - regptr->dll = platform.uart_dll; /* Set Divisor Latch Low Byte */ - regptr->dlm = 0x00; /* Set Divisor Latch High Byte */ - - regptr->lcr = UART_LCR_8N1; /* 8 bit, No Parity, 1 Stop */ - regptr->fcr = 0x00; /* Disable FIFO for now */ - /* OUT2 is used to control the board's interrupt tri-state */ - /* buffer. It should be set high to generate interrupts properly. */ - regptr->mcr = UART_MCR_OUT2; /* Turn on user-defined OUT2. */ - - /* Enable interrupts */ - regptr->ier = UART_IER_ERBFI | UART_IER_ETBEI | UART_IER_ELSI; - - /* Enable UART FIFOs, clear and set interrupt trigger level */ - regptr->fcr = UART_FCR_EFIFO | UART_FCR_RRESET - | UART_FCR_TRESET | UART_FCR_TRIG2; - - /* Enable processor handling of UART interrupt requests */ - interruptVector[devptr->irq] = devptr->intr; - enable_irq(devptr->irq); - return OK; -} diff --git a/device/uart-ns16550/uartHwPutc.c b/device/uart-ns16550/uartHwPutc.c deleted file mode 100644 index 9d92eeb8..00000000 --- a/device/uart-ns16550/uartHwPutc.c +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @file uartHwPutc.c - */ -/* Embedded Xinu, Copyright (C) 2009, 2013. All rights reserved. */ - -#include -#include "ns16550.h" - -void uartHwPutc(void *csr, uchar c) -{ - volatile struct ns16550_uart_csreg *regptr = csr; - - regptr->thr = c; -} diff --git a/device/uart-ns16550/uartHwStat.c b/device/uart-ns16550/uartHwStat.c deleted file mode 100644 index 25f2675f..00000000 --- a/device/uart-ns16550/uartHwStat.c +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @file uartHwStat.c - */ -/* Embedded Xinu, Copyright (C) 2009, 2013. All rights reserved. */ - -#include -#include -#include "ns16550.h" - -void uartHwStat(void *csr) -{ - static const char * const label[2] = { "OFF", "ON " }; - uint enabled; - volatile struct ns16550_uart_csreg *regptr = csr; - - printf("\n\tINTERRUPT ENABLE:\n"); - printf("\t------------------------------------------\n"); - - enabled = (regptr->ier & UART_IER_ERBFI) ? 1 : 0; - printf("\t%s Receiver FIFO Reached Trigger Level\n", label[enabled]); - - enabled = (regptr->ier & UART_IER_ETBEI) ? 1 : 0; - printf("\t%s Transmitter FIFO Empty\n", label[enabled]); - - enabled = (regptr->ier & UART_IER_ELSI) ? 1 : 0; - printf("\t%s Receiver Error or BREAK\n", label[enabled]); - - enabled = (regptr->ier & UART_IER_EMSI) ? 1 : 0; - printf("\t%s Modem Status", label[enabled]); -} diff --git a/device/uart-ns16550/uartInterrupt.c b/device/uart-ns16550/uartInterrupt.c deleted file mode 100644 index a0f4bbc2..00000000 --- a/device/uart-ns16550/uartInterrupt.c +++ /dev/null @@ -1,133 +0,0 @@ -/** - * @file uartInterrupt.c - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include "ns16550.h" - -extern int resdefer; - -/** - * @ingroup uarthardware - * - * Decode hardware interrupt request from UART device. - */ -interrupt uartInterrupt(void) -{ - int u = 0, iir = 0, lsr = 0, count = 0; - char c; - struct uart *uartptr = NULL; - struct ns16550_uart_csreg *regptr = NULL; - - resdefer = 1; /* deferral rescheduling. */ - - for (u = 0; u < NUART; u++) - { - uartptr = &uarttab[u]; - if (NULL == uartptr) - { - continue; - } - regptr = (struct ns16550_uart_csreg *)uartptr->csr; - if (NULL == regptr) - { - continue; - } - - /* Check interrupt identification register */ - iir = regptr->iir; - if (iir & UART_IIR_IRQ) - { - continue; - } - - /* - * Decode interrupt cause based upon the value taken from the - * UART interrupt identification register. Clear interrupt source, - * and perform the appropriate handling to coordinate properly - * with the upper half of the driver. - */ - - /* Decode interrupt cause */ - iir &= UART_IIR_IDMASK; - switch (iir) - { - /* Receiver line status interrupt */ - case UART_IIR_RLSI: - lsr = regptr->lsr; - uartptr->lserr++; - break; - - /* Receiver data available or timed out */ - case UART_IIR_RDA: - case UART_IIR_RTO: - uartptr->iirq++; - count = 0; - while (regptr->lsr & UART_LSR_DR) - { - c = regptr->buffer; - if (uartptr->icount < UART_IBLEN) - { - uartptr->in - [(uartptr->istart + - uartptr->icount) % UART_IBLEN] = c; - uartptr->icount++; - count++; - } - else - { - uartptr->ovrrn++; - } - } - uartptr->cin += count; - signaln(uartptr->isema, count); - - /* Fall through -- Rx status trumps Tx status on Qemu. */ - - /* Transmitter holding register empty */ - case UART_IIR_THRE: - lsr = regptr->lsr; /* Read from LSR to clear interrupt */ - if (!(lsr & UART_LSR_THRE)) - break; - uartptr->oirq++; - count = 0; - if (uartptr->ocount > 0) - { - /* Write characters to the lower half of the UART. */ - do - { - count++; - uartptr->ocount--; - regptr->buffer = uartptr->out[uartptr->ostart]; - uartptr->ostart = (uartptr->ostart + 1) % UART_OBLEN; - } - while ((count < UART_FIFO_LEN) && (uartptr->ocount > 0)); - } - - if (count) - { - uartptr->cout += count; - signaln(uartptr->osema, count); - } - /* If no characters were written, set the output idle flag. */ - else - { - uartptr->oidle = TRUE; - } - break; - - /* Modem status change */ - case UART_IIR_MSC: - break; - } - } - - if (--resdefer > 0) - { - resdefer = 0; - resched(); - } -} diff --git a/device/uart-pl011/pl011.h b/device/uart-pl011/pl011.h index 96d4e2c5..2149160d 100644 --- a/device/uart-pl011/pl011.h +++ b/device/uart-pl011/pl011.h @@ -141,9 +141,17 @@ struct pl011_uart_csreg #define PL011_ICR_CTSMIC (1<<1) //CTS interrupt clear #define PL011_ICR_RIMIC (1<<0) //RI interrupt clear -#define PL011_FIFO_LEN 8 /**< During testing on a Raspberry Pi, I could only send 8. */ - -#define PL011_BAUD_INT(x) (3000000 / (16 * (x))) -#define PL011_BAUD_FRAC(x) (int)((((3000000.0 / (16.0 * (x)))-PL011_BAUD_INT(x))*64.0)+0.5) //9600 baud may be slightly off with this calcualtion +#define PL011_FIFO_LEN 8 /**< During testing on a Raspberry Pi, I could only sen 8. */ + +/* Different versions of Pi have different + * UART clock frequencies */ +#ifdef _XINU_PLATFORM_ARM_RPI_3_ +#define UARTCLK 48000000 +#elif defined _XINU_PLATFORM_ARM_RPI_ +#define UARTCLK 3000000 +#endif + +#define PL011_BAUD_INT(x) (UARTCLK / (16 * (x))) +#define PL011_BAUD_FRAC(x) (int)((((UARTCLK / (16.0 * (x)))-PL011_BAUD_INT(x))*64.0)+0.5) //9600 baud may be slightly off with this calcualtion #endif /* _PL011_H_ */ diff --git a/device/uart-pl011/uartHwInit.c b/device/uart-pl011/uartHwInit.c index 50c0dcab..41850e35 100644 --- a/device/uart-pl011/uartHwInit.c +++ b/device/uart-pl011/uartHwInit.c @@ -7,7 +7,6 @@ #include #include #include "pl011.h" - #ifdef _XINU_PLATFORM_ARM_RPI_ /* Offset of UART registers from the starti of the GPIO registers. */ @@ -51,13 +50,36 @@ static void setup_gpio_pins(void *uart_regs) } #endif /* _XINU_PLATFORM_ARM_RPI_ */ + +#ifdef _XINU_PLATFORM_ARM_RPI_3_ + +#include +#include + +static void setup_gpio_pins(void) +{ + volatile struct rpi_gpio_regs *regptr = + (volatile struct rpi_gpio_regs *)(GPIO_REGS_BASE); + + /* set up pins 14 & 15 to use alt0, for uart Rx and Tx */ + regptr->gpfsel[1] &= ~((7 << 12) | (7 << 15)); + regptr->gpfsel[1] |= (4 << 12) | (4 << 15); + + /* Disable pull-up/down on pins 14 & 15 */ + regptr->gppud = 0; + udelay(2); + regptr->gppudclk[0] = (1 << 14) | (1 << 15); + udelay(2); + regptr->gppudclk[0] = 0; + +} + +#endif /* _XINU_PLATFORM_ARM_RPI_3_ */ + devcall uartHwInit(device *devptr) { volatile struct pl011_uart_csreg *regptr = devptr->csr; - /* TODO: It doesn't work without this delay, but why? */ - udelay(1500); - /* Disable the UART by zeroing the "control register". */ regptr->cr = 0; @@ -66,6 +88,10 @@ devcall uartHwInit(device *devptr) setup_gpio_pins((void*)regptr); #endif +#ifdef _XINU_PLATFORM_ARM_RPI_3_ + setup_gpio_pins(); +#endif + /* Poll the "flags register" to wait for the UART to stop transmitting or * receiving. */ while (regptr->fr & PL011_FR_BUSY) @@ -104,14 +130,13 @@ devcall uartHwInit(device *devptr) /* Allow the UART to generate interrupts only when receiving or * transmitting. */ regptr->imsc = PL011_IMSC_RXIM | PL011_IMSC_TXIM; - /* We have decided that we are going to leave FIFOs off for now. Since the * FIFOs are of size 16 and the lowest trigger level you can set for the * receive FIFO is 1/8, the first interrupt isn't triggered until there are * at least two bytes in the receive FIFO. We want an interrupt as soon as * a byte arrives */ -#if 0 - /* Enable UART FIFOs. */ +#if 0 + /* Enable UART FIFOs. */ regptr->lcrh |= PL011_LCRH_FEN; /* Set the interrupt FIFO level select register. This configures the amount @@ -126,7 +151,7 @@ devcall uartHwInit(device *devptr) /* Register the UART's interrupt handler with XINU's interrupt vector, then * actually enable the UART's interrupt line. */ - interruptVector[devptr->irq] = devptr->intr; - enable_irq(devptr->irq); + interruptVector[devptr->irq] = devptr->intr; + enable_irq(devptr->irq); return OK; } diff --git a/device/uart-pl011/uartInterrupt.c b/device/uart-pl011/uartInterrupt.c index d72ff872..0a37d896 100644 --- a/device/uart-pl011/uartInterrupt.c +++ b/device/uart-pl011/uartInterrupt.c @@ -15,136 +15,136 @@ */ interrupt uartInterrupt(void) { - uint u; - - /* Set resdefer to prevent other threads from being scheduled before this - * interrupt handler finishes. This prevents this interrupt handler from - * being executed re-entrantly. */ - extern int resdefer; - resdefer = 1; - - /* Check for interrupts on each UART. Note: this assumes all the UARTs in - * 'uarttab' are PL011 UARTs. */ - for (u = 0; u < NUART; u++) - { - uint mis, count; - uchar c; - volatile struct pl011_uart_csreg *regptr; - struct uart *uartptr; - - /* Get a pointer to the UART structure and a pointer to the UART's - * hardware registers. */ - uartptr = &uarttab[u]; - regptr = uartptr->csr; - - /* Check the Masked Interrupt Status register to determine which - * interrupts have occurred, then handle them. */ - mis = regptr->mis; - if (mis & PL011_MIS_TXMIS) - { - /* Transmit interrupt is asserted. If FIFOs are enabled, this - * happens when the amount of data in the transmit FIFO is less than - * or equal to the programmed trigger level. If FIFOs are disabled, - * this happens if the Tx holding register is empty. */ - - /* Increment number of transmit interrupts received on this UART. - * */ - uartptr->oirq++; - - /* Explicitly clear the transmit interrupt. This is necessary - * because there may not be enough bytes in the output buffer to - * fill the FIFO greater than the transmit interrupt trigger level. - * If FIFOs are disabled, this applies if there are 0 bytes to - * transmit and therefore nothing to fill the Tx holding register - * with. */ - regptr->icr = PL011_ICR_TXIC; - - /* If there are bytes pending in the output buffer, write them to - * the UART until either there are no bytes remaining or there is no - * space remaining in the transmit FIFO. (If FIFOs are disabled, - * the Tx holding register acts like a FIFO of size 1, so the code - * still works.) Otherwise, the UART is now idle, so set the - * "oidle" flag, which will allow the next call to uartWrite() to - * start transmitting again by writing a byte directly to the - * hardware. */ - if (uartptr->ocount > 0) - { - count = 0; - do - { - regptr->dr = uartptr->out[uartptr->ostart]; - uartptr->ostart = (uartptr->ostart + 1) % UART_OBLEN; - uartptr->ocount--; - count++; - } while (!(regptr->fr & PL011_FR_TXFF) && (uartptr->ocount > 0)); - - /* One or more bytes were successfully removed from the output - * buffer and written to the UART hardware. Increment the total - * number of bytes written to this UART and signal up to @count - * threads waiting in uartWrite() to tell them there is now - * space in the output buffer. */ - uartptr->cout += count; - signaln(uartptr->osema, count); - } - else - { - uartptr->oidle = TRUE; - } - } - if (mis & PL011_MIS_RXMIS) - { - /* Receive interrupt is asserted. If FIFOs are enabled, this - * happens when the amount of data in the receive FIFO is greater - * than or equal to the programmed trigger level. If FIFOs are - * disabled, this happens when the Rx holding register was filled - * with one byte. */ - - /* Increment number of receive interrupts received on this UART. */ - uartptr->iirq++; - - /* Number of bytes successfully buffered so far. */ - count = 0; - - /* Read bytes from the receive FIFO until it is empty again. (If - * FIFOs are disabled, the Rx holding register acts as a FIFO of - * size 1, so the code still works.) */ - do - { - /* Get a byte from the UART's receive FIFO. */ - c = regptr->dr; - if (uartptr->icount < UART_IBLEN) - { - /* There is space for the byte in the input buffer, so add - * it and tally one character received. */ - uartptr->in[(uartptr->istart + - uartptr->icount) % UART_IBLEN] = c; - uartptr->icount++; - count++; - } - else - { - /* There is *not* space for the byte in the input buffer, so - * ignore it and increment the overrun count. */ - uartptr->ovrrn++; - } - } while (!(regptr->fr & PL011_FR_RXFE)); - /* The receive interrupt will have been automatically cleared - * because we read bytes from the receive FIFO until it became - * empty. */ - - /* Increment cin by the number of bytes successfully buffered and - * signal up to that many threads that are currently waiting in - * uartRead() for buffered data to become available. */ - uartptr->cin += count; - signaln(uartptr->isema, count); - } - } - - /* Now that the UART interrupt handler is finished, we can safely wake up - * any threads that were signaled. */ - if (--resdefer > 0) - { - resdefer = 0; - resched(); - } + uint u; + + /* Set resdefer to prevent other threads from being scheduled before this + * interrupt handler finishes. This prevents this interrupt handler from + * being executed re-entrantly. */ + extern int resdefer; + resdefer = 1; + + /* Check for interrupts on each UART. Note: this assumes all the UARTs in + * 'uarttab' are PL011 UARTs. */ + for (u = 0; u < NUART; u++) + { + uint mis, count; + uchar c; + volatile struct pl011_uart_csreg *regptr; + struct uart *uartptr; + + /* Get a pointer to the UART structure and a pointer to the UART's + * hardware registers. */ + uartptr = &uarttab[u]; + regptr = uartptr->csr; + + /* Check the Masked Interrupt Status register to determine which + * interrupts have occurred, then handle them. */ + mis = regptr->mis; + if (mis & PL011_MIS_TXMIS) + { + /* Transmit interrupt is asserted. If FIFOs are enabled, this + * happens when the amount of data in the transmit FIFO is less than + * or equal to the programmed trigger level. If FIFOs are disabled, + * this happens if the Tx holding register is empty. */ + + /* Increment number of transmit interrupts received on this UART. + * */ + uartptr->oirq++; + + /* Explicitly clear the transmit interrupt. This is necessary + * because there may not be enough bytes in the output buffer to + * fill the FIFO greater than the transmit interrupt trigger level. + * If FIFOs are disabled, this applies if there are 0 bytes to + * transmit and therefore nothing to fill the Tx holding register + * with. */ + regptr->icr = PL011_ICR_TXIC; + + /* If there are bytes pending in the output buffer, write them to + * the UART until either there are no bytes remaining or there is no + * space remaining in the transmit FIFO. (If FIFOs are disabled, + * the Tx holding register acts like a FIFO of size 1, so the code + * still works.) Otherwise, the UART is now idle, so set the + * "oidle" flag, which will allow the next call to uartWrite() to + * start transmitting again by writing a byte directly to the + * hardware. */ + if (uartptr->ocount > 0) + { + count = 0; + do + { + regptr->dr = uartptr->out[uartptr->ostart]; + uartptr->ostart = (uartptr->ostart + 1) % UART_OBLEN; + uartptr->ocount--; + count++; + } while (!(regptr->fr & PL011_FR_TXFF) && (uartptr->ocount > 0)); + + /* One or more bytes were successfully removed from the output + * buffer and written to the UART hardware. Increment the total + * number of bytes written to this UART and signal up to @count + * threads waiting in uartWrite() to tell them there is now + * space in the output buffer. */ + uartptr->cout += count; + signaln(uartptr->osema, count); + } + else + { + uartptr->oidle = TRUE; + } + } + if (mis & PL011_MIS_RXMIS) + { + /* Receive interrupt is asserted. If FIFOs are enabled, this + * happens when the amount of data in the receive FIFO is greater + * than or equal to the programmed trigger level. If FIFOs are + * disabled, this happens when the Rx holding register was filled + * with one byte. */ + + /* Increment number of receive interrupts received on this UART. */ + uartptr->iirq++; + + /* Number of bytes successfully buffered so far. */ + count = 0; + + /* Read bytes from the receive FIFO until it is empty again. (If + * FIFOs are disabled, the Rx holding register acts as a FIFO of + * size 1, so the code still works.) */ + do + { + /* Get a byte from the UART's receive FIFO. */ + c = regptr->dr; + if (uartptr->icount < UART_IBLEN) + { + /* There is space for the byte in the input buffer, so add + * it and tally one character received. */ + uartptr->in[(uartptr->istart + + uartptr->icount) % UART_IBLEN] = c; + uartptr->icount++; + count++; + } + else + { + /* There is *not* space for the byte in the input buffer, so + * ignore it and increment the overrun count. */ + uartptr->ovrrn++; + } + } while (!(regptr->fr & PL011_FR_RXFE)); + /* The receive interrupt will have been automatically cleared + * because we read bytes from the receive FIFO until it became + * empty. */ + + /* Increment cin by the number of bytes successfully buffered and + * signal up to that many threads that are currently waiting in + * uartRead() for buffered data to become available. */ + uartptr->cin += count; + signaln(uartptr->isema, count); + } + } + + /* Now that the UART interrupt handler is finished, we can safely wake up + * any threads that were signaled. */ + if (--resdefer > 0) + { + resdefer = 0; + resched(); + } } diff --git a/device/uart-x86/Makerules b/device/uart-x86/Makerules deleted file mode 100644 index cfcbb800..00000000 --- a/device/uart-x86/Makerules +++ /dev/null @@ -1,25 +0,0 @@ - -# Name of this component (the directory this file is stored in) -COMP = device/uart-x86 - -# Source files for this component -C_FILES = kgetc.c \ - kputc.c \ - ../uart/uartControl.c \ - ../uart/uartGetc.c \ - uartHwInit.c \ - uartHwPutc.c \ - uartHwStat.c \ - ../uart/uartInit.c \ - uartInterrupt.c \ - ../uart/uartPutc.c \ - ../uart/uartRead.c \ - ../uart/uartWrite.c \ - ../uart/uartStat.c \ - ../uart/kprintf.c \ - ../uart/kvprintf.c -S_FILES = - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/device/uart-x86/kgetc.c b/device/uart-x86/kgetc.c deleted file mode 100644 index d42badec..00000000 --- a/device/uart-x86/kgetc.c +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @file kgetc.c - */ -/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ - -#include -#include -#include "x86uart.h" - -syscall kgetc(device *pdev) -{ - int irmask; - volatile struct uart_csreg *pucsr = pdev->csr; - uchar c; - - irmask = pucsr->ier; /* Save UART interrupt state. */ - pucsr->ier = 0; /* Disable UART interrupts. */ - - while (0 == (pucsr->lsr & UART_LSR_DR)) - { - } - - /* read character from Receive Holding Register */ - c = pucsr->rbr; - - pucsr->ier = irmask; /* Restore UART interrupts. */ - return c; -} diff --git a/device/uart-x86/kputc.c b/device/uart-x86/kputc.c deleted file mode 100644 index 98407224..00000000 --- a/device/uart-x86/kputc.c +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @file kputc.c - */ -/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ - -#include -#include "x86uart.h" - -syscall kputc(uchar c, device *pdev) -{ - void *pucsr = pdev->csr; - - while ((inb((ulong)pucsr + UART_LSR) & UART_LSR_THRE) == 0) - { - } - - outb((ulong)pucsr + UART_DATA, c); - - if (c == '\n') - { - while ((inb((ulong)pucsr + UART_LSR) & UART_LSR_THRE) == 0) - { - } - outb((ulong)pucsr + UART_DATA, '\r'); - } - - return OK; -} diff --git a/device/uart-x86/uartHwInit.c b/device/uart-x86/uartHwInit.c deleted file mode 100644 index 2cb04ee6..00000000 --- a/device/uart-x86/uartHwInit.c +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @file uartHwInit.c - */ -/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ - -#include -#include -#include -#include "x86uart.h" - -devcall uartHwInit(device *devptr) -{ - void *pucsr = devptr->csr; - - /* Set baud rate */ - outb((ulong)pucsr+UART_LCR, UART_LCR_DLAB); /* divisor latch access */ - outb((ulong)pucsr+UART_DLL, platform.uart_dll); /* divisor latch low */ - /* DLL 12 -> 9600 bps */ - /* DLL 1 -> 115200 bps */ - outb((ulong)pucsr+UART_DLM, 0); /* divisor latch high */ - - outb((ulong)pucsr+UART_LCR, UART_LCR_8N1); /* 8N1 mode */ - outb((ulong)pucsr+UART_FCR, 0); /* Disable FIFO */ - outb((ulong)pucsr+UART_MCR, UART_MCR_OUT2); /* User-defined OUT2 */ - /* OUT2 is used to control the board's interrupt tri-state */ - /* buffer. It should be set high to generate interrupt properly. */ - - /* Enable interrupts */ - outb((ulong)pucsr+UART_IER, UART_IER_ERBFI | UART_IER_ETBEI | UART_IER_ELSI); - - /* Enable UART hardware FIFOs, clear contents and set interrupt trigger level */ - outb((ulong)pucsr+UART_FCR, - UART_FCR_EFIFO | UART_FCR_RRESET | UART_FCR_TRESET | UART_FCR_TRIG2); - - set_handler(IRQBASE+devptr->irq, devptr->intr); - - return OK; -} diff --git a/device/uart-x86/uartHwPutc.c b/device/uart-x86/uartHwPutc.c deleted file mode 100644 index 9e757435..00000000 --- a/device/uart-x86/uartHwPutc.c +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @file uartHwPutc.c - */ -/* Embedded Xinu, Copyright (C) 2009, 2013. All rights reserved. */ - -#include -#include "x86uart.h" - -void uartHwPutc(void *csr, uchar c) -{ - outb((ulong)csr + UART_DATA, c); -} diff --git a/device/uart-x86/uartHwStat.c b/device/uart-x86/uartHwStat.c deleted file mode 100644 index 7100f512..00000000 --- a/device/uart-x86/uartHwStat.c +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @file uartHwStat.c - */ -/* Embedded Xinu, Copyright (C)2009, 2013. All rights reserved. */ - -#include -#include -#include "x86uart.h" - -void uartHwStat(void *csr) -{ - struct uart_csreg *pucsr = csr; - static const char *label[2] = { "OFF", "ON " }; - int uart_ier, level; - - pucsr = csr; - - printf("\n\tINTERRUPT ENABLE:\n"); - printf("\t------------------------------------------\n"); - - uart_ier = inb((ulong)pucsr + UART_IER); - level = (uart_ier & UART_IER_ERBFI) ? 1 : 0; - printf("\t%s Receiver FIFO Reached Trigger Level\n", label[level]); - - level = (uart_ier & UART_IER_ETBEI) ? 1 : 0; - printf("\t%s Transmitter FIFO Empty\n", label[level]); - - level = (uart_ier & UART_IER_ELSI) ? 1 : 0; - printf("\t%s Receiver Error or BREAK\n", label[level]); - - level = (uart_ier & UART_IER_EMSI) ? 1 : 0; - printf("\t%s Modem Status", label[level]); - - printf("\n"); -} diff --git a/device/uart-x86/uartInterrupt.c b/device/uart-x86/uartInterrupt.c deleted file mode 100644 index 8ac30b42..00000000 --- a/device/uart-x86/uartInterrupt.c +++ /dev/null @@ -1,114 +0,0 @@ -/** - * @file uartInterrupt.c - */ -/* Embedded XINU, Copyright (C) 2007. All rights reserved. */ - -#include -#include -#include -#include "x86uart.h" -#include -#include -#include - -/** - * Decode hardware interrupt request from UART device. - */ -interrupt uartInterrupt(void) -{ - int u = 0, iir = 0, lsr = 0, count = 0; - char c; - struct uart *puart = NULL; - struct uart_csreg *pucsr = NULL; - - for (u = 0; u < NUART; u++) - { - puart = &uarttab[u]; - pucsr = puart->csr; - if (NULL == pucsr) - { - continue; - } - - /* Check interrupt identification register */ - iir = inb((ulong)pucsr+UART_IIR); - if (iir & UART_IIR_IRQ) - { - continue; - } - - /* - * Decode interrupt cause based upon the value taken from the - * UART interrupt identification register. Clear interrupt source, - * and perform the appropriate handling to coordinate properly - * with the upper half of the driver. - */ - - /* Decode interrupt cause */ - iir &= UART_IIR_IDMASK; - switch (iir) - { - /* Receiver line status interrupt */ - case UART_IIR_RLSI: - lsr = inb((ulong)pucsr+UART_LSR); - puart->lserr++; - break; - - /* Receiver data available or timed out */ - case UART_IIR_RDA: - case UART_IIR_RTO: - puart->iirq++; - count = 0; - while (inb((ulong)pucsr+UART_LSR) & UART_LSR_DR) - { - c = inb((ulong)pucsr+UART_DATA); - if (puart->icount < UART_IBLEN) - { - puart->in[(puart->istart+puart->icount) % UART_IBLEN] = c; - puart->icount++; - count++; - } - else - { - puart->ovrrn++; - } - } - puart->cin += count; - signaln(puart->isema, count); - break; - - /* Transmitter holding register empty */ - case UART_IIR_THRE: - puart->oirq++; - lsr = inb((ulong)pucsr+UART_LSR); /* Read from LSR to clear interrupt */ - count = 0; - if (puart->ocount > 0) - { - /* Write characters to the lower half of the UART. */ - do - { - count++; - puart->ocount--; - outb((ulong)pucsr+UART_DATA, puart->out[puart->ostart]); - puart->ostart = (puart->ostart + 1) % UART_OBLEN; - } while ((count < UART_FIFO_LEN) && (puart->ocount > 0)); - } - - if (count) - { - puart->cout += count; - signaln(puart->osema, count); - } - /* If no characters were written, set the output idle flag. */ - else - { - puart->oidle = TRUE; - } - break; - - /* Modem status change */ - case UART_IIR_MSC: - break; - } - } -} diff --git a/device/uart-x86/x86uart.h b/device/uart-x86/x86uart.h deleted file mode 100644 index e6aa0240..00000000 --- a/device/uart-x86/x86uart.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @file x86uart.h - * - */ -/* Embedded XINU, Copyright (C) 2007. All rights reserved. */ - -#ifndef _X86UART_H_ -#define _x86UART_H_ - -#include -#include -#include - -/** - * Control and status registers for the 16550 UART. This structure is - * mapped directly to the base address for the CSR. - */ -struct uart_csreg -{ - volatile uchar buffer; /**< receive buffer (read only) */ - /**< OR transmit hold (write only) */ - volatile uchar ier; /**< interrupt enable */ - volatile uchar iir; /**< interrupt ident (read only) */ - /**< OR FIFO control (write only) */ - volatile uchar lcr; /**< line control */ - volatile uchar mcr; /**< modem control */ - volatile uchar lsr; /**< line status */ - volatile uchar msr; /**< modem status */ - volatile uchar scr; /**< scratch */ -}; - -/* Base address for TTY */ -#define UART_BASE 0x3f8 - -/* UART Register numbers */ -#define UART_DATA 0 -#define UART_IER 1 -#define UART_IIR 2 -#define UART_FCR 2 -#define UART_LCR 3 -#define UART_MCR 4 -#define UART_LSR 5 -#define UART_MSR 6 - -#define UART_DLL 0 /* LCR_DLAB = 1 */ -#define UART_DLM 1 /* LCR_DLAB = 1 */ - -/* Alternative names for control and status registers */ -#define rbr buffer /**< receive buffer (read only) */ -#define thr buffer /**< transmit hold (write only) */ -#define fcr iir /**< FIFO control (write only) */ -#define dll buffer /**< divisor latch low byte */ -#define dlm ier /**< divisor latch high byte */ - -/* UART Bit flags for control and status registers */ -/* Interrupt enable bits */ -#define UART_IER_ERBFI 0x01 /**< Received data interrupt mask */ -#define UART_IER_ETBEI 0x02 /**< Transmitter buffer empty interrupt */ -#define UART_IER_ELSI 0x04 /**< Recv line status interrupt mask */ -#define UART_IER_EMSI 0x08 /**< Modem status interrupt mask */ - -/* Interrupt identification masks */ -#define UART_IIR_IRQ 0x01 /**< Interrupt pending bit */ -#define UART_IIR_IDMASK 0x0E /**< 3-bit field for interrupt ID */ -#define UART_IIR_MSC 0x00 /**< Modem status change */ -#define UART_IIR_THRE 0x02 /**< Transmitter holding register empty */ -#define UART_IIR_RDA 0x04 /**< Receiver data available */ -#define UART_IIR_RLSI 0x06 /**< Receiver line status interrupt */ -#define UART_IIR_RTO 0x0C /**< Receiver timed out */ - -/* FIFO control bits */ -#define UART_FCR_EFIFO 0x01 /**< Enable in and out hardware FIFOs */ -#define UART_FCR_RRESET 0x02 /**< Reset receiver FIFO */ -#define UART_FCR_TRESET 0x04 /**< Reset transmit FIFO */ -#define UART_FCR_TRIG0 0x00 /**< RCVR FIFO trigger level one char */ -#define UART_FCR_TRIG1 0x40 /**< RCVR FIFO trigger level 1/4 */ -#define UART_FCR_TRIG2 0x80 /**< RCVR FIFO trigger level 2/4 */ -#define UART_FCR_TRIG3 0xC0 /**< RCVR FIFO trigger level 3/4 */ - -/* Line control bits */ -#define UART_LCR_DLAB 0x80 /**< Divisor latch access bit */ -#define UART_LCR_8N1 0x03 /**< 8 bits, no parity, 1 stop */ - -/* Modem control bits */ -#define UART_MCR_OUT2 0x08 /**< User-defined OUT2. */ -#define UART_MCR_LOOP 0x10 /**< Enable loopback test mode */ - -/* Line status bits */ -#define UART_LSR_DR 0x01 /**< Data ready */ -#define UART_LSR_THRE 0x20 /**< Transmit-hold-register empty */ -#define UART_LSR_TEMT 0x40 /**< Transmitter empty */ - -#define UART_FIFO_LEN 16 /**< Size of the hardware FIFO buffer */ - -/* UART Buffer lengths */ -#define UART_IBLEN 1024 -#define UART_OBLEN 1024 - -#endif /* _X86UART_H_ */ diff --git a/device/uart/kprintf.c b/device/uart/kprintf.c index d52d8cd9..1e573b84 100644 --- a/device/uart/kprintf.c +++ b/device/uart/kprintf.c @@ -6,11 +6,14 @@ #include #include +#include + +mutex_t serial_lock; /** * @ingroup uartgeneric * - * kernel printf: formatted, synchronous output to SERIAL0. + * kernel printf: Multicore-safe (by mutex locks), formatted, synchronous output to SERIAL0. * * @param format * The format string. Not all standard format specifiers are supported by @@ -26,9 +29,14 @@ syscall kprintf(const char *format, ...) { int retval; va_list ap; - + va_start(ap, format); + + mutex_acquire(serial_lock); retval = kvprintf(format, ap); + mutex_release(serial_lock); + va_end(ap); + return retval; } diff --git a/device/uart/uartInit.c b/device/uart/uartInit.c index e8f43e03..f7a9243d 100644 --- a/device/uart/uartInit.c +++ b/device/uart/uartInit.c @@ -30,6 +30,9 @@ devcall uartInit(device *devptr) struct uart *uartptr = &uarttab[devptr->minor]; + extern mutex_t serial_lock; + serial_lock = mutex_create(); + /* Initialize statistical counts. */ uartptr->cout = 0; uartptr->cin = 0; @@ -48,7 +51,6 @@ devcall uartInit(device *devptr) { return SYSERR; } - /* Initialize the output buffer, including a semaphore for threads to wait * on. */ uartptr->osema = semcreate(UART_OBLEN); @@ -61,9 +63,8 @@ devcall uartInit(device *devptr) semfree(uartptr->isema); return SYSERR; } - /* Initialize the actual hardware. */ - if (OK != uartHwInit(devptr)) + if (OK != uartHwInit(devptr)) { semfree(uartptr->isema); semfree(uartptr->osema); diff --git a/device/usb/usbcore.c b/device/usb/usbcore.c index 53b5fdfb..ae9597a9 100644 --- a/device/usb/usbcore.c +++ b/device/usb/usbcore.c @@ -66,6 +66,8 @@ #include #include #include +#include "../system/platforms/arm-rpi3/mmu.h" +#include /** Maximum number of simultaneous USB devices supported. */ #define MAX_NUSBDEV 32 @@ -75,7 +77,8 @@ /** Table of USB device structures that can be dynamically assigned to actual * devices as needed. */ -static struct usb_device usb_devices[MAX_NUSBDEV]; +// XXX change back to static +struct usb_device usb_devices[MAX_NUSBDEV]; /** Table of USB device drivers that have been registered with the USB core. */ static const struct usb_device_driver *usb_device_drivers[MAX_NUSBDEV]; @@ -201,6 +204,7 @@ usb_submit_xfer_request(struct usb_xfer_request *req) enum usb_transfer_type type; enum usb_direction dir; #endif + irqmask im; usb_status_t status; @@ -208,7 +212,8 @@ usb_submit_xfer_request(struct usb_xfer_request *req) !req->dev->inuse) { usb_error("Bad usb_xfer_request: no device or completion callback " - "function\n"); + "function\r\n"); + return USB_STATUS_INVALID_PARAMETER; } @@ -218,7 +223,7 @@ usb_submit_xfer_request(struct usb_xfer_request *req) if (req->dev->state == USB_DEVICE_DETACHMENT_PENDING) { usb_dev_debug(req->dev, "Device detachment pending; " - "refusing new xfer\n"); + "refusing new xfer\r\n"); restore(im); return USB_STATUS_DEVICE_DETACHED; } @@ -235,14 +240,14 @@ usb_submit_xfer_request(struct usb_xfer_request *req) dir = req->setup_data.bmRequestType >> 7; } usb_dev_debug(req->dev, "Submitting xfer request (%u bytes, " - "type=%s, dir=%s)\n", + "type=%s, dir=%s)\r\n", req->size, usb_transfer_type_to_string(type), usb_direction_to_string(dir)); if (type == USB_TRANSFER_TYPE_CONTROL) { usb_dev_debug(req->dev, "Control message: {.bmRequestType=0x%02x, " - ".bRequest=0x%02x, wValue=0x%04x, wIndex=0x%04x, wLength=0x%04x}\n", + ".bRequest=0x%02x, wValue=0x%04x, wIndex=0x%04x, wLength=0x%04x}\r\n", req->setup_data.bmRequestType, req->setup_data.bRequest, req->setup_data.wValue, @@ -291,7 +296,7 @@ usb_complete_xfer(struct usb_xfer_request *req) usb_dev_debug(req->dev, "Calling completion callback (Actual transfer size %u " - "of %u bytes, type=%s, dir=%s, status=%d)\n", + "of %u bytes, type=%s, dir=%s, status=%d)\r\n", req->actual_size, req->size, usb_transfer_type_to_string( req->endpoint_desc ? @@ -411,6 +416,7 @@ usb_control_msg(struct usb_device *dev, semfree(sem); return USB_STATUS_OUT_OF_MEMORY; } + req->dev = dev; req->endpoint_desc = endpoint_desc; req->recvbuf = data; @@ -429,7 +435,7 @@ usb_control_msg(struct usb_device *dev, wait(sem); status = req->status; - /* Force error if actual size was not the same as requested size. */ + /* Force error if actual size was not the same as requested size. */ if (status == USB_STATUS_SUCCESS && req->actual_size != req->size) { status = USB_STATUS_INVALID_DATA; @@ -439,7 +445,8 @@ usb_control_msg(struct usb_device *dev, } usb_free_xfer_request(req); semfree(sem); - return status; + + return status; } /** @@ -480,7 +487,7 @@ usb_get_descriptor(struct usb_device *dev, uint8_t bRequest, uint8_t bmRequestTy { /* Get descriptor length. */ struct usb_descriptor_header hdr; - + status = usb_control_msg(dev, NULL, bRequest, bmRequestType, wValue, wIndex, &hdr, sizeof(hdr)); if (status != USB_STATUS_SUCCESS) @@ -490,7 +497,7 @@ usb_get_descriptor(struct usb_device *dev, uint8_t bRequest, uint8_t bmRequestTy if (hdr.bLength < sizeof(hdr)) { - usb_dev_error(dev, "Descriptor length too short\n"); + usb_dev_error(dev, "Descriptor length too short\r\n"); return USB_STATUS_INVALID_DATA; } @@ -514,7 +521,7 @@ usb_read_device_descriptor(struct usb_device *dev, uint16_t maxlen) { /* Note: we do not really need to use usb_get_descriptor() here because we * never read more than the minimum length of the device descriptor. */ - return usb_control_msg(dev, NULL, + return usb_control_msg(dev, NULL, USB_DEVICE_REQUEST_GET_DESCRIPTOR, USB_BMREQUESTTYPE_DIR_IN | USB_BMREQUESTTYPE_TYPE_STANDARD | @@ -584,6 +591,7 @@ usb_read_configuration_descriptor(struct usb_device *dev, uint8_t configuration) status = usb_get_configuration_descriptor(dev, configuration, dev->config_descriptor, desc.wTotalLength); + if (status != USB_STATUS_SUCCESS) { return status; @@ -602,7 +610,7 @@ usb_read_configuration_descriptor(struct usb_device *dev, uint8_t configuration) if (hdr->bLength < sizeof(struct usb_descriptor_header)) { - goto out_invalid; + goto out_invalid; } switch (hdr->bDescriptorType) @@ -616,7 +624,8 @@ usb_read_configuration_descriptor(struct usb_device *dev, uint8_t configuration) endpoint_idx + 1 != dev->interfaces[interface_idx]->bNumEndpoints) { - usb_dev_debug(dev, "Number of endpoints incorrect\n"); + usb_dev_debug(dev, "Number of endpoints incorrect\r\n"); + goto out_invalid; } if (((struct usb_interface_descriptor*)hdr)->bAlternateSetting != 0) @@ -630,7 +639,7 @@ usb_read_configuration_descriptor(struct usb_device *dev, uint8_t configuration) { usb_dev_error(dev, "Too many interfaces (this driver only " - "supports %u per configuration)\n", + "supports %u per configuration)\r\n", USB_DEVICE_MAX_INTERFACES); return USB_STATUS_DEVICE_UNSUPPORTED; } @@ -654,7 +663,7 @@ usb_read_configuration_descriptor(struct usb_device *dev, uint8_t configuration) { usb_dev_error(dev, "Too many endpoints (this driver only " - "supports %u per interface)\n", + "supports %u per interface)\r\n", USB_DEVICE_MAX_ENDPOINTS); return USB_STATUS_DEVICE_UNSUPPORTED; } @@ -668,14 +677,14 @@ usb_read_configuration_descriptor(struct usb_device *dev, uint8_t configuration) } if (interface_idx + 1 != dev->config_descriptor->bNumInterfaces) { - usb_dev_debug(dev, "Number of interfaces incorrect (interface_idx=%d)\n", + usb_dev_debug(dev, "Number of interfaces incorrect (interface_idx=%d)\r\n", interface_idx); goto out_invalid; } return USB_STATUS_SUCCESS; out_invalid: - usb_dev_error(dev, "Configuration descriptor invalid\n"); + usb_dev_error(dev, "Configuration descriptor invalid\r\n"); return USB_STATUS_INVALID_DATA; } @@ -789,7 +798,7 @@ usb_free_device(struct usb_device *dev) dev->state = USB_DEVICE_DETACHMENT_PENDING; if (dev->xfer_pending_count != 0) { - usb_dev_debug(dev, "Waiting for %u pending xfers to complete\n", + usb_dev_debug(dev, "Waiting for %u pending xfers to complete\r\n", dev->xfer_pending_count); dev->quiescent_state_waiter = gettid(); receive(); @@ -799,12 +808,12 @@ usb_free_device(struct usb_device *dev) /* Unbind the device driver if needed. */ if (dev->driver != NULL && dev->driver->unbind_device != NULL) { - usb_dev_debug(dev, "Unbinding %s\n", dev->driver->name); + usb_dev_debug(dev, "Unbinding %s\r\n", dev->driver->name); dev->driver->unbind_device(dev); } /* Free configuration descriptor and device structure. */ - usb_dev_debug(dev, "Releasing USB device structure.\n"); + usb_dev_debug(dev, "Releasing USB device structure.\r\n"); if (dev->config_descriptor != NULL) { memfree(dev->config_descriptor, dev->config_descriptor->wTotalLength); @@ -839,7 +848,7 @@ usb_try_to_bind_device_driver(struct usb_device *dev) status = USB_STATUS_DEVICE_UNSUPPORTED; for (i = 0; i < usb_num_device_drivers; i++) { - usb_dev_debug(dev, "Attempting to bind %s to device\n", + usb_dev_debug(dev, "Attempting to bind %s to device\r\n", usb_device_drivers[i]->name); status = usb_device_drivers[i]->bind_device(dev); if (status != USB_STATUS_DEVICE_UNSUPPORTED) @@ -847,7 +856,7 @@ usb_try_to_bind_device_driver(struct usb_device *dev) if (status == USB_STATUS_SUCCESS) { dev->driver = usb_device_drivers[i]; - usb_info("Bound %s to %s\n", dev->driver->name, + usb_info("Bound %s to %s\r\n", dev->driver->name, usb_device_description(dev)); } break; @@ -887,36 +896,36 @@ usb_attach_device(struct usb_device *dev) * transfers. This works because the maximum packet size is guaranteed to * be at least 8 bytes. */ usb_dev_debug(dev, "Getting maximum packet size from start of " - "device descriptor\n"); + "device descriptor\r\n"); dev->descriptor.bMaxPacketSize0 = 8; status = usb_read_device_descriptor(dev, 8); if (status != USB_STATUS_SUCCESS) { - usb_dev_error(dev, "Failed to read start of device descriptor: %s\n", + usb_dev_error(dev, "Failed to read start of device descriptor: %s\r\n", usb_status_string(status)); return status; } - usb_dev_debug(dev, "Using bMaxPacketSize0=%u\n", dev->descriptor.bMaxPacketSize0); + usb_dev_debug(dev, "Using bMaxPacketSize0=%u\r\n", dev->descriptor.bMaxPacketSize0); /* Assign an address to this device. To get a unique address we just use * the 1-based index of the `struct usb_device' in the usb_devices table. */ address = (dev - usb_devices) + 1; - usb_dev_debug(dev, "Assigning address %u to new device\n", address); + usb_dev_debug(dev, "Assigning address %u to new device\r\n", address); status = usb_set_address(dev, address); if (status != USB_STATUS_SUCCESS) { - usb_dev_error(dev, "Failed to assign address: %s\n", + usb_dev_error(dev, "Failed to assign address: %s\r\n", usb_status_string(status)); return status; } /* Read the device descriptor to find information about this device. */ - usb_debug("Reading device descriptor.\n"); + usb_debug("Reading device descriptor.\r\n"); status = usb_read_device_descriptor(dev, sizeof(dev->descriptor)); if (status != USB_STATUS_SUCCESS) { - usb_dev_error(dev, "Failed to read device descriptor: %s\n", + usb_dev_error(dev, "Failed to read device descriptor: %s\r\n", usb_status_string(status)); return status; } @@ -925,50 +934,53 @@ usb_attach_device(struct usb_device *dev) /* Read product and manufacturer strings if present. */ if (dev->descriptor.iProduct != 0) { - usb_debug("Reading product string.\n"); + usb_debug("Reading product string.\r\n"); usb_get_ascii_string(dev, dev->descriptor.iProduct, dev->product, sizeof(dev->product)); } if (dev->descriptor.iManufacturer != 0) { - usb_debug("Reading manufacturer string.\n"); + usb_debug("Reading manufacturer string.\r\n"); usb_get_ascii_string(dev, dev->descriptor.iManufacturer, dev->manufacturer, sizeof(dev->manufacturer)); } #endif /* Read the first configuration descriptor. */ - usb_debug("Reading configuration descriptor.\n"); + usb_debug("Reading configuration descriptor.\r\n"); status = usb_read_configuration_descriptor(dev, 0); if (status != USB_STATUS_SUCCESS) { - usb_dev_error(dev, "Failed to read configuration descriptor: %s\n", + usb_dev_error(dev, "Failed to read configuration descriptor: %s\r\n", usb_status_string(status)); - return status; + return status; } /* Configure the device with its first reported configuration. */ - usb_dev_debug(dev, "Assigning configuration %u (%u interfaces available)\n", + usb_dev_debug(dev, "Assigning configuration %u (%u interfaces available)\r\n", dev->config_descriptor->bConfigurationValue, dev->config_descriptor->bNumInterfaces); status = usb_set_configuration(dev, dev->config_descriptor->bConfigurationValue); if (status != USB_STATUS_SUCCESS) { - usb_dev_error(dev, "Failed to set device configuration: %s\n", + usb_dev_error(dev, "Failed to set device configuration: %s\r\n", usb_status_string(status)); return status; } /* Report the device attachment at an informational log level. */ - usb_info("Attaching %s\n", usb_device_description(dev)); + usb_info("Attaching %s\r\n", usb_device_description(dev)); /* Try to bind a driver to the newly configured device. */ status = usb_try_to_bind_device_driver(dev); + // XXX TODO delay moves along execution for some reason... + udelay(12); + if (status == USB_STATUS_DEVICE_UNSUPPORTED) { - usb_dev_info(dev, "No driver found for device.\n"); + usb_dev_info(dev, "No driver found for device.\r\n"); /* No currently registered driver supports the new device. However, * this should not be considered a failure to attach the device, since * the needed driver may just not be registered yet. */ @@ -976,7 +988,7 @@ usb_attach_device(struct usb_device *dev) } else if (status != USB_STATUS_SUCCESS) { - usb_dev_error(dev, "Failed to bind driver to new USB device: %s\n", + usb_dev_error(dev, "Failed to bind driver to new USB device: %s\r\n", usb_status_string(status)); } return status; @@ -1030,7 +1042,7 @@ usb_register_device_driver(const struct usb_device_driver *drv) if (NULL == drv->bind_device) { - usb_error("bind_device function must be implemented\n"); + usb_error("bind_device function must be implemented\r\n"); return USB_STATUS_INVALID_PARAMETER; } @@ -1038,7 +1050,7 @@ usb_register_device_driver(const struct usb_device_driver *drv) if (usb_num_device_drivers >= MAX_NUSBDRV) { usb_error("Can't register new USB device driver: " - "too many drivers already registered\n"); + "too many drivers already registered\r\n"); status = USB_STATUS_UNSUPPORTED_REQUEST; } else @@ -1057,7 +1069,7 @@ usb_register_device_driver(const struct usb_device_driver *drv) if (!already_registered) { usb_device_drivers[usb_num_device_drivers++] = drv; - usb_info("Registered %s\n", drv->name); + usb_info("Registered %s\r\n", drv->name); /* Check if a device compatible with this driver is already present * on the bus. */ usb_hub_for_device_in_tree(usb_root_hub, @@ -1106,26 +1118,26 @@ syscall usbinit(void) status = hcd_start(); if (status != USB_STATUS_SUCCESS) { - usb_error("Failed to start USB host controller: %s\n", + usb_error("Failed to start USB host controller: %s\r\n", usb_status_string(status)); goto err_free_usb_bus_lock; } - usb_debug("Successfully started USB host controller\n"); + usb_debug("Successfully started USB host controller\r\n"); root_hub = usb_alloc_device(NULL); - usb_debug("Attaching root hub\n"); + usb_debug("Attaching root hub\r\n"); status = usb_attach_device(root_hub); if (status != USB_STATUS_SUCCESS) { - usb_error("Failed to attach root hub: %s\n", usb_status_string(status)); + usb_error("Failed to attach root hub: %s\r\n", usb_status_string(status)); goto err_free_root_hub; } usb_root_hub = root_hub; - usb_debug("Successfully initialized USB subsystem\n"); + usb_debug("Successfully initialized USB subsystem\r\n"); usb_unlock_bus(); return OK; diff --git a/device/usb/usbdebug.c b/device/usb/usbdebug.c index 124d73fe..83482fa8 100644 --- a/device/usb/usbdebug.c +++ b/device/usb/usbdebug.c @@ -34,39 +34,39 @@ * usb_error() instead. */ void usb_log(int priority, const char *func, - struct usb_device *dev, const char *format, ...) + struct usb_device *dev, const char *format, ...) { - va_list va; - irqmask im; - - if (priority < USB_MIN_LOG_PRIORITY) - { - return; - } - - im = disable(); - - kprintf("USB: "); - if (priority <= USB_LOG_PRIORITY_DEBUG) - { - kprintf("[DEBUG] "); - } - else if (priority >= USB_LOG_PRIORITY_ERROR) - { - kprintf("[ERROR] "); - } - if (dev != NULL) - { - kprintf("Device %u: ", dev->address); - } - if (priority <= USB_LOG_PRIORITY_DEBUG) - { - kprintf("%s(): ", func); - } - va_start(va, format); - kvprintf(format, va); - va_end(va); - restore(im); + va_list va; + irqmask im; + + if (priority < USB_MIN_LOG_PRIORITY) + { + return; + } + + im = disable(); + + kprintf("USB: "); + if (priority <= USB_LOG_PRIORITY_DEBUG) + { + kprintf("[DEBUG] "); + } + else if (priority >= USB_LOG_PRIORITY_ERROR) + { + kprintf("[ERROR] "); + } + if (dev != NULL) + { + kprintf("Device %u: ", dev->address); + } + if (priority <= USB_LOG_PRIORITY_DEBUG) + { + kprintf("%s(): ", func); + } + va_start(va, format); + kvprintf(format, va); + va_end(va); + restore(im); } #endif @@ -86,30 +86,30 @@ void usb_log(int priority, const char *func, const char * usb_status_string(usb_status_t status) { - switch (status) - { - case USB_STATUS_SUCCESS: - return "success"; - case USB_STATUS_OUT_OF_MEMORY: - return "out of memory"; - case USB_STATUS_UNSUPPORTED_REQUEST: - return "unsupported request"; - case USB_STATUS_DEVICE_UNSUPPORTED: - return "device unsupported"; - case USB_STATUS_TIMEOUT: - return "request timed out"; - case USB_STATUS_HARDWARE_ERROR: - return "hardware error"; - case USB_STATUS_INVALID_DATA: - return "invalid data"; - case USB_STATUS_INVALID_PARAMETER: - return "invalid parameter"; - case USB_STATUS_NOT_PROCESSED: - return "transfer not processed yet"; - case USB_STATUS_DEVICE_DETACHED: - return "device was detached"; - } - return "unknown error"; + switch (status) + { + case USB_STATUS_SUCCESS: + return "success"; + case USB_STATUS_OUT_OF_MEMORY: + return "out of memory"; + case USB_STATUS_UNSUPPORTED_REQUEST: + return "unsupported request"; + case USB_STATUS_DEVICE_UNSUPPORTED: + return "device unsupported"; + case USB_STATUS_TIMEOUT: + return "request timed out"; + case USB_STATUS_HARDWARE_ERROR: + return "hardware error"; + case USB_STATUS_INVALID_DATA: + return "invalid data"; + case USB_STATUS_INVALID_PARAMETER: + return "invalid parameter"; + case USB_STATUS_NOT_PROCESSED: + return "transfer not processed yet"; + case USB_STATUS_DEVICE_DETACHED: + return "device was detached"; + } + return "unknown error"; } /** @@ -126,34 +126,34 @@ usb_status_string(usb_status_t status) const char * usb_class_code_to_string(enum usb_class_code class_code) { - switch (class_code) - { - case USB_CLASS_CODE_INTERFACE_SPECIFIC: - return "None (see interface descriptors)"; - case USB_CLASS_CODE_AUDIO: - return "Audio"; - case USB_CLASS_CODE_COMMUNICATIONS_AND_CDC_CONTROL: - return "Communications and CDC Control"; - case USB_CLASS_CODE_HID: - return "HID (Human Interface Device)"; - case USB_CLASS_CODE_IMAGE: - return "Image"; - case USB_CLASS_CODE_PRINTER: - return "Printer"; - case USB_CLASS_CODE_MASS_STORAGE: - return "Mass Storage"; - case USB_CLASS_CODE_HUB: - return "Hub"; - case USB_CLASS_CODE_VIDEO: - return "Video"; - case USB_CLASS_CODE_WIRELESS_CONTROLLER: - return "Wireless Controller"; - case USB_CLASS_CODE_MISCELLANEOUS: - return "Miscellaneous"; - case USB_CLASS_CODE_VENDOR_SPECIFIC: - return "Vendor Specific"; - } - return "Unknown"; + switch (class_code) + { + case USB_CLASS_CODE_INTERFACE_SPECIFIC: + return "None (see interface descriptors)"; + case USB_CLASS_CODE_AUDIO: + return "Audio"; + case USB_CLASS_CODE_COMMUNICATIONS_AND_CDC_CONTROL: + return "Communications and CDC Control"; + case USB_CLASS_CODE_HID: + return "HID (Human Interface Device)"; + case USB_CLASS_CODE_IMAGE: + return "Image"; + case USB_CLASS_CODE_PRINTER: + return "Printer"; + case USB_CLASS_CODE_MASS_STORAGE: + return "Mass Storage"; + case USB_CLASS_CODE_HUB: + return "Hub"; + case USB_CLASS_CODE_VIDEO: + return "Video"; + case USB_CLASS_CODE_WIRELESS_CONTROLLER: + return "Wireless Controller"; + case USB_CLASS_CODE_MISCELLANEOUS: + return "Miscellaneous"; + case USB_CLASS_CODE_VENDOR_SPECIFIC: + return "Vendor Specific"; + } + return "Unknown"; } /** @@ -170,16 +170,16 @@ usb_class_code_to_string(enum usb_class_code class_code) const char * usb_speed_to_string(enum usb_speed speed) { - switch (speed) - { - case USB_SPEED_HIGH: - return "high"; - case USB_SPEED_FULL: - return "full"; - case USB_SPEED_LOW: - return "low"; - } - return "unknown"; + switch (speed) + { + case USB_SPEED_HIGH: + return "high"; + case USB_SPEED_FULL: + return "full"; + case USB_SPEED_LOW: + return "low"; + } + return "unknown"; } /** @@ -196,18 +196,18 @@ usb_speed_to_string(enum usb_speed speed) const char * usb_transfer_type_to_string(enum usb_transfer_type type) { - switch (type) - { - case USB_TRANSFER_TYPE_CONTROL: - return "Control"; - case USB_TRANSFER_TYPE_ISOCHRONOUS: - return "Isochronous"; - case USB_TRANSFER_TYPE_BULK: - return "Bulk"; - case USB_TRANSFER_TYPE_INTERRUPT: - return "Interrupt"; - } - return "Unknown"; + switch (type) + { + case USB_TRANSFER_TYPE_CONTROL: + return "Control"; + case USB_TRANSFER_TYPE_ISOCHRONOUS: + return "Isochronous"; + case USB_TRANSFER_TYPE_BULK: + return "Bulk"; + case USB_TRANSFER_TYPE_INTERRUPT: + return "Interrupt"; + } + return "Unknown"; } /** @@ -224,14 +224,14 @@ usb_transfer_type_to_string(enum usb_transfer_type type) const char * usb_direction_to_string(enum usb_direction dir) { - switch (dir) - { - case USB_DIRECTION_OUT: - return "OUT"; - case USB_DIRECTION_IN: - return "IN"; - } - return "Unknown"; + switch (dir) + { + case USB_DIRECTION_OUT: + return "OUT"; + case USB_DIRECTION_IN: + return "IN"; + } + return "Unknown"; } @@ -242,19 +242,19 @@ usb_direction_to_string(enum usb_direction dir) static void utf16le_to_ascii(const uint16_t utf16le_str[], uint nchars, char *ascii_str) { - uint i; - - for (i = 0; i < nchars; i++) - { - if (utf16le_str[i] <= 0x7f) - { - ascii_str[i] = utf16le_str[i]; - } - else - { - ascii_str[i] = '?'; - } - } + uint i; + + for (i = 0; i < nchars; i++) + { + if (utf16le_str[i] <= 0x7f) + { + ascii_str[i] = utf16le_str[i]; + } + else + { + ascii_str[i] = '?'; + } + } } /** @@ -283,15 +283,15 @@ utf16le_to_ascii(const uint16_t utf16le_str[], uint nchars, char *ascii_str) */ usb_status_t usb_get_string_descriptor(struct usb_device *dev, uint8_t index, uint16_t lang_id, - struct usb_string_descriptor *buf, uint16_t buflen) + struct usb_string_descriptor *buf, uint16_t buflen) { - return usb_get_descriptor(dev, - USB_DEVICE_REQUEST_GET_DESCRIPTOR, - USB_BMREQUESTTYPE_DIR_IN | - USB_BMREQUESTTYPE_TYPE_STANDARD | - USB_BMREQUESTTYPE_RECIPIENT_DEVICE, - (USB_DESCRIPTOR_TYPE_STRING << 8) | index, lang_id, - buf, buflen); + return usb_get_descriptor(dev, + USB_DEVICE_REQUEST_GET_DESCRIPTOR, + USB_BMREQUESTTYPE_DIR_IN | + USB_BMREQUESTTYPE_TYPE_STANDARD | + USB_BMREQUESTTYPE_RECIPIENT_DEVICE, + (USB_DESCRIPTOR_TYPE_STRING << 8) | index, lang_id, + buf, buflen); } /** @@ -319,60 +319,60 @@ usb_get_string_descriptor(struct usb_device *dev, uint8_t index, uint16_t lang_i */ usb_status_t usb_get_ascii_string(struct usb_device *dev, uint32_t iString, - char *strbuf, uint32_t strbufsize) + char *strbuf, uint32_t strbufsize) { - struct { - struct usb_string_descriptor desc; - uint16_t padding[128]; - } buf; - uint16_t lang_id; - usb_status_t status; - uint i; - uint num_languages; - uint num_chars; - - /* Get the list of available languages. */ - status = usb_get_string_descriptor(dev, 0, 0, &buf.desc, sizeof(buf)); - if (status != USB_STATUS_SUCCESS) - { - return status; - } - - /* Make sure the list of available languages is nonempty. */ - num_languages = (buf.desc.bLength - sizeof(struct usb_descriptor_header)) / - sizeof(uint16_t); - if (num_languages == 0) - { - usb_dev_error(dev, "String descriptor language list is empty\n"); - return USB_STATUS_INVALID_DATA; - } - - /* Choose the first listed variant of English, or fall back to the first - * language listed if English is not found. */ - lang_id = buf.desc.bString[0]; - for (i = 0; i < num_languages; i++) - { - if ((buf.desc.bString[i] & USB_PRIMARY_LANGUAGE_MASK) == USB_LANG_ENGLISH) - { - lang_id = buf.desc.bString[i]; - break; - } - } - - /* Get the actual string descriptor we wanted. */ - status = usb_get_string_descriptor(dev, iString, lang_id, - &buf.desc, sizeof(buf)); - if (status != USB_STATUS_SUCCESS) - { - return status; - } - - /* "Translate" the string from UTF-16LE to ASCII. */ - num_chars = min((buf.desc.bLength - sizeof(struct usb_descriptor_header)) / - sizeof(uint16_t), strbufsize - 1); - utf16le_to_ascii(buf.desc.bString, num_chars, strbuf); - strbuf[num_chars] = '\0'; - return USB_STATUS_SUCCESS; + struct { + struct usb_string_descriptor desc; + uint16_t padding[128]; + } buf; + uint16_t lang_id; + usb_status_t status; + uint i; + uint num_languages; + uint num_chars; + + /* Get the list of available languages. */ + status = usb_get_string_descriptor(dev, 0, 0, &buf.desc, sizeof(buf)); + if (status != USB_STATUS_SUCCESS) + { + return status; + } + + /* Make sure the list of available languages is nonempty. */ + num_languages = (buf.desc.bLength - sizeof(struct usb_descriptor_header)) / + sizeof(uint16_t); + if (num_languages == 0) + { + usb_dev_error(dev, "String descriptor language list is empty\r\n"); + return USB_STATUS_INVALID_DATA; + } + + /* Choose the first listed variant of English, or fall back to the first + * language listed if English is not found. */ + lang_id = buf.desc.bString[0]; + for (i = 0; i < num_languages; i++) + { + if ((buf.desc.bString[i] & USB_PRIMARY_LANGUAGE_MASK) == USB_LANG_ENGLISH) + { + lang_id = buf.desc.bString[i]; + break; + } + } + + /* Get the actual string descriptor we wanted. */ + status = usb_get_string_descriptor(dev, iString, lang_id, + &buf.desc, sizeof(buf)); + if (status != USB_STATUS_SUCCESS) + { + return status; + } + + /* "Translate" the string from UTF-16LE to ASCII. */ + num_chars = min((buf.desc.bLength - sizeof(struct usb_descriptor_header)) / + sizeof(uint16_t), strbufsize - 1); + utf16le_to_ascii(buf.desc.bString, num_chars, strbuf); + strbuf[num_chars] = '\0'; + return USB_STATUS_SUCCESS; } /** @@ -389,17 +389,17 @@ usb_get_ascii_string(struct usb_device *dev, uint32_t iString, static const char * usb_bcd_version_to_string(uint16_t bcdUSB) { - static char string[3 + 1 + 2 + 1 + 2 + 1]; - char *p = string; - p += sprintf(string, "%u.%u", - (bcdUSB >> 8) & 0xff, /* At most 3 digits */ - (bcdUSB >> 4) & 0xf); /* At most 2 digits */ - /* (plus period) */ - if (bcdUSB & 0xf) - { - sprintf(p, ".%u", bcdUSB & 31); /* At most 2 digits (plus period) */ - } - return string; + static char string[3 + 1 + 2 + 1 + 2 + 1]; + char *p = string; + p += sprintf(string, "%u.%u", + (bcdUSB >> 8) & 0xff, /* At most 3 digits */ + (bcdUSB >> 4) & 0xf); /* At most 2 digits */ + /* (plus period) */ + if (bcdUSB & 0xf) + { + sprintf(p, ".%u", bcdUSB & 31); /* At most 2 digits (plus period) */ + } + return string; } /** @@ -417,172 +417,175 @@ usb_bcd_version_to_string(uint16_t bcdUSB) const char * usb_device_description(const struct usb_device *dev) { - uint i; - enum usb_class_code class; - static char device_description[512]; - char *p; - - p = device_description; - - /* Start with speed and USB version information. */ - p += sprintf(p, "%s-speed USB %s", - usb_speed_to_string(dev->speed), - usb_bcd_version_to_string(dev->descriptor.bcdUSB)); - - /* Try to find a class description of the device, taking into account that - * the class may be stored either in the device descriptor or an interface - * descriptor. */ - class = dev->descriptor.bDeviceClass; - if (class == 0) - { - for (i = 0; i < dev->config_descriptor->bNumInterfaces; i++) - { - if (dev->interfaces[i]->bInterfaceClass != 0) - { - class = dev->interfaces[i]->bInterfaceClass; - } - } - } - - /* Add the class description if we found one and it was not something - * meaningless like the vendor specific class. */ - if (class != 0 && - class != USB_CLASS_CODE_VENDOR_SPECIFIC && - class != USB_CLASS_CODE_MISCELLANEOUS) - { - p += sprintf(p, " %s class", - usb_class_code_to_string(class)); - } - - /* This is indeed a device. */ - p += sprintf(p, " device"); - - /* Add the product name, if the device provides it. */ - if (dev->product[0] != '\0') - { - p += sprintf(p, " (%s)", dev->product); - } - - /* Add vendor and product IDs. */ - p += sprintf(p, " (idVendor=0x%04x, idProduct=0x%04x)", - dev->descriptor.idVendor, - dev->descriptor.idProduct); - - /* Return the resulting string. */ - return device_description; + uint i; + enum usb_class_code class; + static char device_description[512]; + char *p; + + p = device_description; + + /* Start with speed and USB version information. */ + p += sprintf(p, "%s-speed USB %s", + usb_speed_to_string(dev->speed), + usb_bcd_version_to_string(dev->descriptor.bcdUSB)); + + /* Try to find a class description of the device, taking into account that + * the class may be stored either in the device descriptor or an interface + * descriptor. */ + class = dev->descriptor.bDeviceClass; + if (class == 0) + { + for (i = 0; i < dev->config_descriptor->bNumInterfaces; i++) + { + if (dev->interfaces[i]->bInterfaceClass != 0) + { + class = dev->interfaces[i]->bInterfaceClass; + } + } + } + + /* Add the class description if we found one and it was not something + * meaningless like the vendor specific class. */ + if (class != 0 && + class != USB_CLASS_CODE_VENDOR_SPECIFIC && + class != USB_CLASS_CODE_MISCELLANEOUS) + { + p += sprintf(p, " %s class", + usb_class_code_to_string(class)); + } + + /* This is indeed a device. */ + p += sprintf(p, " device"); + + /* Add the product name, if the device provides it. */ + if (dev->product[0] != '\0') + { + p += sprintf(p, " (%s)", dev->product); + } + + /* Add vendor and product IDs. */ + p += sprintf(p, " (idVendor=0x%04x, idProduct=0x%04x)", + dev->descriptor.idVendor, + dev->descriptor.idProduct); + + /* Return the resulting string. */ + return device_description; } -static void +void usb_print_device_descriptor(const struct usb_device *dev, - const struct usb_device_descriptor *desc) + const struct usb_device_descriptor *desc) { - printf(" [Device Descriptor]\n"); - printf(" bLength: %u\n", desc->bLength); - printf(" bDescriptorType: 0x%02x (Device)\n", desc->bDescriptorType); - printf(" bcdUSB: 0x%02x (USB %s compliant)\n", - desc->bcdUSB, usb_bcd_version_to_string(desc->bcdUSB)); - printf(" bDeviceClass: 0x%02x (%s)\n", - desc->bDeviceClass, usb_class_code_to_string(desc->bDeviceClass)); - printf(" bDeviceSubClass: 0x%02x\n", desc->bDeviceSubClass); - printf(" bDeviceProtocol: 0x%02x\n", desc->bDeviceProtocol); - printf(" bMaxPacketSize0: %u\n", desc->bMaxPacketSize0); - printf(" idVendor: 0x%04x\n", desc->idVendor); - printf(" idProduct: 0x%04x\n", desc->idProduct); - printf(" iManufacturer: %u\n", desc->iManufacturer); - if (dev->manufacturer[0] != '\0') - { - printf(" (%s)\n", dev->manufacturer); - } - printf(" iProduct: %u\n", desc->iProduct); - if (dev->product[0] != '\0') - { - printf(" (%s)\n", dev->product); - } - printf(" iSerialNumber: %u\n", desc->iSerialNumber); - printf(" bNumConfigurations: %u\n", desc->bNumConfigurations); - putchar('\n'); + printf(" [Device Descriptor]\n"); + printf(" bLength: %u\n", desc->bLength); + printf(" bDescriptorType: 0x%02x (Device)\n", desc->bDescriptorType); + printf(" bcdUSB: 0x%02x (USB %s compliant)\n", + desc->bcdUSB, usb_bcd_version_to_string(desc->bcdUSB)); + printf(" bDeviceClass: 0x%02x (%s)\n", + desc->bDeviceClass, usb_class_code_to_string(desc->bDeviceClass)); + printf(" bDeviceSubClass: 0x%02x\n", desc->bDeviceSubClass); + printf(" bDeviceProtocol: 0x%02x\n", desc->bDeviceProtocol); + printf(" bMaxPacketSize0: %u\n", desc->bMaxPacketSize0); + printf(" idVendor: 0x%04x\n", desc->idVendor); + printf(" idProduct: 0x%04x\n", desc->idProduct); + printf(" iManufacturer: %u\n", desc->iManufacturer); + if (dev->manufacturer[0] != '\0') + { + printf(" (%s)\n", dev->manufacturer); + } + printf(" iProduct: %u\n", desc->iProduct); + if (dev->product[0] != '\0') + { + printf(" (%s)\n", dev->product); + } + printf(" iSerialNumber: %u\n", desc->iSerialNumber); + printf(" bNumConfigurations: %u\n", desc->bNumConfigurations); + putchar('\n'); } static void usb_print_configuration_descriptor(const struct usb_device *dev, - const struct usb_configuration_descriptor *desc) + const struct usb_configuration_descriptor *desc) { - printf(" [Configuration Descriptor]\n"); - printf(" bLength: %u\n", desc->bLength); - printf(" bDescriptorType: 0x%02x (Configuration)\n", - desc->bDescriptorType); - printf(" wTotalLength: %u\n", desc->wTotalLength); - printf(" bNumInterfaces: %u\n", desc->bNumInterfaces); - printf(" bConfigurationValue: %u\n", desc->bConfigurationValue); - printf(" iConfiguration: %u\n", desc->iConfiguration); - printf(" bmAttributes: 0x%02x\n", desc->bmAttributes); - if (desc->bmAttributes & USB_CONFIGURATION_ATTRIBUTE_SELF_POWERED) - { - printf(" (Self powered)\n"); - } - if (desc->bmAttributes & USB_CONFIGURATION_ATTRIBUTE_REMOTE_WAKEUP) - { - printf(" (Remote wakeup)\n"); - } - printf(" bMaxPower: %u (%u mA)\n", - desc->bMaxPower, desc->bMaxPower * 2); - putchar('\n'); + printf(" [Configuration Descriptor]\n"); + printf(" bLength: %u\n", desc->bLength); + printf(" bDescriptorType: 0x%02x (Configuration)\n", + desc->bDescriptorType); + printf(" wTotalLength: %u\n", desc->wTotalLength); + printf(" bNumInterfaces: %u\n", desc->bNumInterfaces); + printf(" bConfigurationValue: %u\n", desc->bConfigurationValue); + printf(" iConfiguration: %u\n", desc->iConfiguration); + printf(" bmAttributes: 0x%02x\n", desc->bmAttributes); + if (desc->bmAttributes & USB_CONFIGURATION_ATTRIBUTE_SELF_POWERED) + { + printf(" (Self powered)\n"); + } + if (desc->bmAttributes & USB_CONFIGURATION_ATTRIBUTE_REMOTE_WAKEUP) + { + printf(" (Remote wakeup)\n"); + } + printf(" bMaxPower: %u (%u mA)\n", + desc->bMaxPower, desc->bMaxPower * 2); + putchar('\n'); +// kprintf("\r\n"); } static void usb_print_interface_descriptor(const struct usb_device *dev, - const struct usb_interface_descriptor *desc) + const struct usb_interface_descriptor *desc) { - printf(" [Interface Descriptor]\n"); - printf(" bLength: %u\n", desc->bLength); - printf(" bDescriptorType: 0x%02x (Interface)\n", desc->bDescriptorType); - printf(" bInterfaceNumber: %u\n", desc->bInterfaceNumber); - printf(" bAlternateSetting: %u\n", desc->bAlternateSetting); - printf(" bNumEndpoints: %u\n", desc->bNumEndpoints); - printf(" bInterfaceClass: 0x%02x (%s)\n", desc->bInterfaceClass, - usb_class_code_to_string(desc->bInterfaceClass)); - printf(" bInterfaceSubClass: 0x%02x\n", desc->bInterfaceSubClass); - printf(" bInterfaceProtocol: 0x%02x\n", desc->bInterfaceProtocol); - printf(" iInterface: %u\n", desc->iInterface); - putchar('\n'); + printf(" [Interface Descriptor]\n"); + printf(" bLength: %u\n", desc->bLength); + printf(" bDescriptorType: 0x%02x (Interface)\n", desc->bDescriptorType); + printf(" bInterfaceNumber: %u\n", desc->bInterfaceNumber); + printf(" bAlternateSetting: %u\n", desc->bAlternateSetting); + printf(" bNumEndpoints: %u\n", desc->bNumEndpoints); + printf(" bInterfaceClass: 0x%02x (%s)\n", desc->bInterfaceClass, + usb_class_code_to_string(desc->bInterfaceClass)); + printf(" bInterfaceSubClass: 0x%02x\n", desc->bInterfaceSubClass); + printf(" bInterfaceProtocol: 0x%02x\n", desc->bInterfaceProtocol); + printf(" iInterface: %u\n", desc->iInterface); + putchar('\n'); +// kprintf("\r\n"); } static void usb_print_endpoint_descriptor(const struct usb_device *dev, - const struct usb_endpoint_descriptor *desc) + const struct usb_endpoint_descriptor *desc) { - printf(" [Endpoint Descriptor]\n"); - printf(" bLength: %u\n", desc->bLength); - printf(" bDescriptorType: 0x%02x (Endpoint)\n", desc->bDescriptorType); - printf(" bEndpointAddress: 0x%02x (Number %u, %s)\n", - desc->bEndpointAddress, desc->bEndpointAddress & 0xf, - ((desc->bEndpointAddress >> 7) ? "IN" : "OUT")); - printf(" bmAttributes: 0x%02x (%s endpoint)\n", - desc->bmAttributes, - ((desc->bmAttributes & 0x3) == USB_TRANSFER_TYPE_CONTROL ? "control" : - (desc->bmAttributes & 0x3) == USB_TRANSFER_TYPE_ISOCHRONOUS ? "isochronous" : - (desc->bmAttributes & 0x3) == USB_TRANSFER_TYPE_BULK ? "bulk" : - "interrupt")); - printf(" wMaxPacketSize: 0x%02x (max packet size %u bytes)\n", - desc->wMaxPacketSize, desc->wMaxPacketSize & 0x7ff); - printf(" bInterval: %u\n", desc->bInterval); - putchar('\n'); + printf(" [Endpoint Descriptor]\n"); + printf(" bLength: %u\n", desc->bLength); + printf(" bDescriptorType: 0x%02x (Endpoint)\n", desc->bDescriptorType); + printf(" bEndpointAddress: 0x%02x (Number %u, %s)\n", + desc->bEndpointAddress, desc->bEndpointAddress & 0xf, + ((desc->bEndpointAddress >> 7) ? "IN" : "OUT")); + printf(" bmAttributes: 0x%02x (%s endpoint)\n", + desc->bmAttributes, + ((desc->bmAttributes & 0x3) == USB_TRANSFER_TYPE_CONTROL ? "control" : + (desc->bmAttributes & 0x3) == USB_TRANSFER_TYPE_ISOCHRONOUS ? "isochronous" : + (desc->bmAttributes & 0x3) == USB_TRANSFER_TYPE_BULK ? "bulk" : + "interrupt")); + printf(" wMaxPacketSize: 0x%02x (max packet size %u bytes)\n", + desc->wMaxPacketSize, desc->wMaxPacketSize & 0x7ff); + printf(" bInterval: %u\n", desc->bInterval); + putchar('\n'); +// kprintf("\r\n"); } static void usb_print_configuration(const struct usb_device *dev) { - uint i, j; - - usb_print_configuration_descriptor(dev, dev->config_descriptor); - for (i = 0; i < dev->config_descriptor->bNumInterfaces; i++) - { - usb_print_interface_descriptor(dev, dev->interfaces[i]); - for (j = 0; j < dev->interfaces[i]->bNumEndpoints; j++) - { - usb_print_endpoint_descriptor(dev, dev->endpoints[i][j]); - } - } + uint i, j; + + usb_print_configuration_descriptor(dev, dev->config_descriptor); + for (i = 0; i < dev->config_descriptor->bNumInterfaces; i++) + { + usb_print_interface_descriptor(dev, dev->interfaces[i]); + for (j = 0; j < dev->interfaces[i]->bNumEndpoints; j++) + { + usb_print_endpoint_descriptor(dev, dev->endpoints[i][j]); + } + } } /** @@ -591,12 +594,13 @@ usb_print_configuration(const struct usb_device *dev) static usb_status_t usbinfo_device_callback(struct usb_device *dev) { - printf("[USB Device %03u]\n", dev->address); - usb_print_device_descriptor(dev, &dev->descriptor); - usb_print_configuration(dev); + printf("[USB Device %03u]\n", dev->address); + usb_print_device_descriptor(dev, &dev->descriptor); + usb_print_configuration(dev); - putchar('\n'); - return USB_STATUS_SUCCESS; + putchar('\n'); +// kprintf("\r\n"); + return USB_STATUS_SUCCESS; } #define USBINFO_TREE_SPACES_PER_LEVEL 6 @@ -605,31 +609,35 @@ usbinfo_device_callback(struct usb_device *dev) static usb_status_t usbinfo_tree_callback(struct usb_device *dev) { - uint i, j, n; - - if (dev->depth != 0) - { - n = (dev->depth - 1) * USBINFO_TREE_SPACES_PER_LEVEL; - for (j = 0; j < USBINFO_TREE_LINES_PER_PORT; j++) - { - for (i = 0; i < n; i++) - { - putchar(' '); - } - putchar('|'); - putchar('\n'); - } - for (i = 0; i < n; i++) - { - putchar(' '); - } - for (i = 0; i < USBINFO_TREE_SPACES_PER_LEVEL; i++) - { - putchar('-'); - } - } - printf("%03u [%s]\n", dev->address, usb_device_description(dev)); - return USB_STATUS_SUCCESS; + uint i, j, n; + + if (dev->depth != 0) + { + n = (dev->depth - 1) * USBINFO_TREE_SPACES_PER_LEVEL; + for (j = 0; j < USBINFO_TREE_LINES_PER_PORT; j++) + { + for (i = 0; i < n; i++) + { + putchar(' '); + } + putchar('|'); + putchar('\n'); +// kprintf("|\r\n"); + } + for (i = 0; i < n; i++) + { + putchar(' '); +// kprintf(" "); + } + for (i = 0; i < USBINFO_TREE_SPACES_PER_LEVEL; i++) + { + putchar('-'); +// kprintf("-"); + } + } + printf("%03u [%s]\n", dev->address, usb_device_description(dev)); +// kprintf("%03u [%s]\r\n", dev->address, usb_device_description(dev)); + return USB_STATUS_SUCCESS; } #endif /* !USB_EMBEDDED */ @@ -646,29 +654,31 @@ usbinfo_tree_callback(struct usb_device *dev) syscall usbinfo(void) { #if USB_EMBEDDED - fprintf(stderr, "usbinfo not supported in USB_EMBEDDED mode.\n"); - return SYSERR; + fprintf(stderr, "usbinfo not supported in USB_EMBEDDED mode.\n"); + return SYSERR; #else - struct usb_device *root_hub = usb_root_hub; - - if (root_hub == NULL) - { - fprintf(stderr, "USB subsystem not initialized.\n"); - return SYSERR; - } - - /* USB is a dynamic bus and devices may be attached/detached at any time. - * Therefore, we need to "lock" the bus to prevent devices from being - * attached or detached from the bus. Otherwise we may not get a consistent - * snapshot of the bus, or a device could even be freed while we're printing - * it. */ - usb_lock_bus(); - usb_hub_for_device_in_tree(root_hub, usbinfo_device_callback); - - printf("\nDiagram of USB:\n\n"); - usb_hub_for_device_in_tree(root_hub, usbinfo_tree_callback); - usb_unlock_bus(); - return OK; + struct usb_device *root_hub = usb_root_hub; + + if (root_hub == NULL) + { + fprintf(stderr, "USB subsystem not initialized.\n"); +// kprintf("USB subsystem not initialized.\r\n"); + return SYSERR; + } + + /* USB is a dynamic bus and devices may be attached/detached at any time. + * Therefore, we need to "lock" the bus to prevent devices from being + * attached or detached from the bus. Otherwise we may not get a consistent + * snapshot of the bus, or a device could even be freed while we're printing + * it. */ + usb_lock_bus(); + usb_hub_for_device_in_tree(root_hub, usbinfo_device_callback); + + printf("\nDiagram of USB:\n\n"); +// kprintf("\r\nDiagram of USB:\r\n\r\n"); + usb_hub_for_device_in_tree(root_hub, usbinfo_tree_callback); + usb_unlock_bus(); + return OK; #endif /* !USB_EMBEDDED */ } diff --git a/device/usb/usbhub.c b/device/usb/usbhub.c index 69473ff7..f5d23489 100644 --- a/device/usb/usbhub.c +++ b/device/usb/usbhub.c @@ -59,6 +59,8 @@ #include #include #include +#include +#include /** Maximum number of ports per hub supported by this driver. (USB 2.0 * theoretically allows up to 255 ports per hub.) */ @@ -172,7 +174,7 @@ static usb_status_t hub_read_descriptor(struct usb_hub *hub) { usb_status_t status; - usb_dev_debug(hub->device, "Reading hub descriptor.\n"); + usb_dev_debug(hub->device, "Reading hub descriptor.\r\n"); status = usb_get_descriptor(hub->device, USB_HUB_REQUEST_GET_DESCRIPTOR, USB_BMREQUESTTYPE_DIR_IN | @@ -183,7 +185,7 @@ hub_read_descriptor(struct usb_hub *hub) sizeof(hub->descriptor_varData)); if (status != USB_STATUS_SUCCESS) { - usb_dev_error(hub->device, "Failed to read hub descriptor: %s\n", + usb_dev_error(hub->device, "Failed to read hub descriptor: %s\r\n", usb_status_string(status)); } return status; @@ -196,7 +198,7 @@ port_get_status(struct usb_port *port) usb_status_t status; usb_dev_debug(port->hub->device, - "Retrieving status of port %u\n", port->number); + "Retrieving status of port %u\r\n", port->number); status = usb_control_msg(port->hub->device, NULL, USB_HUB_REQUEST_GET_STATUS, USB_BMREQUESTTYPE_DIR_IN | @@ -204,11 +206,11 @@ port_get_status(struct usb_port *port) USB_BMREQUESTTYPE_RECIPIENT_OTHER, 0, port->number, &port->status, sizeof(port->status)); - usb_dev_debug(port->hub->device, "Got port status\n"); + usb_dev_debug(port->hub->device, "Got port status\r\n"); if (status != USB_STATUS_SUCCESS) { usb_dev_error(port->hub->device, - "Failed to get status for port %u: %s\n", + "Failed to get status for port %u: %s\r\n", port->number, usb_status_string(status)); } return status; @@ -281,7 +283,7 @@ port_reset(struct usb_port *port) usb_status_t status; uint i; - usb_dev_debug(port->hub->device, "Resetting port %u\n", port->number); + usb_dev_debug(port->hub->device, "Resetting port %u\r\n", port->number); /* Tell the hardware to reset. */ status = port_set_feature(port, USB_PORT_RESET); @@ -336,7 +338,7 @@ port_attach_device(struct usb_port *port) status = port_reset(port); if (status != USB_STATUS_SUCCESS) { - usb_dev_error(port->hub->device, "Failed to reset port %u: %s\n", + usb_dev_error(port->hub->device, "Failed to reset port %u: %s\r\n", port->number, usb_status_string(status)); return; } @@ -344,7 +346,7 @@ port_attach_device(struct usb_port *port) new_device = usb_alloc_device(port->hub->device); if (new_device == NULL) { - usb_error("Too many USB devices attached\n"); + usb_error("Too many USB devices attached\r\n"); status = USB_STATUS_OUT_OF_MEMORY; port_clear_feature(port, USB_PORT_ENABLE); return; @@ -374,7 +376,7 @@ port_attach_device(struct usb_port *port) } usb_dev_info(port->hub->device, - "New %s-speed device connected to port %u\n", + "New %s-speed device connected to port %u\r\n", usb_speed_to_string(new_device->speed), port->number); new_device->port_number = port->number; @@ -382,7 +384,7 @@ port_attach_device(struct usb_port *port) if (status != USB_STATUS_SUCCESS) { usb_dev_error(port->hub->device, - "Failed to attach new device to port %u: %s\n", + "Failed to attach new device to port %u: %s\r\n", port->number, usb_status_string(status)); usb_free_device(new_device); port_clear_feature(port, USB_PORT_ENABLE); @@ -401,9 +403,9 @@ port_detach_device(struct usb_port *port) if (port->child != NULL) { usb_lock_bus(); - usb_dev_debug(port->hub->device, "Port %u: device detached.\n", + usb_dev_debug(port->hub->device, "Port %u: device detached.\r\n", port->number); - usb_info("Detaching %s\n", usb_device_description(port->child)); + usb_info("Detaching %s\r\n", usb_device_description(port->child)); usb_free_device(port->child); port->child = NULL; usb_unlock_bus(); @@ -426,7 +428,7 @@ port_status_changed(struct usb_port *port) } usb_dev_debug(port->hub->device, - "Port %u: {wPortStatus=0x%04x, wPortChange=0x%04x}\n", + "Port %u: {wPortStatus=0x%04x, wPortChange=0x%04x}\r\n", port->number, port->status.wPortStatus, port->status.wPortChange); @@ -437,7 +439,7 @@ port_status_changed(struct usb_port *port) { /* Connection changed: a device was connected or disconnected. */ - usb_dev_debug(port->hub->device, "Port %u: device now %s\n", + usb_dev_debug(port->hub->device, "Port %u: device now %s\r\n", port->number, (port->status.connected ? "connected" : "disconnected")); @@ -554,7 +556,10 @@ hub_thread(void) uint32_t portmask; uint i; - usb_dev_debug(req->dev, "Processing hub status change\n"); + usb_dev_debug(req->dev, "Processing hub status change\r\n"); + + // XXX TODO delay moves along execution for some reason... + udelay(25); /* The format of the message is a bitmap that indicates which ports have * had status changes. We ignore bit 0, which indicates status change @@ -576,12 +581,12 @@ hub_thread(void) } else { - usb_dev_error(req->dev, "Status change request failed: %s\n", + usb_dev_error(req->dev, "Status change request failed: %s\r\n", usb_status_string(req->status)); } /* Re-submit the status change request. */ - usb_dev_debug(req->dev, "Re-submitting status change request\n"); + usb_dev_debug(req->dev, "Re-submitting status change request\r\n"); usb_submit_xfer_request(req); } } @@ -667,7 +672,7 @@ hub_init_ports(struct usb_hub *hub) if (hub->descriptor.bNbrPorts > HUB_MAX_PORTS) { usb_dev_error(hub->device, - "Too many ports on hub (%u > HUB_MAX_PORTS=%u)\n", + "Too many ports on hub (%u > HUB_MAX_PORTS=%u)\r\n", hub->descriptor.bNbrPorts, HUB_MAX_PORTS); return USB_STATUS_DEVICE_UNSUPPORTED; } @@ -690,7 +695,7 @@ hub_power_on_ports(struct usb_hub *hub) uint i; usb_status_t status; - usb_dev_debug(hub->device, "Powering on %u USB ports\n", + usb_dev_debug(hub->device, "Powering on %u USB ports\r\n", hub->descriptor.bNbrPorts); for (i = 0; i < hub->descriptor.bNbrPorts; i++) @@ -699,7 +704,7 @@ hub_power_on_ports(struct usb_hub *hub) if (status != USB_STATUS_SUCCESS) { usb_dev_error(hub->device, - "Failed to power on port %u: %s\n", i, + "Failed to power on port %u: %s\r\n", i, usb_status_string(status)); return status; } @@ -735,7 +740,7 @@ hub_bind_device(struct usb_device *dev) (dev->endpoints[0][0]->bmAttributes & 0x3) != USB_TRANSFER_TYPE_INTERRUPT) { - return USB_STATUS_DEVICE_UNSUPPORTED; + return USB_STATUS_DEVICE_UNSUPPORTED; } /* Do one-time initialization of the hub driver. */ @@ -749,7 +754,7 @@ hub_bind_device(struct usb_device *dev) hub_id = hub_alloc(); if (SYSERR == hub_id) { - usb_error("Too many hubs attached.\n"); + usb_error("Too many hubs attached.\r\n"); return USB_STATUS_DEVICE_UNSUPPORTED; } @@ -764,7 +769,7 @@ hub_bind_device(struct usb_device *dev) return status; } - usb_dev_debug(dev, "Attaching %sUSB hub with %u ports\n", + usb_dev_debug(dev, "Attaching %sUSB hub with %u ports\r\n", (hub->descriptor.wHubCharacteristics & USB_HUB_CHARACTERISTIC_IS_COMPOUND_DEVICE) ? "compound device " : "", diff --git a/device/usbfs/Makerules b/device/usbfs/Makerules new file mode 100644 index 00000000..9112f232 --- /dev/null +++ b/device/usbfs/Makerules @@ -0,0 +1,23 @@ +# This Makefile contains rules to build this directory + +# Name of this component (the directory this file is stored in) +COMP = device/usbfs + +# Source files for this component +C_FILES = usbFsBindDevice.c \ + usbFsControl.c \ + usbFsPutc.c \ + usbFsWrite.c \ + usbFsFlush.c \ + usbFsGetc.c \ + usbFsInit.c \ + usbFsRead.c \ + usbFsWrite.c \ + usbFsInterrupt.c \ + usbFsUnbindDevice.c + +S_FILES = + +# Add the files to the compile source path +DIR = ${TOPDIR}/${COMP} +COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/device/usbfs/usbFsBindDevice.c b/device/usbfs/usbFsBindDevice.c new file mode 100644 index 00000000..f55751ca --- /dev/null +++ b/device/usbfs/usbFsBindDevice.c @@ -0,0 +1,146 @@ +/** + * @file usbFsBinddevice + */ +/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ + +#include +#include +#include + +#define MSC_SUBCLASS_BOOT 6 +#define MSC_BOOT_PROTOCOL_STORAGE 0x50 +#define HID_REQUEST_SET_PROTOCOL 0x0B +#define HID_BOOT_PROTOCOL 0 + +usb_status_t usbFsBindDevice(struct usb_device *dev) { + uint i, j; + const struct usb_interface_descriptor *fs_interface; + const struct usb_endpoint_descriptor *in_bulk_endpoint; + const struct usb_endpoint_descriptor *out_bulk_endpoint; + struct usbfs *fs; + + usb_status_t status; + + USBFS_TRACE("Attempting to bind USB device (%s %s: address %u)", dev->manufacturer, dev->product, dev->address); + + if (USB_CLASS_CODE_INTERFACE_SPECIFIC != dev->descriptor.bDeviceClass) { + USBFS_TRACE("Device does not have interface specific class: " + "can't have any MSC interfaces!"); + return USB_STATUS_DEVICE_UNSUPPORTED; + } + + USBFS_TRACE("Looking for MSC interface supporting filesystem protocol"); + fs_interface = NULL; + + for (i = 0; i < dev->config_descriptor->bNumInterfaces; i++) { + struct usb_interface_descriptor *interface = dev->interfaces[i]; + + USBFS_TRACE("Examining interface (index=%u, bInterfaceNumber=%u)", + i, interface->bInterfaceNumber); + if (USB_CLASS_CODE_MASS_STORAGE != interface->bInterfaceClass) { + USBFS_TRACE("Not a MSC interface"); + continue; + } + + if (MSC_SUBCLASS_BOOT != interface->bInterfaceSubClass || + MSC_BOOT_PROTOCOL_STORAGE != interface->bInterfaceProtocol) { + USBFS_TRACE("Interface does not support storage boot protocol"); + continue; + } + + /* Find the IN and OUT endpoints. */ + in_bulk_endpoint = NULL; + out_bulk_endpoint = NULL; + + for (j = 0; j < interface->bNumEndpoints; j++) { + if ((dev->endpoints[i][j]->bmAttributes & 0x3) == + USB_TRANSFER_TYPE_BULK + && (dev->endpoints[i][j]->bEndpointAddress >> 7) == + USB_DIRECTION_IN) + { + in_bulk_endpoint = dev->endpoints[i][j]; + continue; + } + if ((dev->endpoints[i][j]->bmAttributes & 0x3) == + USB_TRANSFER_TYPE_BULK + && (dev->endpoints[i][j]->bEndpointAddress >> 7) == + USB_DIRECTION_OUT) + { + out_bulk_endpoint = dev->endpoints[i][j]; + continue; + } + } + + if (NULL == in_bulk_endpoint) { + USBFS_TRACE("Interface has no IN bulk endpoint"); + continue; + } + + if (NULL == out_bulk_endpoint) { + USBFS_TRACE("Interface has no OUT bulk endpoint"); + continue; + } + + USBFS_TRACE("Interface is supported"); + fs_interface = interface; + break; + } + if (NULL == fs_interface) { + USBFS_TRACE("No MSC interface with filesystem boot protocol found"); + return USB_STATUS_DEVICE_UNSUPPORTED; + } + + /* Map this newly attached USB Mass Storage to usbfs structure. */ + fs = NULL; + for (i = 0; i < NUSBFS; i++) { + if (usbfstab[i].initialized && !usbfstab[i].attached) { + USBFS_TRACE("Using USB filesystem control block %u", i); + fs = &usbfstab[i]; + break; + } + } + + if (NULL == fs) { + USBFS_TRACE("All initialized filesystem devices already in use"); + return USB_STATUS_DEVICE_UNSUPPORTED; + } + + /* Put keyboard in boot protocol mode, not report mode. */ + { + usb_status_t status; + + USBFS_TRACE("Placing filesystem in boot protocol mode"); + // status = usb_control_msg(dev, NULL, HID_REQUEST_SET_PROTOCOL, +// USB_BMREQUESTTYPE_TYPE_CLASS | +// USB_BMREQUESTTYPE_DIR_OUT | +// USB_BMREQUESTTYPE_RECIPIENT_INTERFACE, +// HID_BOOT_PROTOCOL, +// fs_interface->bInterfaceNumber, NULL, 0); + if (USB_STATUS_SUCCESS != status) { + USBFS_TRACE("Failed to place filesystem in boot protocol mode: %s", usb_status_string(status)); + return USB_STATUS_DEVICE_UNSUPPORTED; + } + } + + dev->driver_private = fs; + + fs->intr->dev = dev; + fs->intr->endpoint_desc = in_bulk_endpoint; + fs->intr->completion_cb_func = usbFsInterrupt; + fs->intr->private = fs; + + fs->outr->dev = dev; + fs->outr->endpoint_desc = out_bulk_endpoint; + fs->outr->completion_cb_func = usbFsInterrupt; + fs->outr->private = fs; + + USBFS_TRACE("Asking filesystem for data"); + + status = usb_submit_xfer_request(fs->intr); + if (USB_STATUS_SUCCESS != status) { + return status; + } + fs->attached = TRUE; + + return USB_STATUS_SUCCESS; +} diff --git a/device/usbfs/usbFsControl.c b/device/usbfs/usbFsControl.c new file mode 100644 index 00000000..b0b642ab --- /dev/null +++ b/device/usbfs/usbFsControl.c @@ -0,0 +1,57 @@ +/** + * @file usbKbdControl.c + */ +/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ + +#include +#include + +/** + * Control parameters to a USB keyboard. + * @param devptr pointer to USB keyboard device + * @param func index of function to run (defined in usbkbd.h) + * @param arg1 first argument to called function + * @param arg2 second argument to called function + * + * @return + * SYSERR if control function not recognized; otherwise a + * control-function-dependent value. + */ +devcall usbFsControl(device *devptr, int func, long arg1, long arg2) +{ + irqmask im; + struct usbfs *fs; + int retval; + + USBFS_TRACE("devptr->minor=%u, func=%d, arg1=%ld, arg2=%ld", + (uint)devptr->minor, func, arg1, arg2); + + im = disable(); + fs = &usbfstab[devptr->minor]; + retval = SYSERR; + + if (!fs->initialized) + { + restore(im); + return retval; + } + + switch (func) + { + case USBFS_CTRL_SET_IFLAG: + retval = fs->iflags & arg1; + fs->iflags |= arg1; + break; + + case USBFS_CTRL_CLR_IFLAG: + retval = fs->iflags & arg1; + fs->iflags &= ~arg1; + break; + + case USBFS_CTRL_GET_IFLAG: + retval = fs->iflags; + break; + } + restore(im); + return retval; +} diff --git a/device/usbfs/usbFsFlush.c b/device/usbfs/usbFsFlush.c new file mode 100644 index 00000000..d5a5a00e --- /dev/null +++ b/device/usbfs/usbFsFlush.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +devcall usbFsFlush(device *devptr) { + struct usbfs *usbptr; + device *phw; + irqmask im; + + usbptr = &usbfstab[devptr->minor]; + phw = usbptr->phw; + im = disable(); + + if (phw == NULL) { + return SYSERR; + } + + if (usbptr->ostart > 0) { + if (SYSERR == + (*phw->write) (phw, (void *)(usbptr->out), usbptr->ostart)) + { + restore(im); + return SYSERR; + } + + usbptr->ostart = 0; + } + + restore(im); + + return OK; +} diff --git a/device/usbfs/usbFsGetc.c b/device/usbfs/usbFsGetc.c new file mode 100644 index 00000000..8e05b491 --- /dev/null +++ b/device/usbfs/usbFsGetc.c @@ -0,0 +1,35 @@ +/** + * @file usbKbdGetc.c + */ +/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ + +#include + +/** + * Read a single character from a USB keyboard. + * + * @param devptr + * Pointer to the device table entry for a USB keyboard. + * + * @return + * On success, returns the character read as an unsigned char + * cast to an int. If keyboard has not been initialized or is + * in non-blocking mode and no data is available, returns ::SYSERR. + */ +devcall usbFsGetc(device *devptr) +{ + uchar ch; + int retval; + + USBFS_TRACE("usbFsGetc has been called on address"); + + retval = usbFsRead(devptr, &ch, 1); + if (retval == 1) + { + return ch; + } + else + { + return SYSERR; + } +} diff --git a/device/usbfs/usbFsInit.c b/device/usbfs/usbFsInit.c new file mode 100644 index 00000000..d2237457 --- /dev/null +++ b/device/usbfs/usbFsInit.c @@ -0,0 +1,81 @@ +/** + * @file usbFsInit.c + */ +/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ + +#include +#include + +/** Table of USB keyboard control blocks */ +struct usbfs usbfstab[NUSBFS]; + +/** USB device driver structure for the usbkbd driver */ +static struct usb_device_driver usbfs_driver = { + .name = "USB Mass Storage Device driver (MSC boot protocol)", + .bind_device = usbFsBindDevice, + .unbind_device = usbFsUnbindDevice, +}; + +/** + * Initializes the specified USB keyboard. + * + * This actually only prepares the corresponding keyboard structure for use and + * does not depend on a physical keyboard being attached. The physical keyboard + * is recognized only when it is attached, and any read requests to the device + * will block until that point. + */ +devcall usbFsInit(device *devptr) +{ + usb_status_t status; + struct usbfs *fs; + + fs = &usbfstab[devptr->minor]; + + USBFS_TRACE("Initializing usb filesystem"); + + /* Already initialized? */ + if (fs->initialized) + { + goto err; + } + + /* Initialize input queue. */ + fs->isema = semcreate(0); + if (SYSERR == fs->isema) + { + goto err; + } + + /* Allocate USB transfer request for keyboard data. */ + fs->intr = usb_alloc_xfer_request(512); + if (NULL == fs->intr) + { + goto err_semfree; + } + + fs->outr = usb_alloc_xfer_request(512); + if (NULL == fs->outr) + { + goto err_semfree; + } + + fs->initialized = TRUE; + + /* Register the keyboard USB device driver with the USB subsystem. + * (no-op if already registered). */ + status = usb_register_device_driver(&usbfs_driver); + if (status != USB_STATUS_SUCCESS) + { + goto err_free_req; + } + + return OK; + +err_free_req: + fs->initialized = FALSE; + usb_free_xfer_request(fs->intr); +err_semfree: + semfree(fs->isema); +err: + return SYSERR; +} diff --git a/device/usbfs/usbFsInterrupt.c b/device/usbfs/usbFsInterrupt.c new file mode 100644 index 00000000..134170c9 --- /dev/null +++ b/device/usbfs/usbFsInterrupt.c @@ -0,0 +1,17 @@ +#include +#include +#include + +void usbFsInterrupt(struct usb_xfer_request *req) { + struct usbfs *fs = req->private; + + if (req->status == USB_STATUS_SUCCESS && req->actual_size == 0) { + USBFS_TRACE("Filesystem report received"); + + const uchar *data = req->recvbuf; + uint mod_idx = 0; + uint count = 0; + uint i; + } + usb_submit_xfer_request(req); +} diff --git a/device/usbfs/usbFsPutc.c b/device/usbfs/usbFsPutc.c new file mode 100644 index 00000000..6adf7e5f --- /dev/null +++ b/device/usbfs/usbFsPutc.c @@ -0,0 +1,17 @@ +#include +#include + +devcall usbFsPutc(device *devptr, char ch) { + int ret; + + USBFS_TRACE("usbFsPutc has been called on device"); + + USBFS_TRACE("Calling usbFsWrite(%c, 1)", ch); + + ret = usbFsWrite(devptr, &ch, 1); + if (ret == 1) { + return (uchar)ch; + } else { + return SYSERR; + } +} diff --git a/device/usbfs/usbFsRead.c b/device/usbfs/usbFsRead.c new file mode 100644 index 00000000..f41effcf --- /dev/null +++ b/device/usbfs/usbFsRead.c @@ -0,0 +1,69 @@ +/** + * @file usbKbdRead.c + */ +/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ + +#include +#include + +/** + * Read data from a USB keyboard. + * + * @param devptr + * Pointer to the device table entry for a USB keyboard. + * @param buf + * Pointer to a buffer into which to place the read data. + * @param len + * Maximum number of bytes of data to read. + * + * @return + * On success, returns the number of bytes read, which normally is @p len, + * but may be less than @p len if the keyboard has been set to non-blocking + * mode. Returns ::SYSERR on other error (currently, only if usbKbdInit() + * has not yet been called). + */ +devcall usbFsRead(device *devptr, void *buf, uint len) +{ + irqmask im; + struct usbfs *fs; + uint count; + + /* Disable interrupts and get a pointer to the keyboard structure. */ + im = disable(); + fs = &usbfstab[devptr->minor]; + + /* Make sure usbFsInit() has run. */ + if (!fs->initialized) + { + restore(im); + return SYSERR; + } + + /* Attempt to read each byte requested. */ + USBFS_TRACE("Attempting to read %u bytes from filesystem", len); + for (count = 0; count < len; count++) + { + /* If the filesystem is in non-blocking mode, ensure there is a byte + * available in the input buffer from the interrupt handler. If not, + * return early with a short count. */ + if ((fs->iflags & USBFS_IFLAG_NOBLOCK) && fs->icount == 0) + { + USBFS_TRACE("No bytes available in the input buffer from interrupt handler"); + break; + } + + /* Wait for there to be at least one byte in the input buffer from the + * interrupt handler, then remove it. */ + USBFS_TRACE("Waiting for at least one bytes in the input buffer"); + wait(fs->isema); + ((uchar*)buf)[count] = fs->in[fs->istart]; + fs->icount--; + fs->istart = (fs->istart + 1) % USBFS_IBLEN; + USBFS_TRACE("Received a byte"); + } + + /* Restore interrupts and return the number of bytes read. */ + restore(im); + USBFS_TRACE("Return count=%u", count); + return count; +} diff --git a/device/usbfs/usbFsUnbindDevice.c b/device/usbfs/usbFsUnbindDevice.c new file mode 100644 index 00000000..cf87b6c8 --- /dev/null +++ b/device/usbfs/usbFsUnbindDevice.c @@ -0,0 +1,22 @@ +/** + * @file usbUnbindDevice.c + */ +/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ + +#include +#include + +/** + * Function called by the USB subsystem when a keyboard bound with + * usbKbdBindDevice() has been detached. + */ +void usbFsUnbindDevice(struct usb_device *dev) +{ + struct usbfs *fs; + + USBFS_TRACE("USB storage device disconnected (%s %s: address %u)", + dev->manufacturer, dev->product, dev->address); + fs = dev->driver_private; + fs->attached = FALSE; +} + diff --git a/device/usbfs/usbFsWrite.c b/device/usbfs/usbFsWrite.c new file mode 100644 index 00000000..124afadc --- /dev/null +++ b/device/usbfs/usbFsWrite.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include + +devcall usbFsWrite(device *devptr, void *buf, uint len) { + struct usbfs *usbptr; + device *phw; + uchar ch = 0; + uint count = 0; + uchar *buffer = buf; + + usbptr = &usbfstab[devptr->minor]; + phw = usbptr->phw; + if (phw == NULL) { + return SYSERR; + } + + USBFS_TRACE("Writing to device"); + + wait(usbptr->osema); + + while (count < len) { + ch = buffer[count++]; + + if (usbptr->ostart >= USBFS_OBLEN - 1) { + if (usbFsFlush(devptr) == SYSERR) + return SYSERR; + } + + switch (ch) { + case '\n': + usbptr->out[usbptr->ostart++] = '\r'; + usbptr->out[usbptr->ostart++] = '\n'; + + if (usbFsFlush(devptr) == SYSERR) { + return SYSERR; + } + break; + default: + usbptr->out[usbptr->ostart++] = ch; + break; + } + } + signal(usbptr->osema); + + return count; +} diff --git a/docs/mips/Common-Firmware-Environment.rst b/docs/mips/Common-Firmware-Environment.rst deleted file mode 100644 index 237f9dce..00000000 --- a/docs/mips/Common-Firmware-Environment.rst +++ /dev/null @@ -1,211 +0,0 @@ -Common Firmware Environment -=========================== - -About ------ - -The **Common Firmware Environment** (**CFE**) is the firmware -developed by Broadcom for the BCM947xx SoC platform (among others). -It is the first code that runs when the router boots and performs -functions similar to Apple's Open Firmware: - -- Initializes the system -- Sets up a basic environment in which code can run -- Optionally provides a command line interface non-standard usage -- Loads and executes a kernel image (expecting to be jettisoned shortly - thereafter) - -So, in normal operation, a user will not see CFE working at all; it -will load the Linksys kernel and send it on its merry way without -hesitation. For us, however, CFE is crucial, because it provides us -with the ability to load an image over the network using TFTP. - -We have access to two major documents covering CFE, the reference -manual, and the functional specification. Much of the content in these -two documents overlaps. - -.. _getting_into_cfe: - -Getting into CFE ----------------- - -To get into CFE, it will be very helpful to enable "boot wait" from the -Administration Tab under the router's Web GUI. This will cause the -router to wait on startup for a signal to stop booting into the firmware -and enter CFE. - -Once you have that set up and you've :doc:`connected to the router -`, just type "reboot" (assuming -OpenWRT is installed, it may be different for other firmwares) to -reboot the router. This can also be done by power-cycling the router. -As it's booting up, send a continuous stream of Ctrl+C characters to -cancel booting and you'll be entered right into CFE. - -From there, you can prod around CFE's features or load your own kernel -using the command line interface. - -Command Line Interface ----------------------- - -The CFE Command Line Interface (CLI) is a very simple "shell-like" -command prompt. It has a few environmental variables and minimal -functionality. However, it is complex enough power to load a boot -image over the network and begin executing code. The User interface is -described on page 19 of 145 in the `CFE documentation -`__. - -To get the to the CLI, you can use either the power-on method or load -OpenWRT and type reboot. The CFE boot screen looks like: - -.. code-block:: none - - CFE version 1.0.37 for BCM947XX (32bit,SP,LE) - Build Date: Fri Sep 23 17:46:42 CST 2005 (root@localhost.localdomain) - Copyright (C) 2000,2001,2002,2003 Broadcom Corporation. - - Initializing Arena - Initializing Devices. - - No DPN - et0: Broadcom BCM47xx 10/100 Mbps Ethernet Controller 3.90.37.0 - CPU type 0x29008: 200MHz - Total memory: 16384 KBytes - - Total memory used by CFE: 0x80300000 - 0x803A39C0 (670144) - Initialized Data: 0x803398D0 - 0x8033BFE0 (10000) - BSS Area: 0x8033BFE0 - 0x8033D9C0 (6624) - Local Heap: 0x8033D9C0 - 0x803A19C0 (409600) - Stack Area: 0x803A19C0 - 0x803A39C0 (8192) - Text (code) segment: 0x80300000 - 0x803398D0 (235728) - Boot area (physical): 0x003A4000 - 0x003E4000 - Relocation Factor: I:00000000 - D:00000000 - - Boot version: v3.7 - The boot is CFE - - mac_init(): Find mac [00:16:B6:28:7D:4F] in location 0 - Nothing... - - eou_key_init(): Find key pair in location 0 - The eou device id is same - The eou public key is same - The eou private key is same - Device eth0: hwaddr 00-16-B6-28-7D-4F, ipaddr 192.168.1.1, mask 255.255.255.0 - gateway not set, nameserver not set - Reading :: Failed.: Interrupted - CFE> ^C - CFE> - -Of course, items like the hwaddr will be different from router to -router. - -Once you have a command prompt, you can type ``help`` and get a listing -of commands available: - -.. code-block:: none - - CFE> help - Available commands: - - rndis Broadcom USB RNDIS utility. - et Broadcom Ethernet utility. - modify Modify flash data. - nvram NVRAM utility. - reboot Reboot. - flash Update a flash memory device - memtest Test memory. - f Fill contents of memory. - e Modify contents of memory. - d Dump memory. - u Disassemble instructions. - autoboot Automatic system bootstrap. - batch Load a batch file into memory and execute it - go Verify and boot OS image. - boot Load an executable file into memory and execute it - load Load an executable file into memory without executing it - save Save a region of memory to a remote file via TFTP - ping Ping a remote IP host. - arp Display or modify the ARP Table - ifconfig Configure the Ethernet interface - show devices Display information about the installed devices. - unsetenv Delete an environment variable. - printenv Display the environment variables - setenv Set an environment variable. - help Obtain help for CFE commands - - For more information about a command, enter 'help command-name' - *** command status = 0 - CFE> - -A command status of 0 is always a good thing, other command statuses are -errors. - -The next two commands are very important to booting a custon kernel -image: ``ifconfig`` and ``boot``. - -``ifconfig`` is just the Linux counterpart, it will set up the specified -interface. For our router, we have the switch portion of the router -connected to a xinu server (which is simply a TFTP and DHCP server). -From there we type ``ifconfig -auto eth0`` which will ask the xinu -server for an IP address and set up the router. - -.. code-block:: none - - CFE> ifconfig -auto eth0 - Device eth0: hwaddr 00-16-B6-28-7D-4F, ipaddr 192.168.5.2, mask 255.255.254.0 - gateway 192.168.5.220, nameserver 192.168.5.220, domain xinu.mu.edu - *** command status = 0 - CFE> - -We now have an IP address and can transfer our boot image. - -For our purposes, we name our boot images after the unit on which it -will load (supervoc is our demo router). - -.. code-block:: none - - CFE> boot -elf 192.168.5.220:supervoc.boot - Loader:elf Filesys:tftp Dev:eth0 File:192.168.5.220:supervoc.boot Options:(null) - Loading: 0x80001000/3145 0x80001c49/23 Entry at 0x80001000 - Closing network. - Starting program at 0x80001000 - -Let's walk through these lines: - -.. code-block:: none - - boot -elf 192.168.5.220:supervoc.boot - -This will begin booting the ``supervoc.boot`` kernel that is located at -192.168.5.220 (our xinu server and, no, name resolution does not -work). - -.. code-block:: none - - Loader:elf Filesys:tftp Dev:eth0 File:192.168.5.220:supervoc.boot Options:(null) - -A fairly explanatory line stating the file type it is loading -(``elf``), the file system to be used (``tftp``), the device which it -is using to transfer the image (``eth0``), and where that image is -from (``192.168.5.220:supervoc.boot``). - -.. code-block:: none - - Loading: 0x80001000/3145 0x80001c49/23 Entry at 0x80001000 - -This is also a line of explanation. The first portion -(``0x80001000/3145``) tells us the 'physical' address of where we -begin loading our image and the size of the image (in bytes). Next is -the address of the end of the image (``0x80001c49/23``) and (I -believe) the amount of padding to make the image size base 16. The -last part is the address which CFE will branch to upon completion of -upload, this is the start of your kernel. - -.. code-block:: none - - Closing network. - Starting program at 0x80001000 - -The closes the network and begins execution the code at address -``0x8000100``. Any lines of text outputted after this are from your -boot image (unless CFE throws an exception and shows a memory dump). diff --git a/docs/mips/EJTAG-ID-Codes-and-Implementation-Registers.rst b/docs/mips/EJTAG-ID-Codes-and-Implementation-Registers.rst deleted file mode 100644 index 93a0f424..00000000 --- a/docs/mips/EJTAG-ID-Codes-and-Implementation-Registers.rst +++ /dev/null @@ -1,32 +0,0 @@ -EJTAG ID Codes and Implementation Registers -=========================================== - -When an EJTAG system is reset, the data register is automatically filled -with the result of an IDCODE instruction. This code usually includes the -processor and the manufacturer, although it is not a standard. The -important part of the IDCODE is using it to determine if your host -hardware is communicating with your target. Whether or not the host -speaks fluent jtag, if it can navigate to the data register and shift -out the contents, one can see if the electrical connection is sound. - -**IDCODEs** - -WT54GLv1.1 : 0x0535217F - -WRT54Gv8 : 0x1535417F - -WRT350Nv1.0 : 0x0478517F - -The implementation code instruction returns an indication of features on -the particular platform. Below is the information from the MIPS EJTAG -Specification, document #MD00047. - -**IMPCODEs** - -WT54GLv1.1 : 0x00800904 - -WRT54Gv8 : 0x00810904 - -WRT350Nv1.0 : 0x00810904 - -.. figure:: images/Impcode.png diff --git a/docs/mips/EJTAG.rst b/docs/mips/EJTAG.rst deleted file mode 100644 index 95f63cb0..00000000 --- a/docs/mips/EJTAG.rst +++ /dev/null @@ -1,83 +0,0 @@ -EJTAG -===== - -EJTAG is a MIPS-specific extension of IEEE 1149.1, the Joint Test Action -Group. Allows interfacing with additional logic in SoC - -- direct control of processor for step-by-step debugging -- access to busses and registers - - - aids in debugging - - possible usage as additional peripheral data bus - - direct writing to flash for firmware updates (and de-bricking) - -Debugging ---------- - -Attempting to use GNU debugger: http://www.gnu.org/software/gdb. GDB -uses its own Remote Serial Protocol (RDB) to communicate to remote -targets. This protocol could be used to communicate with the XINU -backends through the current serial connection. Although, this would -require additions to XINU: communication with the GDB host; altering of -exception handler to allow GDB to take control of target processor. - -The use of the EJTAG port on the WRT54-series routers gives the user -hardware control of the processor, avoiding the need for strategically -placed breakpoints and XINU interrupt subsystem modification. -Additionally, requests by the debugger for specicfic data can be aquired -directly from registers. The trick to this operation is software that -can interpret commands from RDB into EJTAG signals to be sent through -the host parallel port, and vice-versa. An implementation of this -interpreter can be found at -http://www.totalembedded.com/open_source/jtag/mips32_ejtag.php. - -Specific Implementations ------------------------- - -So far, development has focused exclusively on the WRT54GL. For anyone -investigating the capabilities of the WRT54GL EJTAG system, note the -instruction register size is a full 8 bits, not the 5 bits required by -specification. Believing the 54GL CP0 Debug Program Counter register -to be returning erroneous addresses, headers are being added to a 54G -v.8, and a 350N v.1. For IDCODEs and implementation register values -check :doc:`EJTAG-ID-Codes-and-Implementation-Registers`. - -Probes ------- - -Images are of three variant EJTAG connections. The first two buffered by -active line drivers, the last passive. Xinu research is currently using -an active probe similar to the OpenWRT "Wiggler" clone; although, the -parallel port pinouts match the unbuffered cable diagram. Note that the -unbuffered cable at the bottom of this page is only proven by xinu -research functional in writing to the Test Access Port. It may not read -data back from the target device. Additionally, rumor claims that the -cable can be no longer than 6" (not 6'). This is partially substantiated -by photographs "out there" of similar 6 inch cables used with a variety -of devices. - -.. figure:: images/Te_jtag_cable.png - :width: 900px - - Total Embedded buffered cable - -.. figure:: images/Wiggler.png - :width: 700px - - "wiggler" clone from OpenWRT - -.. figure:: images/JTAGunbuffered.png - :width: 400px - - unbuffered cable from OpenWRT; used by de-brick utility - -.. figure:: images/Xinu-Wiggler.png - :width: 700px - - Our current buffer/wiggler setup - -See also --------- - -- :doc:`EJTAG-ID-Codes-and-Implementation-Registers` - diff --git a/docs/mips/Exception-and-Interrupt-Handling.rst b/docs/mips/Exception-and-Interrupt-Handling.rst deleted file mode 100644 index 195fe7c2..00000000 --- a/docs/mips/Exception-and-Interrupt-Handling.rst +++ /dev/null @@ -1,24 +0,0 @@ -Exception and Interrupt Handling (MIPS) -======================================= - -On MIPS processors, |EX| tilizes a interrupt handling system which -allows components to register custom interrupt handlers to the system -at runtime or fall-back to the default trap handler. - -MIPS processors will jump to and execute code beginning at ``0x8000 -0180`` when an exception or interrupt occurs. Code for handling traps -must occupy no more than ``0x20`` bytes at this location (eight -instructions), therefore Embedded Xinu uses three instructions to jump -to different code which will handle traps more robustly. - -In order to handle exceptions (such as TLB misses) efficiently, Embedded -Xinu uses an interrupt vector system to quickly read the exception code, -load the registered exception handler, and jump to the handler. If any -of these steps do not exist, the handler will fall-back to the default -trap handler. - -If an interrupt has occurred it is important to save the state of the -processor and handle the interrupt gracefully so the system can -continue running. Thus, if the interrupt handler was called by an -interrupt and not an exception, the code will save the state of the -processor and perform a similar lookup for interrupt handlers. diff --git a/docs/mips/Flash-Driver.rst b/docs/mips/Flash-Driver.rst deleted file mode 100644 index 9230d09a..00000000 --- a/docs/mips/Flash-Driver.rst +++ /dev/null @@ -1,116 +0,0 @@ -Flash driver -============ - -|EX| uses a multi-layered approach to dealing with :doc:`Flash-Memory` -on platforms where it is available (including MIPS-based routers such -as the :doc:`WRT54GL`). This allows the presentation of a simple and -consistent interface to user programs, while handling the more -complicated hardware interface underneath. - -High level API --------------- - -Like other drivers in Embedded Xinu, the Flash driver provides user -level calls to ``open()``, ``close()``, ``read()``, ``write()``, and -``control()``. In order to begin using a device the user must ``open()`` -it, this initializes the logical layer and sets up structures for use. -The complimentary ``close()`` function will clear those structures and -write any cached data to the underlying Flash hardware. - -``control()`` provides several functions for getting information and -performing operations on the driver. The control functions are presented -below. - -- ``FLASH_BLOCK_SIZE`` returns the size of logical blocks for the Flash - device. -- ``FLASH_N_BLOCKS`` returns the number of block available on the Flash - device. -- ``FLASH_SYNC`` forces a synchronization from cached data onto Flash - memory, the two forms are: - - - ``FLASH_BLOCK`` synchronizes a specific erase block, and - - ``FLASH_LOGBLOCK`` synchronizes a logical block of data. - -``read()`` and ``write()`` -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The Flash device takes three slightly different parameters for -``read()`` and ``write()`` when compared to other devices in Embedded -Xinu. Normal devices will take the device identifier, a buffer, and the -size of the buffer. Since the Flash device uses fixed size logical -blocks, it is assumed that the buffer will be the size of a single -logical block. Therefore, the Flash driver API for ``read()`` and -``write()`` is: - -.. code:: c - - read(int device_id, char *buffer, uint block_number); - write(int device_id, char *buffer, uint block_number); - -Logical Layer -------------- - -Normal block-oriented devices present a consistent view of data storage -with each block being a small fixed size ranging from 512 bytes to 4,096 -bytes. Flash memory does not act like normal block-oriented devices -though. The underlying hardware is separated into erase block regions of -which there can be four. Each erase block region can hold a number of -erase blocks of a fixed size. These fixed sizes can be any size that is -a power of two. For example, on the WRT54GL platform, Flash is separated -into two erase block regions, one with 8 - 8 KB erase blocks and the -other with 63 - 64 KB erase blocks. - -To avoid the user level programmer from having to deal with this -inconsistent view of erase blocks, the logical layer of the Flash driver -splits all of Flash memory into uniformly sized logical blocks (at -present this is 512 byte blocks). When a call to ``read()`` occurs, the -logical layer will determine what erase block the logical block maps to, -determine if the erase block has already been loaded into RAM and return -a pointer to the cached data. Similarly, a call to ``write()`` will -perform a mapping from logical to erase block and write the data to the -cached memory. If too many erase blocks are stored in RAM, the logical -layer will evict a block and if it has been modified since the read it -will write it back to Flash memory. - -.. _flash_driver_physical_layer: - -Physical Layer --------------- - -Once the logical to erase block mapping has occurred, the logical layer -can pass the erase block stored in RAM to the physical layer to perform -the low level hardware operations. At this layer, the software only -deals in erase block units and uses manufacturer specific code. -Currently, Embedded Xinu fully supports the Intel Standard Command Set -(SCS) and the AMD/Samsung SCS is a work in progress. - -Largely, the routines to handle the hardware follow similar concepts. -When a non-read request is made to the physical layer the software steps -through a series of operations to change an erase block from read-mode -to program or erase mode. When this happens, the software is able to -safely modify the data. - -An interesting property of Flash memory is that certain devices allow -program and erase operations to be suspended, so it may be possible to -spin the physical layer off as a separate pre-emptible process. -Unfortunately, while the Intel SCS supports suspend/resume operations -the AMD/Samsung SCS does not, so this would lead to compatibility issues -if implemented. - -NVRAM ------ - -:ref:`NVRAM settings ` are stored in Flash memory and take -advantage of both the logical and physical layers of the Flash driver. -When NVRAM is first initialized, the Flash driver determines what -logical block the settings begin in and then begins reading and -storing the settings into RAM. Each tuple is indexed into a hash table -and allocated a piece of memory to store the data in. When a setting -is changed, the original value is released from memory and the new -value is added. If a value is requested, the driver will simply find -the storage location and return the pointer to the data. - -When the updated settings are committed to Flash, the NVRAM driver will -discover the logical block to erase block mapping, create a complete -erase block with the new settings, cause a write in the physical layer, -and finally force a synchronization to commit the settings to Flash. diff --git a/docs/mips/Flash-Memory.rst b/docs/mips/Flash-Memory.rst deleted file mode 100644 index 17220b3e..00000000 --- a/docs/mips/Flash-Memory.rst +++ /dev/null @@ -1,122 +0,0 @@ -Flash memory -============ - -.. note:: - - This page appears to have been written with :doc:`WRT54GL` routers - in mind and may or may not be applicable to other platforms. - -Like other memory mapped hardware devices on the MIPS platform, -**Flash memory** has an address range in KSEG1. This means that the -memory is **unmapped** and **uncached**. An interesting, and -important, piece of information is that all 4 megabytes of Flash -memory is mapped 1-1 into the address range between ``0xBC00 0000`` -and ``0xBC3F FFFF``. This allows for random read-access without using -an interface to load the data a fixed amount of registers. - -Data Locations --------------- - -Stored on Flash memory are several important parts to make a backend -work properly, some of these data points are listed below. - -- ``0xBC00 1000`` has backup NVRAM settings. If the "proper" settings - become corrupt, CFE will replace the proper settings with these. -- ``0xBC00 1E00`` holds the "true" MAC address of device. During CFE - boot, this is the address that will be used. Once a full kernel has - been loaded the MAC address may be different. -- ``0xBC00 1F00`` holds the current CFE boot version (should be "v3.7" - for :doc:`WRT54GLs `). -- ``0xBC00 2000`` is the beginning of CFE code. -- ``0xBC03 F400`` is a unique device ID (should match the NVRAM setting - for ``eou_device_id``). -- ``0xBC03 F408`` is a unique private key for device (should match the - NVRAM setting for ``eou_private_key``). -- ``0xBC03 F508`` is a unique public key for device (should match the - NVRAM setting for ``eou_public_key``). -- ``0xBC04 0000`` is the beginning of the operating system kernel - (|EX| or some Linux variant). Typically, this will be a gzipped - version of the raw kernel code prefixed with a - :doc:`TRX-Header`. -- ``0xBC3F 8000`` is the location of proper :ref:`NVRAM settings - `. - -This is not a comprehensive list of memory locations within Flash -memory, but a guide of where some values may be stored when trying to -interface with a new system. - -Writing Flash -------------- - -Writing data to Flash memory is not simply a matter of writing data to -the memory address. For the WRT54GL backends the common NOR type of -Flash memory is used. As with all Flash memories there are certain -properties that must be followed when storing data. - -An important property of NOR based Flash memory is that each bit on -Flash can only be changed from a ``1`` to a ``0`` and not the other way -around. So if a byte has the pattern ``1001 1101`` only the high bits -can be written. This presents an interesting challenge for efficient -file system structures. Once a bit has been set to ``0`` and the -operating system wishes to reset the bit to ``1`` a special erase -command must be sent to the device. Because of this Flash memory is -broken down into several distinct segments called *erase blocks*. These -erase blocks can vary in size between Flash memory chips and even within -the same chip. After sending the command to erase an erase block, the -entire erase block will be set to ``1``\ s, allowing any data to be -written. The specific method of erasing and writing data depends on the -manufacturer of the underlying hardware. In general it is a matter of -writing a sequence of values to a certain location to prepare the -device, then writing the new data to the correct position. These -operations are more detailed on the :doc:`Flash-Driver` page -under :ref:`physical layer `. - -Common Flash Interface ----------------------- - -Luckily for software authors, the manufacturers of Flash memory have -developed a standard for discovering information about a Flash device, -called the Common Flash Interface (CFI). By implementing a CFI query -routine, the operating system can discover what command set the chip -implements (Intel, AMD, and Mitsubishi all have a standard command set -and extended command set). Other information that can be queried is -voltages, timeouts for writing and erasing, access mode (word or byte), -device size (as :math:`2^n`), and information about up-to four erase -block regions. The information about each erase block region will -consist of the size of an erase block in the region and the number of -equally sized erase blocks that exist in the regions. - -.. _nvram: - -NVRAM ------ - -While technically a misnomer, NVRAM (non-volatile random access memory) -refers specifically to the platform settings stored across power cycles -of the device. These settings will always begin 8 pages (32 kilobytes) -away from the end of Flash memory. In the case of the WRT54GL, this -means NVRAM settings are stored beginning at ``0xBC3F 8000``. At this -point there is a 20 byte header which is laid out as follows: - -| `` 0                   1                   2                   3   `` -| `` 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 `` -| ``+---------------------------------------------------------------+`` -| ``|                     magic number ('FLSH')                     |`` -| ``+---------------------------------------------------------------+`` -| ``|                length (header size + variables)               |`` -| ``+---------------+---------------+-------------------------------+`` -| ``|      CRC      |    version    |         SDRAM Init (?)        |`` -| ``+---------------+---------------+-------------------------------+`` -| ``|       SDRAM config (?)        |       SDRAM refresh (?)       |`` -| ``+-------------------------------+-------------------------------+`` -| ``|                        NCDL value (?)                         |`` -| ``+---------------------------------------------------------------+`` - -Several of the values are not used by Embedded Xinu as the values -represent something that is not fully understood (all the SDRAM values -and the NCDL value). - -Immediately after the header begins the NVRAM settings as NULL delimited -``name=value`` tuples stored as plain text. It is possible that after -the final tuple the settings are NULL character padded to the nearest 4 -byte word. diff --git a/docs/mips/General-Purpose-Input-Output.rst b/docs/mips/General-Purpose-Input-Output.rst deleted file mode 100644 index efff1bb0..00000000 --- a/docs/mips/General-Purpose-Input-Output.rst +++ /dev/null @@ -1,59 +0,0 @@ -General purpose input and output -================================ - -.. note:: - - This page appears to have been written with :doc:`WRT54GL` routers - in mind and may not be applicable to other platforms. - -**General Purpose Input and Output** (**GPIO**) is a simple method of -communication. Currently the shell implements the **led** and -**gpiostat** commands to use these ports. - -Port Assignments ----------------- - -======== =================== -Pin Assignment -======== =================== -GPIO 0 WLAN LED -GPIO 1 Power LED -GPIO 2 Cisco LED White -GPIO 3 Cisco LED Orange -GPIO 4 Cisco Button -GPIO 5 *Unknown* -GPIO 6 Reset Button -GPIO 7 DMZ LED -======== =================== - -Registers ---------- - -There are four control and status registers, each which is 2 bytes. - -- Input (0xb8000060) - If a GPIO pin is set for output, its input bit - is automatically set to 0. -- Output (0xb8000064) - If a GPIO pin is set for input, its output bit - is automatically set to 0. -- Enable (0xb8000068) - Determines if a GPIO pin is used for input or - output. A bit value of 0 is input and 1 is output. -- Control (0xb800006c) - Usage is currently unknown. - -LEDs ----- - -Research Notes: - -- An LED is enabled by setting its enable bit to 1. -- When an LED is enabled, its input bit becomes 0. -- Once an LED is enabled, if its output bit is 0, the LED is on and if - its output bit is 1, the LED is off. - -Resources ---------- - -- `SD Card Reader - Driver `__ -- `Adding an MMC/SD - Card `__ - diff --git a/docs/mips/HOWTO-Backup-Router.rst b/docs/mips/HOWTO-Backup-Router.rst deleted file mode 100644 index 41f837ad..00000000 --- a/docs/mips/HOWTO-Backup-Router.rst +++ /dev/null @@ -1,85 +0,0 @@ -Backing up your router -====================== - -.. note:: - - This page appears to have been written with :doc:`WRT54GL` routers - in mind and may or may not be applicable to other platforms. - -When experimenting with kernels, you may find yourself corrupting the -router and having to recover from a known good state. It is a good idea -to make a copy of the CFE when it is in its original factory -configuration for if and when. Here are a few different methods -depending on your resources: - -dd-wrt ------- - -If you are running a relatively recent version of -`dd-wrt `__, you can download the CFE from the -web interface. - -Location: ``http://ROUTER_IP/backup/cfe.bin>`` - -CFE ---- - -To backup the CFE from within the CFE itself you need an active -:doc:`serial console ` and a live -network connection to a :doc:`TFTP server -`. On the TFTP server, create a file for -the backup image. It must be world writable. If you do not pre-create -the file for the TFTP client, the backup may fail. We name and label -our routers to keep them straight. Consider naming the backup image -after each router's hostname if you have many of them. - -Example:: - - user@xinuserver:tftpboot$ touch routername.cfe - user@xinuserver:tftpboot$ chmod a+w routername.cfe - -Access the :doc:`CFE ` using the -:ref:`usual method `. - -If necessary, configure the network interface and check the connection -to your TFTP server (192.168.6.10 in this example):: - - CFE> ifconfig eth0 -auto - Device eth0: hwaddr 00-1E-E5-86-02-7A, ipaddr 192.168.6.122, mask 255.255.255.0 - gateway 192.168.6.50, nameserver 134.48.7.10, domain xinu.mu.edu - *** command status = 0 - CFE> ping 192.168.6.10 - 192.168.6.10 (192.168.6.10) is alive - 192.168.6.10 (192.168.6.10): 1 packets sent, 1 received - *** command status = 0 - -Save the CFE region to the file you created on the TFTP server:: - - CFE> save 192.168.6.10:routername.cfe BC000000 40000 - 262144 bytes written to 192.168.6.10:routername.cfe - *** command status = 0 - -Note: You can also save the entire flash image (CFE+Kernel+NVRAM) by -passing 400000 as the length instead of 40000. This isn't really -necessary, but you might find it referenced elsewhere. If you have to -:doc:`recover ` via JTAG it will take a LONG -time to restore the entire flash image. It is much more efficient to -load just the CFE, then upload the kernel via TFTP and use a factory -reset to restore NVRAM. - -JTAG ----- - -For this method to work, we assume you have a working :doc:`EJTAG` -interface to your router. For details, check out our -:doc:`HOWTO-Recover-Router` page. - -Use the ``-probeonly`` option to figure out what options TJTAG needs for -your particular setup. - -Backup the CFE with TJTAG:: - - user@host:tjtag$ ./tjtag -backup:cfe /wiggler /noemw /noreset - -TJTAG will create a CFE.BIN file with some sort of timestamp identifier -appended to the filename. Rename and store somewhere safe. diff --git a/docs/mips/HOWTO-Connect-to-Modified-Router.rst b/docs/mips/HOWTO-Connect-to-Modified-Router.rst deleted file mode 100644 index 8a247f50..00000000 --- a/docs/mips/HOWTO-Connect-to-Modified-Router.rst +++ /dev/null @@ -1,258 +0,0 @@ -Connecting to a modified router -=============================== - -Summary -------- - -This will explain how to connect to the serial ports on a modified -Linksys WRT54G using serial communication software. In our tutorial we -will use Picocom for our serial communication software because it is -free and easy to get with a front end or server running Linux. - -Before Starting ---------------- - -Expose a serial port on the router -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You must have successfully modified a Linksys WRT54G to expose at least -its first serial port in such a way that you can connect it to another -machine with serial communications software. If you have not done so -yet, please see :doc:`HOWTO-Modify-the-Linksys-Hardware`. - -Acquire serial communication software -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -There is a freely available software package for serial communication on -almost every major platform. Picocom is one such piece of software that -is easy to obtain on a machine running Linux. To get Picocom installed -on your front end simply open a terminal and type -`` yum install picocom `` (or use your system's package install command -if it does not support the `` yum `` command). **NOTE:** you may need -*root* access to your front end machine in order to install packages. We -installed Picocom on a front end machine running Fedora 9 and got the -following output:: - - [root@argolis ~]# yum install picocom - Loaded plugins: refresh-packagekit - Setting up Install Process - Parsing package install arguments - Resolving Dependencies - --> Running transaction check - ---> Package picocom.i386 0:1.4-4.fc9 set to be updated - --> Finished Dependency Resolution - - Dependencies Resolved - - ============================================================================= - Package Arch Version Repository Size - ============================================================================= - Installing: - picocom i386 1.4-4.fc9 fedora 29 k - - Transaction Summary - ============================================================================= - Install 1 Package(s) - Update 0 Package(s) - Remove 0 Package(s) - - Total download size: 29 k - Is this ok [y/N]: y - Downloading Packages: - (1/1): picocom-1.4-4.fc9.i386.rpm | 29 kB 00:00 - Running rpm_check_debug - Running Transaction Test - Finished Transaction Test - Transaction Test Succeeded - Running Transaction - Installing: picocom ######################### [1/1] - - Installed: picocom.i386 0:1.4-4.fc9 - Complete! - [root@argolis ~]# - -Alternatively, if you are building multiple backends to be made -available as a pool, our suite of XINU `Console Tools `__ -includes a basic serial console utility called **tty-connect**. However -it is recommended that you do **not** use the XINU `Console -Tools `__'s **tty-connect** utility for directly -connecting a single back end router to a front end machine because this -utility does not allow the user to send a ``ctrl-C`` command over the -serial connection, which is necessary in the upcoming steps in order to -properly communicate with your router. - -Steps to Connect to the Router ------------------------------- - -Task One: Connect Serial (& Optionally Network) Cable(s) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Ensure that the connection is going from UART0 (the first serial -port--if you followed our instructions on :doc:`modifying the router -` it will be the **DB9 Female** -serial port on the left) as this is where the console will be running. -If you are connecting a standard PC serial port (a DTE) to your -router, use a straight serial cable. Other arrangements may require a -:doc:`Null Modem `; check your -transmit/receive line polarities to be sure. - -Also, because the goal is to upload custom code to the router, it would -be a good idea to connect the router to your network by wiring it up via -one of the numbered LAN ports on the back of the router (NOT the -Internet/WAN port). This is not necessary to simply connect and -communicate with the router, but it is necessary if you want to try and -boot the router running your own custom code (which is the point of this -Xinu lab after all). - -Task Two: Configure your Serial Communication Software -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The connection used by the router's serial port is fairly standard: -115200bps, with 8 data bits, no parity bit, and 1 stop bit, or 8N1. Set -your software to connect using these settings. - -If you are following our tutorial and using Picocom as your serial -connection software, the command to open Picocom with these settings is -`` picocom -b 115200 /dev/ttyS0 `` (where `` /dev/ttyS0 `` is the name -of your front end's serial communication device hooked up to the -router). By default the other necessary settings are already set on -picocom; it's default connection uses 8 data bits, no parity bits, and 1 -stop bit. If you use picicom to set up a connection you should get -output like the following:: - - [root@argolis ~]# picocom -b 115200 /dev/ttyS0 - picocom v1.4 - - port is : /dev/ttyS0 - flowcontrol : none - baudrate is : 115200 - parity is : none - databits are : 8 - escape is : C-a - noinit is : no - noreset is : no - nolock is : no - send_cmd is : ascii_xfr -s -v -l10 - receive_cmd is : rz -vv - - Terminal ready - -Task Three: Power up the Router -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Yes, that means plug it in. - -With serial communications software listening, you should see something -like the following output:: - - CFE version 1.0.37 for BCM947XX (32bit,SP,LE) - Build Date: Mon Nov 14 18:06:25 CST 2005 (root@localhost.localdomain) - Copyright (C) 2000,2001,2002,2003 Broadcom Corporation. - - Initializing Arena - Initializing Devices. - - No DPN - et0: Broadcom BCM47xx 10/100 Mbps Ethernet Controller 3.90.37.0 - CPU type 0x29008: 200MHz - Total memory: 16384 KBytes - - Total memory used by CFE: 0x80300000 - 0x803A39C0 (670144) - Initialized Data: 0x803398D0 - 0x8033BFE0 (10000) - BSS Area: 0x8033BFE0 - 0x8033D9C0 (6624) - Local Heap: 0x8033D9C0 - 0x803A19C0 (409600) - Stack Area: 0x803A19C0 - 0x803A39C0 (8192) - Text (code) segment: 0x80300000 - 0x803398D0 (235728) - Boot area (physical): 0x003A4000 - 0x003E4000 - Relocation Factor: I:00000000 - D:00000000 - - Boot version: v3.7 - The boot is CFE - - mac_init(): Find mac [00:18:39:6F:78:15] in location 0 - Nothing... - - eou_key_init(): Find key pair in location 0 - The eou device id is same - The eou public key is same - The eou private key is same - Device eth0: hwaddr 00-18-39-6F-78-15, ipaddr 192.168.1.1, mask 255.255.255.0 - gateway not set, nameserver not set - Loader:raw Filesys:raw Dev:flash0.os File: Options:(null) - Loading: ...... 1601536 bytes read - Entry at 0x80001000 - Closing network. - Starting program at 0x80001000 - CPU revision is: 00029008 - Primary instruction cache 16kb, linesize 16 bytes (2 ways) - Primary data cache 8kb, linesize 16 bytes (2 ways) - Linux version 2.4.20 (root@localhost.localdomain) (gcc version 3.2.3 with Broadcom modifications) - ... - (snip) - ... - Hit enter to continue... - -Pressing enter will give you a root shell:: - - BusyBox v0.60.0 (2005.11.14-09:45+0000) Built-in shell (msh) - Enter 'help' for a list of built-in commands. - - # - -Task Four: Access the Common Firmware Environment CLI -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you reboot the router while holding CTRL+C on the serial console, you -will get a CFE prompt:: - - CFE version 1.0.37 for BCM947XX (32bit,SP,LE) - Build Date: Mon Nov 14 18:06:25 CST 2005 (root@localhost.localdomain) - Copyright (C) 2000,2001,2002,2003 Broadcom Corporation. - - Initializing Arena - Initializing Devices. - - No DPN - et0: Broadcom BCM47xx 10/100 Mbps Ethernet Controller 3.90.37.0 - CPU type 0x29008: 200MHz - Total memory: 16384 KBytes - - Total memory used by CFE: 0x80300000 - 0x803A39C0 (670144) - Initialized Data: 0x803398D0 - 0x8033BFE0 (10000) - BSS Area: 0x8033BFE0 - 0x8033D9C0 (6624) - Local Heap: 0x8033D9C0 - 0x803A19C0 (409600) - Stack Area: 0x803A19C0 - 0x803A39C0 (8192) - Text (code) segment: 0x80300000 - 0x803398D0 (235728) - Boot area (physical): 0x003A4000 - 0x003E4000 - Relocation Factor: I:00000000 - D:00000000 - - Boot version: v3.7 - The boot is CFE - - mac_init(): Find mac [00:18:39:6F:78:15] in location 0 - Nothing... - - eou_key_init(): Find key pair in location 0 - The eou device id is same - The eou public key is same - The eou private key is same - Device eth0: hwaddr 00-18-39-6F-78-15, ipaddr 192.168.1.1, mask 255.255.255.0 - gateway not set, nameserver not set - Automatic startup canceled via Ctrl-C - CFE> ^C - CFE> ^C - CFE> - -See the CFE page for more information about using this prompt. - -What to do next? ----------------- - -Now that you have successfully modified and connected to your router, -you are ready to :doc:`Build ` and :doc:`Deploy -` XINU. - -Acknowledgements ----------------- - -*This work is supported in part by NSF grant DUE-CCLI-0737476.* diff --git a/docs/mips/HOWTO-Install-OpenWRT.rst b/docs/mips/HOWTO-Install-OpenWRT.rst deleted file mode 100644 index 6f5f5b10..00000000 --- a/docs/mips/HOWTO-Install-OpenWRT.rst +++ /dev/null @@ -1,91 +0,0 @@ -Installing OpenWRT -================== - -What is OpenWRT? ----------------- - -OpenWRT is essentially a Linux distribution for embedded systems, -specifically routers. It has an incredibly modular structure which -allows it to build easily for dozens of different devices and makes -package selection easy. It also makes browsing around its source -relatively difficult. When you first download a copy of "White Russian", -the stable branch of OpenWRT, you don't have a Linux kernel, or even a -toolchain, but you have its unique build system, which is everything you -need to build a firmware image. As far as we can tell the build process -follows these steps: - -- Download the correct toolchain -- Build the toolchain -- Download a linux kernel -- Download selected packages -- Use the toolchain to build the kernel / packages -- Smush everything together into several flavors of executable - (depending on file system) -- Also create versions with proper Linksys headers so that they can be - uploaded though the web interface as "legit" firmware upgrades - -So though the precious bounty is not in the original download, once -you complete the build process, the build system leaves the linux -source behind in the **build_mipsel** directory, and the toolchain is -left waiting to be swiped as well. Although we recommend building your -own :ref:`cross compiler ` which can be more finely -tuned. - -The |EX| project has used OpenWRT's linux source as a reference in our -work on implementing XINU for MIPS. - -Installing OpenWRT ------------------- - -This is a quick overview of the very easy process of installing the -OpenWRT open source firmware into a LinkSys WRT54GL. Several much more -detailed sources of documentation exist on this [#installing1]_ -[#installing2]_, but we include -bare essentials here for simplicity's sake and also because the bulk of -OpenWRT does not interest us--it only provides us with a working -open-source implementation of an embedded operating system on the -router. - -OpenWRT provides a mature environment for exploring your router -hardware, but is not required to run XINU. - -Before Starting -~~~~~~~~~~~~~~~ - -Get the latest OpenWRT binary from -http://downloads.openwrt.org/whiterussian/newest/bin/. The correct file -is ``openwrt-wrt54g-squashfs.bin`` - -Steps to Install OpenWRT -~~~~~~~~~~~~~~~~~~~~~~~~ - -#. Connect to the LinkSys web interface by visiting its address (default - 192.168.1.1) in a web browser. -#. Upload the OpenWRT file as a "firmware update". -#. Watch as your router magically[#magic]_ transforms into an - OpenWRT-running box. - -What to do next? -~~~~~~~~~~~~~~~~ - -First it is a good idea to play around with the OpenWRT installation and -get a feel for its web interface. You can also login via ssh to the -router and poke around its directory structure. - -The next big step towards a custom operating system on the router is -covered in the next HOWTO in which we will :doc:`modify the Linksys -hardware `. - -Related Links -------------- - -- http://www.openwrt.org - OpenWRT home page -- http://wiki.openwrt.org/OpenWrtDocs/Hardware/Linksys/WRT54GL - - information on WRT54GL router - -Notes ------ - -.. [#installing1] http://wiki.openwrt.org/OpenWrtDocs/Installing -.. [#installing2] http://wiki.openwrt.org/InstallingWrt54gl -.. [#magic] https://en.wikipedia.org/wiki/Magic_(paranormal) diff --git a/docs/mips/HOWTO-Modify-the-ASUS-Hardware.rst b/docs/mips/HOWTO-Modify-the-ASUS-Hardware.rst deleted file mode 100644 index b810f60e..00000000 --- a/docs/mips/HOWTO-Modify-the-ASUS-Hardware.rst +++ /dev/null @@ -1,260 +0,0 @@ -Modifying the ASUS hardware -=========================== - -Summary -------- - -The purpose of this walk through is to explain how to add hardware to -the ASUS wl-330gE router to take advantage of the serial port on the -router and use it to communicate with the serial console for |EX|. -This communication is important for interacting with the :doc:`Common -Firmware Environment `'s, or :doc:`CFE -`, command line interface which is -necessary to run |EX| on the router. - -Before Starting ---------------- - -**NOTE:** The following lists all the *necessary* parts. However, the -following tutorial describes assembling the transceiver on one of our -custom transceiver boards. One could assemble the parts of the entire -transceiver properly without the board, but with more difficulty. Our -transceiver board design is freely available for public use. - -- `Transceiver schematic - `__ is in - postscript format, suitable for `XCircuit - `__. - -- `Transceiver PCB layout `__ - is in `PCB format `__. - -- `Transceiver fabrication tarball - `__ - contains Gerber photoplotter and CNC drill files suitable for - professional fabrication. (No warranty express or implied, - obviously.) - -Parts List -~~~~~~~~~~ -.. list-table:: - :widths: 5 15 20 15 5 - :header-rows: 1 - - * - Quantity - - Part Name - - Details - - Part / Model Number - - Price - * - 1 - - ASUS [[wl-330gE]] Router - - 802.11b/g wireless access point - - http://usa.asus.com/ - - ~$40.00 - * - 1 - - IDC socket connector - - 4 pin header - - Jameco - - - * - 1 - - IDC socket connector - - 5 pin header - - Jameco - - - * - 1 - - IDC shrouded double header - - 0.1”, 10 conductor - - Jameco 67811CM - - $0.33 - * - 1 - - ADM202 Transceiver Chip - - Serial Transceiver ADM202EAN - - Jameco 1800464 - - $1.60 - * - 2 - - Capacitor 220 nF - - Tantalum,.22uF,35V,10% - - Jameco 33507 - - $0.18 - * - 3 - - Capacitor 100 nF - - Tantalum,.1uF,35V,10% - - Jameco 33488 - - $0.22 - * - 1 - - DB9 Female - - 22AWG,SOLDER CUP - - Jameco 15771CM - - $0.59 - -(We provide this parts list as a data point; we offer no guarantees -about current prices, and it is not our intent to endorse any -particular vendor.) - -Tools List -~~~~~~~~~~ - -- Soldering Iron -- Dremel tool (for cutting holes in plastic case) -- Continuity Tester (Multimeter, or some other way of checking for - proper connections) -- Voltmeter (Multimeter will work for this, too) - -Steps to Modify the Hardware ----------------------------- - -Task One: Open the Router -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Using a screwdriver, remove the two nails located underneath the -router and gently remove the top of the router from the bottom, -revealing the PCB. - -**DO NOTE: This is where the warranty on the router is voided!** - -Task Two: Attach the Serial Header -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The PCB is easily removable at this state from the router. Located in -the center of the PCB is the Broadcom BCM5354 chip. Above the chip are -four holes that are aligned vertically. The four holes represent the -input and output for the serial interface, along with the 3.3 volt -power and ground sources for the serial port. - -For easier connectivity, we can use a 4-pin header on the board to -easily attach and detach a 4 connection cable. Use a soldering iron to -solder the 4-pin header onto the board. - -Task Three: Create space for access to serial port on the router -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Using a dremel or other power tool, carefully cut out a rectangular -shaped hole on the faceplate of the router. The hole should be cut -above the words “Portable” and it should be 3 mm wide and 1 cm in -height, or enough to see the serial port through the hole. This will -be used for a 4-wired cable to attach the router to the transceiver -board, detailed in step seven. - -Task Four: Creating the ADM202 Transceiver Circuit Board -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. figure:: images/Transceiver_schematic_wl-330gE.jpg - :width: 400px - :figwidth: 400px - :scale: 100% - :align: left - - Schematic showing the connections between the components of the - ADM202 transceiver circuit board and between the board and the DB9 - serial port. - -.. figure:: images/Transceiver_board.jpg - :width: 150px - :figwidth: 150px - :scale: 100% - :align: right - - Blank transceiver board before adding components. - -.. figure:: images/Complete_transceiver_board.jpg - :width: 150px - :figwidth: 150px - :scale: 100% - :align: right - - Transceiver board with all components in place except ribbon cables. - -A transceiver circuit is needed to convert the 3.3 volt serial signals -from the router to conventional RS-232 serial voltages. To do this, we -need a small square of “perf board”, or other circuit prototyping -techniques. A soldering iron needs to be used to solder the components -onto the board. - -Solder the shrouded double header, the socket, and the capacitors onto -the board. The direction of the pins matter due to their polarity. - -Once the components have been placed on the board, use a continuity -tester to check the connection between the header soldered into the -router's board and the socket on the transceiver board. Now the ADM202 -chip can be inserted onto the board. Next, wires need to be soldered -onto the bottom of the transceiver board. Since this router only has -one transceiver board, only three of the holes need wires. Under the -J2 label, solder wires into the two left most holes. Under the J1 -label, which is under the chip, solder a wire on the right most hole. - -Task Five: Attach Transceiver Board to the Router -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The easiest way to accomplish this is to use an 4-wire audio cable -between the router's serial header and the shrouded double header on -the transceiver board. Using the 4-pin header on the router, connect -the four wires from the audio cable into the 4-pin header. On the -transceiver board, follow the diagram to match the corresponding -cables on the shrouded double header, but using a 5-pin serial header -to easily attack to the shrouded double header. - -.. figure:: images/Serial_Port_Connection.jpg - :width: 400px - :figwidth: 400px - :scale: 100% - :align: left - - Schematic showing the connections between the components of the - ADM202 transceiver circuit board and between the board and the DB9 - serial port. - -Task Six: Attach Transceiver Board to DB9 Serial Ports -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Since the router is very small, it will not have space to place the -DB9 Serial Port. Therefore, a small container needs to be created to -encase all of the components. This will be discussed in step seven. -Take the three wires from the transceiver board and attach them to the -DB9 female according to the diagram. Make sure that the solder cups 1, -4, and 6 are connected to each other and solder cups 7 and 8 are -connected to each other in the DB9 Female serial port. Notice that in -the case of the DB9 Female the T1OUT pin of the ADM202 transceiver -chip needs to be connected to solder cup 2, the R1IN pin of the ADM202 -transceiver chip needs to be connected to solder cup 3, and the ground -needs to be connected to solder cup 5. - -.. figure:: images/DB9_serial_port_wiring.jpg - :width: 400px - :figwidth: 400px - :scale: 100% - :align: right - - Diagram demonstrating proper wiring between the transceiver board - and the DB9 serial port. - -Now you can use a continuity tester to make sure that all the -connections are good and that no wires or solder cups are touching. -The router should be placed back it its case, and the box keeping all -the components together should separate the router from the -transceiver board. It will be very bad if the circuit board and the -transceiver board were to touch. - -Task Seven: Creating a box case for the component -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ASUS router is small, but because of this, there is no space for -the DB9 female serial port, the adaptor, the relay, and the -transceiver board. Because of this, a box is needed to enclose all of -these components together. The box should have holes cut out for the -DB9 female serial port, the power adapter and the Ethernet port. Also, -a small barrier needs to be placed between the transceiver board and -the relay so they do not meet. The PCB can be safely placed inside the -ASUS router case. - -What to do next? ----------------- - -Connect UART0 (the DB9 Female serial port) to a computer and follow -the next HOWTO on using a PC to :doc:`connect to a modified router -`. - - -References ----------- - -*This work is supported in part by NSF grant DUE-CCLI-0737476.* diff --git a/docs/mips/HOWTO-Modify-the-Linksys-Hardware.rst b/docs/mips/HOWTO-Modify-the-Linksys-Hardware.rst deleted file mode 100644 index 42d8a6a3..00000000 --- a/docs/mips/HOWTO-Modify-the-Linksys-Hardware.rst +++ /dev/null @@ -1,431 +0,0 @@ -Modifying the Linksys hardware -============================== - -Summary -------- - -This will walk through adding hardware to a `Linksys -`__ :doc:`WRT54GL ` wireless router -that will take advantage of existing connections on the PCB for two -UART connections, which will be exposed as DB9 serial port connectors -mounted to the faceplate of the router. These connections can be used -to communicate with the serial console for |EX| and also to interact -with the :doc:`Common Firmware Environment -`'s command line interface. Gaining -direct access to :doc:`CFE ` is a key -step towards being able to run |EX| on the router. - -Before Starting ---------------- - -**NOTE:** The following lists all the *necessary* parts. However, the -following tutorial describes assembling the transceiver on one of our -custom transceiver boards. One could assemble the parts of the entire -transceiver properly without the board, but with more difficulty. Our -transceiver board design is freely available for public use. - -- `Transceiver schematic - `__ is in - postscript format, suitable for `XCircuit - `__. - -- `Transceiver PCB layout `__ - is in `PCB format `__. - -- `Transceiver fabrication tarball - `__ - contains Gerber photoplotter and CNC drill files suitable for - professional fabrication. (No warranty express or implied, - obviously.) - -Parts List -~~~~~~~~~~ - -.. list-table:: - :widths: 5 15 20 15 5 - :header-rows: 1 - - * - Quantity - - Part Name - - Details - - Part / Model Number - - Price - * - 1 - - Linksys :doc:`WRT54GL ` Router - - 802.11b/g wireless broadband router - - `Linksys WRT54GL `__ - - ~$65.00 - * - 1 - - Ribbon cable - - 28 AWG, 10 conductor, 25' - - Jameco 643508CM - - $4.99 - * - 2 - - IDC socket connector - - 0.1”, 10 conductor - - Jameco 32491CM - - $0.25 - * - 2 - - IDC shrouded double header - - 0.1”, 10 conductor - - Jameco 67811CM - - $0.33 - * - 1 - - ADM202 Transceiver Chip - - Serial Transceiver ADM202EAN - - Jameco 1800464 - - $1.60 - * - 2 - - Capacitor 220 nF - - Tantalum,.22uF,35V,10% - - Jameco 33507 - - $0.18 - * - 3 - - Capacitor 100 nF - - Tantalum,.1uF,35V,10% - - Jameco 33488 - - $0.22 - * - 1 - - DB9 Female - - 22AWG,SOLDER CUP - - Jameco 15771CM - - $0.59 - * - 1 - - DB9 Male - - 22AWG,SOLDER CUP - - Jameco 15747CM - - $0.59 - -(We provide this parts list as a data point; we offer no guarantees -about current prices, and it is not our intent to endorse any -particular vendor.) - -Tools List -~~~~~~~~~~ - -- Soldering Iron -- Dremel tool (for cutting holes in plastic case) -- Continuity Tester (Multimeter, or some other way of checking for proper connections) -- Voltmeter (Multimeter will work for this, too) - -Steps to Modify the Hardware ----------------------------- - -Task One: Open the Router -~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. figure:: images/Opening-linksys.jpg - :figwidth: 400px - :width: 400px - :scale: 100% - :align: center - - It's really very easy. - - -There are no screws or tools needed to open the router, just pop open -the front with your thumbs as shown in the picture. Some nice -`illustrated opening instructions -`__ can be -found for a more detailed explanation of this step. - -**DO NOTE: This is where the warranty on the router is voided!** - -Task Two: Attach the Serial Header -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. figure:: images/Wrt54gl-layout.jpg - :figwidth: 350px - :width: 350px - :scale: 100% - :align: left - - An overhead view to get your bearings. The serial header is (D) here. - -First you need to unscrew the two screws keeping the router's board -attached to the case. Once the PCB has been removed from the case, -locate the serial header holes provided by Linksys. This would be a -grid of 10 holes (5x2) located on the bottom-right corner of the board -when the antennae stubs are on top (see the top-down photo for -clarification). These ten holes hold all of the input and output for -the two serial interfaces--UART0, and UART1--on the device. - -.. figure:: images/Serial.jpg - :figwidth: 250px - :width: 250px - :scale: 100% - :align: right - - A closer look at our attached serial header. - -Now, we could just solder wires right onto these holes, but a by -placing a nice 10-pin header on the board we can easily attach and -detach a 10 connection cable. Here you will use your **soldering -iron** to solder the **IDC shrouded double header** onto the board. -Make sure to note where the 1 pin is on the board (marked with a -square around the hole instead of a circle) and where the 1 pin is -located on the header (on ours it was marked with a triangle). Make -sure that these two line up when soldering the header into the board. - -Task Three: Create the ADM202 Transceiver Circuit Board -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. figure:: images/Transceiver_schematic.jpg - :figwidth: 400px - :width: 400px - :scale: 100% - :align: left - - Schematic showing the connections between the components of the - ADM202 transceiver circuit board and between the board and the DB9 - serial ports. - -.. figure:: images/Transceiver_board.jpg - :figwidth: 200px - :width: 200px - :scale: 100% - :align: right - - Blank transceiver board before adding components. - -.. figure:: images/Complete_transceiver_board.jpg - :figwidth: 200px - :width: 200px - :scale: 100% - :align: right - - Transceiver board with all components in place except ribbon cables. - -.. figure:: images/Completed_transceiver.jpg - :figwidth: 400px - :width: 400px - :scale: 100% - :align: left - - Complete transceiver board with all components in place. - -The next step is to build the transceiver circuit, which converts the -3.3 volt serial signals from the router to conventional RS-232 serial -voltages. The circuit includes only a handful of components, so it -can be assembled using a small square of "perf board", or a variety of -other inexpensive circuit prototyping techniques. We use a -custom-made printed circuit board to simplify assembly, as shown here. -(Link to page with PCB specs, and directions.) Again, you'll need -your **soldering iron** to secure the different pieces in the -transceiver board. - -Using the diagram on the left, solder the **shrouded double -header**, the **socket**, and the **capacitors** into the board -in the appropriate places. **NOTE:** the positions of the components -on the physical board are not represented in the diagram, but the -silkscreen on the board indicates placement and orientation. -**FURTHER NOTE:** each component has a proper polarity or pin -marking -- direction matters! - -The pictures to the right show the transceiver board in various stages -of completion. The top one shows the blank board on which the other -components will be added. The bottom one shows the **shrouded double -header**, the **socket**, and the **capacitors** soldered in -place. It also shows the actual ADM202 chip inserted into the socket, -however, before inserting the chip it is a good idea to test what -you've completed so far. - -Use a **continuity tester** to check the connection between the -header soldered into the router's board and the socket on your -transceiver board. The next step we recommend for testing your work is -to plug in the router and use a **voltmeter** to check that the -*ground* and *power* pins on the socket (pins 15 and 16) are -registering at 3.3 volts. Now, actually insert the ADM202 chip into -the socket and power up the router again, making sure that the lights -turn on and nothing shorts out. - -The next step is to get six wires from a chopped up piece of the -ribbon cable (or any six spare wires) and solder them into place in -the six holes (two sets of three) at the bottom of the transceiver -board. The resulting completed transceiver board should look something -like the picture below the diagram. - -Task Four: Attach Tranceiver Board to the Router -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. figure:: images/Tranceiver_attached.jpg - :figwidth: 200px - :width: 200px - :scale: 100% - :align: left - - Transceiver board attached via ribbon cable to the serial header - soldered into the router's board. - -.. figure:: images/Front_sticker.jpg - :figwidth: 100px - :width: 100px - :scale: 100% - :align: right - -.. figure:: images/Front.jpg - :figwidth: 100px - :width: 100px - :scale: 100% - :align: right - -.. figure:: images/Drilled_front.jpg - :figwidth: 100px - :width: 100px - :scale: 100% - :align: right - -First take a piece of ribbon cable and attach each end to one of your -IDC socket connectors. Notice the marker on the connector that -signifies where pin 1 of the header will connect to. Make sure that -the same side of the ribbon cable is attached to the marked side of -both connectors. In other words make sure that the same wire will line -up with pin 1 on both headers when the connectors are eventually -attached to the headers. The next step is to actually plug in the -connectors to the headers. Attach one connector to the header we -soldered into the router's board and the other connector to the header -we soldered into the transceiver board. The result should look -something like the picture to the left. Now is a good time to reattach -the router's board to its case by screwing the two screws into place -and then closing up both black pieces of the back part of the router's -case. - -Task Five: Attach Transceiver Board to DB9 Serial Ports -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Before soldering the wires from the transceiver board to the serial -ports, it is a good idea to drill two holes in the front of the -router's casing to use for the serial ports and also two small holes -on each side of the bigger ones to use for screws or bolts to keep the -**DB9 Serial Ports** in place. The three pictures to the right show -how to take off the front sticker and what the case should look like -after you've drilled two holes in the front for the serial ports. It -is also a good idea to cut the sticker and place the left part back on -to cover up the remaining holes in the casing. - -.. figure:: images/Serial_ports_diagram.jpg - :figwidth: 300px - :width: 300px - :scale: 100% - :align: left - - Diagram of wiring to connect the two DB9 serial ports to the - transceiver board. - -Next, feed the six wires coming from the transceiver board through the -two holes you just drilled. Make sure that the three wires soldered -into the holes marked **J1** on the transceiver board go through the -hole on the left of the front of the router and the three wires -soldered into the holes marked **J2** on the transceiver board go -through the hole on the right of the front of the router. - -Following the diagram to the left, solder some spare wires or chopped -pieces of ribbon cable into the two DB9 serial ports. Notice that -solder cups 1, 4, and 6 are connected to each other and solder cups 7 -and 8 are connected to each other on both the **DB9 Female** and **DB9 -Male** serial ports. Then, again following the diagram, solder in the -wires coming from **J1** into the appropriate solder cups of the **DB9 -Female** and the wires coming from **J2** into the appropriate solder -cups of the **DB9 Male**. - -Notice that in the case of the **DB9 Female** the *T1OUT* pin of the -ADM202 transceiver chip needs to be connected to solder cup 2, the -*R1IN* pin of the ADM202 transceiver chip needs to be connected to -solder cup 3, and the *ground* needs to be connected to solder cup 5. - -Also, notice that in the case of the **DB9 Male** the *R2IN* pin of -the ADM202 transceiver chip needs to be connected to solder cup 2, the -*T2OUT* pin of the ADM202 transceiver chip needs to be connected to -solder cup 3, and the *ground* needs to be connected to solder cup 5. - -Feeding the wires through the holes and connecting the serial ports in -this way ensures that the router's primary serial device will be -connected to the **DB9 Female** serial port and will be located on the -left side while the router's secondary serial device will be connected -to the **DB9 Male** serial port and will be located on the right side -of the front of the router. - -After all the soldering is done it is a good idea to use a -**continuity tester** to make sure that all the connections are good -and no wires or solder cups may be accidentally touching. Your result -should look something like the pictures below. Now is a good time to -tape the transceiver board down to the front of the case. It would be -extremely bad for the transceiver board to rub up against the router's -circuit board when it was plugged in. - -======================== ========================= -|Serial_ports_done| |Serial_ports_done1| ------------------------- ------------------------- -|Serial_ports_done_capt| |Serial_ports_done1_capt| -======================== ========================= - -.. |Serial_ports_done| image:: images/Serial_ports_done.jpg - :width: 400px - :scale: 100% - -.. |Serial_ports_done_capt| replace:: - Front view of what the router will look like after the DB9 serial - ports are correctly soldered into place, but before they have been - screwed and secured into the router's case. - -.. |Serial_ports_done1| image:: images/Serial_ports_done1.jpg - :width: 400px - :scale: 100% - -.. |Serial_ports_done1_capt| replace:: - Overhead picture of what the router will look like - after the DB9 serial ports are correctly soldered - into place, but before they have been screwed and - secured into the router's case. - -Task Six: Close the Router -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This final task is best described in photos: - -======================== ========================= -|Attach_Back| |Attach_Front| ------------------------- ------------------------- -|Attach_Back_capt| |Attach_Front_capt| -======================== ========================= - -.. |Attach_Back| image:: images/Attach_Back.jpg - :width: 400px - :scale: 100% - -.. |Attach_Back_capt| replace:: - Now that everything is connected we can re-assemble it. First you - put on the back/top half. Keyed ribbon cable is plugged in to - serial port header on circuit board. - -.. |Attach_Front| image:: images/Attach_Front.jpg - :width: 400px - :scale: 100% - -.. |Attach_Front_capt| replace:: - Next you can carefully install the front half (making sure not to - break any of the wires we have). - -Task Seven: Rejoice -~~~~~~~~~~~~~~~~~~~ - -.. figure:: images/Complete.jpg - :figwidth: 500px - :width: 500px - :scale: 100% - :align: center - - Now you have a WRT54GL with two serial ports installed and ready - to run your own operating system. - -What to do next? ----------------- - -Connect UART0 (the DB9 Female serial port) to a computer and follow -the next HOWTO on using a PC to :doc:`connect to a modified router -`. - -Acknowledgements ----------------- - -*This work is supported in part by NSF grant DUE-CCLI-0737476.* diff --git a/docs/mips/HOWTO-Recover-Router.rst b/docs/mips/HOWTO-Recover-Router.rst deleted file mode 100644 index afafc928..00000000 --- a/docs/mips/HOWTO-Recover-Router.rst +++ /dev/null @@ -1,439 +0,0 @@ -Recovering a router -=================== - -So you've created yourself an expensive paperweight... - -Not to worry! If you aren't breaking things, then chances are you -aren't making hardcore progress. This page serves as a knowledge pool -for methods to revive routers that are corrupted or otherwise -considered non-functional. The information below is mostly specific to -the WRT54GL as it is our most popular and well understood platform at -this time. The process is somewhat similar for other models/platforms; -however, some of the utilities are limited to specific platforms and -commands vary slightly between bootloaders (ex. `U-Boot -`__ vs CFE). - -Sometimes the router won't boot because of a corrupted NVRAM variable -and a simple factory reset will resolve the problem. Chances are if -you've sought out this page you are in much deeper and probably need a -more serious TFTP or :doc:`JTAG ` recovery. We'll start with the -simple solutions and work our way to the more intense recovery methods. - -Before You Begin ----------------- - -If you haven't already, :doc:`backup your router's configuration -`. Hopefully you did this earlier so you can -restore to a "known good" working state. If you didn't, it is still a -good idea to do that now; it can always get worse. You'll also want -to grab yourself a copy of some reliable firmware. The default -firmware that shipped with your router is a good place to start -(generally available from the manufacturer's website). Otherwise, a -stable release of your favorite embedded Linux distribution is a good -alternative. - -Factory Reset -------------- - -Don't get your hopes up for this one, but sometimes -:wikipedia:`Occam's razor` applies to router recovery. To do a factory -reset, hold down the reset switch for about 10 seconds while the unit -is powered on, then unplug it. Let it rest for a little while then -power it back up. If this isn't working for you, try the dd-wrt -`30/30/30 -`__ reset -method. - -There's another option if you have access to a serial console, but -your router isn't necessarily readily accessible (say locked in a rack -somewhere with a pool of backends). Access the CFE as you normally -would. Then, issue the command ``CFE> nvram erase`` and then reboot. -Some models do not properly reinitialize their NVRAM variables -automatically, so be careful with this method. The WRT54GL does -recover them conveniently from a separate stored location in flash. - -If you haven't caught on by now, these methods erase any custom settings -that were stored in NVRAM. Don't forget to re-configure and commit your -network settings, if applicable. - -Serial Console --------------- - -Now is a good time to check that your serial console is up and running. -If you don't see any text coming across the serial link, then you should -double check your transceiver is working properly. Swap with a working -one or at least try the one in question on another working router, if -you have one available. If you can access the web interface (assuming -the OS in flash has one) at either the default IP address or the one you -configured, then your flash image is probably fine--fix your serial -console. It is important that you are confident your serial console if -functional; henceforth we'll be looking for output on the serial port as -a metric for whether each recovery method is successful or not. - -If you can see text and access the CFE but your router won't boot, try -re-flashing the firmware with TFTP. - -If you are confident the serial interface hardware is working properly -but your router appears dead, then proceed to the next section. - -JTAG ----- - -In a nutshell, JTAG is an external interface that allows external -control of an SoC and its memory. You can read more about this on our -EJTAG page. JTAG allows us to recover routers that are completely -unresponsive (aka debricking). Before continuing, you'll need a JTAG -cable (active or passive will do) and a header soldered to the JTAG -connector on your router. See the references below for some suggestions -on this bit. - -Software -~~~~~~~~ - -For WRT54GL recovery, the popular programs are the original -HairyDairyMaid utility and a port called TJTAG. If you purchase a -commercial cable, it may come with a hardware specific recovery tool. -This guide focuses on TJTAG. Download a copy of the source (linked -below) and compile as usual. - -If you built your own cable, chances are it uses a legacy printer style -parallel port interface. You'll need adequate permissions to use this -device in order to run the JTAG software. In \*nix style systems usually -means the user you execute TJTAG as must be a member of the ``lp`` -group. - -The result of the ``groups`` command should look something like this -before you continue: - -.. code-block:: none - - user@host:~$ groups - user lp dialout - -Membership of the ``dialout`` group isn't strictly necessary; however, -you will need this as well if you want to use a local serial console. - -Establish a Connection -~~~~~~~~~~~~~~~~~~~~~~ - -Now we must verify that TJTAG can properly connect to the JTAG -interface on the router. Connect the JTAG cable to both your PC and -the router but leave the power disconnected. On most routers you will -be fighting the :wikipedia:`watchdog timer` so it is a good idea to -type out whatever command you want to execute (without hitting -``enter``), then provide power, and finally quickly hit ``enter`` as -soon as the router LEDs light up. - -Active vs Passive -^^^^^^^^^^^^^^^^^ - -If you built the active buffered cable you need to add the ``/wiggler`` -option to all of your TJTAG commands. The passive unbuffered cable does -not require this option and you should leave it off when using this type -of cable. If you anticipate needing to revive routers often, an active -cable is surely worth the additional investment in time and parts so you -aren't restricted to working within 6 inches of your parallel port. -Otherwise, the unbuffered cable works great provided you can manage the -logistics of the restricted cable length. - -TJTAG Options -^^^^^^^^^^^^^ - -The next trick is to find the magical combination of optional TJTAG -parameters which makes your router happy. Even within a single -make/model this seems to vary greatly--most likely because of various -flash chip manufacturers. For starters, we'll use the ``-probeonly`` -option to guess and check which options will work before modifying the -contents of flash. Usually something like - - ``user@host:tjtag$ ./tjtag -probeonly /wiggler /noemw /noreset`` - -will do the trick. If you are not getting the desired output (see -below), try experimenting with the DMA, break, and reset switches. Once -you've mastered the combinatorics game, you can move onto read/write -operations. - -Successful Output -^^^^^^^^^^^^^^^^^ - -When you've got the right combinations of parameters, you should see an -output like this: - -.. code-block:: none - - ============================================== - EJTAG Debrick Utility v3.0.1 Tornado-MOD - ============================================== - - Probing bus ... Done - - Instruction Length set to 8 - - CPU Chip ID: 00000101001101010010000101111111 (0535217F) - *** Found a Broadcom BCM5352 Rev 1 CPU chip *** - - - EJTAG IMPCODE ....... : 00000000100000000000100100000100 (00800904) - - EJTAG Version ....... : 1 or 2.0 - - EJTAG DMA Support ... : Yes - - EJTAG Implementation flags: R4k MIPS32 - - Issuing Processor / Peripheral Reset ... Skipped - Enabling Memory Writes ... Skipped - Halting Processor ... ... Done - Clearing Watchdog ... Done - - Probing Flash at (Flash Window: 0x1fc00000) ... - Done - - Flash Vendor ID: 00000000000000000000000011101100 (000000EC) - Flash Device ID: 00000000000000000010001010100010 (000022A2) - *** Found a K8D3216UBC 2Mx16 BotB (4MB) Flash Chip *** - - - Flash Chip Window Start .... : 1fc00000 - - Flash Chip Window Length ... : 00400000 - - Selected Area Start ........ : 00000000 - - Selected Area Length ....... : 00000000 - - - - *** REQUESTED OPERATION IS COMPLETE *** - -The last line is important. Don't move on until you get this response. - -Troubleshooting -^^^^^^^^^^^^^^^ - -If you see something like this: - -.. code-block:: none - - ============================================== - EJTAG Debrick Utility v3.0.1 Tornado-MOD - ============================================== - - Probing bus ... Done - - Instruction Length set to 8 - - CPU Chip ID: 00000101001101010010000101111111 (0535217F) - *** Found a Broadcom BCM5352 Rev 1 CPU chip *** - - - EJTAG IMPCODE ....... : 00000000100000000000100100000100 (00800904) - - EJTAG Version ....... : 1 or 2.0 - - EJTAG DMA Support ... : Yes - - EJTAG Implementation flags: R4k MIPS32 - - Issuing Processor / Peripheral Reset ... Done - -You probably don't have the correct combination of options for your -router. Play with the different switches available before attempting -to read/write from flash. - -If you see something like this: - -.. code-block:: none - - ============================================== - EJTAG Debrick Utility v3.0.1 Tornado-MOD - ============================================== - - Probing bus ... Done - - Instruction Length set to 5 - - CPU Chip ID: 11111111111111111111111111111111 (FFFFFFFF) - *** Unknown or NO CPU Chip ID Detected *** - - *** Possible Causes: - 1) Device is not Connected. - 2) Device is not Powered On. - 3) Improper JTAG Cable. - 4) Unrecognized CPU Chip ID. - -Aside from what the output mentions already check that - -- the header is soldered properly -- tjtag has permission to use the parallel port -- you didn't forget the ``/wiggler`` switch (active cable only). - -General Advice for Read/Write Operations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In the next few steps you'll attempt to correct some issues in flash -memory that might prevent the router from booting correctly. Ideally -when you deal with flash, it is best not to interrupt the process before -it finishes on its own. That is why it is important to get the TJTAG -options correct with the ``-probeonly`` option. If an operation hangs -while attempting to read/write, don't panic. It is probably in your best -interests not to buy any lottery tickets tonight, but most likely all is -not lost. Be patient--be sure you've given it ample time to complete. If -it doesn't seem to be making any progress then you probably need to -reset the router. Various sources on the Internet have different -opinions on the best way to reset. Nevertheless, we've found that -disconnecting the power first and then canceling the operation (via -CTRL+C) works the best. Lastly, try the operation again (double check -your parameters). - -Erase NVRAM -~~~~~~~~~~~ - -Step 1. As before, it's a good idea to ensure NVRAM has been wiped out -and isn't harboring corrupt variables. Use the same TJTAG options that -got you a successful completion when trying to probe the device. - -Example: - - ``user@host:tjtag$ ./tjtag -erase:nvram /wiggler /noemw /noreset`` - -When the device reboots, it should reinitialize the correct NVRAM -settings from the backup location within the CFE. If you now have a -serial console, success, you're good to go. Don't forget to reconfigure -any custom NVRAM settings. If that didn't work, read on. - -Erase the Kernel -~~~~~~~~~~~~~~~~ - -Step 2. For whatever reason, it is possible for a corrupted kernel to -prevent the bootloader from producing any output. Again, use the same -options you figured out during the ``-probeonly`` phase. - -Example: - - ``user@host:tjtag$ ./tjtag -erase:kernel /wiggler /noemw /noreset`` - -After rebooting your router, you should get console output that -indicates the CFE was upset to find there's no kernel to load from -flash. This is normal; you did just erase this region of flash -(hopefully). Now you can proceed to flashing a new kernel or maybe you -just want to :ref:`load an elf image ` over -the network. - -Still got a blank serial console? Read on. - -CFE Recovery -~~~~~~~~~~~~ - -Step 3. Your last ditch effort is to replace the bootloader. If your CFE -is corrupted then there's no hope of booting. Luckily, we can flash new -one using TJTAG. The CFE contains a few settings unique to each router. -If you made a backup of your CFE before things went South, you can use -that to restore the router to working order. If you don't have a backup, -you can borrow a copy from another identical router. In the latter case -you must customize the CFE binary a bit before using it on a different -router. In the event you don't have access to a working router of the -same make and model, try searching around on the Internet for a pristine -CFE. There have been a few "CFE collection" projects out there; you -might get lucky. - -Transplant Another Router's CFE -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If you have the original CFE for this exact router, skip ahead to the -next section. Otherwise, start by cloning the CFE of your good router -using :doc:`the usual methods `. - -There are a few CFE variables unique to each router. For the WRT54GL, -see our :doc:`flash memory ` page for specific locations. -There should be a unique identifier and a pair of cryptography keys as -well as the device MAC addresses. We're primarily concerned with the MAC -address of the first physical Ethernet interface, but feel free to -update the others as well. For the WRT54GL, 0x1E00 contains the MAC -address used by the CFE at boot time. While you can override this -setting later for your kernel in your local network configuration or -NVRAM, you can't fool the bootloader (well you can, but not -persistently). Especially, if you are running a pseudo-static DHCP -configuration for a pool of backends, you'll get lots of network -conflicts during the boot process unless this is set correctly. For the -WRT54GL, this MAC address should match the one on the bottom sticker. -Other routers have various schemes/offsets for what the address should -be relative to the one printed on the case depending on how many -physical interfaces the unit has and how the manufacturer chose to -allocate the addresses. If you are feeling ambitious, you can update the -default NVRAM settings in the CFE backup location so they are correct -when you do a factory reset. Alternatively, these can always be -corrected later using the NVRAM utilities. - -To edit the CFE, fire up your favorite hex editor and tweak each -location as necessary. We happen to like ``shed``, which has a nice -``nano`` like interface. Note that with ``shed`` your changes are -affecting the file directly as you make them. There is no "quit without -saving" option. It is always a good idea to make a copy of the CFE.BIN -file you are planning to edit so you can revert to the original without -having to grab it off the good router again. - -Example: - -.. code-block:: none - - offset asc hex dec oct bin - 00001DFE: 00 000 000 00000000 - 00001DFF: 00 000 000 00000000 - 00001E00: C 43 067 103 01000011 - 00001E01: 0 30 048 060 00110000 - 00001E02: : 3A 058 072 00111010 - 00001E03: F 46 070 106 01000110 - 00001E04: F 46 070 106 01000110 - 00001E05: : 3A 058 072 00111010 - 00001E06: E 45 069 105 01000101 - 00001E07: E 45 069 105 01000101 - 00001E08: : 3A 058 072 00111010 - 00001E09: C 43 067 103 01000011 - 00001E0A: 0 30 048 060 00110000 - 00001E0B: : 3A 058 072 00111010 - 00001E0C: F 46 070 106 01000110 - 00001E0D: F 46 070 106 01000110 - 00001E0E: : 3A 058 072 00111010 - 00001E0F: E 45 069 105 01000101 - 00001E10: E 45 069 105 01000101 - 00001E11: 00 000 000 00000000 - 00001E12: FF 255 377 11111111 - 00001E13: FF 255 377 11111111 - 00001E14: FF 255 377 11111111 - 1E00/40000 (hex) - SPACE|E edit S|W|F search J jump to T dec/hex D dump 1|2|4 cursor - X exit R|N repeat B bin edit A ext. asc P preview ` endian - -You should now have a CFE.BIN file with the correct MAC address(es) -ready for flashing! Proceed to the instructions below as if you had a -correct backup all along. - -Using the Same Router's Backup -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Copy your CFE binary to a file called CFE.BIN in the same directory as -the TJTAG executable. You don't have a choice for what file TJTAG reads -in. When you are ready to write it to the router, once again make sure -you know which TJTAG switches keep your particular router happy. - -Example: - - ``user@host:tjtag$ ./tjtag -flash:cfe /wiggler /noemw /noreset`` - -Now, go get a cup of coffee or take a power nap. Bit-banging a few -hundred kilobytes with a parallel interface can take awhile. You should -see exactly what TJTAG is writing to flash whirring by as well as the -percentage written slowly increasing. Sometimes the watchdog timer -doesn't disable correctly and you have to try this a few times before it -will keep going. If it going to fail usually this happens within the -first few seconds. - -A fresh CFE should fix most stubborn routers that aren't physically -damaged, but we make no guarantees. Your mileage may vary. Hopefully you -have your serial console back and you can proceed to restoring a new -kernel. If your router is still unresponsive, unfortunately we have no -more advice for you. It is probably time to invest in a new one. - -External References -------------------- - -- `OpenWrt JTAG - Reference `__ - (includes various DIY cable designs and links to commercial products) -- `OpenWrt Utilities `__ - (HairyDairyMaid Download) -- `TJTAG - Download `__ -- `TIAO Wiki Debrick - Guide `__ -- `Shed `__ (Simple Hex Editor) - diff --git a/docs/mips/Memory.rst b/docs/mips/Memory.rst deleted file mode 100644 index dbad6647..00000000 --- a/docs/mips/Memory.rst +++ /dev/null @@ -1,221 +0,0 @@ -Memory -====== - -Memory on MIPS-based processors is broken into several segments, -consuming the entire 32-address space. These segments are arranged as -follows: - -- `User Segment`_ (USEG), 2 GB **mapped** and - **cached**, addresses ``0x0000 0000`` through ``0x7FFF FFFF`` -- `Kernel Segment 0`_ (KSEG0), 512 MB **unmapped** and **cached**, - addresses ``0x8000 0000`` through ``0x9FFF FFFF`` -- `Kernel Segment 1`_ (KSEG1), 512 MB **unmapped** and **uncached**, - addresses ``0xA000 0000`` through ``0xBFFF FFFF`` -- `Kernel Segment 2`_ (KSEG2), 1 GB **mapped** and **cached**, - addresses ``0xC000 0000`` through ``0xFFFF FFFF`` - -Note that the :doc:`WRT54GL` only has 16 MB of main memory, so a 1-1 -mapping is not be available above ``0x..FF FFFF``. - -.. _mips_user_segment: - -User Segment ------------- - -The user segment of memory, or USEG, is the range of memory addresses -from ``0x0000 0000`` through ``0x7FFF FFFF``. This memory is both mapped -and cached, meaning that any attempt to access memory within this range -will result in the hardware consulting the memory manager prior to -access. **Note** that any attempted access in this range must with the -CPU privilege level set to user mode (i.e. :math:`Status(KSU) = 2`) or -the processor must be in the exception state with the error level bit -set (i.e. :math:`Status(EXL) = 1`). In the latter case, all mappings -turn into 1-1, so directly accessing these address is not recommended. - -Under normal operation, when an address in this memory range is -accessed, the processor will query the memory management unit is -consulted for a mapping. In turn this will ask the translation lookaside -buffer (TLB), and if no mapping is found cause a TLB load or store -exception. When this exception occurs, the operating system is consulted -and should write the correct mapping to the TLB and return from the -exception handler. - -It should be noted that when a TLB exception occurs in the USEG range of -addresses, a special "fast" exception handler is consulted instead of -the normal exception handler. This fast handler is at most 32 -instructions long and begins at ``0x8000 0000``. - -User Segment under Xinu -~~~~~~~~~~~~~~~~~~~~~~~ - -Embedded Xinu has basic :doc:`memory management -` as of the 2.0 release. During -initialization, the kernel allocates some amount of memory (defined in -``xinu.conf`` as ``UHEAP_SIZE``) to act as the user memory heap. Once -this memory is initialized, calls to ``malloc`` and ``free`` will use -the user heap for memory allocation and automatically insert mappings -into the system page table. All mappings are 1-1 since there is no -backing store for a virtual memory subsystem, though it would be -possible to provide each thread with a private address space this -requires lots of memory overhead. - -Exception code to handle TLB faults is in the -:source:`tlbMissHandler() ` function and simply -performs a lookup of the faulting address in the system page table, -checks to see if it is valid and in the correct address space, and -inserts the mapping in the TLB hardware. - -Kernel Segments ---------------- - -While the first part of memory is dedicated to the user segment, the -remainder is the kernel segment. Unlike the user segment, the kernel -segment is sub-divided into three segments with different memory access -properties. **Note** that these properties can be very important if you -are dealing with device drivers and/or hardware that uses direct memory -access (DMA) because there may be caching considerations. - -In brief: - -- `KSEG0 `_ uses **unmapped** and **cached** memory - accesses, -- `KSEG1 `_ uses **unmapped** and **uncached** - memory accesses, and -- `KSEG2 `_ uses **mapped** and **cached** memory - accesses. - -Kernel Segment 0 -~~~~~~~~~~~~~~~~ - -The first kernel segment, or KSEG0, is the range of memory addresses -from ``0x8000 0000`` through ``0x9FFF FFFF``. This memory is -**unmapped** and **cached**, meaning that when the processor attempts -to access an address in this range it will not consult the memory -manager for a mapping, but will store and modifications in the on-chip -memory cache. **Note** that when allocating memory for a device -driver that will be using DMA, the caching effects could lead to major -headaches. If memory is being given to a hardware backend it should be -mapped into the range of `KSEG1 `_. - -On many MIPS processors the first page (4096 bytes) of KSEG0 is -considered to be reserved system space where small amounts of -specialized code can be loaded for fast execution. Typically, this -memory is used for exception handling and the following sections are -reserved for the following: - -- ``0x8000 0000`` (32 instructions) is for the TLB exception handler, -- ``0x8000 0080`` (32 instructions) is for the 64-bit TLB exception - handler, and -- ``0x8000 0180`` (32 instructions) is for the generic exception - handler. - -Other reserved portions of this memory page remain unknown. - -After the reserved system page, the operating system is free to use -memory however it sees fit. - -KSEG0 under Xinu -^^^^^^^^^^^^^^^^ - -Embedded Xinu uses KSEG0 extensively for kernel operations. As the -:doc:`WRT54GL` uses a 32-bit MIPS processor, Embedded Xinu loads a -quick TLB handler into memory at ``0x8000 0000`` and a generic -exception handler at ``0x8000 0180``, both of these are limited to 32 -instructions and jump to higher level C code when needed. It is -important to note that Embedded Xinu also makes use of reserved memory -starting at ``0x8000 0200`` to store an array of exception handler -entry points (32-bit function pointers for 32 possible exceptions) and -``0x8000 0280`` to store an array of interrupt handler entry points -(32-bit function pointers for 8 possible interrupts). - -Xinu loads the kernel entry point beginning at ``0x8000 1000``, and upon -booting begins execution at that address. Within Embedded Xinu, the -memory segments are in the following order (as defined by -``ld.script``): text, read-only data, data, and block started by symbol -(BSS, uninitialized data). The kernel allocates a small kernel stack -after the BSS segment and finally initializes a dynamic memory heap for -the remaining physical memory addresses. - -The :doc:`kernel memory allocator ` will -allocate memory from the kernel heap as requested. Since Embedded Xinu -uses a single page table, all kernel addresses will be mapped -read-only in all address spaces, giving a user thread the ability to -read from but not write to kernel memory. - -Kernel Segment 1 -~~~~~~~~~~~~~~~~ - -The second kernel segment, or KSEG1, is the range of memory addresses -from ``0xA000 0000`` through ``0xBFFF FFFF``. This memory **unmapped** -and **uncached**, meaning that when the processor attempts to access -an address in this range it will not consult the memory manager for a -mapping and it *will* bypass the on-chip memory cache for memory loads -and stores. - -By skipping the hardware cache, KSEG1 will see slower memory accesses -because it must get data directly from the RAM. Because of this, it is -not typical to use KSEG1 for normal kernel operations, rather this -segment is useful for accessing memory that is mapped to some other -hardware device on the platform. These mappings will either be -pre-existing, so they are out-of-range of physical memory addresses, or -they will be dynamically allocated memory that will be shared between -the operating system and some hardware device. - -KSEG1 under Xinu -^^^^^^^^^^^^^^^^ - -Embedded Xinu uses several hardware devices that are mapped -out-of-range of physical memory and some hardware devices that use -dynamically allocated memory for sharing. Some devices on the -:doc:`WRT54GL` that are beyond the range of physical memory are: - -- Broadcom I/O controller registers at ``0xB800 0000``, -- UART registers at ``0xB800 0300`` and ``0xB800 0400``, -- Broadcom Ethernet 47xx registers at ``0xB800 1000``, -- Broadcom Wireless LAN controller registers at ``0xB800 5000``, -- Broadcom 47xx RoboSwitch registers at ``0xB800 6000``, and -- :doc:`Flash memory ` (4 MB) read mapped beginning at - ``0xBC00 0000``. - -Certain drivers (such as the Ethernet driver), also take advantage of -shared memory between the operating system and the hardware. This -requires the use of dynamically allocated kernel memory (originating in -KSEG0), that has been mapped to KSEG1 address range. This is not -problematic because both KSEG0 and KSEG1 use a 1-1 memory mapping. With -the Ethernet driver of Embedded Xinu, the shared memory that is in KSEG1 -hold the DMA descriptor rings and the Ethernet packet buffers to store -the packets in. - -Kernel Segment 2 -~~~~~~~~~~~~~~~~ - -The third kernel segment, or KSEG2, is the range of memory addresses -from ``0xC000 0000`` through ``0xFFFF FFFF``. This memory is both -**mapped** and **cached**, meaning that the processor will consult the -memory manager for a mapping and store memory modifications in the -on-chip cache. - -Like the user segment of memory any attempt to access memory in KSEG2 -will result in the processor querying the memory manager and the TLB to -find a mapping. If a mapping does not exist the processor will generate -a TLB load or store exception and the operating system must fill the TLB -entry. Unlike USEG, a TLB exception will not jump to the "fast" handler -and instead follow the normal path for exception handling through the -generic exception mechanism. - -This memory segment could be useful to create the appearance of page -aligned data to the underlying hardware or operating system if needed. - -KSEG2 under Xinu -^^^^^^^^^^^^^^^^ - -Embedded Xinu does not make use of any KSEG2 memory yet. However, to -take advantage of the Context register of MIPS processors when a TLB -exception occurs, it is possible that a mapping of the system page table -to KSEG2 might exist in future versions. - -References ----------- - -* Sweetman, Dominic. *See MIPS Run*. San Francisco: Morgan Kaufmann - Publishers, 2007. diff --git a/docs/mips/Mips-console.rst b/docs/mips/Mips-console.rst deleted file mode 100644 index c84dc650..00000000 --- a/docs/mips/Mips-console.rst +++ /dev/null @@ -1,76 +0,0 @@ -Mips console -============ - -.. code:: bash - - #!/usr/bin/expect -f - - - set ip 192.168.1.2 - - proc powercycle {} { - send -null 1 - expect "(command-mode)" - send -- "p" - #expect "powered on" - - expect { - "CFE> " { } - -re ".*\r\n" { send "\003" - exp_continue } - } - } - - - set timeout -1 - if {$argc > 1} { - puts "$argc, $argv" - puts "usage: mips-console [backend]" - exit - } - - if {$argc == 1} { - set backend $argv - set spawned [spawn xinu-console -c mips $argv] - } else { - set backend null - set spawned [spawn xinu-console -c mips] - } - expect { - "error: connection not available" - { send_user "error: connection not available\r\n" - exit } - -re "connection '(.*)', class '(.*)', host '(.*)'\r\n" - { set backend $expect_out(1,string) - set class $expect_out(2,string) - set host $expect_out(3,string) - # send_user "connection $backend, class $class, host $host\r\n" - } - } - sleep 1 - send -null 1 - expect "(command-mode) " - send -- "d" - expect "file: " - send -- "xinu.boot\r" - expect { - "download complete\r\n" - { } - "No such file or directory" - { send_user "No such file: xinu.boot\r\n" - exit } - } - sleep 1 - send -- "\r" - set boot 1 - expect { - -timeout 1 "CFE> " {set boot 0} - } - if {1==$boot} powercycle - send -- "ifconfig -auto eth0\r" - expect "CFE> " - send -- "boot -elf $ip:$backend" - send -- ".boot\r" - expect -- "Starting program" - interact - diff --git a/docs/mips/Mipsel-qemu.rst b/docs/mips/Mipsel-qemu.rst deleted file mode 100644 index 792922a1..00000000 --- a/docs/mips/Mipsel-qemu.rst +++ /dev/null @@ -1,28 +0,0 @@ -mipsel-qemu -=========== - -|EX| has been ported to the MIPSel (little-endian MIPS) virtual -environment provided by `QEMU `__. This provides an -easy way to run a basic Embedded Xinu environment on a RISC -architecture without devoting "real" hardware. - -Building --------- - -:ref:`Compile Embedded Xinu ` with -``PLATFORM=mipsel-qemu``. Note that this requires a :ref:`cross -compiler ` targeting little-endian MIPS ("mipsel"). -This will produce the file ``xinu.boot`` in the ``compile/`` -directory. - -Running -------- - -:: - - $ qemu-system-mipsel -M mips -m 16M -kernel xinu.boot -nographic - -Notes ------ - -The ``mipsel-qemu`` platform does not yet support networking. diff --git a/docs/mips/Processor.rst b/docs/mips/Processor.rst deleted file mode 100644 index bea99717..00000000 --- a/docs/mips/Processor.rst +++ /dev/null @@ -1,106 +0,0 @@ -Processor -========= - -Coprocessor 0 contains a wealth of information which is required of any -MIPS CPU. Registers of note are processor identification (register 15) -and two configuration registers (register 16, select 0 and select 1). -Below is what has been gleaned from the processor on the WRT54GL and the -WRT54G (differences will be noted). - -Processor Identification ------------------------- - -This register will contain information about what company manufactured -the CPU, what options are installed, the implementation of the processor -and the revision of the processor. - -| ``0x00029008 (WRT54GL)`` -| ``0x00029029 (WRT54G)`` - -The identification is split into 4 8-byte chunks in the following order -(starting with bit 31): manufacturer options, manufacturer -identification, processor implementation, and revision. For both the -WRT54GL and the WRT454G there are no manufacturer options. A -manufacturer identification of 0x02 is reserved for broadcom processors. -Of most importance is the processor implementation, which for both units -is 0x90, which makes the processor a MIPS4KEc (MIPS32 R2 compliant). The -last field, revision, is the only difference and should be unimportant -for XINU. - -Configuration -------------- - -Configuration for MIPS processors is stored on coprocessor 0, and -contains important information about what the processor supports, how -memory works, and what is implemented on the processor. Configuration is -always in register 16, but it is possible to access different data by -selecting what configuartion data we are looking for (select 0 for -CONFIG1, select 1 for CONFIG2). - -Config, select 0 -~~~~~~~~~~~~~~~~ - -Both the WRT54GL and WRT54G contain the same value for config registers -``0x80000083``. The significant information is listed below: - -- bit 31 - (1) CP0\_CONFIG1 exisits -- bit 15 - (0) Little Endian -- bit 14:13 - (0) MIPS 32 standard -- bit 12:10 - (0) Revision 1 -- bit 9:7 - (1) MIPS 32/64 Compliant TLB -- bit 3 - (0) I-cache is not indexed or tagged with virtual addresses -- bit 2:0 - (3) kseg0 coherency algorithm (cacheable) - -Config, select 1 -~~~~~~~~~~~~~~~~ - -The second configuration register on the MIPS processor reports slightly -different data between the WRT54GL and the WRT54G. Data from the WRT54GL -will be introduced first. - -``0x3ed94c82 (WRT54GL)`` - -- bit 30:25 - (31) 2\ :sup:`5` entries in TLB (31+1) -- bit 24:22 - (3) I-cache number of index positions 64\*2\ :sup:`3` = - 512-bytes -- bit 21:19 - (3) I-cache line size 2\*2\ :sup:`3` = 16-bytes -- bit 18:16 - (1) I-cache associativity (A+1) = 2-way set associative -- bit 15:13 - (2) D-cache number of index positions 64\*2\ :sup:`2` = - 256-bytes -- bit 12:10 - (3) D-cache line size 2\*2\ :sup:`3` = 16-bytes -- bit 9:7 - (1) D-cache associativity (A+1) = 2-way set associative -- bit 6 - (0) no CP2 -- bit 5 - (0) no MDMX ASE implementation -- bit 4 - (0) no performance counter -- bit 3 - (0) no watchpoint register -- bit 2 - (0) no MIPS16e instruction set available -- bit 1 - (1) EJTAG debug unit IS available -- bit 0 - (0) no floating point unit attached - -This gives the following data: I-cache has 512 sets/way, 16 bytes/line, -and is 2-way set-associative (16 KByte I-cache) and D-cache has 256 -sets/way, 16 bytes/line, and is 2-way set-associative (8 KByte D-cache). - -``0x3e9b6c86 (WRT54G)`` - -- bit 30:25 - (31) 2\ :sup:`5` entries in TLB (31+1, same as WRT54GL) -- bit 24:22 - (2) I-cache number of index positions 64\*2\ :sup:`2` = - 256-bytes -- bit 21:19 - (3) I-cache line size 2\*2\ :sup:`3` = 16-bytes -- bit 18:16 - (3) I-cache associativity (A+1) = 2-way set associative -- bit 15:13 - (3) D-cache number of index positions 64\*2\ :sup:`3` = - 512-bytes -- bit 12:10 - (3) D-cache line size 2\*2\ :sup:`3` = 16-bytes -- bit 9:7 - (1) D-cache associativity (A+1) = 2-way set associative -- bit 6 - (0) no CP2 -- bit 5 - (0) no MDMX ASE implementation -- bit 4 - (0) no performance counter -- bit 3 - (0) no watchpoint register -- bit 2 - (1) MIPS16e instruction set IS available -- bit 1 - (1) EJTAG debug unit IS available -- bit 0 - (0) no floating point unit attached - -Again, giving the following data (which does differ from the WRT54GL): -I-cache has 256 sets/way, 16 bytes/line, and is 2-way set-associative (8 -KByte I-cache) and D-cache has 512 sets/way, 16 bytes/line, and is 2-way -set-associative (16 KByte D-cache) diff --git a/docs/mips/Serial-Adapter-Diagrams.rst b/docs/mips/Serial-Adapter-Diagrams.rst deleted file mode 100644 index ede3d64f..00000000 --- a/docs/mips/Serial-Adapter-Diagrams.rst +++ /dev/null @@ -1,47 +0,0 @@ -Serial adapter diagrams -======================= - -RJ45/DB9 adapters ------------------ - -Below are diagrams for RJ45 to DB9 adapters allowing connection -between an `Etherlite serial bay and XINU backends -` in a pool. The first diagram is -for UART 0 (DTE). The second diagram is for the platform-dependent -UART 1 (DCE). - -.. image:: images/DB9M.png - :width: 400px - :align: center - -.. image:: images/NullModem.png - :width: 400px - :align: center - -Null Modem ----------- - -The null modem adapter is required to make connections between -available UART 1 ports on two machines. The above UART 1 diagram -functions as a null modem when connecting directly to other backends, -as well as to the EtherLite serial bay. - -EtherLite to Baytech --------------------- - -The third diagram represents a connection between the between a -Baytech serial-controlled power strip and the EtherLite terminal annex. -The final two diagrams are the Baytech/Etherlite diagram broken into two -parts, representing the mating of two individual RJ45/DB9 adapters. - -.. image:: images/BaytechWiring.png - :width: 500px - :align: center - -.. image:: images/DB9M.png - :width: 300px - :align: center - -.. image:: images/Baytech.png - :width: 300px - :align: center diff --git a/docs/mips/Startup.rst b/docs/mips/Startup.rst deleted file mode 100644 index 6a310fd4..00000000 --- a/docs/mips/Startup.rst +++ /dev/null @@ -1,20 +0,0 @@ -Startup -======= - -.. raw:: mediawiki - - {{Historical}} - -CFE Jettison ------------- - -CFE begins executing code at 0x80001000. It passes a firmware handler, -firmware entry point, and an entry point seal. The firmware entry point -handler points to an address in the middle of the heap space (confirmed -once to point to 0x803029FC, which may or may not be a deterministic -address). - -Cache Flush ------------ - -The L1 instruction and data caches are intialized and flushed. diff --git a/docs/mips/Switch-Driver.rst b/docs/mips/Switch-Driver.rst deleted file mode 100644 index 3b67c54b..00000000 --- a/docs/mips/Switch-Driver.rst +++ /dev/null @@ -1,61 +0,0 @@ -Switch driver -============= - -Ethernet Port Numbering ------------------------ - -On the back of a Linksys WRT54GL router, the Ethernet ports appear in -this order: - -+-------+-----+-----+-----+-----+ -| WAN | 1 | 2 | 3 | 4 | -+-------+-----+-----+-----+-----+ - -Internally, the Ethernet ports are indexed in this order: - -+-----+-----+-----+-----+-----+ -| 4 | 3 | 2 | 1 | 0 | -+-----+-----+-----+-----+-----+ - -CFE and OpenWRT VLAN Configuration ----------------------------------- - -In order to use the Linksys WRT54GL routers for complex routing -purposes, both CFE and the operating system burned into Flash must be -modified to separate the four LAN ports into their own network -interfaces. - -By default, the four LAN ports (0-3) are part of the same VLAN in CFE. -(Port 5 is internal to the CPU.) - -| ``CFE> nvram get vlan0ports`` -| ``3 2 1 0 5*`` -| ``*** command status = 0`` - -This needs to be changed so that only one LAN port is in the VLAN. -Select an appropriate port number based on the diagram above. The port -that remains in the VLAN should be the one connected to the Xinu server. - -| ``CFE> nvram set vlan0ports="0 5*"`` -| ``*** command status = 0`` -| ``CFE> nvram commit`` -| ``*** command status = 0`` - -The network configuration on OpenWRT must also be changed. - -``root@OpenWrt:/# vi /etc/config/network`` - -The file will originally contain this section. - -| ``#### VLAN configuration`` -| ``config switch eth0`` -| ``        option vlan0    "0 1 2 3 5*"`` -| ``        option vlan1    "4 5"`` - -It should be changed to look like this where the port in vlan0 is the -one connected to the Xinu server. - -| ``#### VLAN configuration`` -| ``config switch eth0`` -| ``        option vlan0    "0 5*"`` -| ``        option vlan1    "4 5"`` diff --git a/docs/mips/TRX-Header.rst b/docs/mips/TRX-Header.rst deleted file mode 100644 index ec01abeb..00000000 --- a/docs/mips/TRX-Header.rst +++ /dev/null @@ -1,62 +0,0 @@ -TRX header -========== - -TRX is the format used to store kernel images in :doc:`Flash-Memory` -for CFE based (and possibly others) routers. Unfortunately, not much -is known about the format or what limitations and rules exist. -Currently, |EX| uses a simple utility from the OpenWRT repository to -build TRX images. However, the quality of our TRX images seems to vary -between revisions of the operating system. We do not yet know why. -Possible reasons include: - -- alignment problems, -- compression/extraction problems, -- incorrectly configuration at startup (differences between TFTP - booting and booting from Flash), or a -- combination of above and some unknown problem. - -What we do know is the format of the 28 byte TRX header, it is as -follows: - -.. code-block:: none - -  0                   1                   2                   3    -  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1  - +---------------------------------------------------------------+ - |                     magic number ('HDR0')                     | - +---------------------------------------------------------------+ - |                  length (header size + data)                  | - +---------------+---------------+-------------------------------+ - |                       32-bit CRC value                        | - +---------------+---------------+-------------------------------+ - |           TRX flags           |          TRX version          | - +-------------------------------+-------------------------------+ - |                      Partition offset[0]                      | - +---------------------------------------------------------------+ - |                      Partition offset[1]                      | - +---------------------------------------------------------------+ - |                      Partition offset[2]                      | - +---------------------------------------------------------------+ - -After the TRX header, the data section begins. - -Code Pattern ------------- - -It is common to see an additional 32 byte header prepended to the TRX -image as a way to tag certain firmware images specific to a particular -hardware platform. The first 4 bytes correspond to an ASCII "Code -Pattern" that makes this identification. For example, the WRT54G series -routers (including the WRT54GL) contain the characters ``W54G`` as the -first field in this additional header. Some methods of writing to flash, -such as the Linksys Web GUI and TFTP, check for this pattern before -actually writing the firmware. The flash process will error out when -attempting to flash a router without the correct code pattern using -these methods. When the code pattern header is present, filenames -traditionally have the ``.bin`` extension instead of ``.trx``. - -Our TRX image creation process for Xinu uses the `addpattern -`__ -utility from OpenWRT to add the correct pattern to our TRX file. This -utility also supports additional fields in the code pattern header: -dates, versions, board ID, and flags. diff --git a/docs/mips/UART-Driver.rst b/docs/mips/UART-Driver.rst deleted file mode 100644 index efdeda7e..00000000 --- a/docs/mips/UART-Driver.rst +++ /dev/null @@ -1,127 +0,0 @@ -UART driver -=========== - -.. note:: - - This page appears to have been written with :doc:`WRT54GL` routers - in mind and may or may not be applicable to other platforms. - -.. image:: images/UartAsyncDriver.png - :width: 450px - :align: right - -The UART driver is a char-oriented driver designed to work with a -National Semiconductor 16550 UART. The driver is responsible for -receiving and sending bytes of data asynchronously. - -The UART driver is divided into two sections: an upper half and a lower -half. The two halves communicate via semaphores and buffers. The lower -half is interrupt driven and interacts with the physical hardware. The -upper half of the driver interacts with user programs. It does not -interact directly with the hardware nor does it spinlock while waiting -for the hardware to be ready. The upper half waits on semaphores which -are signaled by the lower half to indicate bytes of data or free space -are avaialable in the appropriate buffer. - -Physical UART -------------- - -The XINU backends have been equipped with serial ports that are -representative of the National Semiconductor 16550 UART. Documentation -on the 16550 UART can be found at -http://www.national.com/ds.cgi/NS/NS16C552.pdf. - -Initialization --------------- - -Intialize defines the starting values for all members of the control -block: statistical counts are zeroed, buffers are defined, and -semaphores are allocated. Also part of the initialization process is -setting values in the control and status registers: - -- Line control is set to 8 bit, no parity, 1 stop. -- Receiver FIFO full, transmitt buffer empty, and receiver line status - interrupts are enabled. -- Hardware FIFOs are enabled. -- Divisor Latch bits (high and low) - - - The divisor can be calculated by using the formula: - - :math:`divisor=\frac{baud\_base+\frac{baud\_rate}{2}}{baud\_rate}.` - -Where ``baud_rate`` is the speed you wish to connect at (typically -115,200) and - - :math:`baud\_base=\frac{clockrate}{16}`. - -The clockrate should be measured in hertz and may not be equivalent to -the clockspeed. (The WRT54GL, for example, has a hard-coded clockrate of -20,000,000 or 20MHz, while the WRT54G has a clockrate of about 25MHz.) - -Upper Half (Read and Write) ---------------------------- - -Read is part of the upper half of the driver that fills a user supplied -buffer with bytes from the input buffer filled by the lower half of the -driver. If the input buffer is empty, read waits for the lower half to -signal on the input semaphore and indicate bytes are avaiable in the -input buffer. - -Write is part of the upper half of the driver and places bytes from a -user supplied buffer into the output buffer read by the lower half of -the driver. If there is no free space in the output buffer, write waits -for the lower half to signal on the output semaphore and indicate free -space is available in the output buffer. - -Lower Half (Interrupt Handler) ------------------------------- - -The interrupt handler is the lower half of the driver. The 16550 UART -sends an interrupt (if enabled) when the transmitter FIFO is empty or -the receiver FIFO has reached its available bytes tigger level. Three -different types of interrupts are handled by the lower half: - -- Line or modem status: The interrupt is merely noted in the UART's - statistical counts. -- Receiver hardware FIFO trigger level: The driver moves bytes from the - UART's receive hardware FIFO into the input buffer. Received bytes - are read from the UART until the Data Ready bit in the Line Status - Register is no longer set. The input semaphore is signaled to let the - upper half know bytes of data are in the input buffer. -- Transmitter hardware FIFO empty: The lower half fills the UART's - transmit hardware FIFO from the output buffer. The interrupt handler - fills the transmit hardware FIFO until the FIFO is full or the output - buffer is empty. The output semaphore is signaled to let the upper - half know bytes of space are available in the output buffer. - -Control -------- - -The control functions are used to set, clear, and get the input and -output flags for the UART driver. Non-blocking flags indicate the upper -half read and write functions should perform as much of the requested -read or write length as possible, but should not block to wait for the -lower half to fill or empty the input or output buffers. When the echo -input flag is set, the UART outputs every byte as it is received in -addition to placing the byte in the input buffer. - -Loopback -~~~~~~~~ - -``UART_ENABLE_LOOPBACK`` and ``UART_DISABLE_LOOPBACK`` control functions -enable and disable hardware loopback. Be aware that loopback is -precarious and must be used carefully. It is recommended that you turn -off interrupts prior to enabling loopback and after disabling loopback -to avoid interleaving output while in loopback mode. - -Prior to enabling and disabling hardware loopback, the control function -ensures the transmitter is completely empty and has completed all -previous transmission. When in loopback mode the hardware does not throw -interrupts, so the control functions call the UART interrupt handler -explicitly. - -See also --------- - -- :doc:`/features/TTY-Driver` - diff --git a/docs/mips/WRT54GL.rst b/docs/mips/WRT54GL.rst deleted file mode 100644 index ab3621a4..00000000 --- a/docs/mips/WRT54GL.rst +++ /dev/null @@ -1,20 +0,0 @@ -WRT54GL -======= - -This page lists details about the `Linksys `__ -WRT54GL device. - -Hardware Info -------------- - -As reported by OpenWRT -~~~~~~~~~~~~~~~~~~~~~~ - -- **eth0**: Broadcom 47xx 10/100BaseT Ethernet -- **eth1**: Broadcom BCM4320 802.11 Wireless Controller 3.90.37.0 - -See also --------- - -- WRT54G - diff --git a/docs/mips/images/Attach_Back.jpg b/docs/mips/images/Attach_Back.jpg deleted file mode 100644 index 9fbf651e..00000000 Binary files a/docs/mips/images/Attach_Back.jpg and /dev/null differ diff --git a/docs/mips/images/Attach_Front.jpg b/docs/mips/images/Attach_Front.jpg deleted file mode 100644 index c7149f65..00000000 Binary files a/docs/mips/images/Attach_Front.jpg and /dev/null differ diff --git a/docs/mips/images/Baytech.png b/docs/mips/images/Baytech.png deleted file mode 100644 index d4566dc9..00000000 Binary files a/docs/mips/images/Baytech.png and /dev/null differ diff --git a/docs/mips/images/BaytechWiring.png b/docs/mips/images/BaytechWiring.png deleted file mode 100644 index 58363aaf..00000000 Binary files a/docs/mips/images/BaytechWiring.png and /dev/null differ diff --git a/docs/mips/images/Complete.jpg b/docs/mips/images/Complete.jpg deleted file mode 100644 index 8584fbe8..00000000 Binary files a/docs/mips/images/Complete.jpg and /dev/null differ diff --git a/docs/mips/images/Complete_transceiver_board.jpg b/docs/mips/images/Complete_transceiver_board.jpg deleted file mode 100644 index 0dee57e2..00000000 Binary files a/docs/mips/images/Complete_transceiver_board.jpg and /dev/null differ diff --git a/docs/mips/images/Completed_transceiver.jpg b/docs/mips/images/Completed_transceiver.jpg deleted file mode 100644 index 4d7b4eec..00000000 Binary files a/docs/mips/images/Completed_transceiver.jpg and /dev/null differ diff --git a/docs/mips/images/DB9M.png b/docs/mips/images/DB9M.png deleted file mode 100644 index 36a9af02..00000000 Binary files a/docs/mips/images/DB9M.png and /dev/null differ diff --git a/docs/mips/images/DB9_serial_port_wiring.jpg b/docs/mips/images/DB9_serial_port_wiring.jpg deleted file mode 100644 index 00000e12..00000000 Binary files a/docs/mips/images/DB9_serial_port_wiring.jpg and /dev/null differ diff --git a/docs/mips/images/Drilled_front.jpg b/docs/mips/images/Drilled_front.jpg deleted file mode 100644 index fa8c7fff..00000000 Binary files a/docs/mips/images/Drilled_front.jpg and /dev/null differ diff --git a/docs/mips/images/Front.jpg b/docs/mips/images/Front.jpg deleted file mode 100644 index f7cf3005..00000000 Binary files a/docs/mips/images/Front.jpg and /dev/null differ diff --git a/docs/mips/images/Front_sticker.jpg b/docs/mips/images/Front_sticker.jpg deleted file mode 100644 index 0742ebf3..00000000 Binary files a/docs/mips/images/Front_sticker.jpg and /dev/null differ diff --git a/docs/mips/images/Impcode.png b/docs/mips/images/Impcode.png deleted file mode 100644 index 6d1d853b..00000000 Binary files a/docs/mips/images/Impcode.png and /dev/null differ diff --git a/docs/mips/images/JTAGunbuffered.png b/docs/mips/images/JTAGunbuffered.png deleted file mode 100644 index 1c4f532d..00000000 Binary files a/docs/mips/images/JTAGunbuffered.png and /dev/null differ diff --git a/docs/mips/images/NullModem.png b/docs/mips/images/NullModem.png deleted file mode 100644 index 65585a46..00000000 Binary files a/docs/mips/images/NullModem.png and /dev/null differ diff --git a/docs/mips/images/Opening-linksys.jpg b/docs/mips/images/Opening-linksys.jpg deleted file mode 100644 index 88fc3a35..00000000 Binary files a/docs/mips/images/Opening-linksys.jpg and /dev/null differ diff --git a/docs/mips/images/Serial.jpg b/docs/mips/images/Serial.jpg deleted file mode 100644 index cce62fac..00000000 Binary files a/docs/mips/images/Serial.jpg and /dev/null differ diff --git a/docs/mips/images/Serial_Port_Connection.jpg b/docs/mips/images/Serial_Port_Connection.jpg deleted file mode 100644 index 91b29eac..00000000 Binary files a/docs/mips/images/Serial_Port_Connection.jpg and /dev/null differ diff --git a/docs/mips/images/Serial_ports_diagram.jpg b/docs/mips/images/Serial_ports_diagram.jpg deleted file mode 100644 index 690c9bb9..00000000 Binary files a/docs/mips/images/Serial_ports_diagram.jpg and /dev/null differ diff --git a/docs/mips/images/Serial_ports_done.jpg b/docs/mips/images/Serial_ports_done.jpg deleted file mode 100644 index 05aa7e27..00000000 Binary files a/docs/mips/images/Serial_ports_done.jpg and /dev/null differ diff --git a/docs/mips/images/Serial_ports_done1.jpg b/docs/mips/images/Serial_ports_done1.jpg deleted file mode 100644 index 1c31777d..00000000 Binary files a/docs/mips/images/Serial_ports_done1.jpg and /dev/null differ diff --git a/docs/mips/images/Te_jtag_cable.png b/docs/mips/images/Te_jtag_cable.png deleted file mode 100644 index 399d88cc..00000000 Binary files a/docs/mips/images/Te_jtag_cable.png and /dev/null differ diff --git a/docs/mips/images/Tranceiver_attached.jpg b/docs/mips/images/Tranceiver_attached.jpg deleted file mode 100644 index 4534162e..00000000 Binary files a/docs/mips/images/Tranceiver_attached.jpg and /dev/null differ diff --git a/docs/mips/images/Transceiver_board.jpg b/docs/mips/images/Transceiver_board.jpg deleted file mode 100644 index ef777cb0..00000000 Binary files a/docs/mips/images/Transceiver_board.jpg and /dev/null differ diff --git a/docs/mips/images/Transceiver_schematic.jpg b/docs/mips/images/Transceiver_schematic.jpg deleted file mode 100644 index 2cb67c0b..00000000 Binary files a/docs/mips/images/Transceiver_schematic.jpg and /dev/null differ diff --git a/docs/mips/images/Transceiver_schematic_wl-330gE.jpg b/docs/mips/images/Transceiver_schematic_wl-330gE.jpg deleted file mode 100644 index b27d36bf..00000000 Binary files a/docs/mips/images/Transceiver_schematic_wl-330gE.jpg and /dev/null differ diff --git a/docs/mips/images/UartAsyncDriver.png b/docs/mips/images/UartAsyncDriver.png deleted file mode 100644 index 05985ce1..00000000 Binary files a/docs/mips/images/UartAsyncDriver.png and /dev/null differ diff --git a/docs/mips/images/Wiggler.png b/docs/mips/images/Wiggler.png deleted file mode 100644 index 94e6ba07..00000000 Binary files a/docs/mips/images/Wiggler.png and /dev/null differ diff --git a/docs/mips/images/Wrt54gl-layout.jpg b/docs/mips/images/Wrt54gl-layout.jpg deleted file mode 100644 index 2f725f3b..00000000 Binary files a/docs/mips/images/Wrt54gl-layout.jpg and /dev/null differ diff --git a/docs/mips/images/Xinu-Wiggler.png b/docs/mips/images/Xinu-Wiggler.png deleted file mode 100644 index 9af047cf..00000000 Binary files a/docs/mips/images/Xinu-Wiggler.png and /dev/null differ diff --git a/docs/mips/index.rst b/docs/mips/index.rst deleted file mode 100644 index 9ced69f2..00000000 --- a/docs/mips/index.rst +++ /dev/null @@ -1,7 +0,0 @@ -MIPS ports (including Linksys routers) -====================================== - -.. toctree:: - :glob: - - * diff --git a/include/bufpool.h b/include/bufpool.h index 1090b31d..e6d0bcea 100644 --- a/include/bufpool.h +++ b/include/bufpool.h @@ -51,7 +51,8 @@ struct bfpentry extern struct bfpentry bfptab[]; /* function prototypes */ -void *bufget(int); +#define bufget(x) bufget_(x, __FILE__, __FUNCTION__) +void *bufget_(int, const char *, const char *); syscall buffree(void *); int bfpalloc(uint, uint); syscall bfpfree(int); diff --git a/include/core.h b/include/core.h new file mode 100644 index 00000000..5cf09998 --- /dev/null +++ b/include/core.h @@ -0,0 +1,20 @@ +/* 2017 Embedded Xinu Team + * core.h + * + * Contains Core Start addresses, semaphores, and CPUID function. +*/ +#ifndef _CORE_H_ +#define _CORE_H_ + +#ifdef _XINU_PLATFORM_ARM_RPI_3_ +#define CORE_MBOX_BASE 0x4000008C +#define CORE_MBOX_OFFSET 0x10 + +extern unsigned int getmode(void); +extern unsigned int getcpuid(void); +extern unsigned int core_init_sp[]; +extern void unparkcore(int, void *, void *); +extern void pld(void *); +extern void pldw(void *); +#endif /* _XINU_PLATFORM_ARM_RPI_3_ */ +#endif /* _CORE_H_ */ diff --git a/include/debug.h b/include/debug.h index 3a652e2c..4d8379e6 100644 --- a/include/debug.h +++ b/include/debug.h @@ -15,5 +15,9 @@ void hexdump(void *buffer, ulong length, bool text); void debugbreak(void); void debugret(void); +void _debug_util(const char *file, const char *func, int line, const char *format, ...); + +//#define DEBUG(msg) kprintf("[DEBUG] %s, line %d: %s\r\n", __FILE__, __LINE__, msg) +#define DEBUG(format, ...) _debug_util(__FILE__, __func__, __LINE__, format, ##__VA_ARGS__) #endif /* _DEBGU_H_ */ diff --git a/include/dma_buf.h b/include/dma_buf.h new file mode 100644 index 00000000..70824fe6 --- /dev/null +++ b/include/dma_buf.h @@ -0,0 +1,21 @@ +/** + * @file dma_buf.h + * Definitions for dma buffer allocation and maintenance. + * + */ +/* Embedded Xinu, Copyright (C) 2019. All rights reserved. */ + +#ifndef _DMA_BUF_H_ +#define _DMA_BUF_H_ + +#include +#include + +extern uint8_t dma_buf_space[]; + +/* DMA buffer function prototypes */ +syscall dma_buf_init(void); +void *dma_buf_alloc(uint); +syscall dma_buf_free(void *, uint); + +#endif /* _DMA_BUF_H_ */ diff --git a/include/framebuffer.h b/include/framebuffer.h index 68fe54c4..cfecd7b9 100644 --- a/include/framebuffer.h +++ b/include/framebuffer.h @@ -10,26 +10,47 @@ #include #include +extern volatile unsigned int mbox[36]; +int mbox_call(unsigned char); + +#define MMIO_BASE 0x3F000000 +#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880) +#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0)) +#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10)) +#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14)) +#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18)) +#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C)) +#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20)) +#define MBOX_RESPONSE 0x80000000 +#define MBOX_FULL 0x80000000 +#define MBOX_EMPTY 0x40000000 +#define MBOX_TAG_LAST 0 + /* Framebuffer specific constants and definitions. */ #define MAILBOX_FULL 0x80000000 // set bit in status register if no space in mailbox #define MAILBOX_EMPTY 0x40000000 // set bit in status register if nothing to read from mailbox -#define MMIO_BASE 0x20000000 // base address for peripherals -#define MAILBOX_CHANNEL 1 // framebuffer uses channel 1; no reason to mess around with anything else +#define MMIO_BASE 0x3F000000 // base address for peripherals + +#define MAILBOX_CH_PROPERTY 8 #define MAILBOX_BASE 0xB880 // base address for mailbox registers -#define MAILBOX_READ 0x00 // the register we read from -#define MAILBOX_WRITE 0x20 //the register we write to -#define MAILBOX_STATUS 0x18 //the status register +#define MBOX_REQUEST 0 +//#define MAILBOX_READ 0x0 // the register we read from +//#define MAILBOX_WRITE 0x8 // the register we write to +//#define MAILBOX_STATUS 0x6 // the status register #define CHAR_WIDTH 8 #define CHAR_HEIGHT 12 + extern unsigned char FONT[]; -#define DEFAULT_HEIGHT 768 -#define DEFAULT_WIDTH 1024 +#define DEFAULT_HEIGHT 768 +#define DEFAULT_WIDTH 1024 #define BIT_DEPTH 32 #define MAXRETRIES 3 //if screen fails to initialize after three tries, halt /* Some basic colors. 8 bits transparency, 8 bits blue, 8 bits green, 8 bits red.*/ + +/* #define WHITE 0xFFFFFFFF #define RED 0xFF0000FF #define GREEN 0xFF00FF00 @@ -50,17 +71,41 @@ extern unsigned char FONT[]; #define PURPLE 0xFF82004B #define BLUEIVY 0xFFC79030 #define PINK 0xFF9000FF - -#define ERRORCOLOR 0x00000000 +*/ + +/* Reformatted colors. 8 bits transparency, 8 bits red, 8 bits green, 8 bits blue. */ + +#define WHITE 0xFFFFFFFF +#define RED 0xFFFF0000 +#define GREEN 0xFF00FF00 +#define BLUE 0xFF0000FF +#define BLACK 0xFF000000 +#define GRAY 0xFF808080 +#define SILVER 0xFFC0C0C0 +#define YELLOW 0xFFFFFF00 +#define CYAN 0xFF00FFFF +#define MAGENTA 0xFFFF00FF +#define INDIGO 0xFF2E0854 +#define DARKBLUE 0xFF0000A0 +#define ORANGE 0xFFFFA500 +#define BROWN 0xFF6F4E37 +#define RASPBERRY 0xFFE30B5C +#define LEAFGREEN 0xFF009900 +#define DARKGREEN 0xFF254117 +#define PURPLE 0xFF4B0082 +#define BLUEIVY 0xFF3090C7 +#define PINK 0xFFFF0090 + +#define ERRORCOLOR 0x00000000 struct defaultcolor { - char *colorname; - ulong colornum; + char *colorname; + ulong colornum; }; /* flip the bytes to get the blue, green, red order and tack on a 255 transparency. */ #define colorconvert(x) ((((((x)& 0xff)<<24) | (((x)>>24) & 0xff) | \ - (((x) & 0xff0000)>>8) | (((x) & 0xff00)<<8)) >> 8) | 0xff000000) + (((x) & 0xff0000)>>8) | (((x) & 0xff00)<<8)) >> 8) | 0xff000000) /* Turtle constants */ #define TURTLE_BODY 0xFF347C2C #define TURTLE_HEAD 0xFF438D80 @@ -108,13 +153,13 @@ extern ulong linemap[]; #define MAXNEWCOMMANDS 10 /* cannot add more than 10 new commands at a time */ struct defaultcommand { - char commandname[COMMANDNAMELENGTH]; - void (*command) (char*); + char commandname[COMMANDNAMELENGTH]; + void (*command) (char*); }; struct newcommand { - char name[COMMANDNAMELENGTH]; - char text[COMMANDLENGTH]; + char name[COMMANDNAMELENGTH]; + char text[COMMANDLENGTH]; }; extern struct newcommand newcommandtab[]; diff --git a/include/network.h b/include/network.h index 2b6c8054..fad514bc 100644 --- a/include/network.h +++ b/include/network.h @@ -17,7 +17,7 @@ */ /* Tracing macros */ -//#define TRACE_NET TTY1 +//#define TRACE_NET SERIAL0 #ifdef TRACE_NET #include #define NET_TRACE(...) { \ diff --git a/include/platform.h b/include/platform.h index f958dbd3..fb1f03f8 100644 --- a/include/platform.h +++ b/include/platform.h @@ -9,6 +9,7 @@ #include #include +#include /** Maximum length of platform name and family strings, including the * null-terminator. */ @@ -39,6 +40,11 @@ struct platform * set by platforminit(). */ void *maxaddr; + /** The ARM Cortex A53 is capable of up to 64KB in L1 data cache. + * The Raspbery Pi 3 Model B+ has L1 cache enabled. This value is obtained + * by platforminit() in reference to the Cortex A53 CCSIDR */ + int dcache_size; + /** Frequency of the system timer in cycles per second. Must be set by * platforminit() if RTCLOCK is enabled. This is the frequency at which the * values returned by clkcount() change. */ diff --git a/include/queue.h b/include/queue.h index 1ff7b7c4..00b9a5f0 100644 --- a/include/queue.h +++ b/include/queue.h @@ -25,11 +25,15 @@ #define _QUEUE_H_ #include +#include + +extern unsigned int getcpuid(void); #ifndef NQENT /** NQENT = 1 per thread, 2 per list, 2 per sem */ -#define NQENT (NTHREAD + 4 + NSEM + NSEM) +#define NQENT (NTHREAD + 4 + 6 + NSEM + NSEM) + #endif #define EMPTY (-2) /**< null pointer for queues */ @@ -49,7 +53,11 @@ struct queent }; extern struct queent quetab[]; -extern qid_typ readylist; +extern qid_typ readylist[]; + +extern mutex_t quetab_mutex; +void quetab_acquire(void); +void quetab_release(void); #define quehead(q) (q) #define quetail(q) ((q) + 1) diff --git a/include/semaphore.h b/include/semaphore.h index 36910e1c..67fe512c 100644 --- a/include/semaphore.h +++ b/include/semaphore.h @@ -8,6 +8,7 @@ #define _SEMAPHORE_H_ #include +#include /* Semaphore state definitions */ #define SFREE 0x01 /**< this semaphore is free */ @@ -27,6 +28,9 @@ struct sement /* semaphore table entry */ }; extern struct sement semtab[]; +extern mutex_t semtab_mutex[]; +void semtab_acquire(semaphore); +void semtab_release(semaphore); /* isbadsem - check validity of reqested semaphore id and state */ #define isbadsem(s) ((s >= NSEM) || (SFREE == semtab[s].state)) diff --git a/include/shell.h b/include/shell.h index d7682df5..2e6f1e4f 100644 --- a/include/shell.h +++ b/include/shell.h @@ -16,28 +16,27 @@ #define SHELL_CMDSTK 8192 /**< size of command proc. stack */ #define SHELL_CMDPRIO 20 /**< command process priority */ -/* Message constants */ -#define SHELL_BANNER_DEFAULT "\n\033[1;31m--------------------------------------\n ____ ___.__ \n \\ \\/ /|__| ____ __ __ \n \\ / | |/ \\| | \\ \n / \\ | | | \\ | / \n /___/\\ \\|__|___| /____/ \n \\_/ \\/ v2.0 \n--------------------------------------\n\033[0;39m\n" +/* Message constants: Updated by the Xinu Team, 2018 + * NONVT100: for platforms that do not support escape codes which provide color. */ -#define SHELL_BANNER_DEFAULT_NONVT100 "--------------------------------------\n ____ ___.__ \n \\ \\/ /|__| ____ __ __ \n \\ / | |/ \\| | \\ \n / \\ | | | \\ | / \n /___/\\ \\|__|___| /____/ \n \\_/ \\/ v3.14 \n--------------------------------------\n\n" +#define SHELL_BANNER_PI3 "\n\033[1;96m _______.\n\033[1;31m------------------------------------------------\033[1;96m/_____./|\033[1;31m------\n ____ ___\033[1;32m.__ \033[1;31m .___ \033[1;32m .__ \033[1;96m | ____ | |\033[1;31m\n \\ \\/ /\033[1;32m|__|\033[1;31m ____ __ __ | _ \\ \033[1;32m|__| \033[1;96m |/ /_| | |\033[1;31m\n \\ / | |/ \\| | \\ | |_| || | \033[1;96m |__ | |\033[1;31m\n / \\ | | | \\ | / | __/ | | \033[1;96m /___| | .\033[1;31m\n /___/\\ \\|__|___| /____/ | | |__| \033[1;96m | ______/\033[1;31m\n \\_/ \\/ |/ \033[1;96m |/ \033[1;32m\n 2019 v3.0 \033[1;31m\n---------------------------------------------------------------\033[0;39m\n" -#define SHELL_BANNER_PI "\n\033[1;31m-----------------------------------------------------\n ____ ___\033[1;32m.__\033[1;31m .___ \033[1;32m.__\033[1;31m\n \\ \\/ /\033[1;32m|__|\033[1;31m ____ __ __ | _ \\ \033[1;32m|__|\033[1;31m\n \\ / | |/ \\| | \\ | |_| || |\n / \\ | | | \\ | / | __/ | |\n /___/\\ \\|__|___| /____/ | | |__|\n \\_/ \\/ |/ v3.14\n-----------------------------------------------------\n\033[0;39m\n" +#define SHELL_BANNER_PI3_NONVT100 "\n _______.\n------------------------------------------------/_____./|------\n ____ ___.__ .___ .__ | ____ | |\n \\ \\/ /|__| ____ __ __ | _ \\ |__| |/ /_| | |\n \\ / | |/ \\| | \\ | |_| || | |__ | |\n / \\ | | | \\ | / | __/ | | /___| | .\n /___/\\ \\|__|___| /____/ | | |__| | ______/\n \\_/ \\/ |/ |/ \n 2019 v3.0 \n---------------------------------------------------------------\n" -#define SHELL_BANNER_PI_NONVT100 "-----------------------------------------------------\n ____ ___.__ .___ .__\n \\ \\/ /|__| ____ __ __ | _ \\ |__|\n \\ / | |/ \\| | \\ | |_| || |\n / \\ | | | \\ | / | __/ | |\n /___/\\ \\|__|___| /____/ | | |__|\n \\_/ \\/ |/ v3.14\n-----------------------------------------------------\n\n" - -#ifdef _XINU_PLATFORM_ARM_RPI_ -# define SHELL_BANNER SHELL_BANNER_PI -# define SHELL_BANNER_NONVT100 SHELL_BANNER_PI_NONVT100 -#else -# define SHELL_BANNER SHELL_BANNER_DEFAULT -# define SHELL_BANNER_NONVT100 SHELL_BANNER_DEFAULT_NONVT100 -#endif +# define SHELL_BANNER SHELL_BANNER_PI3 +# define SHELL_BANNER_NONVT100 SHELL_BANNER_PI3_NONVT100 /** start message */ #define SHELL_START "Welcome to the wonderful world of Xinu!\n" //#define SHELL_START "\033[1;5;37;41mThis is NOT the kernel you are looking for!\033[0;39m\n" #define SHELL_EXIT "Shell closed.\n" /**< exit message */ -#define SHELL_PROMPT "xsh" /**< prompt */ + +#ifdef _XINU_PLATFORM_ARM_RPI_3_ +#define SHELL_PROMPT "\033[1;31mxsh" /**< prompt */ +#else +#define SHELL_PROMPT "xsh" +#endif + #define MAX_PROMPT_LEN 32 /**< basic prompt max length */ #define SHELL_SYNTAXERR "Syntax error.\n" /**< syntax error */ #define SHELL_CHILDERR "Cannot create.\n" /**< command error */ @@ -126,5 +125,6 @@ shellcmd xsh_user(int, char *[]); shellcmd xsh_vlanstat(int, char *[]); shellcmd xsh_voip(int, char *[]); shellcmd xsh_xweb(int, char *[]); +shellcmd xsh_random(int, char *[]); #endif /* _SHELL_H_ */ diff --git a/include/stdio.h b/include/stdio.h index 66616c97..f22ede76 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -10,6 +10,8 @@ #include #include /* For thrtab and thrcurrent. */ +extern unsigned int getcpuid(void); + /* * Standard in/out/err * Note: The C99 specification states that they are macro expansions to a @@ -19,15 +21,15 @@ /** @ingroup libxc * Standard input */ -#define stdin ((thrtab[thrcurrent]).fdesc[0]) +#define stdin ((thrtab[thrcurrent[getcpuid()]]).fdesc[0]) /** @ingroup libxc * Standard output */ -#define stdout ((thrtab[thrcurrent]).fdesc[1]) +#define stdout ((thrtab[thrcurrent[getcpuid()]]).fdesc[1]) /** @ingroup libxc * Standard error */ -#define stderr ((thrtab[thrcurrent]).fdesc[2]) +#define stderr ((thrtab[thrcurrent[getcpuid()]]).fdesc[2]) /* Formatted input */ int _doscan(const char *fmt, va_list ap, diff --git a/include/thread.h b/include/thread.h index dd4c3f4c..6f6eeb43 100644 --- a/include/thread.h +++ b/include/thread.h @@ -13,7 +13,9 @@ #include #include #include -#endif /* __ASSEMBLER__ */ +#include + +extern unsigned int getcpuid(void); /* unusual value marks the top of the thread stack */ #define STACKMAGIC 0x0A0AAAA9 @@ -32,6 +34,9 @@ /* miscellaneous thread definitions */ #define TNMLEN 16 /**< length of thread "name" */ #define NULLTHREAD 0 /**< id of the null thread */ +#define NULLTHREAD1 1 /**< id of secondary null threads */ +#define NULLTHREAD2 2 +#define NULLTHREAD3 3 #define BADTID (-1) /**< used when invalid tid needed */ /* thread initialization constants */ @@ -63,8 +68,6 @@ #define THRENTSIZE 148 #define STKDIVOFFSET 104 -#ifndef __ASSEMBLER__ - /** * Defines what an entry in the thread table looks like. */ @@ -87,7 +90,14 @@ struct thrent extern struct thrent thrtab[]; extern int thrcount; /**< currently active threads */ -extern tid_typ thrcurrent; /**< currently executing thread */ +extern tid_typ thrcurrent[]; /**< currently executing thread */ + +extern unsigned int getcpuid(void); +extern unsigned int core_affinity[]; +extern mutex_t thrtab_mutex[]; + +void thrtab_acquire(tid_typ); +void thrtab_release(tid_typ); /* Inter-Thread Communication prototypes */ syscall send(tid_typ, message); @@ -107,6 +117,7 @@ int resched(void); syscall sleep(uint); syscall unsleep(tid_typ); syscall yield(void); +int ready_multi(tid_typ, unsigned int); /** * @ingroup threads @@ -120,4 +131,4 @@ void userret(void); #endif /* __ASSEMBLER__ */ -#endif /* _THREAD_H_ */ +#endif /* _THREAD_H_ */ diff --git a/include/usb_std_defs.h b/include/usb_std_defs.h index 39263cc6..e6c77f48 100644 --- a/include/usb_std_defs.h +++ b/include/usb_std_defs.h @@ -151,14 +151,14 @@ struct usb_control_setup_data { } __packed; /** Fields that begin every standard USB descriptor. */ -struct usb_descriptor_header { +struct __attribute__((__packed__, aligned(4))) usb_descriptor_header { uint8_t bLength; uint8_t bDescriptorType; -} __packed; +}; /** Standard format of USB device descriptors. See Table 9-8 in 9.6.1 of the * USB 2.0 specification. */ -struct usb_device_descriptor { + struct usb_device_descriptor { uint8_t bLength; uint8_t bDescriptorType; uint16_t bcdUSB; diff --git a/include/usb_util.h b/include/usb_util.h index af02289e..22a22e04 100644 --- a/include/usb_util.h +++ b/include/usb_util.h @@ -26,8 +26,7 @@ struct usb_device; /** Minimum priority for USB messages. Only messages with priority greater than * or equal to this will be printed. */ -#define USB_MIN_LOG_PRIORITY 4 - +#define USB_MIN_LOG_PRIORITY 2 /**********************************************************************/ /** Priority for USB error messages. */ diff --git a/include/usbfs.h b/include/usbfs.h new file mode 100644 index 00000000..2291061b --- /dev/null +++ b/include/usbfs.h @@ -0,0 +1,67 @@ +#ifndef _USBFS_H_ +#define _USBFS_H_ + +#include +#include +#include +#include + +struct usb_xfer_request; +struct usb_device; + +#define USBFS_IFLAG_NOBLOCK 0x0001 /**< do non-blocking input */ +#define USBFS_CTRL_SET_IFLAG 0x0010 /**< set input flags */ +#define USBFS_CTRL_CLR_IFLAG 0x0011 /**< clear input flags */ +#define USBFS_CTRL_GET_IFLAG 0x0012 /**< get input flags */ + +/* Tracing macros */ +#define ENABLE_TRACE_USBFS +#ifdef ENABLE_TRACE_USBFS +# include +# include +# define USBFS_TRACE(...) { \ + kprintf("%s:%d (%d) ", __FILE__, __LINE__, gettid()); \ + kprintf(__VA_ARGS__); \ + kprintf("\r\n"); } +#else +# define USBFS_TRACE(...) +#endif + +#define USBFS_IBLEN 512 +#define USBFS_OBLEN 512 + +devcall usbFsControl(device *devptr, int func, long arg1, long arg2); +devcall usbFsGetc(device *devptr); +devcall usbFsInit(device *devptr); +devcall usbFsPutc(device *devptr, char ch); +devcall usbFsWrite(device *devptr, void *buf, uint len); +void usbFsInterrupt(struct usb_xfer_request *req); +devcall usbFsRead(device *devptr, void *buf, uint len); + +usb_status_t usbFsBindDevice(struct usb_device *dev); +void usbFsUnbindDevice(struct usb_device *dev); + +struct usbfs { + device *phw; + + bool initialized; + bool attached; + uchar iflags; + semaphore isema; + semaphore osema; + uchar istart; + uchar icount; + uchar ostart; + uchar ocount; + uchar in[USBFS_IBLEN]; + uchar out[USBFS_OBLEN]; + struct usb_xfer_request *intr; + struct usb_xfer_request *outr; + + uchar recent_usage_ids[6]; +}; + +extern struct usbfs usbfstab[NUSBFS]; + + +#endif diff --git a/include/xinu.h b/include/xinu.h new file mode 100644 index 00000000..7bad5bb2 --- /dev/null +++ b/include/xinu.h @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/loader/arch/README b/loader/arch/README deleted file mode 100644 index 1dc0671f..00000000 --- a/loader/arch/README +++ /dev/null @@ -1,4 +0,0 @@ -This directory contains CPU-architecture-specific code. - -Note that a CPU architecture may be shared among one or more -Embedded Xinu "platforms" (see ../platforms/ ). diff --git a/loader/arch/mips/start.S b/loader/arch/mips/start.S deleted file mode 100644 index 37c067e3..00000000 --- a/loader/arch/mips/start.S +++ /dev/null @@ -1,284 +0,0 @@ -/** - * @file start.S - * This is where the firmware environment begins to execute code. - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include - -.globl _start - -/** - * The firmware will load the image into temporary - * memory via TFTP and will then jump to this (_start) label. - * The boot loader (_start) flushes L1 instruction and data caches. - */ -_start: - .func _start - /* Clear and invalidate the L1 instruction and data caches */ - jal flushcache - - /* Pass control to Xinu kernel. */ - j _startup - .endfunc - -/** - * Intialize and flush the L1 instruction and data caches. - */ -flushcache: - .func flushcache - - /* Intialize instruction cache */ - - /* - * Register values for following code: - * t0 = CP0_CONFIG - * t1 = CF_I* values - * t2 = index positions - * t3 = associativity - * t4 = number of lines - * t5 = line size - * t6 = I cache size - */ - - /* Obtain Config1 register contents */ - mfc0 t0, CP0_CONFIG, 1 - - /* Obtain CFG_IS */ - srl t1, t0, CONFIG1_IS - andi t1, t1, CONFIG1_MASK - - /* Index positions = 64 * 2^(CFG_IS) */ - li t2, 64 - sll t2, t2, t1 - - /* Obtain CFG_IA */ - srl t1, t0, CONFIG1_IA - andi t1, t1, CONFIG1_MASK - - /* Associativity = CFG_IA + 1*/ - addiu t3, t1, 1 - - /* Number of lines = Associativity * Index positions */ - multu t3, t2 - mflo t4 - - /* Obtain CFG_IL */ - srl t1, t0, CONFIG1_IL - andi t1, t1, CONFIG1_MASK - - /* Line size = 2 * 2^(CFG_IL) */ - li t5, 2 - sll t5, t5, t1 - - /* I cache size = Line size * # of lines */ - multu t5, t4 - mflo t6 - - /* - * Register values for following code: - * t0 = current address - * t1 = ending address - * t4 = number of lines - * t5 = line size - * t6 = I cache size - */ - - /* Clear icache tags to invalidate */ - mtc0 zero, CP0_TAGLO - mtc0 zero, CP0_TAGHI - - li t0, KSEG0_BASE - addu t1, t0, t6 -1: cache INDEX_STORE_TAG_I, 0(t0) - addu t0, t0, t5 - bne t0, t1, 1b - - /* Fill icache once for data field parity */ - li t0, KSEG0_BASE - addu t1, t0, t6 -1: cache FILL_I_CACHE, 0(t0) - addu t0, t0, t5 - bne t0, t1, 1b - - /* Clear tags again--deemed prudent by some */ - li t0, KSEG0_BASE - addu t1, t0, t6 -1: cache INDEX_STORE_TAG_I, 0(t0) - addu t0, t0, t5 - bne t0, t1, 1b - - /* Intialize data cache */ - - /* - * Register values for following code: - * t0 = CP0_CONFIG - * t1 = CF_D* values - * t2 = index positions - * t3 = associativity - * t4 = number of lines - * t5 = line size - * t6 = D cache size - */ - - /* Obtain Config1 register contents */ - mfc0 t0, CP0_CONFIG, 1 - - /* Obtain CFG_DS */ - srl t1, t0, CONFIG1_DS - andi t1, t1, CONFIG1_MASK - - /* Index positions = 64 * 2^(CFG_DS) */ - li t2, 64 - sll t2, t2, t1 - - /* Obtain CFG_DA */ - srl t1, t0, CONFIG1_DA - andi t1, t1, CONFIG1_MASK - - /* Associativity = CFG_DA + 1*/ - addiu t3, t1, 1 - - /* Number of lines = Associativity * Index positions */ - multu t3, t2 - mflo t4 - - /* Obtain CFG_DL */ - srl t1, t0, CONFIG1_DL - andi t1, t1, CONFIG1_MASK - - /* Line size = 2 * 2^(CFG_DL) */ - li t5, 2 - sll t5, t5, t1 - - /* D cache size = Line size * # of lines */ - multu t5, t4 - mflo t6 - - /* - * Register values for following code: - * t0 = current address - * t1 = ending address - * t4 = number of lines - * t5 = line size - * t6 = D cache size - */ - - /* Clear dcache tags to invalidate */ - li t0, KSEG0_BASE - addu t1, t0, t6 -1: cache INDEX_STORE_TAG_I, 0(t0) - addu t0, t0, t5 - bne t0, t1, 1b - - /* Load each line in dcache once */ - li t0, KSEG0_BASE - addu t1, t0, t6 -1: lw t4, 0(t0) - addu t0, t0, t5 - bne t0, t1, 1b - - /* Clear tags again--deemed prudent by some */ - li t0, KSEG0_BASE - addu t1, t0, t6 -1: cache INDEX_STORE_TAG_I, 0(t0) - addu t0, t0, t5 - bne t0, t1, 1b - - jr ra - .endfunc - -#define NULLSTK 8192 - -/** - * _startup sets up the stack pointer and clears the stack for the - * null process. Additionally, the BSS (uninitialized data) section - * is cleared prior to calling the null process. - */ -_startup: - .func _startup - /* Copy IRQ transfer handler to reserved memory location */ - la a0, IRQ_ADDR /* Destination address */ - la a1, intdispatch /* Starting address */ - la a2, (32*4) /* Length of vector */ - jal copyhandler - - /* Clear Xinu-defined trap and interrupt vectors */ - la a0, TRAPVEC_ADDR - la a1, IRQVEC_END - jal memzero - - /* Clear interrupt related registers in the coprocessor */ - mtc0 zero, CP0_STATUS /* Clear interrupt masks */ - mtc0 zero, CP0_CAUSE /* Clear interrupt cause register */ - - /* Clear and invalidate the L1 instruction and data caches */ - jal flushcache - - /* Set up Stack segment (see function summary) */ - li s0, NULLSTK /* Stack is NULLSTK bytes */ - la a0, _end - addu s0, s0, a0 /* Find top of stack (_end + NULLSTK) */ - - /* Word align the top of the stack */ - subu s1, s0, 1 - srl s1, 4 - sll s1, 4 - - /* Initialize the stack and frame pointers */ - move sp, s1 - move fp, s1 - - /* Zero out NULLSTK space below new stack pointer */ - move a1, s0 - jal memzero - - /* Clear the BSS section. */ - la a0, _bss - la a1, _end - jal memzero - - /* Store processor ID */ - mfc0 v0, CP0_PRID - la t0, cpuid - sw v0, 0(t0) - - /* Store bottom of the heap */ - la t0, memheap - sw s0, 0(t0) - - j nulluser /* start the null user process */ - .endfunc - -/** - * @fn void copyhandler(int *dst, int *src, uint bytes) - * Copy text (code) from source to detination (in word-size chunks). - * @param dst location to store the source code - * @param src location holding the source code - * @param bytes size of source code to copy - */ -copyhandler: - .func copyhandler - lw v0, 0(a1) - sw v0, 0(a0) - addiu a1, a1, 4 - addiu a0, a0, 4 - addiu a2, a2, -4 - bgtz a2, copyhandler - jr ra - .endfunc - -/** - * @fn void memzero(int *dstBegin, int *dstEnd) - * Zero memory from dstBegin to dstEnd (non-inclusive). - * @param dstBegin start of the memory area of zero - * @param dstEnd end of the memory area to zero - */ -memzero: - .func memzero - sw zero, 0(a0) - addiu a0, a0, 4 - blt a0, a1, memzero - jr ra - .endfunc diff --git a/loader/platforms/arm-qemu/start.S b/loader/platforms/arm-qemu/start.S deleted file mode 100644 index cf638d76..00000000 --- a/loader/platforms/arm-qemu/start.S +++ /dev/null @@ -1,122 +0,0 @@ -/** - * @file start.S - * - * Initialization code for Embedded Xinu on ARM-QEMU (emulation of an ARM - * Versatile Platform Baseboard). - * - * TODO: This code is mostly duplicated with the corresponding code for the - * Raspberry Pi platform (arm-rpi). The only relevant difference should be the - * address at which the kernel is loaded. - */ -/* Embedded Xinu, Copyright (C) 2013, 2014. All rights reserved. */ - - -#include /* For ARM_MODE_SYS */ - -#define NULLSTK 8192 - -.section .init - .globl _start - - /* _start: Entry point of the Xinu kernel. This will be the very first - * byte of the kernel image and will be loaded by QEMU at address - * 0x10000. */ - .func _start -_start: - /* Save the pointer to the atags (ARM boot tags). The bootloader should - * pass this in r2, but override 0 with 0x100 to deal with old - * bootloaders that assume Linux's default behavior. */ - ldr r3, =atags_ptr - cmp r2, #0 - moveq r2, #0x100 - str r2, [r3] - - /* Continue execution at reset_handler. */ - b reset_handler - .endfunc - -/* ARM exception vector table. This is copied to address 0. See A2.6 - * "Exceptions" of the ARM Architecture Reference Manual. */ -_vectors: - ldr pc, reset_addr /* Reset handler */ - ldr pc, undef_addr /* Undefined instruction handler */ - ldr pc, swi_addr /* Software interrupt handler */ - ldr pc, prefetch_addr /* Prefetch abort handler */ - ldr pc, abort_addr /* Data abort handler */ - ldr pc, reserved_addr /* Reserved */ - ldr pc, irq_addr /* IRQ (Interrupt request) handler */ - ldr pc, fiq_addr /* FIQ (Fast interrupt request) handler */ - -reset_addr: .word reset_handler -undef_addr: .word reset_handler -swi_addr: .word reset_handler -prefetch_addr: .word reset_handler -abort_addr: .word reset_handler -reserved_addr: .word reset_handler -irq_addr: .word irq_handler -fiq_addr: .word reset_handler - -_endvectors: - -.section .text - - /* reset_handler: Reset handler routine executed to start up the kernel, - * when the ARM processor is reset, or (currently) when an unhandled - * exception occurs. */ - .func reset_handler -reset_handler: - - /* Enter SYS mode with all interrupts disabled so the ARM processor is - * in a known state. */ - cpsid if, #ARM_MODE_SYS - - /* Copy the ARM exception table from .init section to address 0, - * including the absolute address table. Here we assume it is exactly - * 16 words. */ - mov r0, #0 - ldr r1, =_vectors - ldmia r1!, {r2-r9} - stmia r0!, {r2-r9} - ldmia r1!, {r2-r9} - stmia r0!, {r2-r9} - - /* Enable the following features by modifying the ARM processor's - * Control Register: - * - * - unaligned memory accesses (bit 22) - * - * Note: Xinu shouldn't do any unaligned memory accesses on purpose, but - * we found that gcc can still generate unaligned memory accesses for - * tasks such as copying character strings. (An alternative would be to - * pass -mno-unaligned-access to gcc to prevent it from doing so.) */ - mrc p15, 0, r0, c1, c0, 0 - orr r0, #1 << 22 - mcr p15, 0, r0, c1, c0, 0 - - /* Clear the .bss section of the kernel. */ - ldr r0, =_bss - ldr r1, =_end - mov r2, #0 - mov r3, #0 - mov r4, #0 - mov r5, #0 - b bssloopa -bssloopb: - stmia r0!, {r2-r5} -bssloopa: - cmp r0, r1 /* check that we still haven't hit the end of bss yet */ - blo bssloopb /* if still below, go backwards and loop */ - - /* Put the null thread's stack directly after the kernel image. */ - add sp, r1, #NULLSTK - - /* The remaining memory available to the ARM will be Xinu's "memheap" - * region, which is used for dynamic memory allocation. Set its - * starting address. */ - ldr r0, =memheap - str sp, [r0] - - /* Branch to the platform-independent C startup code, which takes no - * parameters and never returns. */ - b nulluser - .endfunc diff --git a/loader/platforms/arm-rpi/start.S b/loader/platforms/arm-rpi/start.S deleted file mode 100644 index 9ec8b0fb..00000000 --- a/loader/platforms/arm-rpi/start.S +++ /dev/null @@ -1,121 +0,0 @@ -/** - * @file start.S - * - * Initialization code for Embedded Xinu on the Raspberry Pi. - */ -/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ - - -#include /* For ARM_MODE_SYS */ - -#define NULLSTK 8192 - -.section .init - .globl _start - - /* _start: Entry point of the Xinu kernel. This will be the very first - * byte of the kernel image and on the Raspberry Pi will be loaded by - * the GPU at address 0x8000. */ - .func _start -_start: - /* Save the pointer to the atags (ARM boot tags). The bootloader should - * pass this in r2, but override 0 with 0x100 to deal with old - * bootloaders that assume Linux's default behavior. (This is the case - * with, for example, the bootloader on the BCM2835.) */ - ldr r3, =atags_ptr - cmp r2, #0 - moveq r2, #0x100 - str r2, [r3] - - /* Continue execution at reset_handler. */ - b reset_handler - .endfunc - -/* ARM exception vector table. This is copied to address 0. See A2.6 - * "Exceptions" of the ARM Architecture Reference Manual. */ -_vectors: - ldr pc, reset_addr /* Reset handler */ - ldr pc, undef_addr /* Undefined instruction handler */ - ldr pc, swi_addr /* Software interrupt handler */ - ldr pc, prefetch_addr /* Prefetch abort handler */ - ldr pc, abort_addr /* Data abort handler */ - ldr pc, reserved_addr /* Reserved */ - ldr pc, irq_addr /* IRQ (Interrupt request) handler */ - ldr pc, fiq_addr /* FIQ (Fast interrupt request) handler */ - -reset_addr: .word reset_handler -undef_addr: .word reset_handler -swi_addr: .word reset_handler -prefetch_addr: .word reset_handler -abort_addr: .word reset_handler -reserved_addr: .word reset_handler -irq_addr: .word irq_handler -fiq_addr: .word reset_handler - -_endvectors: - -.section .text - - /* reset_handler: Reset handler routine executed to start up the kernel, - * when the ARM processor is reset, or (currently) when an unhandled - * exception occurs. */ - .func reset_handler -reset_handler: - - /* Enter SYS mode with all interrupts disabled so the ARM processor is - * in a known state. */ - cpsid if, #ARM_MODE_SYS - - /* Copy the ARM exception table from .init section to address 0, - * including the absolute address table. Here we assume it is exactly - * 16 words. */ - mov r0, #0 - ldr r1, =_vectors - ldmia r1!, {r2-r9} - stmia r0!, {r2-r9} - ldmia r1!, {r2-r9} - stmia r0!, {r2-r9} - - /* Enable the following features by modifying the ARM processor's - * Control Register: - * - * - unaligned memory accesses (bit 22) - * - * Note: Xinu shouldn't do any unaligned memory accesses on purpose, but - * we found that gcc can still generate unaligned memory accesses for - * tasks such as copying character strings. (An alternative would be to - * pass -mno-unaligned-access to gcc to prevent it from doing so.) */ - mrc p15, 0, r0, c1, c0, 0 - orr r0, #1 << 22 - mcr p15, 0, r0, c1, c0, 0 - - /* Clear the .bss section of the kernel. */ - ldr r0, =_bss - ldr r1, =_end - mov r2, #0 - mov r3, #0 - mov r4, #0 - mov r5, #0 - b bssloopa -bssloopb: - stmia r0!, {r2-r5} -bssloopa: - cmp r0, r1 /* check that we still haven't hit the end of bss yet */ - blo bssloopb /* if still below, go backwards and loop */ - - /* Put the null thread's stack directly after the kernel image. */ - add sp, r1, #NULLSTK - - /* The remaining memory available to the ARM will be Xinu's "memheap" - * region, which is used for dynamic memory allocation. Set its - * starting address. */ - ldr r0, =memheap - str sp, [r0] - - /* Initialize the Raspberry Pi graphics subsystem. */ - bl screenInit - - /* Branch to the platform-independent C startup code, which takes no - * parameters and never returns. */ - b nulluser - .endfunc diff --git a/loader/platforms/arm-rpi/Makerules b/loader/platforms/arm-rpi3/Makerules similarity index 88% rename from loader/platforms/arm-rpi/Makerules rename to loader/platforms/arm-rpi3/Makerules index 53f48220..73af42cd 100644 --- a/loader/platforms/arm-rpi/Makerules +++ b/loader/platforms/arm-rpi3/Makerules @@ -1,5 +1,5 @@ # Name of this component (the directory this file is stored in) -COMP = loader/platforms/arm-rpi +COMP = loader/platforms/arm-rpi3 # Source files for this component C_FILES = diff --git a/loader/platforms/arm-rpi3/start.S b/loader/platforms/arm-rpi3/start.S new file mode 100644 index 00000000..a48176c7 --- /dev/null +++ b/loader/platforms/arm-rpi3/start.S @@ -0,0 +1,217 @@ +/** + * @file start.S + * + * Initialization code for Embedded Xinu on the Raspberry Pi. + * + * Embedded Xinu, Copyright (C) 2013. All rights reserved. + * + * ----------------------------------------------------------------------------------------- + * + * Specific for Raspberry Pi 3 (BCM2837) - Memory Layout (Not to scale) + * 1GB OF RAM (PHYSICAL MEMORY) AVAILABLE. 1GB == 0x3FFFFFFF + * +----------+ + * | | + * | IO SPACE | -> 0x3F000000 to 0x3FFFFFFF reserved for IO (GPIO, UART, SYS TIMER, USB CORE) + * | | + * +----------+ + * | | + * | | + * | HEAP | -> getmem allocates from here + * | | + * | | + * +----------+ + * | OS STACK | -> becomes the null process' stack + * +----------+ + * | BSS | -> needed for C environment + * +----------+ + * | TEXT | -> XINU code + * | | + * +----------+ + * | RESERVED | -> interrupt handler and vectors go here + * +----------+ + */ + +#include /* For ARM_MODE_SYS */ + +#define NULLSTK 8192 + +.section .init + .globl _start + + /* _start: Entry point of the Xinu kernel. This will be the very first + /* byte of the kernel image and on the Raspberry Pi 3 (32-bit mode) will be loaded by + /* the GPU at address 0x8000. */ + + .func _start +_start: + /* Save the pointer to the atags (ARM boot tags). The Pi 3 *does* pass atags, + * and does so into address 0x100. We access it there, just like the Pi 1. + * The standard protocol for Aarch32 (ARMv8-A) is to pass the atags pointer + * into register r2. We then store it in r3, to be accessed by C code which + * parses the atags. */ + ldr r3, =atags_ptr + cmp r2, #0 + moveq r2, #0x100 + str r2, [r3] + + /* Check if processor is already in SYSTEM mode, + * if it is, jump to reset handler. */ + mrs r0, cpsr + and r0, r0, #0b11111 + cmp r0, #ARM_MODE_SYS + beq reset_handler + + + /* Upon boot, the device loads into HYP (hypervisor) mode, which does not have permission to + * access the CPS opcode. Therefore, to enter the most privelaged mode, + * SYSTEM mode (11111), we first need to enter SUPERVISOR mode. This allows more privelage, + * so that the "cps" opcode may be used to switch to SYSTEM mode. + * First clear bits of CPSR, then enter supervisor mode. Increment the program counter + * by four to skip a 32-bit word. Upon exception return, the CPSR is changed, and + * we are in SUPERVISOR mode. This continues at reset handler, where SYSTEM mode is set. */ + + + /* Go from monitor mode to hypervisor mode */ + /* Required to use exception return method */ + /* Continues execution at line "b reset_handler" */ + mrs r0, cpsr +// bic r0, r0, #ARM_MODE_SYS + orr r0, r0, #ARM_MODE_SYS + msr spsr_cxsf, r0 + add r0, pc, #4 + msr ELR_hyp, r0 + eret + + /* Continue at reset handler. */ + b reset_handler + .endfunc + +/* ARM exception vector table. This is copied to VBAR register. */ +/* Vector table has to be 32-byte aligned. */ +.balign 0x20 +.globl _vectors +_vectors: + ldr pc, reset_addr /* Reset handler */ + ldr pc, undef_addr /* Undefined instruction handler */ + ldr pc, swi_addr /* Software interrupt handler */ + ldr pc, prefetch_addr /* Prefetch abort handler */ + ldr pc, abort_addr /* Data abort handler */ + ldr pc, reserved_addr /* Reserved */ + ldr pc, irq_addr /* IRQ (Interrupt request) handler */ + ldr pc, fiq_addr /* FIQ (Fast interrupt request) handler */ + +reset_addr: .word reset_handler +undef_addr: .word reset_handler +swi_addr: .word reset_handler +prefetch_addr: .word reset_handler +abort_addr: .word reset_handler +reserved_addr: .word reset_handler +irq_addr: .word irq_handler +fiq_addr: .word reset_handler + +_endvectors: + +.section .text + + /* reset_handler: Reset handler routine executed to start up the kernel, + * when the ARM processor is reset, or (currently) when an unhandled + * exception occurs. */ + .func reset_handler +reset_handler: + + /* After entering SUPERVISOR mode, enter SYSTEM mode with all interrupts + * disabled so the ARM processor is in a known state. */ +// cpsid if, #ARM_MODE_SYS + cpsid if + /* Copy the ARM exception table from .init section to address 0, + * including the absolute address table. Here we assume it is exactly + * 16 words. */ + mov r0, #0 + ldr r1, =_vectors + ldmia r1!, {r2-r9} + stmia r0!, {r2-r9} + ldmia r1!, {r2-r9} + stmia r0!, {r2-r9} + + mov r1, #0 + mcr p15, 0, r1, c12, c0, 0 /* Write to VBAR */ + /* Vectors are at address 0x0 */ + + /* Enable the following features by modifying the ARM processor's + * Control Register: + * + * - unaligned memory accesses (bit 22) + * + * Note: Xinu shouldn't do any unaligned memory accesses on purpose, but + * we found that gcc can still generate unaligned memory accesses for + * tasks such as copying character strings. (An alternative would be to + * pass -mno-unaligned-access to gcc to prevent it from doing so.) + */ + + mrc p15, 0, r0, c1, c0, 0 + orr r0, #1 << 22 + mcr p15, 0, r0, c1, c0, 0 + + /* Clear the .bss section of the kernel. */ + ldr r0, =_bss + ldr r1, =_end + mov r2, #0 + mov r3, #0 + mov r4, #0 + mov r5, #0 + b bssloopa + +bssloopb: + stmia r0!, {r2-r5} + +bssloopa: + cmp r0, r1 /* check that we still haven't hit the end of bss yet */ + blo bssloopb /* if still below, go backwards and loop */ + + ldr r3, =core_init_sp + + /* Put the null thread's stack directly after the kernel image. */ + add sp, r1, #NULLSTK /* Core 0 stack pointer */ + str sp, [r3, #0] + + add r0, sp, #NULLSTK /* Core 1 stack pointer */ + str r0, [r3, #4] + + add r1, r0, #NULLSTK /* Core e stack pointer */ + str r1, [r3, #8] + + add r2, r1, #NULLSTK /* Core 3 stack pointer */ + str r2, [r3, #12] + + /* The remaining memory available to the ARM will be Xinu's "memheap" + * region, which is used for dynamic memory allocation. Set its + * starting address. */ + ldr r0, =memheap + str r2, [r0] /* use r2 because this is the last stack allocated for core 3 */ + + + /* Move to ARM register r0 from coprocessor register p15, at op2 5, which is the MPIDR. */ + /* If left shift is zero, start. If not, wait for interrupts in a loop. */ + /* Refer to ARM Cortex-A53 documentation, Section 4.4.1, Table 4-122: */ + /* http://infocenter.arm.com/help/topic/com.arm.doc.ddi0500d/DDI0500D_cortex_a53_r0p2_trm.pdf */ +// mrc p15, 0, r0, c0, c0, 5 +// mov r1, #3 +// and r1, r0, r1 +// cmp r1, #0 + + /* Enable FPU */ + mov r0, #0xf00000 // make cp10 en 11 fully accesible - pi3 - see page 4272 of ARMv8 trm + mcr p15, 0, r0, c1, c0, 2 // Write r0 to CPACR + isb + mov r1, #0x40000000 // Set FPEXC_EN bit to enable the FPU + vmsr FPEXC, r1 + isb + + /* Initialize the Raspberry Pi graphics subsystem */ + bl screenInit + + /* Branch to nulluser function, located in xinu/system/initialize.c + /* The function will initialize the system and become the null thread. */ + b nulluser + .endfunc + diff --git a/loader/platforms/arm-rpi3/start.S~ b/loader/platforms/arm-rpi3/start.S~ new file mode 100644 index 00000000..2043d0cb --- /dev/null +++ b/loader/platforms/arm-rpi3/start.S~ @@ -0,0 +1,310 @@ +/** + * @file start.S + * + * Initialization code for Embedded Xinu on the Raspberry Pi 3. + */ + +/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ + + +#include /* For ARM_MODE_SYS */ + +#define NULLSTK 8192 + +.section .init + .globl _start + + /* _start: Entry point of the Xinu kernel. This will be the very first + * byte of the kernel image and on the Raspberry Pi 3 will be loaded by + * the GPU at address 0x80000. */ + .func _start +_start: + /* Vector table this is a hack so it is at a known address */ + b skip + b hang + b hang + b hang + b hang + b hang + b hang + b hang +.balign 128 + b hang +.balign 128 + b hang +.balign 128 + b hang +.balign 128 + b hang +.balign 128 + b irq_handler +.balign 128 + b hang +.balign 128 + b hang +.balign 128 + b hang +.balign 128 + b irq_handler + + +hang: + b hang + +skip: + // isolate core 0 + mrs x7, mpidr_el1 + mov x8, #0xC1000000 + bic x8, x7, x8 + cbz x8, zero +not_zero: + wfi + b not_zero + +zero: + /* Save the pointer to the atags (ARM boot tags). The bootloader should + * pass this in x0, but override 0 with 0x100 to deal with old + * bootloaders that assume Linux's default behavior. (This is the case + * with, for example, the bootloader on the BCM2837.) */ + ldr x3, =atags_ptr + str x0, [x3] + + /* Set to the correct Exception Level for processor */ + bl el_setter + + /* Continue excecution at reset_handler */ + b reset_handler + .endfunc + +/* ARMv8 exception vector table. */ +_vectors: + /* Current EL with SP0 */ + b sync_addr /* Synchronous */ + .balign 128 + b irq_addr /* IRQ/vIRQ */ + .balign 128 + b fiq_addr /* FIQ/vFIQ */ + .balign 128 + b serr_addr /* SError/vSError */ + .balign 128 + /* Current EL with SPx */ + b sync_addr + .balign 128 + b irq_addr + .balign 128 + b fiq_addr + .balign 128 + b serr_addr + .balign 128 + /* Lower EL using AArch64 */ + b sync_addr + .balign 128 + b irq_addr + .balign 128 + b fiq_addr + .balign 128 + b serr_addr + .balign 128 + /* Lower EL using AArch32 */ + b sync_addr + .balign 128 + b irq_addr + .balign 128 + b fiq_addr + .balign 128 + b serr_addr + +sync_addr: .word reset_handler +irq_addr: .word irq_handler +fiq_addr: .word reset_handler +serr_addr: .word reset_handler + +_endvectors: + +.section .text + +/* el_setter: Sets processor to correct Exception Level (EL1) + * for kernel operation. EL upon boot is EL2, while EL1 is necessary + * for kernel code */ +el_setter: + +/* + // Enable EL2 access to timers + mrs x0, cnthctl_el2 + orr x0, x0, #0x3 + msr cnthctl_el2, x0 + + // Enable EL1 access to timers + mrs x0, cntkctl_el1 + orr x0, x0, #0x3 + msr cntkctl_el1, x0 +*/ + /* Initialize MIDR/MPIDR registers */ +// mrs x0, midr_el1 +// mrs x1, mpidr_el1 +// msr vpidr_el2, x0 +// msr vmpidr_el2, x1 + + /* Disable coprocessor traps */ +// mov x0, #0x33FF +// msr cptr_el2, x0 /* Disable coprocessor traps to EL2 */ +// msr hstr_el2, xzr /* Disable Hyp System Trap */ + + /* Enable FP/SIMD at EL1 */ + mov x0, #3 << 20 /* .FPEN = 0b11, no instructions are trapped */ + msr cpacr_el1, x0 + + /* Initialize HCR_EL2 */ + mov x0, #(1 << 31) /* 64-bit EL1 */ +// orr x0, x0, #(1 << 29) /* Disable HVC */ + /* Route interrupts to EL1 */ + bic x0, x0, #(1 << 5) /* .AMO = 0b0 */ + bic x0, x0, #(1 << 4) /* .IMO = 0b0 */ + bic x0, x0, #(1 << 3) /* .FMO = 0b0 */ + bic x0, x0, #(1 << 27) /* .TGE = 0b0 */ + msr hcr_el2, x0 + + ldr x0, =0x80000 + msr vbar_el1, x0 + + /* SCTLR_EL1 initialization */ + mov x0, #0x0800 + movk x0, #0x30D0, lsl #16 + msr sctlr_el1, x0 + + /* Return to EL1_SP1 mode from EL2 */ + mov x0, sp + msr sp_el1, x0 /* Migrate SP */ + +// mrs x0, vbar_el2 +// msr vbar_el1, x0 /* Migrate VBAR */ + + mov x0, #0x3C5 + msr spsr_el2, x0 /* EL1_SP1 | D | A | I | F */ + msr elr_el2, x30 + + eret + + /* reset_handler: Reset handler routine executed to start up the kernel, + * when the ARM processor is reset, or (currently) when an unhandled + * exception occurs. */ + .func reset_handler +reset_handler: + + +/** + * This function sets up the expected C environment and then runs the null + * process. A major part of the expected C environment is memory + * preparation. The standard XINU executable consists of three main + * segments. (In this context, a 'segment' is a relocatable section, not + * necessarily corresponding to virtual memory segments.) These are: + * Text segment (assembled machine instructions for the program code), + * Data segment (initialized data), and + * BSS ("Block Started by Symbol") segment (uninitialized data). + * The Stack segment provides space for a stack of activation records + * used to implement statically-scoped variables and recursive procedure + * calls in most ALGOL-like languages, including C and all its progeny. + * The BSS is the unitialized data segment produced by the Unix linkers. + * Objects in the BSS segment have only a name and a size, but no value. + * In addition, the running program conceptually also has: + * Stack segment (stack of activation records,) + * Heap segment (area for dynamic memory allocation). + * + * Memory Layout (Not to scale) + * +----------+ + * | | + * | | + * | HEAP | -> getmem allocates from here + * | | + * | | + * +----------+ + * | OS STACK | -> becomes the null process' stack + * +----------+ + * | BSS | -> needed for C environment + * +----------+ + * | TEXT | -> XINU code + * | | + * +----------+ + * | RESERVED | -> interrupt handler and vectors go here + * +----------+ + */ + + /* Clear the .bss section of the kernel. */ + ldr x0, =_bss + ldr x1, =_end + mov x2, #0 + b bssloopa +bssloopb: + str x2, [x0, 8] + str x2, [x0, 16] + str x2, [x0, 24] + str x2, [x0, 32] + add x0, x0, 32 + +bssloopa: + cmp x0, x1 /* check that we still haven't hit the end of bss yet */ + b.lo bssloopb /* if still below, go backwards and loop */ + + + + /* Put the null thread's stack directly after the kernel image. */ + add sp, x1, #NULLSTK + + /* The remaining memory available to the ARM will be Xinu's "memheap" + * region, which is used for dynamic memory allocation. Set its + * starting address. */ + ldr x0, =memheap + mov x1, sp + str x1, [x0] + + /* Put non-used cores in busy wait */ + mrs x7, mpidr_el1 + and x7, x7, #3 + cbz x7, __start_master +0: wfe + b 0b + + + /* Branch to the C environment */ +__start_master: + b nulluser + .endfunc + + +.globl DOWFI +DOWFI: + wfi + ret + +//.globl dmb + +/** + * @fn void dmb(void) + * + * Executes a data memory barrier operation using the c7 (Cache Operations) + * register of system control coprocessor CP15. + * + * All explicit memory accesses occurring in program order before this operation + * will be globally observed before any memory accesses occurring in program + * order after this operation. This includes both read and write accesses. + * + * This differs from a "data synchronization barrier" in that a data + * synchronization barrier will ensure that all previous explicit memory +F + * accesses occurring in program order have fully completed before continuing + * and that no subsequent instructions will be executed until that point, even + * if they do not access memory. This is unnecessary for what we need this for. + * + * On the BCM2835 (Raspberry Pi), this is needed before and after accessing + * peripherals, as documented on page 7 of the "BCM2835 ARM Peripherals" + * document. As documented, it is only needed when switching between + * _different_ peripherals. + */ +/* +dmb: + .func dmb + mov r12, #0 + mcr p15, 0, r12, c7, c10, 5 + mov pc, lr + .endfunc +*/ diff --git a/loader/platforms/e2100l/Makerules b/loader/platforms/e2100l/Makerules deleted file mode 100644 index a1699a23..00000000 --- a/loader/platforms/e2100l/Makerules +++ /dev/null @@ -1,12 +0,0 @@ -# This Makefile contains rules to build files in the loader/ directory. - -# Name of this component (the directory this file is stored in) -COMP = loader/platforms/e2100l - -# Source files for this component -C_FILES = -S_FILES = start.S - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/loader/platforms/e2100l/start.S b/loader/platforms/e2100l/start.S deleted file mode 100644 index 238f4cfa..00000000 --- a/loader/platforms/e2100l/start.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/loader/platforms/mipsel-qemu/Makerules b/loader/platforms/mipsel-qemu/Makerules deleted file mode 100644 index d31a7c8b..00000000 --- a/loader/platforms/mipsel-qemu/Makerules +++ /dev/null @@ -1,12 +0,0 @@ -# This Makefile contains rules to build files in the loader/ directory. - -# Name of this component (the directory this file is stored in) -COMP = loader/platforms/mipsel-qemu - -# Source files for this component -C_FILES = -S_FILES = start.S - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/loader/platforms/mipsel-qemu/start.S b/loader/platforms/mipsel-qemu/start.S deleted file mode 100644 index 238f4cfa..00000000 --- a/loader/platforms/mipsel-qemu/start.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/loader/platforms/wl330ge/Makerules b/loader/platforms/wl330ge/Makerules deleted file mode 100644 index 7652200a..00000000 --- a/loader/platforms/wl330ge/Makerules +++ /dev/null @@ -1,12 +0,0 @@ -# This Makefile contains rules to build files in the loader/ directory. - -# Name of this component (the directory this file is stored in) -COMP = loader/platforms/wl330ge - -# Source files for this component -C_FILES = -S_FILES = start.S - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/loader/platforms/wl330ge/start.S b/loader/platforms/wl330ge/start.S deleted file mode 100644 index 238f4cfa..00000000 --- a/loader/platforms/wl330ge/start.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/loader/platforms/wrt160nl/Makerules b/loader/platforms/wrt160nl/Makerules deleted file mode 100644 index edc693bb..00000000 --- a/loader/platforms/wrt160nl/Makerules +++ /dev/null @@ -1,12 +0,0 @@ -# This Makefile contains rules to build files in the loader/ directory. - -# Name of this component (the directory this file is stored in) -COMP = loader/platforms/wrt160nl - -# Source files for this component -C_FILES = -S_FILES = start.S - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/loader/platforms/wrt160nl/start.S b/loader/platforms/wrt160nl/start.S deleted file mode 100644 index 238f4cfa..00000000 --- a/loader/platforms/wrt160nl/start.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/loader/platforms/wrt54gl/Makerules b/loader/platforms/wrt54gl/Makerules deleted file mode 100644 index cdb852b4..00000000 --- a/loader/platforms/wrt54gl/Makerules +++ /dev/null @@ -1,12 +0,0 @@ -# This Makefile contains rules to build files in the loader/ directory. - -# Name of this component (the directory this file is stored in) -COMP = loader/platforms/wrt54gl - -# Source files for this component -C_FILES = -S_FILES = start.S - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/loader/platforms/wrt54gl/start.S b/loader/platforms/wrt54gl/start.S deleted file mode 100644 index 238f4cfa..00000000 --- a/loader/platforms/wrt54gl/start.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/loader/platforms/x86/Makerules b/loader/platforms/x86/Makerules deleted file mode 100644 index 359084e5..00000000 --- a/loader/platforms/x86/Makerules +++ /dev/null @@ -1,16 +0,0 @@ -# This Makefile contains rules to build files in the loader/ directory. - -# Name of this component (the directory this file is stored in) -COMP = loader/platforms/x86 - -# Source files for this component -C_FILES = -S_FILES = start.S - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} - -${DIR}/start.o: ${DIR}/start.S - $(CC) $(CFLAGS) -DBRELOC=${IMG_START} -o $@ $< - diff --git a/loader/platforms/x86/start.S b/loader/platforms/x86/start.S deleted file mode 100644 index 1a1a6b7e..00000000 --- a/loader/platforms/x86/start.S +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @file start.S - * - */ -/* Embedded XINU, Copyright (C) 2007. All rights reserved. */ - -.text - .align 4 - .globl _start - .extern startup - .extern _end - -_start: - /* disable any interrupts from coming in */ - cli - - movl $_end, %eax # set stack pointer to 64k after end of image - addl $64*1024, %eax - decl %eax # 16-byte align stack pointer - shrl $0x04, %eax - shll $0x04, %eax - movl %eax, %esp # set stack pointer - - jmp startup diff --git a/mailbox/mailboxSend.c b/mailbox/mailboxSend.c index 8b369c99..64cc989e 100644 --- a/mailbox/mailboxSend.c +++ b/mailbox/mailboxSend.c @@ -6,6 +6,7 @@ #include #include #include +#include "../system/platforms/arm-rpi3/mmu.h" /** * @ingroup mailbox diff --git a/network/Makerules b/network/Makerules index 49eb72b5..59453779 100644 --- a/network/Makerules +++ b/network/Makerules @@ -4,7 +4,7 @@ COMP = network # Name of networking modules to include in the built system -NETWORKING = arp dhcpc emulate icmp ipv4 net netaddr route snoop tftp +NETWORKING = arp net dhcpc emulate icmp ipv4 netaddr route snoop tftp DIR = ${TOPDIR}/${COMP} include ${NETWORKING:%=${DIR}/%/Makerules} diff --git a/network/dhcpc/dhcpSendRequest.c b/network/dhcpc/dhcpSendRequest.c index bd91db8b..9e70be40 100644 --- a/network/dhcpc/dhcpSendRequest.c +++ b/network/dhcpc/dhcpSendRequest.c @@ -90,6 +90,7 @@ syscall dhcpSendRequest(int descrp, struct dhcpData *data) *opts++ = DHCP_OPT_END; } while ((optsize = (opts - optarray)) & 3); + /* Get memory for packet */ pkt = netGetbuf(); if (SYSERR == (int)pkt) @@ -168,6 +169,7 @@ syscall dhcpSendRequest(int descrp, struct dhcpData *data) memset(ether->dst, 0xff, ETH_ADDR_LEN); memcpy(ether->src, data->clientHwAddr, ETH_ADDR_LEN); ether->type = hs2net(ETHER_TYPE_IPv4); + if (pktsize == write(descrp, pkt->curr, pktsize)) { retval = OK; diff --git a/shell/Makerules b/shell/Makerules index d502a82b..80c228a2 100644 --- a/shell/Makerules +++ b/shell/Makerules @@ -25,10 +25,12 @@ C_FILES += xsh_uartstat.c C_FILES += xsh_gpiostat.c xsh_led.c # Networking commands -C_FILES += xsh_arp.c xsh_ethstat.c xsh_nc.c xsh_netdown.c xsh_netemu.c xsh_netstat.c xsh_netup.c xsh_ping.c xsh_pktgen.c xsh_rdate.c xsh_route.c xsh_snoop.c xsh_tcpstat.c xsh_telnet.c xsh_telnetserver.c xsh_timeserver.c xsh_udpstat.c xsh_vlanstat.c xsh_voip.c xsh_xweb.c +C_FILES += xsh_arp.c xsh_nc.c xsh_netdown.c xsh_netemu.c xsh_netstat.c xsh_netup.c xsh_ping.c xsh_rdate.c xsh_route.c xsh_snoop.c xsh_tcpstat.c xsh_telnet.c xsh_telnetserver.c xsh_timeserver.c xsh_udpstat.c xsh_voip.c xsh_xweb.c + +#C_FILES += xsh_ethstat.c xsh_pktgen.c xsh_vlanstat.c # TAR commands -C_FILES += xsh_tar.c +#C_FILES += xsh_tar.c # Turtle Graphics commands C_FILES += xsh_turtle.c @@ -42,6 +44,9 @@ C_FILES += xsh_nvram.c # XXX Hack for raspberry pi development, remove this C_FILES += xsh_kexec.c +# XXX Used for raspberry pi 3 development to test random number generator +#C_FILES += xsh_random.c + # USB commands (could be made conditional on USB support if the build system # were to support it...) C_FILES += xsh_usbinfo.c diff --git a/shell/arptest_xshtest_unfinished.c b/shell/arptest_xshtest_unfinished.c new file mode 100644 index 00000000..5023a675 --- /dev/null +++ b/shell/arptest_xshtest_unfinished.c @@ -0,0 +1,887 @@ +/** + * @file test_arp.c + * + */ +/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define failif(cond, failmsg) \ + if ( cond ) { testFail(verbose, failmsg); printf("\t%s:%d\r\n", __FILE__, __LINE__); passed = FALSE; } \ + else { testPass(verbose, ""); } + +#if NETHER + +#ifndef ELOOP +#define ELOOP (-1) +#endif + +extern int _binary_data_testarp_pcap_start; +#define MAX_WAIT 10 + +static thread notifyTest(void) +{ + while (ARP_MSG_RESOLVED != receive()); + return OK; +} + +static thread freeTest(void) +{ + while (TIMEOUT != receive()); + return OK; +} + +static thread lookupTest(uchar *request, int rqlen, uchar *reply, + int rplen) +{ + uchar buf[ELOOP_BUFSIZE]; + control(ELOOP, ELOOP_CTRL_GETHOLD, (int)buf, ELOOP_BUFSIZE); + if (memcmp(buf, request, rqlen) != 0) + { + return SYSERR; + } + write(ELOOP, reply, rplen); + return OK; +} + +#endif /* NETHER */ + +static int test_arp(bool); +shellcmd xsh_test(int nargs, char *args[]) +{ + test_arp(TRUE); + + return 0; +} + +/** + * Tests ARP. + * @return OK when testing is complete + */ +static int test_arp(bool verbose) +{ +#if NETHER + bool passed = TRUE; + int i = 0; + struct netaddr ip; + struct netaddr mask; + struct netaddr praddr; + struct netaddr hwaddr; + struct netaddr addrbuf; + struct pcap_file_header pcap; + struct pcap_pkthdr phdr; + struct packet *pkt; + struct netif *netptr; + struct ethloop *pelp; + uchar *data; + uchar *request; + struct arpPkt *arp; + struct arpEntry *entry; + uchar buf[ELOOP_BUFSIZE]; + int nproc; + int nout; + int wait; + tid_typ tids[ARP_NTHRWAIT]; + tid_typ tid; + irqmask im; + + ip.type = NETADDR_IPv4; + ip.len = IPv4_ADDR_LEN; + ip.addr[0] = 192; + ip.addr[1] = 168; + ip.addr[2] = 1; + ip.addr[3] = 6; + + mask.type = NETADDR_IPv4; + mask.len = IPv4_ADDR_LEN; + mask.addr[0] = 255; + mask.addr[1] = 255; + mask.addr[2] = 255; + mask.addr[3] = 0; + + /* Initialize loopback ethernet and network interface */ + testPrint(verbose, "Test case initialization"); + + data = (uchar *)(&_binary_data_testarp_pcap_start); + memcpy(&pcap, data, sizeof(pcap)); + data += sizeof(pcap); + + if (SYSERR == open(ELOOP)) + { + failif(TRUE, ""); + } + else + { + failif((SYSERR == netUp(ELOOP, &ip, &mask, NULL)), ""); + } + if (!passed) + { + testFail(TRUE, ""); + return OK; + } + + /* Setup pointers to underlying structures */ +#if NNETIF + for (i = 0; i < NNETIF; i++) + { + if ((NET_ALLOC == netiftab[i].state) + && (ELOOP == netiftab[i].dev)) + { + break; + } + } +#endif + netptr = &netiftab[i]; + pelp = &elooptab[devtab[ELOOP].minor]; + + pkt = netGetbuf(); + if ((int)pkt != SYSERR) + { + pkt->nif = netptr; + } + + praddr.type = NETADDR_IPv4; + praddr.len = IPv4_ADDR_LEN; + praddr.addr[0] = 192; + praddr.addr[1] = 168; + praddr.addr[2] = 1; + praddr.addr[3] = 3; + + hwaddr.type = NETADDR_ETHERNET; + hwaddr.len = ETH_ADDR_LEN; + hwaddr.addr[0] = 0xAA; + hwaddr.addr[1] = 0xBB; + hwaddr.addr[2] = 0xCC; + hwaddr.addr[3] = 0xDD; + hwaddr.addr[4] = 0xEE; + hwaddr.addr[5] = 0xFF; + + /* Test arpPkt structure */ + testPrint(verbose, "Header structure (Request)"); + /* Get 1st packet */ + memcpy(&phdr, data, sizeof(phdr)); + data += sizeof(phdr); + if (PCAP_MAGIC != pcap.magic) + { + phdr.caplen = endswap(phdr.caplen); + } + pkt = netGetbuf(); + pkt->len += + ARP_CONST_HDR_LEN + (2 * IPv4_ADDR_LEN) + (2 * ETH_ADDR_LEN); + pkt->curr -= pkt->len; + arp = (struct arpPkt *)pkt->curr; + arp->hwtype = hs2net(ARP_HWTYPE_ETHERNET); + arp->prtype = hs2net(ARP_PRTYPE_IPv4); + arp->hwalen = ETH_ADDR_LEN; + arp->pralen = IPv4_ADDR_LEN; + arp->op = hs2net(ARP_OP_RQST); + memcpy(&arp->addrs[ARP_ADDR_SHA(arp)], netptr->hwaddr.addr, + arp->hwalen); + memcpy(&arp->addrs[ARP_ADDR_SPA(arp)], netptr->ip.addr, arp->pralen); + memcpy(&arp->addrs[ARP_ADDR_DPA(arp)], praddr.addr, arp->pralen); + failif((0 != memcmp(data + ELOOP_LINKHDRSIZE, arp, pkt->len)), ""); + + /* Test arpPkt structure */ + testPrint(verbose, "Header structure (Reply)"); + /* Get 2nd packet */ + data += phdr.caplen; + memcpy(&phdr, data, sizeof(phdr)); + data += sizeof(phdr); + if (PCAP_MAGIC != pcap.magic) + { + phdr.caplen = endswap(phdr.caplen); + } + arp->op = hs2net(ARP_OP_REPLY); + memcpy(&arp->addrs[ARP_ADDR_DHA(arp)], &arp->addrs[ARP_ADDR_SHA(arp)], + arp->hwalen); + arp->addrs[ARP_ADDR_DHA(arp) + ETH_ADDR_LEN - 1] = 0xCC; + memcpy(&arp->addrs[ARP_ADDR_DPA(arp)], praddr.addr, arp->pralen); + memcpy(&arp->addrs[ARP_ADDR_SHA(arp)], netptr->hwaddr.addr, + arp->hwalen); + memcpy(&arp->addrs[ARP_ADDR_SPA(arp)], netptr->ip.addr, arp->pralen); + failif((0 != memcmp(data + ELOOP_LINKHDRSIZE, arp, pkt->len)), ""); + + /* Test arpAlloc, free entry exists */ + testPrint(verbose, "Allocate free entry"); + /* Make first entry used */ + arptab[0].state = ARP_USED; + arptab[0].expires = clktime + ARP_TTL_UNRESOLVED; + entry = arpAlloc(); + failif(((NULL == entry) || (entry == &arptab[0]) + || (0 == (entry->state & ARP_USED))), ""); + + /* Test arpAlloc, free entry exists */ + testPrint(verbose, "Allocate used entry"); + arptab[1].state = ARP_USED; + arptab[1].expires = clktime + 1; + /* Make all entries (except the first 2) have ARP_TTL_RESOLVED */ + for (i = 2; i < ARP_NENTRY; i++) + { + arptab[i].state = ARP_USED; + arptab[i].expires = clktime + ARP_TTL_RESOLVED; + } + entry = arpAlloc(); + failif(((NULL == entry) || (entry != &arptab[1]) + || (0 == (entry->state & ARP_USED))), ""); + + /* Test arpNotify */ + testPrint(verbose, "Notify waiting threads (bad params)"); + failif((SYSERR != arpNotify(NULL, TIMEOUT)), ""); + + /* Test arpNotify */ + testPrint(verbose, "Notify waiting threads"); + entry = &arptab[0]; + entry->state = ARP_UNRESOLVED; + for (i = 0; i < ARP_NTHRWAIT; i++) + { + tid = + create((void *)notifyTest, INITSTK, INITPRIO, "notifyTest", + 0); + tids[i] = tid; + entry->waiting[i] = tid; + entry->count++; + ready(tid, RESCHED_NO); + } + recvclr(); + arpNotify(entry, ARP_MSG_RESOLVED); + nout = FALSE; + nproc = 0; + tid = recvtime(100); + while ((tid != TIMEOUT) && (nproc < ARP_NTHRWAIT)) + { + for (i = 0; i < ARP_NTHRWAIT; i++) + { + if (tid == tids[i]) + { + tids[i] = NULL; + } + } + nproc++; + tid = recvtime(100); + } + for (i = 0; i < ARP_NTHRWAIT; i++) + { + if (tids[i] != NULL) + { + kill(tids[i]); + nout = TRUE; + } + } + failif(nout || (entry->count != 0), ""); + + /* Test arpFree */ + testPrint(verbose, "Free entry (bad params)"); + failif((SYSERR != arpFree(NULL)), ""); + + /* Test arpFree */ + testPrint(verbose, "Free resolved entry"); + entry = &arptab[0]; + entry->state = ARP_RESOLVED; + entry->expires = clktime; + failif(((SYSERR == arpFree(entry)) || (entry->expires != 0)), ""); + + /* Test arpFree */ + testPrint(verbose, "Free unresolved entry"); + entry = &arptab[0]; + entry->state = ARP_UNRESOLVED; + for (i = 0; i < ARP_NTHRWAIT; i++) + { + tid = create((void *)freeTest, INITSTK, INITPRIO, "freeTest", 0); + tids[i] = tid; + entry->waiting[i] = tid; + entry->count++; + ready(tid, RESCHED_NO); + } + recvclr(); + if (SYSERR == arpFree(entry)) + { + failif(TRUE, "Returned SYSERR"); + } + else + { + nout = FALSE; + nproc = 0; + tid = recvtime(100); + while ((tid != TIMEOUT) && (nproc < ARP_NTHRWAIT)) + { + for (i = 0; i < ARP_NTHRWAIT; i++) + { + if (tid == tids[i]) + { + tids[i] = NULL; + } + } + nproc++; + tid = recvtime(100); + } + for (i = 0; i < ARP_NTHRWAIT; i++) + { + if (tids[i] != NULL) + { + kill(tids[i]); + nout = TRUE; + } + } + failif(nout || (entry->count != 0), ""); + } + + /* Test arpGetEntry */ + testPrint(verbose, "Get entry"); + for (i = 0; i < ARP_NENTRY; i++) + { + arpFree(&arptab[i]); + } + nout = 4; + if (ARP_NENTRY < nout) + { + nout = ARP_NENTRY; + } + for (i = 1; i < nout; i++) + { + entry = &arptab[i]; + entry->state = ARP_RESOLVED; + entry->nif = netptr; + praddr.addr[3] = i + 1; + hwaddr.addr[5] = ((i + 0xA) << 4) + (i + 0xA); + netaddrcpy(&entry->hwaddr, &hwaddr); + netaddrcpy(&entry->praddr, &praddr); + entry->expires = clktime + ARP_TTL_RESOLVED; + } + for (i = 1; i < nout; i++) + { + praddr.addr[3] = i + 1; + entry = arpGetEntry(&praddr); + if (entry != &arptab[i]) + { + break; + } + } + failif((i != nout), ""); + + /* Test arpGetEntry with timeout */ + testPrint(verbose, "Get entry (timeout entries)"); + arptab[i].expires = clktime - 1; + praddr.addr[3] = 2; + entry = arpGetEntry(&praddr); + if (entry != &arptab[1]) + { + failif(TRUE, "Incorrect entry"); + } + else + { + failif((arptab[0].state != ARP_FREE), + "Did not free expired entry"); + } + for (i = 0; i < ARP_NENTRY; i++) + { + arpFree(&arptab[i]); + } + + /* Test receive reply for non-existing ARP table entry */ + testPrint(verbose, "Receive ARP reply, new entry"); + /* Get 3rd packet */ + data += phdr.caplen; + memcpy(&phdr, data, sizeof(phdr)); + data += sizeof(phdr); + if (PCAP_MAGIC != pcap.magic) + { + phdr.caplen = endswap(phdr.caplen); + } + praddr.addr[3] = 3; + hwaddr.addr[5] = 0xCC; + nout = pelp->nout; + nproc = netptr->nproc; + write(ELOOP, data, phdr.caplen); + /* Wait until packet is processed */ + wait = 0; + while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) + { + wait++; + sleep(10); + } + if (MAX_WAIT == wait) + { + failif(TRUE, "Wait time expired"); + } + else + { + /* Check entry and ensure reply was not sent */ + entry = NULL; + for (i = 0; i < ARP_NENTRY; i++) + { + if (ARP_RESOLVED == arptab[i].state) + { + entry = &arptab[i]; + break; + } + } + if (NULL == entry) + { + failif(TRUE, "No entry inserted"); + } + else if ((FALSE == netaddrequal(&praddr, &entry->praddr)) + || (FALSE == netaddrequal(&hwaddr, &entry->hwaddr)) + || (entry->nif != netptr) || (entry->count != 0)) + { + failif(TRUE, "Entry incorrect"); + } + else if (pelp->nout > (nout + 1)) + { + failif(TRUE, "Reply sent to reply"); + } + else + { + failif(FALSE, ""); + } + } + + /* Test receive request for non-existing ARP table entry */ + testPrint(verbose, "Receive ARP request, new entry"); + /* Get 4th packet */ + data += phdr.caplen; + memcpy(&phdr, data, sizeof(phdr)); + data += sizeof(phdr); + if (PCAP_MAGIC != pcap.magic) + { + phdr.caplen = endswap(phdr.caplen); + } + praddr.addr[3] = 1; + hwaddr.addr[5] = 0xAA; + nout = pelp->nout; + nproc = netptr->nproc; + im = disable(); + write(ELOOP, data, phdr.caplen); + control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); + restore(im); + /* Wait until packet is processed */ + wait = 0; + while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) + { + wait++; + sleep(100); + } + if (MAX_WAIT == wait) + { + failif(TRUE, "Wait time expired"); + } + else + { + /* Check entry and ensure reply was not sent */ + entry = NULL; + for (i = 0; i < ARP_NENTRY; i++) + { + if ((ARP_RESOLVED == arptab[i].state) + && (netaddrequal(&praddr, &arptab[i].praddr))) + { + entry = &arptab[i]; + break; + } + } + if (NULL == entry) + { + failif(TRUE, "No entry inserted"); + } + else if ((FALSE == netaddrequal(&praddr, &entry->praddr)) + || (FALSE == netaddrequal(&hwaddr, &entry->hwaddr)) + || (entry->nif != netptr) || (entry->count != 0)) + { + failif(TRUE, "Entry incorrect"); + } + else + { + control(ELOOP, ELOOP_CTRL_GETHOLD, (int)buf, ELOOP_BUFSIZE); + /* Get 5th packet */ + data += phdr.caplen; + memcpy(&phdr, data, sizeof(phdr)); + data += sizeof(phdr); + if (PCAP_MAGIC != pcap.magic) + { + phdr.caplen = endswap(phdr.caplen); + } + failif((memcmp(data, buf, phdr.caplen) != 0), + "Invalid reply"); + } + } + + /* Test receive request for non-supported hardware type */ + testPrint(verbose, "Receive ARP request, bad HW type"); + /* Get 6th packet */ + data += phdr.caplen; + memcpy(&phdr, data, sizeof(phdr)); + data += sizeof(phdr); + if (PCAP_MAGIC != pcap.magic) + { + phdr.caplen = endswap(phdr.caplen); + } + praddr.addr[3] = 2; + hwaddr.addr[5] = 0xBB; + nproc = netptr->nproc; + write(ELOOP, data, phdr.caplen); + /* Wait until packet is processed */ + wait = 0; + while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) + { + wait++; + sleep(100); + } + if (MAX_WAIT == wait) + { + failif(TRUE, "Wait time expired"); + } + else + { + /* Ensure entry was not added */ + entry = NULL; + for (i = 0; i < ARP_NENTRY; i++) + { + if ((ARP_RESOLVED == arptab[i].state) + && (netaddrequal(&praddr, &arptab[i].praddr))) + { + entry = &arptab[i]; + break; + } + } + failif((entry != NULL), "Entry inserted"); + } + + /* Test receive reply for non-supported protocol type */ + testPrint(verbose, "Receive ARP reply, bad protocol type"); + /* Get 7th packet */ + data += phdr.caplen; + memcpy(&phdr, data, sizeof(phdr)); + data += sizeof(phdr); + if (PCAP_MAGIC != pcap.magic) + { + phdr.caplen = endswap(phdr.caplen); + } + nproc = netptr->nproc; + write(ELOOP, data, phdr.caplen); + /* Wait until packet is processed */ + wait = 0; + while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) + { + wait++; + sleep(100); + } + if (MAX_WAIT == wait) + { + failif(TRUE, "Wait time expired"); + } + else + { + /* Ensure entry was not added */ + entry = NULL; + for (i = 0; i < ARP_NENTRY; i++) + { + if ((ARP_RESOLVED == arptab[i].state) + && (netaddrequal(&praddr, &arptab[i].praddr))) + { + entry = &arptab[i]; + break; + } + } + failif((entry != NULL), "Entry inserted"); + } + + /* Test receive reply for existing resolved ARP table entry */ + testPrint(verbose, "Receive ARP reply, resolved entry"); + /* Get 8th packet */ + data += phdr.caplen; + memcpy(&phdr, data, sizeof(phdr)); + data += sizeof(phdr); + if (PCAP_MAGIC != pcap.magic) + { + phdr.caplen = endswap(phdr.caplen); + } + praddr.addr[3] = 3; + hwaddr.addr[5] = 0x0C; + nout = pelp->nout; + nproc = netptr->nproc; + write(ELOOP, data, phdr.caplen); + /* Wait until packet is processed */ + wait = 0; + while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) + { + wait++; + sleep(100); + } + if (MAX_WAIT == wait) + { + failif(TRUE, "Wait time expired"); + } + else + { + /* Check entry */ + entry = NULL; + for (i = 0; i < ARP_NENTRY; i++) + { + if ((ARP_RESOLVED == arptab[i].state) + && (netaddrequal(&praddr, &arptab[i].praddr))) + { + entry = &arptab[i]; + break; + } + } + failif((FALSE == netaddrequal(&hwaddr, &entry->hwaddr)), + "Entry incorrect"); + } + + /* Test receive request not for me */ + testPrint(verbose, "Receive ARP request, not mine"); + /* Get 9th packet */ + data += phdr.caplen; + memcpy(&phdr, data, sizeof(phdr)); + data += sizeof(phdr); + if (PCAP_MAGIC != pcap.magic) + { + phdr.caplen = endswap(phdr.caplen); + } + praddr.addr[3] = 4; + hwaddr.addr[5] = 0xDD; + nproc = netptr->nproc; + write(ELOOP, data, phdr.caplen); + /* Wait until packet is processed */ + wait = 0; + while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) + { + wait++; + sleep(100); + } + if (MAX_WAIT == wait) + { + failif(TRUE, "Wait time expired"); + } + else + { + /* Ensure entry was not added */ + entry = NULL; + for (i = 0; i < ARP_NENTRY; i++) + { + if ((ARP_RESOLVED == arptab[i].state) + && (netaddrequal(&praddr, &arptab[i].praddr))) + { + entry = &arptab[i]; + break; + } + } + failif((entry != NULL), "Entry inserted"); + } + + /* Test arpSendRequest */ + testPrint(verbose, "Send ARP request (bad params)"); + failif((SYSERR != arpSendRqst(NULL)), ""); + + /* Test arpSendRequest */ + testPrint(verbose, "Send ARP request"); + /* Get 10th packet */ + data += phdr.caplen; + memcpy(&phdr, data, sizeof(phdr)); + data += sizeof(phdr); + if (PCAP_MAGIC != pcap.magic) + { + phdr.caplen = endswap(phdr.caplen); + } + entry = &arptab[0]; + entry->state = ARP_UNRESOLVED; + entry->nif = netptr; + praddr.addr[3] = 2; + hwaddr.addr[5] = 0xBB; + netaddrcpy(&entry->hwaddr, &hwaddr); + netaddrcpy(&entry->praddr, &praddr); + entry->expires = clktime + ARP_TTL_UNRESOLVED; + control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); + if (SYSERR == arpSendRqst(entry)) + { + failif(TRUE, "Returned SYSERR"); + } + else + { + control(ELOOP, ELOOP_CTRL_GETHOLD, (int)buf, ELOOP_BUFSIZE); + failif((memcmp(buf, data, phdr.caplen) != 0), ""); + } + + /* Test arpLookup */ + testPrint(verbose, "Lookup address (bad params)"); + failif((SYSERR != arpLookup(NULL, NULL, NULL)), ""); + + /* Test arpLookup */ + testPrint(verbose, "Lookup existing resolved address"); + for (i = 0; i < ARP_NENTRY; i++) + { + arpFree(&arptab[i]); + } + entry = &arptab[0]; + entry->state = ARP_RESOLVED; + entry->nif = netptr; + praddr.addr[3] = 1; + hwaddr.addr[5] = 0xAA; + netaddrcpy(&entry->hwaddr, &hwaddr); + netaddrcpy(&entry->praddr, &praddr); + entry->expires = clktime + ARP_TTL_UNRESOLVED; + i = arpLookup(netptr, &praddr, &addrbuf); + if ((SYSERR == i) || (TIMEOUT == i)) + { + failif(TRUE, "Returned SYSERR or TIMEOUT"); + } + else + { + failif((FALSE == netaddrequal(&addrbuf, &hwaddr)), + "Wrong address"); + } + + /* Test arpLookup */ + testPrint(verbose, "Lookup existing unresolved address"); + entry = &arptab[1]; + entry->state = ARP_UNRESOLVED; + entry->nif = netptr; + praddr.addr[3] = 2; + hwaddr.addr[5] = 0xBB; + netaddrcpy(&entry->hwaddr, &hwaddr); + netaddrcpy(&entry->praddr, &praddr); + entry->expires = clktime + ARP_TTL_UNRESOLVED; + control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); + request = data; + wait = phdr.caplen; + /* Get 11th packet */ + data += phdr.caplen; + memcpy(&phdr, data, sizeof(phdr)); + data += sizeof(phdr); + if (PCAP_MAGIC != pcap.magic) + { + phdr.caplen = endswap(phdr.caplen); + } + tid = + ready(create + ((void *)lookupTest, INITSTK, INITPRIO, "lookupTest", 4, + request, wait, data, phdr.caplen), RESCHED_NO); + i = arpLookup(netptr, &praddr, &addrbuf); + if ((SYSERR == i) || (TIMEOUT == i)) + { + kill(tid); + failif(TRUE, "Returned SYSERR or TIMEOUT"); + } + else + { + failif((FALSE == netaddrequal(&addrbuf, &hwaddr)), + "Wrong address"); + } + + /* Test arpLookup */ + testPrint(verbose, "Lookup max threads wait for resolve"); + entry->state = ARP_UNRESOLVED; + entry->count = ARP_NTHRWAIT; + failif((arpLookup(netptr, &praddr, &addrbuf) != SYSERR), ""); + + /* Test arpLookup */ + testPrint(verbose, "Lookup non-existing unresolved addr"); + praddr.addr[3] = 3; + hwaddr.addr[5] = 0xCC; + control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); + request = data; + wait = phdr.caplen; + /* Get 12th packet */ + data += phdr.caplen; + memcpy(&phdr, data, sizeof(phdr)); + data += sizeof(phdr); + if (PCAP_MAGIC != pcap.magic) + { + phdr.caplen = endswap(phdr.caplen); + } + request = data; + wait = phdr.caplen; + /* Get 13th packet */ + data += phdr.caplen; + memcpy(&phdr, data, sizeof(phdr)); + data += sizeof(phdr); + if (PCAP_MAGIC != pcap.magic) + { + phdr.caplen = endswap(phdr.caplen); + } + tid = + ready(create + ((void *)lookupTest, INITSTK, INITPRIO, "lookupTest", 4, + request, wait, data, phdr.caplen), RESCHED_NO); + i = arpLookup(netptr, &praddr, &addrbuf); + if ((SYSERR == i) || (TIMEOUT == i)) + { + kill(tid); + failif(TRUE, "Returned SYSERR or TIMEOUT"); + } + else + { + failif((FALSE == netaddrequal(&addrbuf, &hwaddr)), + "Wrong address"); + } + + /* Test arpLookup */ + testPrint(verbose, "Lookup timeout"); + praddr.addr[3] = 4; + hwaddr.addr[5] = 0xDD; + control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_DROPALL, NULL); + failif((SYSERR != arpLookup(netptr, &praddr, &addrbuf)), ""); + + /* Stop loopback ethernet and network interface */ + testPrint(verbose, "Test case cleanup"); + for (i = 0; i < ARP_NENTRY; i++) + { + arpFree(&arptab[i]); + } + failif(((SYSERR == netFreebuf(pkt)) || (SYSERR == netDown(ELOOP)) + || (SYSERR == close(ELOOP))), ""); + + if (passed) + { + testPass(TRUE, ""); + } + else + { + testFail(TRUE, ""); + } +#else /* NETHER */ + testSkip(TRUE, ""); +#endif /* NETHER == 0 */ + + return OK; +} + +void testFail(bool verbose, const char *msg) +{ + if (TRUE == verbose) + { + kprintf("\033[60G[\033[1;31mFAIL\033[0;39m] %s\n", msg); + } +} + +void testSkip(bool verbose, const char *msg) +{ + if (TRUE == verbose) + { + kprintf("\033[60G[\033[1;33mSKIP\033[0;39m] %s\n", msg); + } +} + +void testPrint(bool verbose, const char *msg) +{ + if (TRUE == verbose) + { + kprintf(" %s", msg); + } +} + +void testPass(bool verbose, const char *msg) +{ + if (TRUE == verbose) + { + kprintf("\033[60G[\033[1;32mPASS\033[0;39m] %s\n", msg); + } +} + diff --git a/shell/shell.c b/shell/shell.c index 54b97557..5fa87c32 100644 --- a/shell/shell.c +++ b/shell/shell.c @@ -27,7 +27,7 @@ const struct centry commandtab[] = { {"dumptlb", FALSE, xsh_dumptlb}, #endif #if NETHER - {"ethstat", FALSE, xsh_ethstat}, + //{"ethstat", FALSE, xsh_ethstat}, #endif {"exit", TRUE, xsh_exit}, #if NFLASH @@ -61,8 +61,15 @@ const struct centry commandtab[] = { {"ps", FALSE, xsh_ps}, #if NETHER {"ping", FALSE, xsh_ping}, - {"pktgen", FALSE, xsh_pktgen}, - {"rdate", FALSE, xsh_rdate}, + //{"pktgen", FALSE, xsh_pktgen}, +#endif + +#ifdef _XINU_PLATFORM_ARM_RPI_3_ +//XXX {"random", TRUE, xsh_random}, +#endif + +#if NETHER + {"rdate", FALSE, xsh_rdate}, #endif {"reset", FALSE, xsh_reset}, #if NETHER @@ -73,19 +80,19 @@ const struct centry commandtab[] = { {"snoop", FALSE, xsh_snoop}, #endif #if USE_TAR - {"tar", FALSE, xsh_tar}, +// {"tar", FALSE, xsh_tar}, #endif #if NETHER {"tcpstat", FALSE, xsh_tcpstat}, - {"telnet", FALSE, xsh_telnet}, - {"telnetserver", FALSE, xsh_telnetserver}, + //XXX{"telnet", FALSE, xsh_telnet}, + //XXX{"telnetserver", FALSE, xsh_telnetserver}, #endif - {"test", FALSE, xsh_test}, +//XXX {"test", FALSE, xsh_test}, #if HAVE_TESTSUITE {"testsuite", TRUE, xsh_testsuite}, #endif #if NETHER - {"timeserver", FALSE, xsh_timeserver}, + //XXX{"timeserver", FALSE, xsh_timeserver}, #endif #if FRAMEBUF {"turtle", FALSE, xsh_turtle}, @@ -101,15 +108,15 @@ const struct centry commandtab[] = { #endif #if NETHER {"udpstat", FALSE, xsh_udpstat}, - {"vlanstat", FALSE, xsh_vlanstat}, - {"voip", FALSE, xsh_voip}, - {"xweb", FALSE, xsh_xweb}, + //XXX{"vlanstat", FALSE, xsh_vlanstat}, + //XXX{"voip", FALSE, xsh_voip}, + //XXX{"xweb", FALSE, xsh_xweb}, #endif {"?", FALSE, xsh_help} }; ulong ncommand = sizeof(commandtab) / sizeof(struct centry); -extern ulong foreground; +//XXXextern ulong foreground; /** * @ingroup shell @@ -167,36 +174,50 @@ thread shell(int indescrp, int outdescrp, int errdescrp) stderr = errdescrp; /* Print shell banner to framebuffer, if exists */ -#if defined(FRAMEBUF) if (indescrp == FRAMEBUF) { - foreground = RASPBERRY; - printf(SHELL_BANNER_NONVT100); - foreground = LEAFGREEN; + foreground = CYAN; + printf(SHELL_BANNER_PI3_NONVT100); + udelay(250); // Temporarily wait for the hardware before changing colors + foreground = LEAFGREEN; printf(SHELL_START); - foreground = GREEN; } else -#endif { - printf(SHELL_BANNER); + printf(SHELL_BANNER_PI3); printf(SHELL_START); } /* Continually receive and handle commands */ while (TRUE) { - /* Display prompt */ - printf(SHELL_PROMPT); + if (indescrp == FRAMEBUF) + { + /* Print shell with colors over the frame buffer */ + foreground = RASPBERRY; + printf(SHELL_PROMPT_FB); + foreground = WHITE; + } + else + { + /* Display prompt using standard ANSI terminal coloring */ + printf(SHELL_PROMPT); + } if (NULL != hostptr) { - printf("@%s$ ", hostptr); - } + if (indescrp == FRAMEBUF) + printf("@%s$ ", hostptr); + else + printf("@%s$ \033[0;39m", hostptr); + } else { - printf("$ "); - } + if (indescrp == FRAMEBUF) + printf("$ "); + else + printf("$ \033[0;39m"); + } /* Setup proper tty modes for input and output */ control(stdin, TTY_CTRL_CLR_IFLAG, TTY_IRAW, NULL); @@ -339,6 +360,8 @@ thread shell(int indescrp, int outdescrp, int errdescrp) continue; } + thrtab_acquire(child); + /* Set file descriptors for newly created thread */ if (NULL == inname) { @@ -358,6 +381,8 @@ thread shell(int indescrp, int outdescrp, int errdescrp) } thrtab[child].fdesc[2] = stderr; + thrtab_release(child); + if (background) { /* Make background thread ready, but don't reschedule */ @@ -375,7 +400,10 @@ thread shell(int indescrp, int outdescrp, int errdescrp) /* Wait for command thread to finish */ while (receive() != child); +#ifndef _XINU_PLATFORM_ARM_RPI_3_ /* sleeps for 10 seconds on the RPI 3... not desirable */ + /* maybe needed for other platforms.. not sure */ sleep(10); +#endif } } diff --git a/shell/testcases.c b/shell/testcases.c new file mode 100644 index 00000000..c36e1df0 --- /dev/null +++ b/shell/testcases.c @@ -0,0 +1,383 @@ +/** + * @file testcases.c + * @provides testcases + * + * + * Modified by: + * + * TA-BOT:MAILTO + * + */ +/* Embedded XINU, Copyright (C) 2007. All rights reserved. */ + +#include + +/** + * Prints the contents of the specified queue + */ +void +ostest_printQueue(qid_typ q) +{ + short head, tail, next, extent; + kprintf("Queue(0x%08X) =\r\n", q); + + head = queuehead(q); + tail = queuetail(q); + next = head; + + extent = NQENT; + + while ((next < NQENT) && (next != tail) && (extent)) + { + kprintf(" [%3d|%3d:%3d]\r\n", next, queuetab[next].prev, queuetab[next].next); + next = queuetab[next].next; + extent--; + } + if (!extent) + { + kprintf(" ...Loop detected in Queue!\r\n"); + } + else + { + kprintf(" [%3d|%3d:%3d]\r\n", tail, queuetab[tail].prev, queuetab[tail].next); + } +} + +/** + * A test process for priority testing + */ +int +testprocE(void) +{ + /* print nothing, do nothing */ + return 0; +} + +/** + * Print the pid of a process + * @param times the number of repititions + */ +int +printTestPid(int times) +{ + int i = 0; + uint cpuid = getcpuid(); + + for (i = 0; i < times; i++) + { + kprintf("This is process %d \r\n", currpid[cpuid]); + + resched(); + } +} + +/** + * Create two simple processes and run them. + * If process B gets to run, it was not starved, + * and aging has been implemented successfully. + */ +void +testStarvation(void) +{ + ready(create((void *) printTestPid, INITSTK, PRIORITY_MED , "PROCESS-A", 1, 10), 0, 0); + ready(create((void *) printTestPid, INITSTK, PRIORITY_LOW , "PROCESS-B", 1, 5), 0, 0); +} + +/** + * testprocF and G are used for testing preemption + */ +void +testprocF(void) +{ + uint cpuid = getcpuid(); + + enable(); + kprintf("Process %d never yields.\r\n", currpid[cpuid]); + while (TRUE) + ; +} + +void +testprocG(pid_typ pid) +{ + uint cpuid = getcpuid(); + + enable(); + irqmask ps; + + ps = disable(); + kprintf("Process %d preempted process %d.\r\n", currpid[cpuid], pid); + + /* Kill all processes before system hangs up */ + kill(pid); + kill(currpid[cpuid]); + + restore(ps); +} + + +/** + * testcases - called after initialization completes to test things. + */ +void testcases(void) +{ + uchar c; + pid_typ pid, pid2; + irqmask im; + + im = disable(); + + kprintf("===TEST BEGIN===\r\n"); + + proctab[10].state = PRSUSP; + proctab[11].state = PRSUSP; + proctab[12].state = PRSUSP; + + // TODO: Test your operating system! + + c = kgetc(); + switch (c) + { + /* Testing prioritize in isolation. */ + case 'a': + ostest_printQueue(readylist[0][PRIORITY_LOW]); + + kprintf("Add [10:PRIORITY_LOW] to queue\r\n"); + + proctab[10].priority = PRIORITY_LOW; + ready(10, 0, 0); + + /* Print queue */ + ostest_printQueue(readylist[0][PRIORITY_LOW]); + + remove(10); + break; + + case 'b': + ostest_printQueue(readylist[0][PRIORITY_LOW]); + ostest_printQueue(readylist[0][PRIORITY_MED]); + + kprintf("Add [10:PRIORITY_LOW] to queue\r\n"); + proctab[10].priority = PRIORITY_LOW; + ready(10, 0, 0); + + kprintf("Add [11:PRIORITY_MED] to queue\r\n"); + proctab[11].priority = PRIORITY_MED; + ready(11, 0, 0); + + ostest_printQueue(readylist[0][PRIORITY_LOW]); + ostest_printQueue(readylist[0][PRIORITY_MED]); + + + remove(10); + remove(11); + + break; + + case 'c': + ostest_printQueue(readylist[0][PRIORITY_LOW]); + ostest_printQueue(readylist[0][PRIORITY_MED]); + + kprintf("Add [10:PRIORITY_MED] to queue\r\n"); + proctab[10].priority = PRIORITY_MED; + ready(10, 0, 0); + + kprintf("Add [11:PRIORITY_LOW] to queue\r\n"); + proctab[11].priority = PRIORITY_LOW; + ready(11, 0, 0); + + ostest_printQueue(readylist[0][PRIORITY_LOW]); + ostest_printQueue(readylist[0][PRIORITY_MED]); + + + remove(10); + remove(11); + + case 'd': + ostest_printQueue(readylist[0][PRIORITY_LOW]); + ostest_printQueue(readylist[0][PRIORITY_MED]); + ostest_printQueue(readylist[0][PRIORITY_HIGH]); + + kprintf("Add [10:PRIORITY_LOW] to queue\r\n"); + proctab[10].priority = PRIORITY_LOW; + ready(10, 0, 0); + + kprintf("Add [11:PRIORITY_MED] to queue\r\n"); + proctab[11].priority = PRIORITY_MED; + ready(11, 0, 0); + + kprintf("Add [12:PRIORITY_HIGH] to queue\r\n"); + proctab[12].priority = PRIORITY_HIGH; + ready(12, 0, 0); + + ostest_printQueue(readylist[0][PRIORITY_LOW]); + ostest_printQueue(readylist[0][PRIORITY_MED]); + ostest_printQueue(readylist[0][PRIORITY_HIGH]); + + remove(10); + remove(11); + remove(12); + + break; + + case 'e': + ostest_printQueue(readylist[0][PRIORITY_LOW]); + ostest_printQueue(readylist[0][PRIORITY_MED]); + ostest_printQueue(readylist[0][PRIORITY_HIGH]); + + kprintf("Add [10:PRIORITY_HIGH] to queue\r\n"); + proctab[10].priority = PRIORITY_HIGH; + ready(10, 0, 0); + + kprintf("Add [11:PRIORITY_MED] to queue\r\n"); + proctab[11].priority = PRIORITY_MED; + ready(11, 0, 0); + + kprintf("Add [12:PRIORITY_MED] to queue\r\n"); + proctab[12].priority = PRIORITY_MED; + ready(12, 0, 0); + + ostest_printQueue(readylist[0][PRIORITY_LOW]); + ostest_printQueue(readylist[0][PRIORITY_MED]); + ostest_printQueue(readylist[0][PRIORITY_HIGH]); + + remove(10); + remove(11); + remove(12); + + break; + + case 'f': + ostest_printQueue(readylist[0][PRIORITY_LOW]); + ostest_printQueue(readylist[0][PRIORITY_MED]); + ostest_printQueue(readylist[0][PRIORITY_HIGH]); + + kprintf("Add [10:PRIORITY_LOW] to queue\r\n"); + proctab[10].priority = PRIORITY_LOW; + ready(10, 0, 0); + + kprintf("Add [11:PRIORITY_LOW] to queue\r\n"); + proctab[11].priority = PRIORITY_LOW; + ready(11, 0, 0); + + kprintf("Add [12:PRIORITY_LOW] to queue\r\n"); + proctab[12].priority = PRIORITY_LOW; + ready(12, 0, 0); + + ostest_printQueue(readylist[0][PRIORITY_LOW]); + ostest_printQueue(readylist[0][PRIORITY_MED]); + ostest_printQueue(readylist[0][PRIORITY_HIGH]); + + remove(10); + remove(11); + remove(12); + + break; + + case 'g': + ostest_printQueue(readylist[0][PRIORITY_LOW]); + ostest_printQueue(readylist[0][PRIORITY_MED]); + ostest_printQueue(readylist[0][PRIORITY_HIGH]); + + kprintf("Add [10:PRIORITY_MED] to queue\r\n"); + proctab[10].priority = PRIORITY_MED; + ready(10, 0, 0); + + kprintf("Add [11:PRIORITY_MED] to queue\r\n"); + proctab[11].priority = PRIORITY_MED; + ready(11, 0, 0); + + kprintf("Add [12:PRIORITY_MED] to queue\r\n"); + proctab[12].priority = PRIORITY_MED; + ready(12, 0, 0); + + ostest_printQueue(readylist[0][PRIORITY_LOW]); + ostest_printQueue(readylist[0][PRIORITY_MED]); + ostest_printQueue(readylist[0][PRIORITY_HIGH]); + + remove(10); + remove(11); + remove(12); + + break; + + case 'h': + ostest_printQueue(readylist[0][PRIORITY_LOW]); + ostest_printQueue(readylist[0][PRIORITY_MED]); + ostest_printQueue(readylist[0][PRIORITY_HIGH]); + + kprintf("Add [10:PRIORITY_HIGH] to queue\r\n"); + proctab[10].priority = PRIORITY_HIGH; + ready(10, 0, 0); + + kprintf("Add [11:PRIORITY_HIGH] to queue\r\n"); + proctab[11].priority = PRIORITY_HIGH; + ready(11, 0, 0); + + kprintf("Add [12:PRIORITY_HIGH] to queue\r\n"); + proctab[12].priority = PRIORITY_HIGH; + ready(12, 0, 0); + + ostest_printQueue(readylist[0][PRIORITY_LOW]); + ostest_printQueue(readylist[0][PRIORITY_MED]); + ostest_printQueue(readylist[0][PRIORITY_HIGH]); + + remove(10); + remove(11); + remove(12); + + break; + + case 'i': + break; + + /* Starvation */ + case 'j': +#if AGING + kprintf("Testing starvation with AGING = TRUE\r\n"); +#else + kprintf("Testing starvation with AGING = FALSE\r\n"); +#endif + testStarvation(); + break; + + /* Preemption */ + case 'k': + enable(); + + /* This process normally would never yield */ + pid = + create((void *) testprocF, INITSTK, PRIORITY_HIGH, "Evil Proc", 0); + + /* This process should run if preemption works */ + pid2 = + create((void *) testprocG, INITSTK, PRIORITY_HIGH, "Pwning Proc", + 1, pid); + + ready(pid, RESCHED_NO, 0); + ready(pid2, RESCHED_YES, 0); + + break; + + default: + kprintf("Unknown test %c.\r\n", c); + break; + } + + while (numproc > 4) + { + resched(); + } + + kprintf("\r\n===TEST END===\r\n"); + + proctab[10].state = PRFREE; + proctab[11].state = PRFREE; + proctab[12].state = PRFREE; + + kprintf("\r\n\r\nAll user processes have completed.\r\n\r\n"); + while (1) + ; + + return; +} diff --git a/shell/xsh_clear.c b/shell/xsh_clear.c index 7c0ad2be..fee1a6e0 100644 --- a/shell/xsh_clear.c +++ b/shell/xsh_clear.c @@ -7,6 +7,7 @@ #include #include #include +#include /** * @ingroup shell @@ -38,6 +39,12 @@ shellcmd xsh_clear(int nargs, char *args[]) return 1; } - printf("\033[2J\033[H\n"); + if (screen_initialized){ + screenClear(background); + cursor_row = 0; + } + else{ + printf("\033[2J\033[H\n"); + } return 0; } diff --git a/shell/xsh_exit.c b/shell/xsh_exit.c index addfdd57..496ff639 100644 --- a/shell/xsh_exit.c +++ b/shell/xsh_exit.c @@ -41,7 +41,7 @@ shellcmd xsh_exit(int nargs, char *args[]) } printf(SHELL_EXIT); - sleep(10); + sleep(1); kill(gettid()); return 0; diff --git a/shell/xsh_kexec.c b/shell/xsh_kexec.c index cbf0c906..5aa464d4 100644 --- a/shell/xsh_kexec.c +++ b/shell/xsh_kexec.c @@ -140,6 +140,7 @@ static void kexec_from_network(int netdev) /* Ensure the DHCP server provided the boot filename and TFTP server IP * address. */ + printf("data.bootfile: %s\n", data.bootfile); if ('\0' == data.bootfile[0] || 0 == data.next_server.type) { fprintf(stderr, "ERROR: DHCP server did not provide boot file " @@ -177,6 +178,7 @@ static void kexec_from_network(int netdev) data.bootfile, str_ip); kernel = (void*)tftpGetIntoBuffer(data.bootfile, &nif->ip, &data.next_server, &size); + printf("kernel=0x%08X, *kernel=0x%08X\n", (uint)kernel, *(uint *)kernel); if (SYSERR == (int)kernel) { @@ -187,7 +189,7 @@ static void kexec_from_network(int netdev) /* Execute the new kernel. */ printf("Executing new kernel (size=%u)\n", size); sleep(100); /* Wait just a fraction of a second for printf()s to finish - (no guarantees though). */ + (no guarantees though). */ kexec(kernel, size); fprintf(stderr, "ERROR: kexec() returned!\n"); diff --git a/shell/xsh_nc.c b/shell/xsh_nc.c index 344812a8..0b2e6816 100644 --- a/shell/xsh_nc.c +++ b/shell/xsh_nc.c @@ -175,13 +175,22 @@ shellcmd xsh_nc(int nargs, char *args[]) fprintf(stderr, "Failed to spawn threads"); return 1; } + + thrtab_acquire(recvthr); + thrtab[recvthr].fdesc[0] = stdin; thrtab[recvthr].fdesc[1] = stdout; thrtab[recvthr].fdesc[2] = stderr; + + thrtab_release(recvthr); + thrtab_acquire(sendthr); + thrtab[sendthr].fdesc[0] = stdin; thrtab[sendthr].fdesc[1] = stdout; thrtab[sendthr].fdesc[2] = stderr; + thrtab_release(sendthr); + /* Start both threads */ while (recvclr() != NOMSG); ready(recvthr, RESCHED_YES); diff --git a/shell/xsh_netup.c b/shell/xsh_netup.c index 8674f36d..c7618d84 100644 --- a/shell/xsh_netup.c +++ b/shell/xsh_netup.c @@ -196,7 +196,7 @@ shellcmd xsh_netup(int nargs, char *args[]) printf("Trying DHCP on %s...\n", devname); /* Wait at most 10 seconds before timing out. */ - result = dhcpClient(descrp, 10, &data); + result = dhcpClient(descrp, 10, &data); if (TIMEOUT == result) { diff --git a/shell/xsh_random.c b/shell/xsh_random.c new file mode 100644 index 00000000..11a2c12e --- /dev/null +++ b/shell/xsh_random.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#ifdef _XINU_PLATFORM_ARM_RPI_3_ +#include +#endif + +static void usage(const char *command); + +#define DEFAULT_MIN 0 +#define DEFAULT_MAX 999999 + +shellcmd xsh_random(int nargs, char *args[]) +{ +#ifdef _XINU_PLATFORM_ARM_RPI_3_ + unsigned int min, max, rand; + + if (2 == nargs && 0 == strcmp(args[1], "--help")) + { + usage(args[0]); + return SHELL_OK; + } + + if (nargs > 3) + { + fprintf(stderr, "ERROR: Too many arguments.\n"); + usage(args[0]); + return SHELL_ERROR; + } + + if (nargs == 3) + { + min = atoi(args[1]); + max = atoi(args[2]); + if (min > max) + { + fprintf(stderr, "ERROR: Minimum is greater than maximum.\n"); + usage(args[0]); + return SHELL_ERROR; + } + } + else if (nargs == 2) + { + min = DEFAULT_MIN; + max = atoi(args[1]); + } + else + { + min = DEFAULT_MIN; + max = DEFAULT_MAX; + } + + rand = random() % (max - min) + min; + printf("%u\n", rand); + return SHELL_OK; +#else + fprintf(stderr, "ERROR: Command not compatible with this platform\n"); + return SHELL_ERROR; +#endif /* _XINU_PLATFORM_ARM_RPI_3_ */ +} + +static void usage(const char *command) +{ + printf( +"Usage: %s \n\n" +"Description:\n" +"\tGenerate a random number.\n" +"Options:\n" +"\t An optional argument, specifies the minimum number to be generated.\n" +"\t Required argument, specifies the maximum number to be generated.\n" + , command); +} diff --git a/shell/xsh_snoop.c b/shell/xsh_snoop.c index 8d27c205..156af487 100644 --- a/shell/xsh_snoop.c +++ b/shell/xsh_snoop.c @@ -330,9 +330,11 @@ shellcmd xsh_snoop(int nargs, char *args[]) } /* Use same stdin, stdout, and sterr as this thread */ + thrtab_acquire(tid); thrtab[tid].fdesc[0] = thrtab[gettid()].fdesc[0]; thrtab[tid].fdesc[1] = thrtab[gettid()].fdesc[1]; thrtab[tid].fdesc[2] = thrtab[gettid()].fdesc[2]; + thrtab_release(tid); /* Start output thread */ recvclr(); diff --git a/shell/xsh_telnetserver.c b/shell/xsh_telnetserver.c index ea2b16c3..d9ec23a5 100644 --- a/shell/xsh_telnetserver.c +++ b/shell/xsh_telnetserver.c @@ -15,6 +15,7 @@ #include #include #include +#include #if NETHER static int argErr(char *command, char *arg) @@ -140,7 +141,7 @@ shellcmd xsh_telnetserver(int nargs, char *args[]) TELNET_TRACE("Spawning %s on %d", thrname, spawntelnet - TELNET0); ready(create((void *)telnetServer, INITSTK, INITPRIO, thrname, 4, descrp, port, spawntelnet, "SHELL2"), - RESCHED_YES); + RESCHED_YES, CORE_ZERO); } #endif diff --git a/shell/xsh_test.c b/shell/xsh_test.c index 4a8f6eaa..6e2b7d68 100644 --- a/shell/xsh_test.c +++ b/shell/xsh_test.c @@ -6,7 +6,15 @@ #include #include - +#include +#include +#include +#include +#include +#include +#include +#include +#include /** * @ingroup shell @@ -19,7 +27,186 @@ * @param args array of arguments * @return non-zero value on error */ + +struct thrent *ppcb = NULL; +int testmain(int argc, char **argv) +{ + uint cpuid = getcpuid(); + int i = 0; + kprintf("\r\n********=======********\r\n"); + + resched(); + + struct thrent *thr = &thrtab[thrcurrent[cpuid]]; + + for (i = 0; i < 10; i++) + { +// resched(); + kprintf("NAME: %s\tTID: %d\tCore: %d\r\n", thr->name, thrcurrent[cpuid], cpuid); + + /* Uncomment the resched() line for cooperative scheduling. */ +// resched(); + } + return 0; +} + +void printQueue(qid_typ q) +{ + int next, tail; + + next = quetab[quehead(q)].next; + tail = quetail(q); + while (next != tail) + { + kprintf("[%d : %d,%d : %d]\r\n", quetab[next].prev, next, quetab[next].key, quetab[next].next); + next = quetab[next].next; + } +} + +void printpcb(int pid) +{ + struct thrent *ppcb = NULL; + + /* Using the process ID, access it in the PCB table. */ + ppcb = &thrtab[pid]; + + /* Printing PCB */ + kprintf("Process name : %s \r\n", ppcb->name); + + switch (ppcb->state) + { + case THRFREE: + kprintf("State of the process : FREE \r\n"); + break; + case THRCURR: + kprintf("State of the process : CURRENT \r\n"); + break; + case THRSUSP: + kprintf("State of the process : SUSPENDED \r\n"); + break; + case THRREADY: + kprintf("State of the process : READY \r\n"); + break; + default: + kprintf("ERROR: Process state not correctly set!\r\n"); + break; + } + + /* Print PCB contents and registers */ + kprintf("Base of run time stack : 0x%08X \r\n", ppcb->stkbase); + kprintf("Stack length of process : %8u \r\n", ppcb->stklen); +} + shellcmd xsh_test(int nargs, char *args[]) { - return 0; + int c, pid; + int pids[12]; + + kprintf("0) Test creation of one process\r\n"); + kprintf("1) Test passing of many args\r\n"); + kprintf("2) Create three processes and run them\r\n"); + kprintf("3) Create three processes and run them on other cores\r\n"); + kprintf("4) Single-core Priority Scheduling\r\n"); + kprintf("5) Multicore Priority Scheduling (RESCHED_YES)\r\n"); + kprintf("6) Multicore Priority Scheduling (RESCHED_NO)\r\n"); + + kprintf("===TEST BEGIN===\r\n"); + + // TODO: Test your operating system! + + device *devptr; + devptr = (device *)&devtab[SERIAL0]; + c = kgetc(devptr); + switch (c) + { + case '0': + // Process creation testcase + pid = create((void *)testmain, INITSTK, 2, "MAIN1", 0, NULL); + printpcb(pid); + break; + + case '1': + // Many arguments testcase + //pid = create((void *)testbigargs, INITSTK, 2, "MAIN1", 8, + // 0x11111111, 0x22222222, 0x33333333, 0x44444444, + // 0x55555555, 0x66666666, 0x77777777, 0x88888888); + printpcb(pid); + // TODO: print out stack with extra args + // TODO: ready(pid, RESCHED_YES, 0); + break; + + case '2': + // Create three copies of a process, and let them play. + ready(create((void *)testmain, INITSTK, 2, "MAIN1", 0, NULL), RESCHED_NO , 0); + ready(create((void *)testmain, INITSTK, 2, "MAIN2", 0, NULL), RESCHED_NO , 0); + ready(create((void *)testmain, INITSTK, 2, "MAIN3", 0, NULL), RESCHED_YES, 0); + break; + + case '3': + // Create 3 processes and ready them on cores 1, 2, 3 + ready(create((void *)testmain, INITSTK, 2, "MAIN1", 0, NULL), RESCHED_NO, 1); + ready(create((void *)testmain, INITSTK, 2, "MAIN2", 0, NULL), RESCHED_NO, 2); + //break; + ready(create((void *)testmain, INITSTK, 2, "MAIN3", 0, NULL), RESCHED_NO, 3); + break; + case '4': + //priority scheduling on the same core; expected output: A, then B or D, end with C + ready(create((void *)testmain, INITSTK, 1, "MAIN A", 0, NULL), RESCHED_NO, 0); + ready(create((void *)testmain, INITSTK, 2, "MAIN B", 0, NULL), RESCHED_NO, 0); + ready(create((void *)testmain, INITSTK, 3, "MAIN C", 0, NULL), RESCHED_NO, 0); + ready(create((void *)testmain, INITSTK, 2, "MAIN D", 0, NULL), RESCHED_NO, 0); + break; + case '5': + //create 3 processes on each core with different priorities; resched on + ready(create((void *)testmain, INITSTK, 1, "PRIORITY1", 0, NULL), RESCHED_YES, 0); + ready(create((void *)testmain, INITSTK, 2, "PRIORITY2", 0, NULL), RESCHED_YES, 0); + ready(create((void *)testmain, INITSTK, 3, "PRIORITY3", 0, NULL), RESCHED_YES, 0); + + ready(create((void *)testmain, INITSTK, 1, "PRIORITY1", 0, NULL), RESCHED_YES, 1); + ready(create((void *)testmain, INITSTK, 2, "PRIORITY2", 0, NULL), RESCHED_YES, 1); + ready(create((void *)testmain, INITSTK, 3, "PRIORITY3", 0, NULL), RESCHED_YES, 1); + + ready(create((void *)testmain, INITSTK, 1, "PRIORITY1", 0, NULL), RESCHED_YES, 2); + ready(create((void *)testmain, INITSTK, 2, "PRIORITY2", 0, NULL), RESCHED_YES, 2); + ready(create((void *)testmain, INITSTK, 3, "PRIORITY3", 0, NULL), RESCHED_YES, 2); + + ready(create((void *)testmain, INITSTK, 1, "PRIORITY1", 0, NULL), RESCHED_YES, 3); + ready(create((void *)testmain, INITSTK, 2, "PRIORITY2", 0, NULL), RESCHED_YES, 3); + ready(create((void *)testmain, INITSTK, 3, "PRIORITY3", 0, NULL), RESCHED_YES, 3); + + break; + case '6': + //create 3 processes on each core with different priorities, resched off + ready(create((void *)testmain, INITSTK, 1, "PRIORITY1", 0, NULL), RESCHED_NO, 0); + ready(create((void *)testmain, INITSTK, 2, "PRIORITY2", 0, NULL), RESCHED_NO, 0); + ready(create((void *)testmain, INITSTK, 3, "PRIORITY3", 0, NULL), RESCHED_NO, 0); + + ready(create((void *)testmain, INITSTK, 1, "PRIORITY1", 0, NULL), RESCHED_NO, 1); + ready(create((void *)testmain, INITSTK, 2, "PRIORITY2", 0, NULL), RESCHED_NO, 1); + ready(create((void *)testmain, INITSTK, 3, "PRIORITY3", 0, NULL), RESCHED_NO, 1); + + ready(create((void *)testmain, INITSTK, 1, "PRIORITY1", 0, NULL), RESCHED_NO, 2); + ready(create((void *)testmain, INITSTK, 2, "PRIORITY2", 0, NULL), RESCHED_NO, 2); + ready(create((void *)testmain, INITSTK, 3, "PRIORITY3", 0, NULL), RESCHED_NO, 2); + + ready(create((void *)testmain, INITSTK, 1, "PRIORITY1", 0, NULL), RESCHED_NO, 3); + ready(create((void *)testmain, INITSTK, 2, "PRIORITY2", 0, NULL), RESCHED_NO, 3); + ready(create((void *)testmain, INITSTK, 3, "PRIORITY3", 0, NULL), RESCHED_NO, 3); + +#if 0 + for (int i = 0; i < 4; i++) + { + kprintf("readylist[%d] dump:\r\n", i); + printQueue(readylist[i]); + kprintf("\r\n"); + } +#endif + break; + default: + break; + } + + kprintf("\r\n===TEST END===\r\n"); + return; } + diff --git a/shell/xsh_testsuite.c b/shell/xsh_testsuite.c index 570a0925..c1ae6276 100644 --- a/shell/xsh_testsuite.c +++ b/shell/xsh_testsuite.c @@ -14,6 +14,7 @@ #include #include #include +#include static void testItem(int, bool); static void help(char *command); @@ -99,13 +100,15 @@ static void testItem(int testnum, bool verbose) testtab[testnum].name, (verbose ? "\n" : "")); /* set file descriptors */ + thrtab_acquire(child); thrtab[child].fdesc[0] = stdin; thrtab[child].fdesc[1] = stdout; thrtab[child].fdesc[2] = stderr; + thrtab_release(child); /* Clear waiting message; Reschedule; */ while (recvclr() != NOMSG); - ready(child, RESCHED_YES); + ready(child, RESCHED_YES, CORE_ZERO); /* Wait for command process to finish */ while (receive() != child); diff --git a/system/Makerules b/system/Makerules index d6024839..4ca8238f 100644 --- a/system/Makerules +++ b/system/Makerules @@ -6,19 +6,23 @@ COMP = system # Source files for this component # Important system components -C_FILES = initialize.c queue.c +C_FILES = initialize.c queue.c main.c # Files for process control -C_FILES += create.c kill.c ready.c resched.c resume.c suspend.c chprio.c getprio.c queue.c getitem.c queinit.c insert.c gettid.c xdone.c yield.c userret.c +C_FILES += create.c kill.c ready.c resched.c resume.c suspend.c queue.c getitem.c queinit.c insert.c gettid.c xdone.c yield.c userret.c +C_FILES += ready.c resched.c queue.c getitem.c insert.c getprio.c # Files for system timer and preemption -C_FILES += clkinit.c clkhandler.c mdelay.c udelay.c insertd.c sleep.c unsleep.c wakeup.c +C_FILES += clkinit.c clkhandler.c mdelay.c insertd.c sleep.c +C_FILES += unsleep.c wakeup.c -# Files for semaphores -C_FILES += semcreate.c semfree.c semcount.c signal.c signaln.c wait.c +C_FILES += udelay.c +# Files for semaphores +C_FILES += signal.c signaln.c wait.c semcreate.c semfree.c semcount.c + # Files for monitors -C_FILES += moncreate.c monfree.c moncount.c lock.c unlock.c +#C_FILES += moncreate.c monfree.c moncount.c lock.c unlock.c # Files for memory management C_FILES += memget.c memfree.c stkget.c bfpalloc.c bfpfree.c bufget.c buffree.c @@ -27,17 +31,21 @@ C_FILES += memget.c memfree.c stkget.c bfpalloc.c bfpfree.c bufget.c buffree.c C_FILES += send.c receive.c recvclr.c recvtime.c # Files for device drivers -C_FILES += close.c control.c getc.c open.c ioerr.c ionull.c read.c putc.c seek.c write.c getdev.c +C_FILES += close.c control.c getc.c +C_FILES += ioerr.c ionull.c read.c putc.c seek.c write.c getdev.c open.c # Files for system debugging C_FILES += debug.c # Files for MiniJava Compiler -C_FILES += minijava.c +#C_FILES += minijava.c # Files for reading tape archives C_FILES += tar.c +# Files for dma buffer management +C_FILES += dma_buf.c + # Add the files to the compile source path DIR = ${TOPDIR}/${COMP} COMP_SRC += ${C_FILES:%=${DIR}/%} diff --git a/system/arch/mips/clkupdate.S b/system/arch/mips/clkupdate.S deleted file mode 100644 index 65b7fe7a..00000000 --- a/system/arch/mips/clkupdate.S +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @file clkupdate.S - * Platform-dependent code for clock interrupt maintenance. - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include - -.globl clkupdate -.globl clkcount - -/** - * @fn void clkupdate(ulong cycles) - * - * Normal case: COMPARE is increased by cycles and stored. - * Abnormal case: We've lost so much time COUNT > COMPARE+cycles. - * Solution: Set COMPARE to COUNT+cycles - */ -clkupdate: - .set noreorder - mfc0 v0, CP0_COMPARE /* v0 = COMPARE */ - mfc0 v1, CP0_COUNT /* v1 = COUNT */ - addu v0, v0, a0 /* v0 = COMPARE + cycles */ - bleu v0, v1, compare_up /* v0 <= COUNT, then goto compare_up */ - nop - jr ra - mtc0 v0, CP0_COMPARE /* Update COMPARE */ - .set reorder - -/* we've missed too many cycles, update COMPARE */ -compare_up: - .set noreorder - addu a0, v1, a0 /* a0 = COUNT + cycles */ - jr ra - mtc0 a0, CP0_COMPARE /* COMPARE = a0 */ - .set reorder - -/** - * @fn void clkcount(void) - * Return free-running clock count. - */ -clkcount: - mfc0 v0, CP0_COUNT - jr ra - diff --git a/system/arch/mips/ctxsw.S b/system/arch/mips/ctxsw.S deleted file mode 100644 index d3367e13..00000000 --- a/system/arch/mips/ctxsw.S +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @file ctxsw.S - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include - -.globl ctxsw - -/*------------------------------------------------------------------------ - * ctxsw - Switch from one thread context to another. - *------------------------------------------------------------------------ - */ -ctxsw: - .func ctxsw - - /* Update address space ID */ - mtc0 a2, CP0_ENTRYHI - /* build context record on stack */ - addiu sp, sp, -CONTEXT - sw ra, CONTEXT-4(sp) - sw ra, CONTEXT-8(sp) - /* save callee-save ("non-volatile") registers */ - sw s0, S0_CON(sp) - sw s1, S1_CON(sp) - sw s2, S2_CON(sp) - sw s3, S3_CON(sp) - sw s4, S4_CON(sp) - sw s5, S5_CON(sp) - sw s6, S6_CON(sp) - sw s7, S7_CON(sp) - sw s8, S8_CON(sp) - sw s9, S9_CON(sp) - /* save outgoing stack pointer */ - sw sp, 0(a0) - /* load incoming stack pointer */ - lw sp, 0(a1) - /* restore callee-save ("non-volatile") registers */ - lw s0, S0_CON(sp) - lw s1, S1_CON(sp) - lw s2, S2_CON(sp) - lw s3, S3_CON(sp) - lw s4, S4_CON(sp) - lw s5, S5_CON(sp) - lw s6, S6_CON(sp) - lw s7, S7_CON(sp) - lw s8, S8_CON(sp) - lw s9, S9_CON(sp) - /* restore argument registers */ - lw a0, CONTEXT(sp) - lw a1, CONTEXT+4(sp) - lw a2, CONTEXT+8(sp) - lw a3, CONTEXT+12(sp) - /* tear down context record and return */ - lw v0, CONTEXT-4(sp) - lw ra, CONTEXT-8(sp) - addiu sp, sp, CONTEXT - - beq v0, ra, ctxdone - mfc0 v1, CP0_STATUS - ori v1, v1, STATUS_IE - mtc0 v1, CP0_STATUS - -ctxdone: - jr v0 - .endfunc diff --git a/system/arch/mips/debugbreak.S b/system/arch/mips/debugbreak.S deleted file mode 100644 index a722a0e9..00000000 --- a/system/arch/mips/debugbreak.S +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @file debugbreak.S - * Give access to the assembly debug breakpoint command that drops - * straight into debug mode. - */ - -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include - -.text -.align 4 -.set mips32 - -/** - * @fn debugbreak - * - * Inserts breakpoint and drops into debug mode. - * Stores return address to DEPC register and jumps - * back to it if processor returns from breakpoint. - */ -.globl debugbreak -debugbreak: - .set noreorder - sdbbp - nop - jr ra - nop - .set reorder diff --git a/system/arch/mips/debugret.S b/system/arch/mips/debugret.S deleted file mode 100644 index d66e6fca..00000000 --- a/system/arch/mips/debugret.S +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @file debugret.s - * Gives userret functionality of killing thread with additional - * no-op at beginning for GDB - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - - .section .mdebug.abi32 - .previous - .text - .align 2 - .globl debugret - .globl debugretstart - -/** - * @fn debugretstart - * prefixed no-op for GDB compatibility - */ -debugretstart: - .ent debugretstart - nop - .end debugretstart -/** - * @fn debugret - * kills thread in same fashion as userret - */ -debugret: - .ent debugret - .frame $fp,24,$31 # vars= 0, regs= 2/0, args= 16, gp= 0 - .mask 0xc0000000,-4 - .fmask 0x00000000,0 - nop - addiu $sp,$sp,-24 - sw $31,20($sp) - sw $fp,16($sp) - move $fp,$sp - jal gettid - move $4,$2 - jal kill - move $sp,$fp - lw $31,20($sp) - lw $fp,16($sp) - addiu $sp,$sp,24 - j $31 - .end debugret - .size debugret, .-debugret - .ident "GCC: (GNU) 4.2.0" diff --git a/system/arch/mips/exception.c b/system/arch/mips/exception.c deleted file mode 100644 index ad7e61e3..00000000 --- a/system/arch/mips/exception.c +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @file exception.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include -#include - -const char *exceptions[] = { - "Int, Interrupt", - "Mod, TLB modification exception", - "TLBL, TLB exception (load or instruction fetch)", - "TLBS, TLB exception (store)", - "AdEL, Address error exception (load or instruction fetch)", - "AdES, Address error exception (store)", - "IBE, Bus error exception (instruction fetch)", - "DBE, Bus error exception (data reference: load or store)", - "Sys, Syscall exception", - "Bp, Breakpoint exception", - "RI, Reserved instruction exception", - "CpU, Coprocessor Unusable exception", - "Ov, Arithmetic Overflow exception", - "Tr, Trap Exception", - "Reserved", - "FPE, Floating point exception", - "Reserved", - "Reserved", - "C2E, Reserved for precise Coprocessor 2 exceptions", - "Reserved", - "Reserved", - "Reserved", - "MDMX, MDMX Unusuable in MIPS64", - "WATCH, Reference to WatchHi/WatchLo address", - "MCheck, Machine Check", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "CacheErr, Cache error / Debug Mode", - "Reserved" -}; - -/** - * Exception handler. - * - * @param cause contents of the cause register to decode exception - * @param frame pointer to the interrupt frame with saved status - * - */ -void exception(long cause, long *frame) -{ - ushort exccode = 0; - - exccode = (cause & CAUSE_EXC) >> CAUSE_EXC_SHIFT; - - kprintf("Xinu Exception 0x%04X, %s\r\n", cause, exceptions[exccode]); - - kprintf("Faulting address: 0x%08X\r\n", frame[(IRQREC_EPC) / 4]); - - kprintf - ("[0x%08X] lo:0x%08X hi:0x%08X cau:0x%08X sta:0x%08X\r\n", - frame + 32, frame[IRQREC_LO / 4], - frame[IRQREC_HI / 4], frame[IRQREC_CAUSE / 4], - frame[IRQREC_STATUS / 4]); - kprintf - ("[0x%08X] s8:0x%08X sp:0x%08X s9:0x%08X ra:0x%08X\r\n", - frame + 28, frame[IRQREC_S8 / 4], - frame[IRQREC_SP / 4], frame[IRQREC_S9 / 4], - frame[IRQREC_RA / 4]); - kprintf("[0x%08X] t8:0x%08X t9:0x%08X k0:0x%08X k1:0x%08X\r\n", - frame + 24, frame[IRQREC_T8 / 4], frame[IRQREC_T9 / 4], - frame[IRQREC_K0 / 4], frame[IRQREC_K1 / 4]); - kprintf("[0x%08X] s4:0x%08X s5:0x%08X s6:0x%08X s7:0x%08X\r\n", - frame + 20, frame[IRQREC_S4 / 4], frame[IRQREC_S5 / 4], - frame[IRQREC_S6 / 4], frame[IRQREC_S7 / 4]); - kprintf("[0x%08X] s0:0x%08X s1:0x%08X s2:0x%08X s3:0x%08X\r\n", - frame + 16, frame[IRQREC_S0 / 4], frame[IRQREC_S1 / 4], - frame[IRQREC_S2 / 4], frame[IRQREC_S3 / 4]); - kprintf("[0x%08X] t4:0x%08X t5:0x%08X t6:0x%08X t7:0x%08X\r\n", - frame + 12, frame[IRQREC_T4 / 4], frame[IRQREC_T5 / 4], - frame[IRQREC_T6 / 4], frame[IRQREC_T7 / 4]); - kprintf("[0x%08X] t0:0x%08X t1:0x%08X t2:0x%08X t3:0x%08X\r\n", - frame + 8, frame[IRQREC_T0 / 4], frame[IRQREC_T1 / 4], - frame[IRQREC_T2 / 4], frame[IRQREC_T3 / 4]); - kprintf("[0x%08X] a0:0x%08X a1:0x%08X a2:0x%08X a3:0x%08X\r\n", - frame + 4, frame[IRQREC_A0 / 4], frame[IRQREC_A1 / 4], - frame[IRQREC_A2 / 4], frame[IRQREC_A3 / 4]); - kprintf("[0x%08X] zer:0x%08X at:0x%08X v0:0x%08X v1:0x%08X\r\n", - frame + 0, frame[IRQREC_ZER / 4], frame[IRQREC_AT / 4], - frame[IRQREC_V0 / 4], frame[IRQREC_V1 / 4]); - - while (1) - { - /* forever */ - } -} diff --git a/system/arch/mips/halt.S b/system/arch/mips/halt.S deleted file mode 100644 index 93c82a71..00000000 --- a/system/arch/mips/halt.S +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @file halt.S - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include - -.globl halt - -/** - * @fn void halt(void) - * - * Essentially this is a busy wait, however the opcode 'wait' puts the - * processor in a powersave state (which can be awoken for arbitrary - * reasons) - */ -halt: - .func halt - wait - j halt - .endfunc - diff --git a/system/arch/mips/intdispatch.S b/system/arch/mips/intdispatch.S deleted file mode 100644 index 6fe3b957..00000000 --- a/system/arch/mips/intdispatch.S +++ /dev/null @@ -1,196 +0,0 @@ -/** - * @file intdispatch.S - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include - -.globl intdispatch - -/** - * @fn void intdispatch(void) - * - * Main interrupt dispatcher - * Jumps to savestate, which does full context save. - * First 32 words of intdispatch are copied to interrupt handler hardware - * address, so first code block cannot exceed 32 instructions. - */ -intdispatch: - .func intdispatch - .set noreorder - .set noat - mfc0 k0, CP0_CAUSE /* 0x00: Get interrupt/exception cause */ - addiu k1, zero, CAUSE_EXC /* 0x01: Load exception bit mask */ - and k0, k0, k1 /* 0x02: Check cause against exception */ - beq k0, zero, 1f /* 0x03: If not exception, savestate */ - lui k1, %hi(TRAPVEC_ADDR) /* 0x04: Load high bits of TRAPVEC */ - addiu k1, %lo(TRAPVEC_ADDR) /* 0x05: Load low bits of TRAPVEC */ - addu k1, k1, k0 /* 0x06: index into TRAPVEC table */ - lw k0, 0(k1) /* 0x07: load exception vector address */ - nop /* 0x08: delay slot */ - beq k0, zero, 1f /* 0x09: if null vector, savestate */ - nop /* 0x0a: delay slot */ - jr k0 /* 0x0b: vector exists, go to it. */ - nop /* 0x0c: delay slot */ -1: j savestate /* 0x0d: jump to long handler */ - nop /* 0x0e: filler */ - nop /* 0x0f: filler */ - nop /* 0x10: filler */ - nop /* 0x11: filler */ - nop /* 0x12: filler */ - nop /* 0x13: filler */ - nop /* 0x14: filler */ - nop /* 0x15: filler */ - nop /* 0x16: filler */ - nop /* 0x17: filler */ - nop /* 0x18: filler */ - nop /* 0x19: filler */ - nop /* 0x1a: filler */ - nop /* 0x1b: filler */ - nop /* 0x1c: filler */ - nop /* 0x1d: filler */ - nop /* 0x1e: filler */ - nop /* 0x1f: filler */ - .set at - .set reorder - -/** - * Save processor state and jump to main handler. The IRQ Handler saves all - * relevant volatile state on the stack, and transfers control to a C function - * for decoding the interrupt source and picking the correct vector. - */ -savestate: - .set noreorder - .set noat - addiu sp, sp, -IRQREC_SIZE - - /* Save AT (assembler temp) before any synthetic opcodes. */ - sw AT, IRQREC_AT(sp) - /* Save interrupt/exception CAUSE value. */ - mfc0 k0, CP0_CAUSE - /* Save program counter from interrupt/exception source. */ - mfc0 k1, CP0_EPC - sw k0, IRQREC_CAUSE(sp) - /* Save STATUS register from coprocessor. */ - mfc0 k0, CP0_STATUS - sw k1, IRQREC_EPC(sp) - sw k0, IRQREC_STATUS(sp) - .set at - .set reorder - - /* Save all general purpose registers. */ - sw v0, IRQREC_V0(sp) - sw v1, IRQREC_V1(sp) - sw a0, IRQREC_A0(sp) - sw a1, IRQREC_A1(sp) - sw a2, IRQREC_A2(sp) - sw a3, IRQREC_A3(sp) - sw t0, IRQREC_T0(sp) - sw t1, IRQREC_T1(sp) - sw t2, IRQREC_T2(sp) - sw t3, IRQREC_T3(sp) - sw t4, IRQREC_T4(sp) - sw t5, IRQREC_T5(sp) - sw t6, IRQREC_T6(sp) - sw t7, IRQREC_T7(sp) - sw s0, IRQREC_S0(sp) - sw s1, IRQREC_S1(sp) - sw s2, IRQREC_S2(sp) - sw s3, IRQREC_S3(sp) - sw s4, IRQREC_S4(sp) - sw s5, IRQREC_S5(sp) - sw s6, IRQREC_S6(sp) - sw s7, IRQREC_S7(sp) - sw t8, IRQREC_T8(sp) - sw t9, IRQREC_T9(sp) - sw k0, IRQREC_K0(sp) - sw k1, IRQREC_K1(sp) - sw gp, IRQREC_S8(sp) - sw sp, IRQREC_SP(sp) - sw fp, IRQREC_S9(sp) - sw ra, IRQREC_RA(sp) - sw zero, IRQREC_ZER(sp) - - /* Save a couple of other volatile regs, hi and lo. */ - mfhi t0 - mflo t1 - sw t0, IRQREC_HI(sp) - sw t1, IRQREC_LO(sp) - - /* Call high-level trap handler. */ - lw a0, IRQREC_CAUSE(sp) - move a1, sp - li a2, CAUSE_EXC - and a2, a0, a2 - beq a2, zero, 1f - jal exception - b restorestate -1: - jal dispatch - -/** - * Common return routine for exceptions and interrupts. All interrupts - * that save state will eventually return here, where the state is restored - * and control is returned to the point where the interrupt occurred. - */ -restorestate: - /* Restore HI and LO special regs. */ - lw t0, IRQREC_HI(sp) - lw t1, IRQREC_LO(sp) - mthi t0 - mtlo t1 - - /* Restore general purpose regs. */ - /* lw zero, IRQREC_ZER(sp) */ - lw ra, IRQREC_RA(sp) - lw fp, IRQREC_S9(sp) - /* lw sp, IRQREC_SP(sp) */ - lw gp, IRQREC_S8(sp) - /* lw k1, IRQREC_K1(sp) */ - /* lw k0, IRQREC_K0(sp) */ - lw t9, IRQREC_T9(sp) - lw t8, IRQREC_T8(sp) - lw s7, IRQREC_S7(sp) - lw s6, IRQREC_S6(sp) - lw s5, IRQREC_S5(sp) - lw s4, IRQREC_S4(sp) - lw s3, IRQREC_S3(sp) - lw s2, IRQREC_S2(sp) - lw s1, IRQREC_S1(sp) - lw s0, IRQREC_S0(sp) - lw t7, IRQREC_T7(sp) - lw t6, IRQREC_T6(sp) - lw t5, IRQREC_T5(sp) - lw t4, IRQREC_T4(sp) - lw t3, IRQREC_T3(sp) - lw t2, IRQREC_T2(sp) - lw t1, IRQREC_T1(sp) - lw t0, IRQREC_T0(sp) - lw a3, IRQREC_A3(sp) - lw a2, IRQREC_A2(sp) - lw a1, IRQREC_A1(sp) - lw a0, IRQREC_A0(sp) - lw v1, IRQREC_V1(sp) - lw v0, IRQREC_V0(sp) - - .set noreorder - .set noat - /* restore EPC */ - lw k0, IRQREC_EPC(sp) - /* restore AT */ - lw AT, IRQREC_AT(sp) - mtc0 k0, CP0_EPC - /* restore STATUS */ - lw k1, IRQREC_STATUS(sp) - /* restore stack pointer */ - addiu sp, sp, IRQREC_SIZE - mtc0 k1, CP0_STATUS - nop - eret - nop - nop - .set at - .set reorder - .endfunc diff --git a/system/arch/mips/interrupt.h b/system/arch/mips/interrupt.h deleted file mode 100644 index 2364634d..00000000 --- a/system/arch/mips/interrupt.h +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @file interrupt.h - * - * Constants and declarations associated with interrupt and exception - * processing, common to MIPS architecture. - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#ifndef _MIPS_INTERRUPT_H_ -#define _MIPS_INTERRUPT_H_ - - -#ifndef __ASSEMBLER__ -typedef unsigned long irqmask; /**< machine status for disable/restore */ - -irqmask disable(void); -irqmask restore(irqmask); -irqmask enable(void); -irqmask enable_cpuirq(irqmask); -irqmask disable_cpuirq(irqmask); -void exlreset(void); -void exlset(void); - -/** - * Definitions to allow C array manipulation of vectors. - * The cast below makes the following a pointer to a table of - * pointers to functions which take no parameters (void) and return - * nothing (void). - */ -#define exceptionVector ((interrupt (**)(void))TRAPVEC_ADDR) -#define interruptVector ((interrupt (**)(void))IRQVEC_ADDR) - -#endif /* __ASSEMBLER__ */ - -/* Indices for exception code */ -#define EXC_INT 0 /**< Interrupt */ -#define EXC_MOD 1 /**< Store on Read-Only Page */ -#define EXC_TLBL 2 /**< No valid TLB entry matches */ -#define EXC_TLBS 3 /**< Standard TLB miss */ -#define EXC_ADEL 4 /**< Address error (load) */ -#define EXC_ADES 5 /**< Address error (store) */ -#define EXC_IBE 6 /**< Instruction Bus Error */ -#define EXC_DBE 7 /**< Data Bus Error */ -#define EXC_SYS 8 /**< System call */ -#define EXC_BP 9 /**< Breakpoint exception */ -#define EXC_RI 10 /**< Reserved instruction */ -#define EXC_CPUN 11 /**< Coprocessor Unusable */ -#define EXC_OVER 12 /**< Arithmetic Overflow */ -#define EXC_TRAP 13 /**< Trap Exception */ -#define EXC_MDMX 22 /**< MDMX unusable */ -#define EXC_WATCH 23 /**< Reference to WatchHi/WatchLo */ -#define EXC_MCHECK 24 /**< Machine Check */ -#define EXC_CACHEERR 30 /**< Cache Error / Debug Mode */ - -/* Offsets for the MIPS interrupt context record. */ -#define IRQREC_ZER 16 -#define IRQREC_AT 20 -#define IRQREC_V0 24 -#define IRQREC_V1 28 -#define IRQREC_A0 32 -#define IRQREC_A1 36 -#define IRQREC_A2 40 -#define IRQREC_A3 44 -#define IRQREC_T0 48 -#define IRQREC_T1 52 -#define IRQREC_T2 56 -#define IRQREC_T3 60 -#define IRQREC_T4 64 -#define IRQREC_T5 68 -#define IRQREC_T6 72 -#define IRQREC_T7 76 -#define IRQREC_S0 80 -#define IRQREC_S1 84 -#define IRQREC_S2 88 -#define IRQREC_S3 92 -#define IRQREC_S4 96 -#define IRQREC_S5 100 -#define IRQREC_S6 104 -#define IRQREC_S7 108 -#define IRQREC_T8 112 -#define IRQREC_T9 116 -#define IRQREC_K0 120 -#define IRQREC_K1 124 -#define IRQREC_S8 128 -#define IRQREC_SP 132 -#define IRQREC_S9 136 -#define IRQREC_RA 140 -#define IRQREC_LO 144 -#define IRQREC_HI 148 -#define IRQREC_CAUSE 152 -#define IRQREC_STATUS 156 -#define IRQREC_EPC 164 -#define IRQREC_SIZE 168 - -/* Indices for interrupt request vector */ -#define IRQ_SW0 0 -#define IRQ_SW1 1 -#define IRQ_HW0 2 -#define IRQ_HW1 3 -#define IRQ_HW2 4 -#define IRQ_HW3 5 -#define IRQ_HW4 6 -#define IRQ_HW5 7 - -#endif /* _MIPS_INTERRUPT_H_ */ diff --git a/system/arch/mips/intutils.S b/system/arch/mips/intutils.S deleted file mode 100644 index 7917c678..00000000 --- a/system/arch/mips/intutils.S +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @file intutils.S - * Functions to control disabling and enabling of interrupts. - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#include - -.globl enable -.globl disable -.globl restore -.globl enable_cpuirq -.globl disable_cpuirq -.globl exlreset -.globl exlset - -/** - * @fn void enable(void) - * Enable all interrupts. - */ -enable: - .func enable - .set noreorder - mfc0 a1, CP0_STATUS - /* IE = 1: Master enable bit for SW and HW */ - li a2, STATUS_IE - or v0, a1, a2 - jr ra - mtc0 v0, CP0_STATUS - .set reorder - .endfunc - -/** - * @fn irqmask disable(void) - * Disable interrupts, return old state. - * @returns state of interrupts before they were disabled - */ -disable: - .func disable - .set noreorder - mfc0 v0, CP0_STATUS - li a0, ~STATUS_IE - and a1, v0, a0 - mtc0 a1, CP0_STATUS - jr ra - nop - .set reorder - .endfunc - -/** - * @fn irqmask restore(irqmask im) - * Restore interrupts to state in im. - * @param im irqmask of interrupt state to restore - * @return state of interrupts when called - */ -restore: - .func restore - .set noreorder - mfc0 a1, CP0_STATUS - nop - or v0, a1, a0 - jr ra - mtc0 v0, CP0_STATUS - .set reorder - .endfunc - - -/** - * @fn void enable_cpuirq(uchar irq) - * Mask on interrupt request source. - * @param irq index of the interrupt to enable - */ -enable_cpuirq: - .func enable_cpuirq - .set noreorder - mfc0 a1, CP0_STATUS - addi a3, zero, 7 - and a0, a0, a3 - addi a0, a0, 8 - li a2, 1 - sllv a2, a2, a0 - or v0, a1, a2 - jr ra - mtc0 v0, CP0_STATUS - .set reorder - .endfunc - -/** - * @fn void disable_cpuirq(uchar irq) - * Mask on interrupt request source. - * @param irq index of the interrupt to disable - */ -disable_cpuirq: - .func disable_cpuirq - .set noreorder - mfc0 a1, CP0_STATUS - addi a0, a0, 8 - li a2, 1 - sllv a2, a2, a0 - nor a2, a2, zero - and v0, a1, a2 - jr ra - mtc0 v0, CP0_STATUS - .set reorder - .endfunc - -/** - * @fn void exlreset(void) - * Turn EXL bit off, allowing exceptions/interrupts to occur again. - */ -exlreset: - .func exlreset - .set noreorder - mfc0 a1, CP0_STATUS - li a2, ~STATUS_EXL - and v0, a1, a2 - jr ra - mtc0 v0, CP0_STATUS - .set reorder - .endfunc - -/** - * @fn void exlset(void) - * Turn EXL bit on, preventing exceptions/interrupts. - */ -exlset: - .func exlset - .set noreorder - mfc0 a1, CP0_STATUS - li a2, STATUS_EXL - or v0, a1, a2 - jr ra - mtc0 v0, CP0_STATUS - .set reorder - .endfunc diff --git a/system/arch/mips/pause.S b/system/arch/mips/pause.S deleted file mode 100644 index c2dc11e1..00000000 --- a/system/arch/mips/pause.S +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @file pause.S - * Platform-dependent code for idling the processor - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include - -.globl pause - -/** - * @fn void pause(void) - * - * Enter some kind of powerdown state (if it exists) that suspends - * execution until an interrupt is detected. - */ -pause: - .func pause - wait - jr ra - .endfunc - diff --git a/system/arch/mips/setupStack.c b/system/arch/mips/setupStack.c deleted file mode 100644 index 25ffe3b5..00000000 --- a/system/arch/mips/setupStack.c +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file setupStack.c - */ -/* Embedded Xinu, Copyright (C) 2009, 2013. All rights reserved. */ - -#include -#include -#include - -/** Set up the context record and arguments on the stack for a new thread - * (MIPS version) */ -void *setupStack(void *stackaddr, void *procaddr, - void *retaddr, uint nargs, va_list ap) -{ - uint i; - ulong *saddr = stackaddr; - - /* In the default calling MIPS convention used by gcc, registers $a0 through - * $a3 are used to pass arguments and any additional arguments spill into - * the stack. However, immediately prior (lower address) to any spilled - * arguments, the caller must still leave 4 words of space so that callee - * can temporarily store arguments there if it chooses. - * - * Therefore, we do not consider $a0 through $a3 to be part of the context - * record itself, but they are still loaded by ctxsw(). This will load up - * to the first four arguments when starting a new thread. - */ - - saddr -= max(nargs, 4); - - /* The MIPS stack should be 8-byte aligned on entry to all procedures. */ - if ((ulong)saddr & 0x4) - { - --saddr; - } - - /* Save arguments on stack. */ - for (i = 0; i < nargs; i++) - { - saddr[i] = va_arg(ap, ulong); - } - - /* Construct context record. */ - saddr -= CONTEXT_WORDS; - - for (i = 0; i < CONTEXT_WORDS - 2; i++) - { - saddr[i] = 0; - } - - /* return address */ - saddr[CONTEXT_WORDS - 2] = (ulong)retaddr; - - /* program counter */ - saddr[CONTEXT_WORDS - 1] = (ulong)procaddr; - - return saddr; -} diff --git a/system/arch/mips/syscall_dispatch.c b/system/arch/mips/syscall_dispatch.c deleted file mode 100644 index 1340f47a..00000000 --- a/system/arch/mips/syscall_dispatch.c +++ /dev/null @@ -1,372 +0,0 @@ -/** - * @file syscall_dispatch.c - * Translate user_* functions to system calls, dispatch to proper sc_* - * functions, and complete. - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include -#include -#include - -/* for argument parsing */ -#define SCARG(type, args) (type)(*args++) - -/* quick and dirty macro to make user->kernel syscalls */ -#define SYSCALL(num) int status; \ - asm("li $2, %0" : : "i"(SYSCALL_##num)); \ - asm("syscall"); \ - asm("move %0, $2" : "=r"(status)); \ - return status; - -/* syscall wrapper prototypes */ -syscall sc_none(int *); -syscall sc_yield(int *); -syscall sc_sleep(int *); -syscall sc_kill(int *); -syscall sc_open(int *); -syscall sc_close(int *); -syscall sc_read(int *); -syscall sc_write(int *); -syscall sc_getc(int *); -syscall sc_putc(int *); -syscall sc_seek(int *); -syscall sc_control(int *); -syscall sc_getdev(int *); -syscall sc_mboxalloc(int *); -syscall sc_mboxfree(int *); -syscall sc_mboxrecv(int *); -syscall sc_mboxsend(int *); - -/* table for determining how to call syscalls */ -const struct syscall_info syscall_table[] = { - {5, (void *)sc_none}, /* SYSCALL_NONE = 0 */ - {0, (void *)sc_yield}, /* SYSCALL_YIELD = 1 */ - {1, (void *)sc_sleep}, /* SYSCALL_SLEEP = 2 */ - {1, (void *)sc_kill}, /* SYSCALL_KILL = 3 */ - {2, (void *)sc_open}, /* SYSCALL_OPEN = 4 */ - {1, (void *)sc_close}, /* SYSCALL_CLOSE = 5 */ - {3, (void *)sc_read}, /* SYSCALL_READ = 6 */ - {3, (void *)sc_write}, /* SYSCALL_WRITE = 7 */ - {1, (void *)sc_getc}, /* SYSCALL_GETC = 8 */ - {2, (void *)sc_putc}, /* SYSCALL_PUTC = 9 */ - {2, (void *)sc_seek}, /* SYSCALL_SEEK = 10 */ - {4, (void *)sc_control}, /* SYSCALL_CONTROL = 11 */ - {1, (void *)sc_getdev}, /* SYSCALL_GETDEV = 12 */ - {1, (void *)sc_mboxalloc}, /* SYSCALL_MBOXALLOC = 13 */ - {1, (void *)sc_mboxfree}, /* SYSCALL_MBOXFREE = 14 */ - {1, (void *)sc_mboxrecv}, /* SYSCALL_MBOXRECV = 15 */ - {2, (void *)sc_mboxsend}, /* SYSCALL_MBOXSEND = 16 */ -}; - -int nsyscall = sizeof(syscall_table) / sizeof(struct syscall_info); - -/** - * Syscall dispatch routine. Given a syscall code and pointer to - * arguments, change execution to function. Otherwise, generate error - * saying no such syscall. - * @param code syscall code to execute - * @param args pointer to arguments for syscall - */ -int syscall_dispatch(int code, int *args) -{ - if (0 <= code && code < nsyscall) - { - return (*syscall_table[code].handler) (args); - } - - return SYSERR; -} - -/** - * syscall wrapper for *no* function, just a test/demo. - * @param args expands to: none. - */ -syscall sc_none(int *args) -{ - return OK; -} - -syscall user_none(void) -{ - SYSCALL(NONE); -} - -/** - * syscall wrapper for yield(). - * @param args expands to: none. - */ -syscall sc_yield(int *args) -{ - /* this may change thread of execution, allow exceptions */ - exlreset(); - - return yield(); -} - -syscall user_yield(void) -{ - SYSCALL(YIELD); -} - -/** - * syscall wrapper for sleep(). - * @param args expands to: uint ms (milliseconds to sleep) - */ -syscall sc_sleep(int *args) -{ - uint ms = SCARG(int, args); - - /* this may change thread of execution, allow exceptions */ - exlreset(); - - return sleep(ms); -} - -syscall user_sleep(uint ms) -{ - SYSCALL(SLEEP); -} - -/** - * syscall wrapper for kill(). - * @param args expands to: tid_typ thread_id - */ -syscall sc_kill(int *args) -{ - tid_typ thread_id = SCARG(tid_typ, args); - - /* this may change thread of execution, allow exceptions */ - exlreset(); - - return kill(thread_id); -} - -syscall user_kill(tid_typ thread_id) -{ - SYSCALL(KILL); -} - -/** - * syscall wrapper for open(). - * @param args expands to: int descrp, int arg - */ -syscall sc_open(int *args) -{ - int descrp = SCARG(int, args); - int arg = SCARG(int, args); - - return open(descrp, arg); -} - -syscall user_open(int descrp, int arg) -{ - SYSCALL(OPEN); -} - -/** - * syscall wrapper for close(). - * @param args expands to: int descrp - */ -syscall sc_close(int *args) -{ - int descrp = SCARG(int, args); - - return close(descrp); -} - -syscall user_close(int descrp) -{ - SYSCALL(CLOSE); -} - -/** - * syscall wrapper for read(). - * @param args expands to: int descrp, void *buffer, uint length - */ -syscall sc_read(int *args) -{ - int descrp = SCARG(int, args); - void *buffer = SCARG(void *, args); - uint length = SCARG(uint, args); - - return read(descrp, buffer, length); -} - -syscall user_read(int descrp, void *buffer, uint length) -{ - SYSCALL(READ); -} - -/** - * syscall wrapper for write(). - * @param args expands to: int descrp, void *buffer, uint length - */ -syscall sc_write(int *args) -{ - int descrp = SCARG(int, args); - void *buffer = SCARG(void *, args); - uint length = SCARG(uint, args); - - return write(descrp, buffer, length); -} - -syscall user_write(int descrp, void *buffer, uint length) -{ - SYSCALL(WRITE); -} - -/** - * syscall wrapper for getc(). - * @param args expands to: int descrp - */ -syscall sc_getc(int *args) -{ - int descrp = SCARG(int, args); - - return getc(descrp); -} - -syscall user_getc(int descrp) -{ - SYSCALL(GETC); -} - -/** - * syscall wrapper for putc(). - * @param args expands to: int descrp, char character - */ -syscall sc_putc(int *args) -{ - int descrp = SCARG(int, args); - char character = SCARG(char, args); - - return putc(descrp, character); -} - -syscall user_putc(int descrp, char character) -{ - SYSCALL(PUTC); -} - -/** - * syscall wrapper for seek(). - * @param args expands to: int descrp, uint offset - */ -syscall sc_seek(int *args) -{ - int descrp = SCARG(int, args); - uint offset = SCARG(uint, args); - - return seek(descrp, offset); -} - -syscall user_seek(int descrp, uint offset) -{ - SYSCALL(SEEK); -} - -/** - * syscall wrapper for control(). - * @param args expands to: int descrp, int function, long arg1, long arg2 - */ -syscall sc_control(int *args) -{ - int descrp = SCARG(int, args); - int function = SCARG(int, args); - long arg1 = SCARG(long, args); - long arg2 = SCARG(long, args); - - return control(descrp, function, arg1, arg2); -} - -syscall user_control(int descrp, int function, long arg1, long arg2) -{ - SYSCALL(CONTROL); -} - -/** - * syscall wrapper for getdev(). - * @param args expands to: char *device_name - */ -syscall sc_getdev(int *args) -{ - char *device_name = SCARG(char *, args); - - return getdev(device_name); -} - -syscall user_getdev(char *device_name) -{ - SYSCALL(GETDEV); -} - -/** - * syscall wrapper for mailboxAlloc(). - * @param args expands to: uint nmsgs - */ -syscall sc_mboxalloc(int *args) -{ - uint nmsgs = SCARG(uint, args); - - return mailboxAlloc(nmsgs); -} - -syscall user_mboxalloc(uint nmsgs) -{ - SYSCALL(MBOXALLOC); -} - -/** - * syscall wrapper for mailboxFree(). - * @param args expands to: mailbox mbox_id - */ -syscall sc_mboxfree(int *args) -{ - mailbox mbox_id = SCARG(mailbox, args); - - return mailboxFree(mbox_id); -} - -syscall user_mboxfree(mailbox mbox_id) -{ - SYSCALL(MBOXFREE); -} - -/** - * syscall wrapper for mailboxReceive(). - * @param args expands to: mailbox mbox_id - */ -syscall sc_mboxrecv(int *args) -{ - mailbox mbox_id = SCARG(mailbox, args); - - return mailboxReceive(mbox_id); -} - -syscall user_mboxrecv(mailbox mbox_id) -{ - SYSCALL(MBOXRECV); -} - -/** - * syscall wrapper for mailboxSend(). - * @param args expands to: mailbox mbox_id, int msg - */ -syscall sc_mboxsend(int *args) -{ - mailbox mbox_id = SCARG(mailbox, args); - int msg = SCARG(int, args); - - return mailboxSend(mbox_id, msg); -} - -syscall user_mboxsend(mailbox mbox_id, int msg) -{ - SYSCALL(MBOXSEND); -} diff --git a/system/arch/mips/syscall_entry.S b/system/arch/mips/syscall_entry.S deleted file mode 100644 index ce9ecb32..00000000 --- a/system/arch/mips/syscall_entry.S +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @file syscall_entry.S - * Entry point for handling syscall exceptions. - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include - -.globl syscall_entry - -/** - * @fn exchandler syscall_entry(void) - * - * Handler for syscall exceptions. Syscall number will be loaded into - * register v0 and arguments should follow standard conventions. Return - * values should be loaded into v0 and v1. - */ -syscall_entry: - .func syscall_entry - addiu sp, sp, -64 /* increase stack */ - mfc0 k0, CP0_EPC /* get EPC */ - sw ra, 60(sp) /* store return address */ - sw k0, 56(sp) /* store EPC */ - - sw a0, 64(sp) /* store arguments in safe positions */ - sw a1, 68(sp) - sw a2, 72(sp) - sw a3, 76(sp) - - sw s0, 16(sp) /* store callee save registers */ - sw s1, 20(sp) - sw s2, 24(sp) - sw s3, 28(sp) - sw s4, 32(sp) - sw s5, 36(sp) - sw s6, 40(sp) - sw s7, 44(sp) - sw s8, 48(sp) - sw s9, 52(sp) - - move a0, v0 /* store code of syscall */ - la a1, 64(sp) /* load pointer to arguments */ - jal syscall_dispatch /* handle system call */ - - lw k0, 56(sp) /* Load up the exception PC */ - addiu k0, k0, 4 /* System call was handled, move on */ - mtc0 k0, CP0_EPC /* Store updated EPC address */ - - lw a0, 64(sp) /* load arguments back to registers */ - lw a1, 68(sp) - lw a2, 72(sp) - lw a3, 76(sp) - - lw s0, 16(sp) /* store callee save registers */ - lw s1, 20(sp) - lw s2, 24(sp) - lw s3, 28(sp) - lw s4, 32(sp) - lw s5, 36(sp) - lw s6, 40(sp) - lw s7, 44(sp) - lw s8, 48(sp) - lw s9, 52(sp) - - lw ra, 60(sp) /* restore return address */ - addiu sp, sp, 64 /* collapse stack */ - eret /* return to user mode */ - nop - .endfunc diff --git a/system/bfpalloc.c b/system/bfpalloc.c index 4c40f518..559042fe 100644 --- a/system/bfpalloc.c +++ b/system/bfpalloc.c @@ -80,6 +80,7 @@ int bfpalloc(uint bufsize, uint nbuf) bufptr->next = (struct poolbuf *)((ulong)bufptr + bufsize); bufptr = bufptr->next; } + signaln(bfpptr->freebuf, nbuf); return id; diff --git a/system/bufget.c b/system/bufget.c index 249d178f..be640fcf 100644 --- a/system/bufget.c +++ b/system/bufget.c @@ -8,6 +8,7 @@ #include #include #include +#include /** * @ingroup memory_mgmt @@ -24,7 +25,7 @@ * If @p poolid does not specify a valid buffer pool, returns ::SYSERR; * otherwise returns a pointer to the resulting buffer. */ -void *bufget(int poolid) +void *bufget_(int poolid, const char *file, const char *func) { struct bfpentry *bfpptr; struct poolbuf *bufptr; @@ -38,6 +39,11 @@ void *bufget(int poolid) bfpptr = &bfptab[poolid]; im = disable(); + if (0 == strncmp("etherWrite", func, 10)) + { + //kprintf("bfpptr->freebuf: %d\r\n", bfpptr->freebuf); + //kprintf("bfpptr->freebuf->count: %d\r\n", semcount(bfpptr->freebuf)); + } wait(bfpptr->freebuf); bufptr = bfpptr->next; bfpptr->next = bufptr->next; diff --git a/system/chprio.c b/system/chprio.c index b939a41f..7bfb912d 100644 --- a/system/chprio.c +++ b/system/chprio.c @@ -26,9 +26,15 @@ syscall chprio(tid_typ tid, int newprio) restore(im); return SYSERR; } + + thrtab_acquire(tid); + thrptr = &thrtab[tid]; oldprio = thrptr->prio; thrptr->prio = newprio; + + thrtab_release(tid); + restore(im); return oldprio; } diff --git a/system/clkhandler.c b/system/clkhandler.c index 9176d4f1..da0493bc 100644 --- a/system/clkhandler.c +++ b/system/clkhandler.c @@ -24,7 +24,7 @@ int resched(void); */ interrupt clkhandler(void) { - clkupdate(platform.clkfreq / CLKTICKS_PER_SEC); + clkupdate(platform.clkfreq / CLKTICKS_PER_SEC); /* Another clock tick passes. */ clkticks++; @@ -36,6 +36,7 @@ interrupt clkhandler(void) clkticks = 0; } + /* We do not have preemption yet.. this breaks the code.. */ /* If sleepq is not empty, decrement first key. */ /* If key reaches zero, call wakeup. */ if (nonempty(sleepq) && (--firstkey(sleepq) <= 0)) diff --git a/system/clkinit.c b/system/clkinit.c index f92810bd..999da58e 100644 --- a/system/clkinit.c +++ b/system/clkinit.c @@ -68,6 +68,7 @@ void clkinit(void) interruptVector[IRQ_TIMER] = clkhandler; enable_irq(IRQ_TIMER); clkupdate(platform.clkfreq / CLKTICKS_PER_SEC); + #endif } diff --git a/system/create.c b/system/create.c index 2f0aa4c5..6a50ced9 100644 --- a/system/create.c +++ b/system/create.c @@ -6,6 +6,7 @@ #include #include #include +#include static int thrnew(void); @@ -48,6 +49,7 @@ tid_typ create(void *procaddr, uint ssize, int priority, /* Allocate new stack. */ saddr = stkget(ssize); + if (SYSERR == (int)saddr) { restore(im); @@ -56,8 +58,13 @@ tid_typ create(void *procaddr, uint ssize, int priority, /* Allocate new thread ID. */ tid = thrnew(); + + thrtab_acquire(tid); + if (SYSERR == (int)tid) { + thrtab_release(tid); + stkfree(saddr, ssize); restore(im); return SYSERR; @@ -85,11 +92,15 @@ tid_typ create(void *procaddr, uint ssize, int priority, /* Set up new thread's stack with context record and arguments. * Architecture-specific. */ va_start(ap, nargs); + thrptr->stkptr = setupStack(saddr, procaddr, INITRET, nargs, ap); va_end(ap); + thrtab_release(tid); + /* Restore interrupts and return new thread TID. */ restore(im); + return tid; } @@ -107,10 +118,25 @@ static int thrnew(void) for (tid = 0; tid < NTHREAD; tid++) { nexttid = (nexttid + 1) % NTHREAD; - if (THRFREE == thrtab[nexttid].state) + + if (THRFREE == thrtab[nexttid].state) { return nexttid; } } + return SYSERR; } + +void thrtab_acquire(tid_typ tid) +{ + pldw(&thrtab[tid]); + pldw(&thrtab[tid].core_affinity); + mutex_acquire(thrtab_mutex[tid]); +} + +void thrtab_release(tid_typ tid) +{ + dmb(); + mutex_release(thrtab_mutex[tid]); +} diff --git a/system/debug.c b/system/debug.c index 149150ec..b316931b 100644 --- a/system/debug.c +++ b/system/debug.c @@ -87,3 +87,15 @@ void hexdump(void *buffer, ulong length, bool canon) fprintf(stdout, "\n"); } } + +void _debug_util(const char *file, const char *func, int line, const char *format, ...) +{ + va_list args; + va_start(args, format); + + kprintf("[DEBUG] %s: %s(), line %d: ", file, func, line); + kprintf(format, args); + kprintf("\r\n"); + + va_end(args); +} diff --git a/system/dma_buf.c b/system/dma_buf.c new file mode 100644 index 00000000..b348361e --- /dev/null +++ b/system/dma_buf.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +// XXX: This code is really bad... +// only being used as a proof-of-concept.. +// definitely will have to implement this differently. + +#define SECTION_SIZE 0x00100000 + +static int freespace_idx = 0; +static int remaining_space = SECTION_SIZE; +static mutex_t dma_buf_mutex; + +uint8_t dma_buf_space[SECTION_SIZE] __aligned(SECTION_SIZE); + +void *dma_buf_alloc(uint size) +{ + void *retval; + retval = (void *)(dma_buf_space + freespace_idx); + + mutex_acquire(dma_buf_mutex); + freespace_idx += size; + remaining_space -= size; + mutex_release(dma_buf_mutex); + + return retval; +} + +syscall dma_buf_free(void *ptr, uint size) +{ + mutex_acquire(dma_buf_mutex); + freespace_idx -= size; + remaining_space += size; + mutex_release(dma_buf_mutex); + + return OK; +} + +syscall dma_buf_init() +{ + freespace_idx = 0; + remaining_space = SECTION_SIZE; + dma_buf_mutex = mutex_create(); + + return OK; +} diff --git a/system/getitem.c b/system/getitem.c index 1f49e7ea..583f77b8 100644 --- a/system/getitem.c +++ b/system/getitem.c @@ -66,11 +66,16 @@ tid_typ getitem(tid_typ tid) { tid_typ prev, next; + quetab_acquire(); + next = quetab[tid].next; prev = quetab[tid].prev; quetab[prev].next = next; quetab[next].prev = prev; quetab[tid].next = EMPTY; quetab[tid].prev = EMPTY; + + quetab_release(); + return tid; } diff --git a/system/gettid.c b/system/gettid.c index 72cd4abc..f55cf46a 100644 --- a/system/gettid.c +++ b/system/gettid.c @@ -14,5 +14,5 @@ */ tid_typ gettid(void) { - return thrcurrent; + return thrcurrent[getcpuid()]; } diff --git a/system/initialize.c b/system/initialize.c index 7802b955..ccd23352 100644 --- a/system/initialize.c +++ b/system/initialize.c @@ -6,33 +6,19 @@ */ /* Embedded Xinu, Copyright (C) 2009, 2013. All rights reserved. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include +#include #ifdef WITH_USB -# include +#include +#include +#include "../device/lan7800/lan7800.h" #endif +#include "platforms/arm-rpi3/mmu.h" +#include + /* Function prototypes */ extern thread main(void); /* main is the first thread created */ static int sysinit(void); /* intializes system structures */ @@ -41,51 +27,61 @@ static int sysinit(void); /* intializes system structures */ struct thrent thrtab[NTHREAD]; /* Thread table */ struct sement semtab[NSEM]; /* Semaphore table */ struct monent montab[NMON]; /* Monitor table */ -qid_typ readylist; /* List of READY threads */ +qid_typ readylist[NCORES]; /* List of READY threads */ struct memblock memlist; /* List of free memory blocks */ struct bfpentry bfptab[NPOOL]; /* List of memory buffer pools */ +/* Declarations of major multicore variables */ +mutex_t quetab_mutex; +mutex_t thrtab_mutex[NTHREAD]; +mutex_t semtab_mutex[NSEM]; +unsigned int core_affinity[NTHREAD]; + +static void core_nulluser(void); + /* Active system status */ int thrcount; /* Number of live user threads */ -tid_typ thrcurrent; /* Id of currently running thread */ +tid_typ thrcurrent[NCORES]; /* Id of currently running thread */ /* Params set by startup.S */ void *memheap; /* Bottom of heap (top of O/S stack) */ ulong cpuid; /* Processor id */ - struct platform platform; /* Platform specific configuration */ -/** +/* * Intializes the system and becomes the null thread. - * This is where the system begins after the C environment has been - * established. Interrupts are initially DISABLED, and must eventually - * be enabled explicitly. This routine turns itself into the null thread - * after initialization. Because the null thread must always remain ready - * to run, it cannot execute code that might cause it to be suspended, wait - * for a semaphore, or put to sleep, or exit. In particular, it must not + * This is where the system begins after the C environment has been + * established. Interrupts are initially DISABLED, and must eventually + * be enabled explicitly. This routine turns itself into the null thread + * after initialization. Because the null thread must always remain ready + * to run, it cannot execute code that might cause it to be suspended, wait + * for a semaphore, or put to sleep, or exit. In particular, it must not * do I/O unless it uses kprintf for synchronous output. */ void nulluser(void) { - /* Platform-specific initialization */ - platforminit(); + /* Platform-specific initialization */ + platforminit(); + + /* General initialization */ + sysinit(); + + unparkcore(1, (void *) core_nulluser, NULL); + unparkcore(2, (void *) core_nulluser, NULL); + unparkcore(3, (void *) core_nulluser, NULL); - /* General initialization */ - sysinit(); + kprintf("\r\n***********************************************************\r\n"); + kprintf("******************** Hello Xinu World! ********************\r\n"); + kprintf("***********************************************************\r\n"); - /* Enable interrupts */ - enable(); + /* Enable interrupts */ + enable(); - /* Spawn the main thread */ - ready(create(main, INITSTK, INITPRIO, "MAIN", 0), RESCHED_YES); + /* Spawn the main thread */ + ready(create(main, INITSTK, INITPRIO, "MAIN", 0), RESCHED_YES); - /* null thread has nothing else to do but cannot exit */ - while (TRUE) - { -#ifndef DEBUG - pause(); -#endif /* DEBUG */ - } + /* null thread has nothing else to do but cannot exit */ + while (TRUE){} } /** @@ -94,123 +90,187 @@ void nulluser(void) */ static int sysinit(void) { - int i; - struct thrent *thrptr; /* thread control block pointer */ - struct memblock *pmblock; /* memory block pointer */ - - /* Initialize system variables */ - /* Count this NULLTHREAD as the first thread in the system. */ - thrcount = 1; - - /* Initialize free memory list */ - memheap = roundmb(memheap); - platform.maxaddr = truncmb(platform.maxaddr); - memlist.next = pmblock = (struct memblock *)memheap; - memlist.length = (uint)(platform.maxaddr - memheap); - pmblock->next = NULL; - pmblock->length = (uint)(platform.maxaddr - memheap); - - /* Initialize thread table */ - for (i = 0; i < NTHREAD; i++) - { - thrtab[i].state = THRFREE; - } - - /* initialize null thread entry */ - thrptr = &thrtab[NULLTHREAD]; - thrptr->state = THRCURR; - thrptr->prio = 0; - strlcpy(thrptr->name, "prnull", TNMLEN); - thrptr->stkbase = (void *)&_end; - thrptr->stklen = (ulong)memheap - (ulong)&_end; - thrptr->stkptr = 0; - thrptr->memlist.next = NULL; - thrptr->memlist.length = 0; - thrcurrent = NULLTHREAD; - - /* Initialize semaphores */ - for (i = 0; i < NSEM; i++) - { - semtab[i].state = SFREE; - semtab[i].queue = queinit(); - } - - /* Initialize monitors */ - for (i = 0; i < NMON; i++) - { - montab[i].state = MFREE; - } - - /* Initialize buffer pools */ - for (i = 0; i < NPOOL; i++) - { - bfptab[i].state = BFPFREE; - } - - /* initialize thread ready list */ - readylist = queinit(); - + int i; + struct thrent *thrptr; /* thread control block pointer */ + struct memblock *pmblock; /* memory block pointer */ + + /* Initialize serial lock */ + serial_lock = mutex_create(); + + /* Initialize system variables */ + /* Count this NULLTHREAD as the first thread in the system. */ + thrcount = NCORES; /* 1 nullthread per core */ + + /* Initialize free memory list */ + memheap = roundmb(memheap); + platform.maxaddr = truncmb(platform.maxaddr); + memlist.next = pmblock = (struct memblock *)memheap; + memlist.length = (uint)(platform.maxaddr - memheap); + pmblock->next = NULL; + pmblock->length = (uint)(platform.maxaddr - memheap); + + /* Initialize thread table */ + for (i = 0; i < NTHREAD; i++) + { + thrtab[i].state = THRFREE; + } + + /* initialize null thread entry */ + thrptr = &thrtab[NULLTHREAD]; + thrptr->state = THRCURR; + thrptr->prio = 0; + strlcpy(thrptr->name, "prnull", TNMLEN); + thrptr->stkbase = (void *)&_end; + thrptr->stklen = (ulong)memheap - (ulong)&_end; + thrptr->stklen = 8192; /* NULLSTK */ + thrptr->stkptr = 0; + thrptr->memlist.next = NULL; + thrptr->memlist.length = 0; + thrptr->core_affinity = CORE_ZERO; + thrcurrent[CORE_ZERO] = NULLTHREAD; + + /* Core 1 NULLTHREAD */ + thrptr = &thrtab[NULLTHREAD1]; + thrptr->state = THRCURR; + thrptr->prio = 0; + strlcpy(thrptr->name, "prnull01", TNMLEN); + thrptr->stkbase = (void *)(&_end + 8192); + thrptr->stklen = 8192; + thrptr->stkptr = 0; + thrptr->memlist.next = NULL; + thrptr->memlist.length = 0; + thrptr->core_affinity = CORE_ONE; + thrcurrent[CORE_ONE] = NULLTHREAD1; + + /* Core 2 NULLTHREAD */ + thrptr = &thrtab[NULLTHREAD2]; + thrptr->state = THRCURR; + thrptr->prio = 0; + strlcpy(thrptr->name, "prnull02", TNMLEN); + thrptr->stkbase = (void *)(&_end + 16384); + thrptr->stklen = 8192; + thrptr->stkptr = 0; + thrptr->memlist.next = NULL; + thrptr->memlist.length = 0; + thrptr->core_affinity = CORE_TWO; + thrcurrent[CORE_TWO] = NULLTHREAD2; + + /* Core 3 NULLTHREAD */ + thrptr = &thrtab[NULLTHREAD3]; + thrptr->state = THRCURR; + thrptr->prio = 0; + strlcpy(thrptr->name, "prnull03", TNMLEN); + thrptr->stkbase = (void *)(&_end + 24576); + thrptr->stklen = 8192; + thrptr->stkptr = 0; + thrptr->memlist.next = NULL; + thrptr->memlist.length = 0; + thrptr->core_affinity = CORE_THREE; + thrcurrent[CORE_THREE] = NULLTHREAD3; + + /* Initialize semaphores */ + for (i = 0; i < NSEM; i++) + { + semtab[i].state = SFREE; + semtab[i].queue = queinit(); + } + + /* Initialize monitors */ + for (i = 0; i < NMON; i++) + { + montab[i].state = MFREE; + } + + /* Initialize buffer pools */ + for (i = 0; i < NPOOL; i++) + { + bfptab[i].state = BFPFREE; + } + + /* initialize thread ready lists */ + for (i = 0; i < NCORES; i++) + { + readylist[i] = queinit(); + } + #if SB_BUS - backplaneInit(NULL); + backplaneInit(NULL); #endif /* SB_BUS */ #if RTCLOCK - /* initialize real time clock */ - clkinit(); + /* initialize real time clock */ + clkinit(); #endif /* RTCLOCK */ #ifdef UHEAP_SIZE - /* Initialize user memory manager */ - { - void *userheap; /* pointer to user memory heap */ - userheap = stkget(UHEAP_SIZE); - if (SYSERR != (int)userheap) - { - userheap = (void *)((uint)userheap - UHEAP_SIZE + sizeof(int)); - memRegionInit(userheap, UHEAP_SIZE); - - /* initialize memory protection */ - safeInit(); - - /* initialize kernel page mappings */ - safeKmapInit(); - } - } + /* Initialize user memory manager */ + { + void *userheap; /* pointer to user memory heap */ + userheap = stkget(UHEAP_SIZE); + if (SYSERR != (int)userheap) + { + userheap = (void *)((uint)userheap - UHEAP_SIZE + sizeof(int)); + memRegionInit(userheap, UHEAP_SIZE); + + /* initialize memory protection */ + safeInit(); + + /* initialize kernel page mappings */ + safeKmapInit(); + } + } #endif #if USE_TLB - /* initialize TLB */ - tlbInit(); - /* register system call handler */ - exceptionVector[EXC_SYS] = syscall_entry; + /* initialize TLB */ + tlbInit(); + /* register system call handler */ + exceptionVector[EXC_SYS] = syscall_entry; #endif /* USE_TLB */ #if NMAILBOX - /* intialize mailboxes */ - mailboxInit(); + /* intialize mailboxes */ + mailboxInit(); #endif #if NDEVS - for (i = 0; i < NDEVS; i++) - { - devtab[i].init((device*)&devtab[i]); - } + for (i = 0; i < NDEVS; i++) + { + devtab[i].init((device*)&devtab[i]); + } #endif + #ifdef WITH_USB - usbinit(); + usbinit(); #endif + #if NVRAM - nvramInit(); + nvramInit(); #endif -#if NNETIF - netInit(); +#if NETHER + netInit(); #endif #if GPIO - gpioLEDOn(GPIO_LED_CISCOWHT); + gpioLEDOn(GPIO_LED_CISCOWHT); #endif - return OK; + + return OK; +} + +static void core_nulluser(void) +{ + unsigned int cpuid; + cpuid = getcpuid(); + + disable(); + while (TRUE) + { + pldw(&quetab[readylist[cpuid]].next); + if (nonempty(readylist[cpuid])) + resched(); + } } diff --git a/system/insert.c b/system/insert.c index bf70382d..06f00609 100644 --- a/system/insert.c +++ b/system/insert.c @@ -19,25 +19,31 @@ */ int insert(tid_typ tid, qid_typ q, int key) { - int next; /* runs through list */ - int prev; /* follows next through list */ - - if (isbadqid(q) || isbadtid(tid)) - { - return SYSERR; - } - - next = quetab[quehead(q)].next; - while (quetab[next].key >= key) - { - next = quetab[next].next; - } - - /* insert tid between prev and next */ - quetab[tid].next = next; - quetab[tid].prev = prev = quetab[next].prev; - quetab[tid].key = key; - quetab[prev].next = tid; - quetab[next].prev = tid; - return OK; + int next; /* runs through list */ + int prev; /* follows next through list */ + + if (isbadqid(q) || isbadtid(tid)) + { + return SYSERR; + } + + quetab_acquire(); + + next = quetab[quehead(q)].next; + + while (quetab[next].key >= key) + { + next = quetab[next].next; + } + + /* insert tid between prev and next */ + quetab[tid].next = next; + quetab[tid].prev = prev = quetab[next].prev; + quetab[tid].key = key; + quetab[prev].next = tid; + quetab[next].prev = tid; + + quetab_release(); + + return OK; } diff --git a/system/insertd.c b/system/insertd.c index 4b3b0966..710628b2 100644 --- a/system/insertd.c +++ b/system/insertd.c @@ -27,6 +27,8 @@ int insertd(tid_typ tid, qid_typ q, int key) return SYSERR; } + quetab_acquire(); + prev = quehead(q); next = quetab[quehead(q)].next; while ((quetab[next].key <= key) && (next != quetail(q))) @@ -45,5 +47,7 @@ int insertd(tid_typ tid, qid_typ q, int key) quetab[next].key -= key; } + quetab_release(); + return OK; } diff --git a/system/intutils.S b/system/intutils.S new file mode 100644 index 00000000..e6d0b592 --- /dev/null +++ b/system/intutils.S @@ -0,0 +1,14 @@ +.globl enable +.globl disable +.globl restore + +enable: + msr daifclr, #0b0010 + ret + .endfunc + +disable: + .endfunc + +restore: + .endfunc diff --git a/system/kill.c b/system/kill.c index 05cd1c3b..0396bd2a 100644 --- a/system/kill.c +++ b/system/kill.c @@ -8,6 +8,7 @@ #include #include #include +#include extern void xdone(void); @@ -22,13 +23,30 @@ syscall kill(tid_typ tid) { register struct thrent *thrptr; /* thread control block */ irqmask im; + unsigned int cpuid; + + cpuid = getcpuid(); im = disable(); - if (isbadtid(tid) || (NULLTHREAD == tid)) + if (isbadtid(tid) || (NULLTHREAD == tid) || (NULLTHREAD1 == tid) || + (NULLTHREAD2 == tid) || (NULLTHREAD3 == tid)) { restore(im); return SYSERR; } + + thrtab_acquire(tid); + + /* cannot kill process that is running on a different core */ + if (thrptr->core_affinity != cpuid) + { + thrtab_release(tid); + restore(im); + return SYSERR; + } + + thrtab_release(tid); + thrptr = &thrtab[tid]; if (--thrcount <= 1) @@ -45,24 +63,36 @@ syscall kill(tid_typ tid) stkfree(thrptr->stkbase, thrptr->stklen); + thrtab_acquire(tid); + thrtab->core_affinity = cpuid; + thrtab_release(tid); + switch (thrptr->state) { case THRSLEEP: unsleep(tid); + thrtab_acquire(tid); thrptr->state = THRFREE; + thrtab_release(tid); break; case THRCURR: + thrtab_acquire(tid); thrptr->state = THRFREE; /* suicide */ + thrtab_release(tid); resched(); case THRWAIT: + semtab_acquire(thrptr->sem); semtab[thrptr->sem].count++; + semtab_release(thrptr->sem); case THRREADY: getitem(tid); /* removes from queue */ default: + thrtab_acquire(tid); thrptr->state = THRFREE; + thrtab_release(tid); } restore(im); diff --git a/system/main.c b/system/main.c index 87f7de71..b453f5dd 100644 --- a/system/main.c +++ b/system/main.c @@ -10,8 +10,11 @@ #include #include #include +#include +#include +#include "platforms/arm-rpi3/mmu.h" -static void print_os_info(void); +void print_os_info(void); /** * Main thread. You can modify this routine to customize what Embedded Xinu @@ -20,163 +23,161 @@ static void print_os_info(void); */ thread main(void) { + #if HAVE_SHELL - int shelldevs[4][3]; - uint nshells = 0; + int shelldevs[4][3]; + uint nshells = 0; #endif - /* Print information about the operating system */ - print_os_info(); + /* Print information about the operating system */ + print_os_info(); - /* Open all ethernet devices */ +//XXX Temporarily disable LAN device until USB transfers are solved. +#define NETHER 0 + /* Open all ethernet devices */ #if NETHER - { - uint i; - - for (i = 0; i < NETHER; i++) - { - if (SYSERR == open(ethertab[i].dev->num)) - { - kprintf("WARNING: Failed to open %s\r\n", - ethertab[i].dev->name); - } - } - } -#endif /* NETHER */ - - /* Set up the first TTY (CONSOLE) */ + struct ether *ethptr; + ushort i; + int result; + for (i = 0; i < NETHER; i++) + { + ethptr = ðertab[ethertab[i].dev->minor]; + result = open(ethertab[i].dev->num); + if (SYSERR == result) + { + kprintf("[ \033[1;31mERROR\033[0;39m ] Failed to open %s\r\n", + ethertab[i].dev->name); + } + else if(ETH_STATE_UP == ethptr->state) + { + kprintf("[ \033[1;32mOK\033[0;39m ] Successfully opened %s\r\n", + ethertab[i].dev->name); + } + } +#endif /* NETHER */ + + /* Set up the first TTY (CONSOLE) */ #if defined(CONSOLE) && defined(SERIAL0) - if (OK == open(CONSOLE, SERIAL0)) - { - #if HAVE_SHELL - shelldevs[nshells][0] = CONSOLE; - shelldevs[nshells][1] = CONSOLE; - shelldevs[nshells][2] = CONSOLE; - nshells++; - #endif - } - else - { - kprintf("WARNING: Can't open CONSOLE over SERIAL0\r\n"); - } + if (OK == open(CONSOLE, SERIAL0)) + { +#if HAVE_SHELL + shelldevs[nshells][0] = CONSOLE; + shelldevs[nshells][1] = CONSOLE; + shelldevs[nshells][2] = CONSOLE; + nshells++; +#endif + } + else + { + kprintf("WARNING: Can't open CONSOLE over SERIAL0\r\n"); + } #elif defined(SERIAL0) - #warning "No TTY for SERIAL0" +#warning "No TTY for SERIAL0" #endif - /* Set up the second TTY (TTY1) if possible */ + /* Set up the second TTY (TTY1) if possible */ #if defined(TTY1) - #if defined(KBDMON0) - /* Associate TTY1 with keyboard and use framebuffer output */ - if (OK == open(TTY1, KBDMON0)) - { - #if HAVE_SHELL - shelldevs[nshells][0] = TTY1; - shelldevs[nshells][1] = TTY1; - shelldevs[nshells][2] = TTY1; - nshells++; - #endif - } - else - { - kprintf("WARNING: Can't open TTY1 over KBDMON0\r\n"); - } - #elif defined(SERIAL1) - /* Associate TTY1 with SERIAL1 */ - if (OK == open(TTY1, SERIAL1)) - { - #if HAVE_SHELL - shelldevs[nshells][0] = TTY1; - shelldevs[nshells][1] = TTY1; - shelldevs[nshells][2] = TTY1; - nshells++; - #endif - } - else - { - kprintf("WARNING: Can't open TTY1 over SERIAL1\r\n"); - } - #endif /* SERIAL1 */ +#if defined(KBDMON0) + + /* Associate TTY1 with keyboard and use framebuffer output */ + if (OK == open(TTY1, KBDMON0)) + { +#if HAVE_SHELL + shelldevs[nshells][0] = TTY1; + shelldevs[nshells][1] = TTY1; + shelldevs[nshells][2] = TTY1; + nshells++; +#endif + } + else + { + kprintf("WARNING: Can't open TTY1 over KBDMON0\r\n"); + } +#elif defined(SERIAL1) + /* Associate TTY1 with SERIAL1 */ + if (OK == open(TTY1, SERIAL1)) + { +#if HAVE_SHELL + shelldevs[nshells][0] = TTY1; + shelldevs[nshells][1] = TTY1; + shelldevs[nshells][2] = TTY1; + nshells++; +#endif + } + else + { + kprintf("WARNING: Can't open TTY1 over SERIAL1\r\n"); + } +#endif /* SERIAL1 */ #else /* TTY1 */ - #if defined(KBDMON0) - #warning "No TTY for KBDMON0" - #elif defined(SERIAL1) - #warning "No TTY for SERIAL1" - #endif +#if defined(KBDMON0) +#warning "No TTY for KBDMON0" +#elif defined(SERIAL1) +#warning "No TTY for SERIAL1" +#endif #endif /* TTY1 */ - /* Start shells */ + /* Start shells */ #if HAVE_SHELL - { - uint i; - char name[16]; - - for (i = 0; i < nshells; i++) - { - sprintf(name, "SHELL%u", i); - if (SYSERR == ready(create - (shell, INITSTK, INITPRIO, name, 3, - shelldevs[i][0], - shelldevs[i][1], - shelldevs[i][2]), - RESCHED_NO)) - { - kprintf("WARNING: Failed to create %s", name); - } - } - } + { + uint i; + char name[16]; + + for (i = 0; i < nshells; i++) + { + sprintf(name, "SHELL%u", i); + if (SYSERR == ready(create + (shell, INITSTK, INITPRIO, name, 3, + shelldevs[i][0], + shelldevs[i][1], + shelldevs[i][2]), + RESCHED_NO)) + { + kprintf("WARNING: Failed to create %s", name); + } + } + } #endif - - return 0; + return 0; } /* Start of kernel in memory (provided by linker) */ extern void _start(void); -static void print_os_info(void) +void print_os_info(void) { - kprintf(VERSION); - kprintf("\r\n\r\n"); - -#ifdef DETAIL - /* Output detected platform. */ - kprintf("Processor identification: 0x%08X\r\n", cpuid); - kprintf("Detected platform as: %s, %s\r\n\r\n", - platform.family, platform.name); -#endif - - /* Output Xinu memory layout */ - kprintf("%10d bytes physical memory.\r\n", - (ulong)platform.maxaddr - (ulong)platform.minaddr); -#ifdef DETAIL - kprintf(" [0x%08X to 0x%08X]\r\n", - (ulong)platform.minaddr, (ulong)(platform.maxaddr - 1)); -#endif - - - kprintf("%10d bytes reserved system area.\r\n", - (ulong)_start - (ulong)platform.minaddr); -#ifdef DETAIL - kprintf(" [0x%08X to 0x%08X]\r\n", - (ulong)platform.minaddr, (ulong)_start - 1); -#endif - - kprintf("%10d bytes Xinu code.\r\n", (ulong)&_end - (ulong)_start); -#ifdef DETAIL - kprintf(" [0x%08X to 0x%08X]\r\n", - (ulong)_start, (ulong)&_end - 1); -#endif - - kprintf("%10d bytes stack space.\r\n", (ulong)memheap - (ulong)&_end); -#ifdef DETAIL - kprintf(" [0x%08X to 0x%08X]\r\n", - (ulong)&_end, (ulong)memheap - 1); -#endif - - kprintf("%10d bytes heap space.\r\n", - (ulong)platform.maxaddr - (ulong)memheap); -#ifdef DETAIL - kprintf(" [0x%08X to 0x%08X]\r\n\r\n", - (ulong)memheap, (ulong)platform.maxaddr - 1); -#endif - kprintf("\r\n"); + kprintf(VERSION); + kprintf("\r\n\r\n"); + + /* Output detected platform. */ + kprintf("Detected platform as: %s, %s\r\n\r\n", + platform.family, platform.name); + + /* Output Xinu memory layout */ + kprintf("%10d bytes physical memory.\r\n", + (ulong)platform.maxaddr - (ulong)platform.minaddr); + kprintf(" [0x%08X to 0x%08X]\r\n", + (ulong)platform.minaddr, (ulong)(platform.maxaddr - 1)); + + /* Output available data cache */ + kprintf("%10d kilobytes L1 data cache.\r\n", platform.dcache_size); + + kprintf("%10d bytes reserved system area.\r\n", + (ulong)_start - (ulong)platform.minaddr); + kprintf(" [0x%08X to 0x%08X]\r\n", + (ulong)platform.minaddr, (ulong)_start - 1); + + kprintf("%10d bytes Xinu code.\r\n", (ulong)&_end - (ulong)_start); + kprintf(" [0x%08X to 0x%08X]\r\n", + (ulong)_start, (ulong)&_end - 1); + + kprintf("%10d bytes stack space.\r\n", (ulong)memheap - (ulong)&_end); + kprintf(" [0x%08X to 0x%08X]\r\n", + (ulong)&_end, (ulong)memheap - 1); + + kprintf("%10d bytes heap space.\r\n", + (ulong)platform.maxaddr - (ulong)memheap); + kprintf(" [0x%08X to 0x%08X]\r\n\r\n", + (ulong)memheap, (ulong)platform.maxaddr - 1); + kprintf("\r\n"); } diff --git a/system/open.c b/system/open.c index d5540076..41cba73e 100644 --- a/system/open.c +++ b/system/open.c @@ -39,7 +39,7 @@ devcall open(int descrp, ...) } devptr = (device *)&devtab[descrp]; va_start(ap, descrp); - result = ((*devptr->open) (devptr, ap)); + result = ((*devptr->open) (devptr, ap)); va_end(ap); return result; } diff --git a/system/platforms/arm-qemu/Makerules b/system/platforms/arm-qemu/Makerules deleted file mode 100644 index fe9b97f0..00000000 --- a/system/platforms/arm-qemu/Makerules +++ /dev/null @@ -1,21 +0,0 @@ -# Rules to build files in this directory - -# Name of this component (the directory this file is stored in) -COMP = system/platforms/arm-qemu - -# Source files for this component -S_FILES = ctxsw.S \ - halt.S \ - intutils.S \ - irq_handler.S \ - memory_barrier.S \ - pause.S - -C_FILES = platforminit.c \ - pl190.c \ - setupStack.c \ - sp804.c - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/system/platforms/arm-qemu/ctxsw.S b/system/platforms/arm-qemu/ctxsw.S deleted file mode 100644 index 0f977114..00000000 --- a/system/platforms/arm-qemu/ctxsw.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/arm-qemu/halt.S b/system/platforms/arm-qemu/halt.S deleted file mode 100644 index 2cc30ea1..00000000 --- a/system/platforms/arm-qemu/halt.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/arm-qemu/interrupt.h b/system/platforms/arm-qemu/interrupt.h deleted file mode 100644 index b5b9e88e..00000000 --- a/system/platforms/arm-qemu/interrupt.h +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @file interrupt.h - * - * Constants and declarations associated with interrupt handling. - */ -/* Embedded Xinu, Copyright (C) 2009, 2013. All rights reserved. */ - -#ifndef _INTERRUPT_H_ -#define _INTERRUPT_H_ - -#include - -typedef interrupt (*interrupt_handler_t)(void); - -extern interrupt_handler_t interruptVector[]; - -typedef unsigned long irqmask; /**< machine status for disable/restore */ - - -void enable(void); -irqmask disable(void); -irqmask restore(irqmask); -void enable_irq(irqmask); -void disable_irq(irqmask); - -#endif /* _INTERRUPT_H_ */ diff --git a/system/platforms/arm-qemu/intutils.S b/system/platforms/arm-qemu/intutils.S deleted file mode 100644 index 98392c50..00000000 --- a/system/platforms/arm-qemu/intutils.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/arm-qemu/irq_handler.S b/system/platforms/arm-qemu/irq_handler.S deleted file mode 100644 index b4265e65..00000000 --- a/system/platforms/arm-qemu/irq_handler.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/arm-qemu/memory_barrier.S b/system/platforms/arm-qemu/memory_barrier.S deleted file mode 100644 index 20761c10..00000000 --- a/system/platforms/arm-qemu/memory_barrier.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/arm-qemu/pause.S b/system/platforms/arm-qemu/pause.S deleted file mode 100644 index 2d51292b..00000000 --- a/system/platforms/arm-qemu/pause.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/arm-qemu/pl190.c b/system/platforms/arm-qemu/pl190.c deleted file mode 100644 index a6ded23f..00000000 --- a/system/platforms/arm-qemu/pl190.c +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @file pl190.c - * - * Driver for the PrimeCell Vectored Interrupt Controller (VIC) (PL190). - * - * This was written using the official manual from ARM Ltd.: - * - * "PrimeCell Vectored Interrupt Controller (PL190) Technical Reference - * Manual", revision r1p2. - * - * Note: this simple driver currently does not actually use vectored interrupts - * (where the controller provides the address of the interrupt service routine - * in VICVECTADDR so that software doesn't have to check VICIRQSTATUS). Nor - * does it allow setting anything as a FIQ (Fast Interrupt Request) rather than - * a regular IRQ. - */ -/* Embedded Xinu, Copyright (C) 2014. All rights reserved. */ - -#include -#include - -static volatile struct { - uint32_t VICIRQSTATUS; /* +0x000 */ - uint32_t VICFIQSTATUS; /* +0x004 */ - uint32_t VICRAWINTR; /* +0x008 */ - uint32_t VICINTSELECT; /* +0x00C */ - uint32_t VICINTENABLE; /* +0x010 */ - uint32_t VICINTENCLEAR; /* +0x014 */ - uint32_t VICSOFTINT; /* +0x018 */ - uint32_t VICSOFTINTCLEAR; /* +0x01C */ - uint32_t VICPROTECTION; /* +0x020 */ - uint32_t VIC_0x024_reserved[3]; /* +0x024 */ - uint32_t VICVECTADDR; /* +0x030 */ - uint32_t VICDEFVECTADDR; /* +0x034 */ - uint32_t VIC_0x038_reserved[50]; /* +0x038 */ - uint32_t VICVECTADDR_REGS[16]; /* +0x100 */ - uint32_t VIC_0x140_reserved[48]; /* +0x140 */ - uint32_t VICVECTCNTL_REGS[16]; /* +0x200 */ - uint32_t VIC_0x240_reserved[872]; /* +0x240 */ - uint32_t VICPERIPHID_REGS[4]; /* +0xFE0 */ - uint32_t VICPCELLID_REGS[4]; /* +0xFF0 */ -} * const regs = (void*)0x10140000; - -interrupt_handler_t interruptVector[32]; - -/** - * Enable an interrupt request line. - * - * @param irq - * Number of the IRQ to enable, which on this platform must be in the - * range [0, 31]. - */ -void enable_irq(irqmask irq) -{ - regs->VICINTENABLE = 1U << irq; -} - -/** - * Disable an interrupt request line. - * - * @param irq - * Number of the IRQ to disable, which on this platform must be in the - * range [0, 31]. - */ -void disable_irq(irqmask irq) -{ - regs->VICINTENCLEAR = 1U << irq; -} - -/** - * Call the service routine for each pending IRQ. - */ -void dispatch(void) -{ - uint32_t status = regs->VICIRQSTATUS; - - do - { - uint irq = 31 - __builtin_clz(status); - interruptVector[irq](); - status ^= 1U << irq; - } - while (status); -} diff --git a/system/platforms/arm-qemu/platforminit.c b/system/platforms/arm-qemu/platforminit.c deleted file mode 100644 index 2df73a0b..00000000 --- a/system/platforms/arm-qemu/platforminit.c +++ /dev/null @@ -1,126 +0,0 @@ -/** - * @file platforminit.c - */ -/* Embedded Xinu, Copyright (C) 2009, 2013, 2014. All rights reserved. */ - -/* TODO: The ARM boot tags (atags) parsing could be shared with the - * Raspberry Pi port. */ - -#include -#include -#include - -/* Definitions of ARM boot tags. */ -enum { - ATAG_NONE = 0x00000000, - ATAG_CORE = 0x54410001, - ATAG_MEM = 0x54410002, - ATAG_VIDEOTEXT = 0x54410003, - ATAG_RAMDISK = 0x54410004, - ATAG_INITRD2 = 0x54410005, - ATAG_SERIAL = 0x54410006, - ATAG_REVISION = 0x54410007, - ATAG_VIDEOLFB = 0x54410008, - ATAG_CMDLINE = 0x54410009, -}; - -/* Below we only define structures for tags we actually use. */ - -/* ARM boot tag header. */ -struct atag_header { - uint32_t size; /* Size of tag, in words, including the header. */ - uint32_t tag; /* One of the ATAG_* values from above. */ -}; - -/* Description of memory region (ATAG_MEM) */ -struct atag_mem { - uint32_t size; - uint32_t start; -}; - -/* Board serial number (ATAG_SERIAL) */ -struct atag_serialnr { - uint32_t low; - uint32_t high; -}; - -/* Format of ARM boot tag */ -struct atag { - struct atag_header hdr; - union { - struct atag_mem mem; - struct atag_serialnr serialnr; - }; -}; - -/** Physical memory address at which the bootloader placed the ARM boot tags. - * This is set by the code in start.S. Here, initialize it to a dummy value to - * prevent it from being placed in .bss. */ -const struct atag *atags_ptr = (void*)-1; - -/* End of kernel (used for sanity check) */ -extern void *_end; - -/* Extract some information from the ARM boot tag list and place it in the - * 'platform' structure. */ -static void parse_atag_list(void) -{ - const struct atag *atag; - bool parse_again; - ulong maxaddr = 0; - - /* We may parse the atags more than once to try to coalesce memory specified - * as multiple contiguous chunks. */ - do - { - parse_again = FALSE; - for (atag = atags_ptr; - atag->hdr.size > 2 && atag->hdr.tag != ATAG_NONE; - atag = (const struct atag*)((const uint*)atag + atag->hdr.size)) - { - switch (atag->hdr.tag) - { - case ATAG_MEM: - if (maxaddr == atag->mem.start && atag->mem.size != 0) - { - maxaddr += atag->mem.size; - parse_again = TRUE; - } - break; - case ATAG_SERIAL: - platform.serial_low = atag->serialnr.low; - platform.serial_high = atag->serialnr.high; - break; - default: - break; - } - } - } while (parse_again); - - /* Set platform maximum address if calculated value is not insane. */ - if (maxaddr >= (ulong)&_end) - { - platform.maxaddr = (void*)maxaddr; - } -} - -extern void sp804_init(void); - -/** - * Initializes platform specific information for the ARM QEMU (Versatile PB) - * hardware. - * - * @return OK - */ -int platforminit(void) -{ - strlcpy(platform.family, "ARM VersatilePB", PLT_STRMAX); - strlcpy(platform.name, "ARM QEMU", PLT_STRMAX); - platform.maxaddr = (void *)0xBFFFFFF; /* Used only if atags are bad */ - platform.clkfreq = 1000000; - platform.serial_low = 0; /* Used only if serial # not found in atags */ - platform.serial_high = 0; /* Used only if serial # not found in atags */ - parse_atag_list(); - sp804_init(); - return OK; -} diff --git a/system/platforms/arm-qemu/setupStack.c b/system/platforms/arm-qemu/setupStack.c deleted file mode 100644 index 4885a9d5..00000000 --- a/system/platforms/arm-qemu/setupStack.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/arm-qemu/sp804.c b/system/platforms/arm-qemu/sp804.c deleted file mode 100644 index 294440da..00000000 --- a/system/platforms/arm-qemu/sp804.c +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @file sp804.c - * - * Driver for the ARM Dual Timer Module (SP804). - * - * This was written using the official manual from ARM Ltd.: - * - * "ARM Dual Timer Module (SP804) Technical Reference Manual", revision r1p0 - * - * This driver uses the first timer in the duo as a oneshot timer for - * clkupdate() and the second timer in the duo as a free-running counter for - * clkcount(). - * - * Although Embedded Xinu could make use of the periodic timer mode that is - * available on the SP804 to eliminate the need to call clkupdate() every timer - * interrupt, this driver uses the oneshot timer mode to be consistent with - * other platforms which don't have periodic timers. - */ -/* Embedded Xinu, Copyright (C) 2014. All rights reserved. */ - -#include -#include - -static volatile struct { - struct { - uint32_t Load; /* +0x00 */ - uint32_t Value; /* +0x04 */ - uint32_t Control; /* +0x08 */ - uint32_t IntClr; /* +0x0C */ - uint32_t RIS; /* +0x10 */ - uint32_t MIS; /* +0x14 */ - uint32_t BGLoad; /* +0x18 */ - uint32_t Reserved; /* +0x1C */ - } timers[2]; -} * const regs = (void*)0x101E2000; -/* On the Versatile PB, there's another SP804 at 0x101E3000. That is, another - * dual timer, for a total of *four* timers. But this driver doesn't use the - * second SP804. */ - -/* Flags for the timer control registers */ -#define SP804_TIMER_ENABLE (1 << 7) -#define SP804_TIMER_PERIODIC (1 << 6) -#define SP804_TIMER_INT_ENABLE (1 << 5) -#define SP804_TIMER_PRESCALE_1 (0 << 2) -#define SP804_TIMER_PRESCALE_16 (1 << 2) -#define SP804_TIMER_PRESCALE_256 (2 << 2) -#define SP804_TIMER_32BIT (1 << 1) -#define SP804_TIMER_ONESHOT (1 << 0) - -void sp804_init(void) -{ - /* Enable the second timer (free-running, no IRQ) */ - regs->timers[1].Control = SP804_TIMER_ENABLE | SP804_TIMER_32BIT; -} - -/* clkcount() interface is documented in clock.h */ -ulong clkcount(void) -{ - /* The timer counts down, hence the inversion. */ - return ~regs->timers[1].Value; -} - -/* clkupdate() interface is documented in clock.h */ -void clkupdate(ulong cycles) -{ - /* Clear the timer IRQ if pending. */ - regs->timers[0].IntClr = 0; - - /* Set the timer interval. */ - regs->timers[0].Load = cycles; - - /* Enable the timer (oneshot, with IRQ) */ - regs->timers[0].Control = SP804_TIMER_ENABLE | SP804_TIMER_32BIT | - SP804_TIMER_ONESHOT | SP804_TIMER_INT_ENABLE; -} diff --git a/system/platforms/arm-rpi/Makerules b/system/platforms/arm-rpi/Makerules deleted file mode 100644 index d2d2b0bc..00000000 --- a/system/platforms/arm-rpi/Makerules +++ /dev/null @@ -1,25 +0,0 @@ -# Rules to build files in this directory - -# Name of this component (the directory this file is stored in) -COMP = system/platforms/arm-rpi - -# Source files for this component -S_FILES = ctxsw.S \ - halt.S \ - intutils.S \ - irq_handler.S \ - memory_barrier.S \ - pause.S - -C_FILES = setupStack.c \ - bcm2835_power.c \ - dispatch.c \ - kexec.c \ - platforminit.c \ - timer.c \ - usb_dwc_hcd.c \ - watchdog.c - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/system/platforms/arm-rpi/bcm2835_power.c b/system/platforms/arm-rpi/bcm2835_power.c deleted file mode 100644 index 8359e645..00000000 --- a/system/platforms/arm-rpi/bcm2835_power.c +++ /dev/null @@ -1,112 +0,0 @@ -/** - * @file bcm2835_power.c - * - * This driver provides the ability to power on and power off hardware, such as - * the USB Controller, on the BCM2835 SoC used on the Raspberry Pi. This makes - * use of the BCM2835's mailbox mechanism. - */ -#include "bcm2835.h" - -static volatile uint *const mailbox_regs = (volatile uint*)MAILBOX_REGS_BASE; - -/* BCM2835 mailbox register indices */ -#define MAILBOX_READ 0 -#define MAILBOX_STATUS 6 -#define MAILBOX_WRITE 8 - -/* BCM2835 mailbox status flags */ -#define MAILBOX_FULL 0x80000000 -#define MAILBOX_EMPTY 0x40000000 - -/* BCM2835 mailbox channels */ -#define MAILBOX_CHANNEL_POWER_MGMT 0 - -/* The BCM2835 mailboxes are used for passing 28-bit messages. The low 4 bits - * of the 32-bit value are used to specify the channel over which the message is - * being transferred */ -#define MAILBOX_CHANNEL_MASK 0xf - -/* Write to the specified channel of the mailbox. */ -static void -bcm2835_mailbox_write(uint channel, uint value) -{ - while (mailbox_regs[MAILBOX_STATUS] & MAILBOX_FULL) - { - } - mailbox_regs[MAILBOX_WRITE] = (value & ~MAILBOX_CHANNEL_MASK) | channel; -} - -/* Read from the specified channel of the mailbox. */ -static uint -bcm2835_mailbox_read(uint channel) -{ - uint value; - - while (mailbox_regs[MAILBOX_STATUS] & MAILBOX_EMPTY) - { - } - do - { - value = mailbox_regs[MAILBOX_READ]; - } while ((value & MAILBOX_CHANNEL_MASK) != channel); - return (value & ~MAILBOX_CHANNEL_MASK); -} - -/* Retrieve the bitmask of power on/off state. */ -static uint -bcm2835_get_power_mask(void) -{ - return (bcm2835_mailbox_read(MAILBOX_CHANNEL_POWER_MGMT) >> 4); -} - -/* Set the bitmask of power on/off state. */ -static void -bcm2835_set_power_mask(uint mask) -{ - bcm2835_mailbox_write(MAILBOX_CHANNEL_POWER_MGMT, mask << 4); -} - -/* Bitmask that gives the current on/off state of the BCM2835 hardware. - * This is a cached value. */ -static uint bcm2835_power_mask; - -/** - * Powers on or powers off BCM2835 hardware. - * - * @param feature - * Device or hardware to power on or off. - * @param on - * ::TRUE to power on; ::FALSE to power off. - * - * @return - * ::OK if successful; ::SYSERR otherwise. - */ -int bcm2835_setpower(enum board_power_feature feature, bool on) -{ - uint bit; - uint newmask; - bool is_on; - - bit = 1 << feature; - is_on = (bcm2835_power_mask & bit) != 0; - if (on != is_on) - { - newmask = bcm2835_power_mask ^ bit; - bcm2835_set_power_mask(newmask); - bcm2835_power_mask = bcm2835_get_power_mask(); - if (bcm2835_power_mask != newmask) - { - return SYSERR; - } - } - return OK; -} - -/** - * Resets BCM2835 power to default state (all devices powered off). - */ -void bcm2835_power_init(void) -{ - bcm2835_set_power_mask(0); - bcm2835_power_mask = 0; -} diff --git a/system/platforms/arm-rpi/ctxsw.S b/system/platforms/arm-rpi/ctxsw.S deleted file mode 100644 index 0f977114..00000000 --- a/system/platforms/arm-rpi/ctxsw.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/arm-rpi/halt.S b/system/platforms/arm-rpi/halt.S deleted file mode 100644 index 2cc30ea1..00000000 --- a/system/platforms/arm-rpi/halt.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/arm-rpi/intutils.S b/system/platforms/arm-rpi/intutils.S deleted file mode 100644 index 98392c50..00000000 --- a/system/platforms/arm-rpi/intutils.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/arm-rpi/irq_handler.S b/system/platforms/arm-rpi/irq_handler.S deleted file mode 100644 index b4265e65..00000000 --- a/system/platforms/arm-rpi/irq_handler.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/arm-rpi/memory_barrier.S b/system/platforms/arm-rpi/memory_barrier.S deleted file mode 100644 index 20761c10..00000000 --- a/system/platforms/arm-rpi/memory_barrier.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/arm-rpi/pause.S b/system/platforms/arm-rpi/pause.S deleted file mode 100644 index 2d51292b..00000000 --- a/system/platforms/arm-rpi/pause.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/arm-rpi/platforminit.c b/system/platforms/arm-rpi/platforminit.c deleted file mode 100644 index f117abbd..00000000 --- a/system/platforms/arm-rpi/platforminit.c +++ /dev/null @@ -1,121 +0,0 @@ -/** - * @file platforminit.c - */ -/* Embedded Xinu, Copyright (C) 2009, 2013. All rights reserved. */ - -#include -#include -#include "bcm2835.h" - -/* Definitions of ARM boot tags. */ -enum { - ATAG_NONE = 0x00000000, - ATAG_CORE = 0x54410001, - ATAG_MEM = 0x54410002, - ATAG_VIDEOTEXT = 0x54410003, - ATAG_RAMDISK = 0x54410004, - ATAG_INITRD2 = 0x54410005, - ATAG_SERIAL = 0x54410006, - ATAG_REVISION = 0x54410007, - ATAG_VIDEOLFB = 0x54410008, - ATAG_CMDLINE = 0x54410009, -}; - -/* Below we only define structures for tags we actually use. */ - -/* ARM boot tag header. */ -struct atag_header { - uint size; /* Size of tag, in words, including the header. */ - uint tag; /* One of the ATAG_* values from above. */ -}; - -/* Description of memory region (ATAG_MEM) */ -struct atag_mem { - uint size; - uint start; -}; - -/* Board serial number (ATAG_SERIAL) */ -struct atag_serialnr { - uint low; - uint high; -}; - -/* Format of ARM boot tag */ -struct atag { - struct atag_header hdr; - union { - struct atag_mem mem; - struct atag_serialnr serialnr; - }; -}; - -/** Physical memory address at which the bootloader placed the ARM boot tags. - * This is set by the code in start.S. Here, initialize it to a dummy value to - * prevent it from being placed in .bss. */ -const struct atag *atags_ptr = (void*)-1; - -/* End of kernel (used for sanity check) */ -extern void *_end; - -/* Extract some information from the ARM boot tag list and place it in the - * 'platform' structure. */ -static void -parse_atag_list(void) -{ - const struct atag *atag; - bool parse_again; - ulong maxaddr = 0; - - /* We may parse the atags more than once to try to coalesce memory specified - * as multiple contiguous chunks. */ - do - { - parse_again = FALSE; - for (atag = atags_ptr; - atag->hdr.size > 2 && atag->hdr.tag != ATAG_NONE; - atag = (const struct atag*)((const uint*)atag + atag->hdr.size)) - { - switch (atag->hdr.tag) - { - case ATAG_MEM: - if (maxaddr == atag->mem.start && atag->mem.size != 0) - { - maxaddr += atag->mem.size; - parse_again = TRUE; - } - break; - case ATAG_SERIAL: - platform.serial_low = atag->serialnr.low; - platform.serial_high = atag->serialnr.high; - break; - default: - break; - } - } - } while (parse_again); - - /* Set platform maximum address if calculated value is not insane. */ - if (maxaddr >= (ulong)&_end) - { - platform.maxaddr = (void*)maxaddr; - } -} - - -/** - * Initializes platform specific information for the Raspberry Pi hardware. - * @return OK - */ -int platforminit(void) -{ - strlcpy(platform.family, "BCM2835", PLT_STRMAX); - strlcpy(platform.name, "Raspberry Pi", PLT_STRMAX); - platform.maxaddr = (void *)0xBFFFFFF; /* Used only if atags are bad */ - platform.clkfreq = 1000000; - platform.serial_low = 0; /* Used only if serial # not found in atags */ - platform.serial_high = 0; /* Used only if serial # not found in atags */ - parse_atag_list(); - bcm2835_power_init(); - return OK; -} diff --git a/system/platforms/arm-rpi/setupStack.c b/system/platforms/arm-rpi/setupStack.c deleted file mode 100644 index 4885a9d5..00000000 --- a/system/platforms/arm-rpi/setupStack.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/arm-rpi3/Makerules b/system/platforms/arm-rpi3/Makerules new file mode 100644 index 00000000..fafb78d6 --- /dev/null +++ b/system/platforms/arm-rpi3/Makerules @@ -0,0 +1,38 @@ +# Rules to build files in this directory + +# Name of this component (the directory this file is stored in) +COMP = system/platforms/arm-rpi3 + +# Source files for this component +S_FILES = ctxsw.S \ + halt.S \ + intutils.S \ + irq_handler.S \ + memory_barrier.S \ + pause.S \ + getmode.S \ + getcpuid.S \ + setupCores.S \ + setmode.S \ + mutex_util.S \ + mmu_util.S \ + preload_data.S \ + +C_FILES = setupStack.c \ + bcm2837_power.c \ + dispatch.c \ + kexec.c \ + platforminit.c \ + timer.c \ + usb_dwc_hcd.c \ + watchdog.c \ + unparkcore.c \ + mmu.c \ + random.c \ + bcm2837_mbox.c \ + des.c \ + mutex.c + +# Add the files to the compile source path +DIR = ${TOPDIR}/${COMP} +COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/system/platforms/arm-rpi/bcm2835.h b/system/platforms/arm-rpi3/bcm2837.h similarity index 81% rename from system/platforms/arm-rpi/bcm2835.h rename to system/platforms/arm-rpi3/bcm2837.h index dbad54c3..df4753f5 100644 --- a/system/platforms/arm-rpi/bcm2835.h +++ b/system/platforms/arm-rpi3/bcm2837.h @@ -1,24 +1,24 @@ /** - * @file bcm2835.h + * @file bcm2837.h * - * Definitions specific to the BCM2835 SoC used in the Raspberry Pi. + * Definitions specific to the BCM2837 SoC used in the Raspberry Pi 3. * * Note that although some of the numbers defined in this file are documented in - * Broadcom's "BCM2835 ARM Peripherals" document, unfortunately some could only + * Broadcom's "BCM2837 ARM Peripherals" document, unfortunately some could only * be found in the Linux source (arch/arm/mach-bcm2708/include/mach/platform.h). */ -#ifndef _BCM2835_H_ -#define _BCM2835_H_ +#ifndef _BCM2837_H_ +#define _BCM2837_H_ #include /******************************************************************** - * ARM physical memory addresses of selected BCM2835 peripherals * + * ARM physical memory addresses of selected BCM2837 peripherals * ********************************************************************/ /* Start of memory-mapped peripherals address space */ -#define PERIPHERALS_BASE 0x20000000 +#define PERIPHERALS_BASE 0x3F000000 /* System timer */ #define SYSTEM_TIMER_REGS_BASE (PERIPHERALS_BASE + 0x3000) @@ -35,6 +35,9 @@ /* PL011 UART */ #define PL011_REGS_BASE (PERIPHERALS_BASE + 0x201000) +/* GPIO */ +#define GPIO_REGS_BASE (PERIPHERALS_BASE + 0x200000) + /* SD host controller */ #define SDHCI_REGS_BASE (PERIPHERALS_BASE + 0x300000) @@ -43,7 +46,7 @@ /*************************************************************************** - * IRQ lines of selected BCM2835 peripherals. Note about the numbering * + * IRQ lines of selected BCM2837 peripherals. Note about the numbering * * used here: IRQs 0-63 are those shared between the GPU and CPU, whereas * * IRQs 64+ are CPU-specific. * ***************************************************************************/ @@ -82,21 +85,23 @@ enum board_power_feature { POWER_USB = 3, }; -extern int bcm2835_setpower(enum board_power_feature feature, bool on); -extern void bcm2835_power_init(void); +extern int bcm2837_setpower(enum board_power_feature feature, bool on); +extern void bcm2837_power_init(void); -#define board_setpower bcm2835_setpower +#define board_setpower bcm2837_setpower /************************************************************************ * Interfaces to memory barriers for peripheral access. * * * * These are necessary due to the memory ordering caveats documented in * - * section 1.3 of Broadcom's "BCM2835 ARM Peripherals" document. * + * section 1.3 of Broadcom's "BCM2837 ARM Peripherals" document. * ************************************************************************/ extern void dmb(void); +extern bool lan7800_isattached; + /* Memory barriers needed before/after one or more reads from a peripheral */ #define pre_peripheral_read_mb dmb #define post_peripheral_read_mb dmb @@ -110,4 +115,4 @@ extern void dmb(void); #define pre_peripheral_access_mb dmb #define post_peripheral_access_mb dmb -#endif /* _BCM2835_H_ */ +#endif /* _BCM2837_H_ */ diff --git a/system/platforms/arm-rpi3/bcm2837_mbox.c b/system/platforms/arm-rpi3/bcm2837_mbox.c new file mode 100644 index 00000000..4b4c7ba5 --- /dev/null +++ b/system/platforms/arm-rpi3/bcm2837_mbox.c @@ -0,0 +1,55 @@ +/* Definitions for Mailbox functions of the BCM2837B0 (Pi 3 B+). + * + * Embedded Xinu Copyright (C) 2009, 2013, 2018. All rights reserved. + * + * Authors: Patrick J. McGee + * Rade Latinovich + */ + +#include +#include +#include +#include "bcm2837_mbox.h" + +/* Add a tag to the mailbox buffer. This step must be done before a mailbox request is built. */ +void add_mailbox_tag(volatile uint32_t* buffer, uint32_t tag, uint32_t buflen, uint32_t len, uint32_t* data) { + volatile uint32_t* start = buffer + SLOT_TAGSTART; + start[SLOT_TAG_ID] = tag; + start[SLOT_TAG_BUFLEN] = buflen; + start[SLOT_TAG_DATALEN] = len & 0x7FFFFFFF; + uint32_t bufwords = buflen >> 2; + + if (0 == data) { + for (int i = 0; i < bufwords; ++i) { + start[SLOT_TAG_DATA + i] = 0; + } + } else { + for (int i = 0; i < bufwords; ++i) { + start[SLOT_TAG_DATA + i] = data[i]; + } + } + /* End of tags, unless overwritten later */ + start[SLOT_TAG_DATA+bufwords] = 0; +} + +/* Ready the buffer by initializing proper lengths, slots. */ +void build_mailbox_request(volatile uint32_t* mailbuffer) { + uint32_t tag_length = mailbuffer[MBOX_HEADER_LENGTH + SLOT_TAG_BUFLEN]; + uint32_t end = (MBOX_HEADER_LENGTH*4) + (TAG_HEADER_LENGTH*4) + tag_length; + uint32_t overall_length = end + 4; + mailbuffer[SLOT_OVERALL_LENGTH] = overall_length; + mailbuffer[SLOT_RR] = RR_REQUEST; +} + +/* Function for getting the MAC address using the corresponding MAC mailbox tag. + * @param volatile uint32_t* mailbuffer Mailbox buffer written with MAC address upon conclusion. */ +void get_mac_mailbox(volatile uint32_t* mailbuffer){ + + /* Load the tag, build the buffer */ + add_mailbox_tag(mailbuffer, MBX_TAG_GET_MAC_ADDRESS, 8, 0, 0); + build_mailbox_request(mailbuffer); + + /* Write the mailbox register */ + bcm2837_mailbox_write(8, (uint32_t)mailbuffer); + bcm2837_mailbox_read(8); +} diff --git a/system/platforms/arm-rpi3/bcm2837_mbox.h b/system/platforms/arm-rpi3/bcm2837_mbox.h new file mode 100644 index 00000000..dcdb955b --- /dev/null +++ b/system/platforms/arm-rpi3/bcm2837_mbox.h @@ -0,0 +1,86 @@ +/* Mailbox driver for the BCM2837B0 (Pi 3 B+). + * + * Embedded Xinu Copyright (C) 2009, 2013, 2018. All rights reserved. + * + * Authors: Patrick J. McGee + * Rade Latinovich + */ + +#include "bcm2837.h" +#include + +/* Mailbox functions */ +void bcm2837_mailbox_write(uint, uint); +uint bcm2837_mailbox_read(uint); +void add_mailbox_tag(volatile uint32_t*, uint32_t, uint32_t, uint32_t, uint32_t*); +void build_mailbox_request(volatile uint32_t*); +void dump_response(volatile uint32_t*, const char*, int); +void print_parameter(volatile uint32_t*, const char*, uint32_t, int); +void get_mac_mailbox(volatile uint32_t*); + +/* Mailbox base offset */ +#define MAILBOX_REGS_BASE (PERIPHERALS_BASE + 0xB880) + +static volatile uint *const mailbox_regs = (volatile uint*)MAILBOX_REGS_BASE; + +/* BCM2837 mailbox register indices */ +#define MAILBOX_READ 0 +#define MAILBOX_STATUS 6 +#define MAILBOX_WRITE 8 + +/* BCM2837 mailbox status flags */ +#define MAILBOX_FULL 0x80000000 +#define MAILBOX_EMPTY 0x40000000 + +/* BCM2837 mailbox channels */ +#define MAILBOX_CHANNEL_POWER_MGMT 0 +#define MAILBOX_CHANNEL_1 1 + +/* The BCM2837 mailboxes are used for passing 28-bit messages. The low 4 bits + * * of the 32-bit value are used to specify the channel over which the message is + * * being transferred */ +#define MAILBOX_CHANNEL_MASK 0xf + +/* Length of mailbox buffer. */ +#define MBOX_BUFLEN 1024 + +/* States for the mailbox. */ +#define RR_REQUEST 0x00000000 +#define RR_RESPONSE_OK 0x80000000 +#define RR_RESPONSE_ERROR 0x80000001 + +#define SLOT_OVERALL_LENGTH 0 +#define SLOT_RR 1 +#define SLOT_TAGSTART 2 + +#define SLOT_TAG_ID 0 +#define SLOT_TAG_BUFLEN 1 +#define SLOT_TAG_DATALEN 2 +#define SLOT_TAG_DATA 3 + +#define MBOX_HEADER_LENGTH 2 +#define TAG_HEADER_LENGTH 3 + +#define MBX_DEVICE_SDCARD 0x00000000 +#define MBX_DEVICE_UART0 0x00000001 +#define MBX_DEVICE_UART1 0x00000002 +#define MBX_DEVICE_USBHCD 0x00000003 +#define MBX_DEVICE_I2C0 0x00000004 +#define MBX_DEVICE_I2C1 0x00000005 +#define MBX_DEVICE_I2C2 0x00000006 +#define MBX_DEVICE_SPI 0x00000007 +#define MBX_DEVICE_CCP2TX 0x00000008 + +/* Mailbox tags for receiving board information. */ +#define MBX_TAG_GET_FIRMWARE 0x00000001 /* in 0, out 4 */ +#define MBX_TAG_GET_BOARD_MODEL 0x00010001 /* in 0, out 4 */ +#define MBX_TAG_GET_BOARD_REVISION 0x00010002 /* in 0, out 4 */ +#define MBX_TAG_GET_MAC_ADDRESS 0x00010003 /* in 0, out 6 */ +#define MBX_TAG_GET_BOARD_SERIAL 0x00010004 /* in 0, out 8 */ +#define MBX_TAG_GET_ARM_MEMORY 0x00010005 /* in 0, out 8 (4 -> base addr, 4 -> len in bytes) */ +#define MBX_TAG_GET_VC_MEMORY 0x00010006 /* in 0, out 8 (4 -> base addr, 4 -> len in bytes) */ +#define MBX_TAG_GET_COMMANDLINE 0x00050001 /* in 0, out variable */ +#define MBX_TAG_GET_DMA_CHANNELS 0x00060001 /* in 0, out 4 */ +#define MBX_TAG_GET_POWER_STATE 0x00020001 /* in 4 -> dev id, out 8 (4 -> device, 4 -> status) */ +#define MBX_TAG_GET_TIMING 0x00020002 /* in 0, out 4 */ +#define MBX_TAG_GET_FIRMWARE 0x00000001 /* in 0, out 4 */ diff --git a/system/platforms/arm-rpi3/bcm2837_power.c b/system/platforms/arm-rpi3/bcm2837_power.c new file mode 100644 index 00000000..7dd2c42f --- /dev/null +++ b/system/platforms/arm-rpi3/bcm2837_power.c @@ -0,0 +1,95 @@ +/** + * @file bcm2837_power.c + * + * This driver provides the ability to power on and power off hardware, such as + * the USB Controller, on the BCM2837B0 SoC used on the Raspberry Pi 3 B+. This makes + * use of the BCM2837B0's mailbox mechanism. + */ +#include "bcm2837.h" +#include "bcm2837_mbox.h" +#include "mmu.h" + +/* Write to the specified channel of the mailbox. */ +void +bcm2837_mailbox_write(uint channel, uint value) +{ + while (mailbox_regs[MAILBOX_STATUS] & MAILBOX_FULL) + { + } + mailbox_regs[MAILBOX_WRITE] = (value & ~MAILBOX_CHANNEL_MASK) | channel; +} + +/* Read from the specified channel of the mailbox. */ +uint +bcm2837_mailbox_read(uint channel) +{ + uint value; + + while (mailbox_regs[MAILBOX_STATUS] & MAILBOX_EMPTY) + { + } + do + { + value = mailbox_regs[MAILBOX_READ]; + } while ((value & MAILBOX_CHANNEL_MASK) != channel); + return (value & ~MAILBOX_CHANNEL_MASK); +} + +/* Retrieve the bitmask of power on/off state. */ +static uint +bcm2837_get_power_mask(void) +{ + return (bcm2837_mailbox_read(MAILBOX_CHANNEL_POWER_MGMT) >> 4); +} + +/* Set the bitmask of power on/off state. */ +static void +bcm2837_set_power_mask(uint mask) +{ + bcm2837_mailbox_write(MAILBOX_CHANNEL_POWER_MGMT, mask << 4); +} + +/* Bitmask that gives the current on/off state of the BCM2837 hardware. + * This is a cached value. */ +static uint bcm2837_power_mask; + +/** + * Powers on or powers off BCM2837 hardware. + * + * @param feature + * Device or hardware to power on or off. + * @param on + * ::TRUE to power on; ::FALSE to power off. + * + * @return + * ::OK if successful; ::SYSERR otherwise. + */ +int bcm2837_setpower(enum board_power_feature feature, bool on) +{ + uint bit; + uint newmask; + bool is_on; + + bit = 1 << feature; + is_on = (bcm2837_power_mask & bit) != 0; + if (on != is_on) + { + newmask = bcm2837_power_mask ^ bit; + bcm2837_set_power_mask(newmask); + bcm2837_power_mask = bcm2837_get_power_mask(); + if (bcm2837_power_mask != newmask) + { + return SYSERR; + } + } + return OK; +} + +/** + * Resets BCM2837 power to default state (all devices powered off). + */ +void bcm2837_power_init(void) +{ + bcm2837_set_power_mask(0); + bcm2837_power_mask = 0; +} diff --git a/system/platforms/arm-rpi3/ctxsw.S b/system/platforms/arm-rpi3/ctxsw.S new file mode 100644 index 00000000..578cda0d --- /dev/null +++ b/system/platforms/arm-rpi3/ctxsw.S @@ -0,0 +1,54 @@ + +/** + * @file ctxsw.s + * @provides ctxsw + * + * COSC 3250 / COEN 4820 Assignment 4 + */ +/* Embedded XINU, Copyright (C) 2013. All rights reserved. */ + +#include + +.text + .align 4 + .globl ctxsw + +/** + * @fn void ctxsw(&oldregs, &newregs) + * + * Switch context (values in registers) to another process, saving the + * current processes information. This function will not return as normally + * thought; as it will load in the stack pointer for a different process and + * jump to that location and begin executing code. + * + * @param &oldregs address of outgoing register save area + * @param &newregs address of incoming register save area + * @return special case -- see above + */ + +ctxsw: + + .func ctxsw + + /* Store registers in respective places in stack. Link register gets saved into location for stack pointer*/ + /* so when process switches back, program will continue execution in correct location*/ + + mrs r12, cpsr + push {r0-r14} + + str sp, [r0] + ldr sp, [r1] + + /* Load registers from respective places in stack. */ + /* Program counter must be loaded last, since program will jump.*/ + /* In this case, returning is same as loading the link register into the program counter*/ + + pop {r0-r12} + msr cpsr_c, r12 + + /* Load link register into program counter*/ + /* Not returning back to function we came from, but going to new function in different process, */ + /* since we changed value of link register*/ + pop {lr, pc} + + .endfunc diff --git a/system/platforms/arm-rpi3/des.c b/system/platforms/arm-rpi3/des.c new file mode 100644 index 00000000..87e4c997 --- /dev/null +++ b/system/platforms/arm-rpi3/des.c @@ -0,0 +1,501 @@ +#include +#include +#include +#include +#include "des.h" +#include "random.h" + +////////////////////////////////////////////////////// +// GLOBAL VARIABLES // +//////////////////////////////////////////////////// + +// Tables bellow can be verified on wikipedia: +// http://en.wikipedia.org/wiki/DES_supplementary_material#Initial_permutation_.28IP.29 + +// Key schedule tables + +const int PC1[56] = { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 +}; +const int Rotations[16] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; +const int PC2[48] = { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 +}; + +// Permutation tables + +const int InitialPermutation[64] = { + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, + 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7 +}; +const int FinalPermutation[64] = { + 40, 8, 48, 16, 56, 24, 64, 32, + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25 +}; + +// Rounds tables + +const int DesExpansion[48] = { + 32, 1, 2, 3, 4, 5, 4, 5, + 6, 7, 8, 9, 8, 9, 10, 11, + 12, 13, 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, 20, 21, + 22, 23, 24, 25, 24, 25, 26, 27, + 28, 29, 28, 29, 30, 31, 32, 1 +}; + +const int DesSbox[8][4][16] = { + { + {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, + { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, + { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, + {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}, + }, + + { + {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, + { 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5}, + { 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15}, + {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}, + }, + + { + {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, + {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1}, + {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7}, + { 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}, + }, + + { + { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, + {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9}, + {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4}, + { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}, + }, + + { + { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, + {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6}, + { 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14}, + {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}, + }, + + { + {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, + {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8}, + { 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6}, + { 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}, + }, + + { + { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, + {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6}, + { 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2}, + { 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}, + }, + + { + {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, + { 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2}, + { 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8}, + { 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}, + }, +}; + +const int Pbox[32] = { + 16, 7, 20, 21, 29, 12, 28, 17, + 1, 15, 23, 26, 5, 18, 31, 10, + 2, 8, 24, 14, 32, 27, 3, 9, + 19, 13, 30, 6, 22, 11, 4, 25 +}; + +////////////////////////////////////////////////////// +// FUNCTIONS // +//////////////////////////////////////////////////// + +void addbit(uint64_t *block, uint64_t from, + int position_from, int position_to) +{ + if(((from << (position_from)) & FIRSTBIT) != 0) + *block += (FIRSTBIT >> position_to); +} + +void Permutation(uint64_t* data, bool initial) +{ + uint64_t data_temp = 0; + for(int ii = 0; ii < 64; ii++) + { + if(initial) + addbit(&data_temp, *data, InitialPermutation[ii] - 1, ii); + else + addbit(&data_temp, *data, FinalPermutation[ii] - 1, ii); + } + *data = data_temp; +} + +bool key_parity_verify(uint64_t key) +{ + int parity_bit = 0; // Parity helper + + for(int ii = 0; ii < 64; ii++) + { + // Test the parity bit (8-th bit) + if(ii % 8 == 7) + { + if(parity_bit == 0) + { + // Test if 8-th bit != 0 + if( ((key << ii) & FIRSTBIT) != (uint64_t)0) + { + kprintf("parity error at bit #%d\n", ii + 1); + return FALSE; + } + } + else + { + // Test if 8-th bit != 1 + if( ((key << ii) & FIRSTBIT) != FIRSTBIT) + { + kprintf("parity error at bit #%d\n", ii + 1); + return FALSE; + } + + } + parity_bit = 0; // Re-init parity_bit for next byte block + } + // Count numbers of 1 in the 7bit block + else + { + if( ((key << ii) & FIRSTBIT) == FIRSTBIT) + parity_bit = parity_bit == 0 ? 1 : 0; + } + } + + return TRUE; +} + +void key_schedule(uint64_t* key, uint64_t* next_key, int round) +{ + // Init + uint64_t key_left = 0; + uint64_t key_right = 0; + + uint64_t key_left_temp = 0; + uint64_t key_right_temp = 0; + + *next_key = 0; // Important ! + + // 1. First round => PC-1 : Permuted Choice 1 + if(round == 0) + { + for(int ii = 0; ii < 56; ii++) + { + if(ii < 28) + addbit(&key_left, *key, PC1[ii] - 1, ii); + else + addbit(&key_right, *key, PC1[ii] - 1, ii % 28); + } + } + // 1'. Other rounds? => Seperate key into two key halves. + else + { + for(int ii = 0; ii < 56; ii++) + { + if(ii < 28) + addbit(&key_left, *key, ii, ii); + else + addbit(&key_right, *key, ii, ii % 28); + } + } + + // 2. Rotations + key_left_temp = Rotations[round] == 1 ? FIRSTBIT : 0xC000000000000000; + key_right_temp = Rotations[round] == 1 ? FIRSTBIT : 0xC000000000000000; + key_left_temp = (key_left & key_left_temp) >> (28 - Rotations[round]); + key_right_temp = (key_right & key_right_temp) >> (28 - Rotations[round]); + + key_left_temp += (key_left << Rotations[round]); + key_right_temp += (key_right << Rotations[round]); + + // Combine the 2 keys into 1 (next_key) + // Next_key will be used for following rounds + for(int ii = 0; ii < 56; ii++) + { + if(ii < 28) + addbit(next_key, key_left_temp, ii, ii); + else + addbit(next_key, key_right_temp, (ii % 28), ii); + } + + // 3. PC-2 : Permuted Choice 2 + *key = 0; + + for(int ii = 0; ii < 48; ii++) + addbit(key, *next_key, PC2[ii] - 1, ii); + + // All Good! + // Use key in the DES rounds. + // Use next_key in this function again as the new key to change +} + +void rounds(uint64_t *data, uint64_t key) +{ + uint64_t right_block = 0; + uint64_t right_block_temp = 0; + + // 1. Block expansion + for(int ii = 0; ii < 48; ii++) + addbit(&right_block, *data, (DesExpansion[ii] + 31), ii); + + // 2. Xor with the key + right_block = right_block ^ key; + + // 3. Substitution + int coordx, coordy; + uint64_t substitued; + + for(int ii = 0; ii < 8; ii++) + { + coordx = ((right_block << 6 * ii) & FIRSTBIT) == FIRSTBIT ? 2 : 0; + if( ((right_block << (6 * ii + 5)) & FIRSTBIT) == FIRSTBIT) + coordx++; + + coordy = 0; + for(int jj = 1; jj < 5; jj++) + { + if( ((right_block << (6 * ii + jj)) & FIRSTBIT) == FIRSTBIT) + { + coordy += 2^(4 - jj); + } + } + + substitued = DesSbox[ii][coordx][coordy]; + substitued = substitued << (60 - (4 * ii)); + right_block_temp += substitued; + } + + // Right_block done + right_block = right_block_temp; + + // 4. Permutation + right_block_temp = 0; + + for(int ii = 0; ii < 32; ii++) + addbit(&right_block_temp, right_block, Pbox[ii] - 1, ii); + + right_block = right_block_temp; + + // 5. Xor with the left block + right_block = right_block ^ *data; + + // Combine the new block and the right block + *data = (*data << 32) + (right_block >> 32); +} + +void genkey(uint64_t *key) +{ + + srand(clkcount()); + + int ii, jj; + int parity_bit = 0; + // generate key + for (ii = 0; ii < 64; ii++) + { + // parity bit + if (ii % 8 == 7) + { + if (parity_bit == 1) + *key += (FIRSTBIT >> ii); + parity_bit = 0; + } + else + { + if (rand() % 2 == 1) + { + *key += (FIRSTBIT >> ii); + parity_bit = parity_bit == 0 ? 1 : 0; + } + } + } + + // test key schedule + uint64_t a_key[16]; + a_key[0] = *key; + uint64_t next_key; + + for (ii = 0; ii < 16; ii++) + { + key_schedule(&a_key[ii], &next_key, ii); + if (ii != 15) + a_key[ii + 1] = next_key; + } + + // test for weak key + bool weak = FALSE; + + for (ii = 0; ii < 16; ii++) + { + for (jj = 0; jj < 16; jj++) + { + if (jj != ii) + { + if (a_key[ii] == a_key[jj]) + weak = TRUE; + } + } + } + + if (TRUE == weak) + genkey(key); +} + +void des_encrypt(char *in, int isize, char *out, uint64_t key) +{ + int i; + + /* make sure input is 8-byte aligned */ + /* (this library has no built in padding */ + if (isize % 8 != 0) + { + kprintf("Input is not 8-byte aligned..\r\n"); + return; + } + + uint nblocks = isize / 8; /* amount of 64-bit blocks in the input buffer */ + uint64_t *input = (uint64_t *) in; + uint64_t *output = (uint64_t *) out; + + /* verify key parity */ + if (!key_parity_verify(key)) + { + kprintf("Bad parity bits in key...\r\n"); + return; + } + + + /* get 16 subkeys */ + uint64_t a_key[16]; + a_key[0] = key; + uint64_t next_key; + + for (i = 0; i < 16; i++) + { + key_schedule(&a_key[i], &next_key, i); + if (i != 15) + a_key[i + 1] = next_key; + } + + /* 16 rounds of encryption */ + uint block = 0; + uint64_t data; + + while (block < nblocks) + { + /* initial permutation */ + data = input[block]; + Permutation(&data, TRUE); + + for (i = 0; i < 16; i++) + rounds(&data, a_key[i]); + + /* final permutation */ + Permutation(&data, FALSE); + + output[block] = data; + block++; + } +} + +void des_decrypt(char *in, int isize, char *out, uint64_t key) +{ + int i; + + /* make sure input is 8-byte aligned */ + /* (this library has no built in padding */ + if (isize % 8 != 0) + { + kprintf("Input is not 8-byte aligned..\r\n"); + return; + } + + uint nblocks = isize / 8; /* amount of 64-bit blocks in the input buffer */ + uint64_t *input = (uint64_t *) in; + uint64_t *output = (uint64_t *) out; + + /* verify key parity */ + if (!key_parity_verify(key)) + { + kprintf("Bad parity bits in key...\r\n"); + return; + } + + + /* get 16 subkeys */ + uint64_t a_key[16]; + a_key[0] = key; + uint64_t next_key; + + for (i = 0; i < 16; i++) + { + key_schedule(&a_key[i], &next_key, i); + if (i != 15) + a_key[i + 1] = next_key; + } + + /* 16 rounds of encryption */ + uint block = 0; + uint64_t data; + + while (block < nblocks) + { + /* initial permutation */ + data = input[block]; + Permutation(&data, TRUE); + + /* switching blocks */ + data = (data << 32) + (data >> 32); + + for (i = 15; i >= 0; i--) + rounds(&data, a_key[i]); + + /* switching blocks back */ + data = (data << 32) + (data >> 32); + + /* final permutation */ + Permutation(&data, FALSE); + + output[block] = data; + block++; + } +} + +// End of file diff --git a/system/platforms/arm-rpi3/des.h b/system/platforms/arm-rpi3/des.h new file mode 100644 index 00000000..877985c1 --- /dev/null +++ b/system/platforms/arm-rpi3/des.h @@ -0,0 +1,51 @@ +// +// Implementation of DES coded by: +// - David Wong, moi@davidwong.fr +// - Jacques Monin, jacques.monin@u-bordeaux.fr +// - Hugo Bonnin, hugo.bonnin@u-bordeaux.fr +// + +#ifndef DES_H +#define DES_H + +////////////////////////////////////////////////////// +// USEFUL DEFINES // +//////////////////////////////////////////////////// + +#define FIRSTBIT 0x8000000000000000 // 1000000000... + +////////////////////////////////////////////////////// +// PROTOTYPES // +//////////////////////////////////////////////////// + +// Addbit helper +// Takes the bit number "position_from" from "from" +// adds it to "block" in position "position_to" +void addbit(uint64_t *block, uint64_t from, + int position_from, int position_to); + +// Initial and Final Permutations +void Permutation(uint64_t* data, bool initial); + +// Verify if the parity bits are okay +bool key_parity_verify(uint64_t key); + +// Key Schedule ( http://en.wikipedia.org/wiki/File:DES-key-schedule.png ) +// input : +// * encrypt : false if decryption +// * next_key : uint64_t next_key 0 +// * round : [[0, 15]] +// changes : +// * [key] is good to be used in the XOR in the rounds +// * [next_key] is the combined leftkey+rightkey to be used +// in the key_schedule for next round +void key_schedule(uint64_t* key, uint64_t* next_key, int round); + +void rounds(uint64_t *data, uint64_t key); + +void genkey(uint64_t *key); +void des_encrypt(char *in, int isize, char *out, uint64_t key); +void des_decrypt(char *in, int isize, char *out, uint64_t key); + + +#endif diff --git a/system/platforms/arm-rpi/dispatch.c b/system/platforms/arm-rpi3/dispatch.c similarity index 96% rename from system/platforms/arm-rpi/dispatch.c rename to system/platforms/arm-rpi3/dispatch.c index bc6eab6f..08ac3089 100644 --- a/system/platforms/arm-rpi/dispatch.c +++ b/system/platforms/arm-rpi3/dispatch.c @@ -17,7 +17,7 @@ #include #include #include -#include "bcm2835.h" +#include "bcm2837.h" /** Layout of the BCM2835 interrupt controller's registers. */ struct bcm2835_interrupt_registers { @@ -76,7 +76,7 @@ static void handle_irq(uchar irq_num) * function. */ static void check_irq_pending(uchar irq_num) { - bool handle = FALSE; + bool handle = FALSE; //RMv7 reference manual in section B1.8.1 /* Check the appropriate hardware register, depending on the IRQ number. */ if (irq_num >= 64) @@ -118,13 +118,14 @@ static inline ulong first_set_bit(ulong word) /** * Processes all pending interrupt requests. * - * On the BCM2835 (Raspberry Pi), this done by iterating through all registered + * On the BCM2837 (Raspberry Pi3), this done by iterating through all registered * interrupts on the ARM and checking whether each one is pending. This is not * necessarily the fastest way to do it, but this should minimize problems with * the poorly-documented hardware and conflicts with the GPU. */ void dispatch(void) { + uint i; for (i = 0; i < 3; i++) @@ -137,6 +138,7 @@ void dispatch(void) check_irq_pending(bit + (i << 5)); } } + } /** diff --git a/system/platforms/arm-rpi3/getcpuid.S b/system/platforms/arm-rpi3/getcpuid.S new file mode 100644 index 00000000..fcffbc39 --- /dev/null +++ b/system/platforms/arm-rpi3/getcpuid.S @@ -0,0 +1,7 @@ +.globl getcpuid +.func getcpuid +getcpuid: + mrc p15, 0, r0, c0, c0, 5 // ACCESS MPIDR REGISTER AND STORE IN R0 + and r0, r0, #7 // RETURN ONLY THE FIRST THREE BITS + bx lr + .endfunc diff --git a/system/platforms/arm-rpi3/getmode.S b/system/platforms/arm-rpi3/getmode.S new file mode 100644 index 00000000..bc905627 --- /dev/null +++ b/system/platforms/arm-rpi3/getmode.S @@ -0,0 +1,7 @@ +.globl getmode + + .func getmode +getmode: + mrs r0, cpsr + bx lr + .endfunc diff --git a/system/platforms/arm-rpi3/halt.S b/system/platforms/arm-rpi3/halt.S new file mode 100644 index 00000000..3e387f8d --- /dev/null +++ b/system/platforms/arm-rpi3/halt.S @@ -0,0 +1,27 @@ +/** + * @file halt.S + */ +/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ + +.globl halt + +#include + +/** + * @fn void halt(void) + * + * Halt the system by sending the processor into an infinite loop. + */ +halt: + .func halt + +_loop: + /* Disable IRQs and FIQs. */ +// msr cpsr_c, #ARM_I_BIT | ARM_F_BIT + + /* Wait for interrupt. */ +// wfi + + /* Shouldn't be necessary, but repeat just in case. */ + b _loop + .endfunc diff --git a/system/platforms/arm-rpi/interrupt.h b/system/platforms/arm-rpi3/interrupt.h similarity index 96% rename from system/platforms/arm-rpi/interrupt.h rename to system/platforms/arm-rpi3/interrupt.h index f1c73852..369db026 100644 --- a/system/platforms/arm-rpi/interrupt.h +++ b/system/platforms/arm-rpi3/interrupt.h @@ -24,6 +24,6 @@ void enable_irq(irqmask); void disable_irq(irqmask); /* Include IRQ definitions */ -#include "bcm2835.h" +#include "bcm2837.h" #endif /* _INTERRUPT_H_ */ diff --git a/system/platforms/arm-rpi3/intutils.S b/system/platforms/arm-rpi3/intutils.S new file mode 100644 index 00000000..d98c80e3 --- /dev/null +++ b/system/platforms/arm-rpi3/intutils.S @@ -0,0 +1,50 @@ +/** + * @file intutils.S + * + * Functions to enable, disable, or restore global interrupts on the ARM. + * + * See http://xinu-os.org/Interrupt_handling_(ARM) for more information. + */ +/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ + +.globl enable +.globl disable +.globl restore + +/** + * @fn void enable(void) + * + * Enable interrupts globally. + */ +enable: + .func enable + cpsie i + mov pc, lr + .endfunc + +/** + * @fn irqmask disable(void) + * + * Disable interrupts globally and returns the old state. + * @return state of interrupts before they were disabled + */ +disable: + .func disable + mrs r0, cpsr + cpsid i + mov pc, lr + .endfunc + +/** + * @fn irqmask restore(irqmask) + * + * Restores the global interrupt mask to a previous state. + * @param im + * irqmask of interrupt state to restore + * @return state of interrupts when called + */ +restore: + .func restore + msr cpsr_c, r0 + mov pc, lr + .endfunc diff --git a/system/platforms/arm-rpi3/irq_handler.S b/system/platforms/arm-rpi3/irq_handler.S new file mode 100644 index 00000000..26f4edaa --- /dev/null +++ b/system/platforms/arm-rpi3/irq_handler.S @@ -0,0 +1,76 @@ +/** + * @file irq_handler.S + */ +/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ + +#include /* Needed for ARM_MODE_SYS definition. */ + +.globl irq_handler + +/** + * Entry point for Xinu's interrupt handler (ARM version). Note: we don't + * actually use the IRQ mode provided by the ARM; instead we switch the + * processor to SYS mode and use the SYS mode stack instead. This makes the ARM + * more similar to other CPUs and removes special cases in the context switch + * code. However, a caveat with this method is that the IRQ handler will use + * the stack of the currently running thread (the one that was interrupted). + * This requires that the stack size of any thread that executes with interrupts + * enabled be set to at least the stack space needed by the thread itself plus + * the maximum stack space needed by any IRQ handler. + */ +irq_handler: + .func irq_handler + + /* Correct LR_irq; this is a quirk of how the ARM processor calls the + * IRQ handler. */ + sub lr, lr, #4 + + /* [Store Return State Decrement Before] */ + /* Store the return state on the SYS mode stack. This includes + * SPSR_irq, which is the CPSR from SYS mode before we were interrupted, + * and LR_irq, which is the address to which we must return to continue + * execution of the interrupted thread. */ + srsdb #ARM_MODE_SYS! + + /* [Change Program State Interrupt Disable] */ + /* Change to SYS mode, with IRQs and FIQs still disabled. */ + cpsid if, #ARM_MODE_SYS + + /* Save on the SYS mode stack any registers that may be clobbered, + * namely the SYS mode LR and all other caller-save general purpose + * registers. Also save r4 so we can use it to store the amount we + * decremented the stack pointer by to align it to an 8-byte boundary + * (see comment below). */ + push {r0-r4, r12, lr} + + /* According to the document "Procedure Call Standard for the ARM + * Architecture", the stack pointer is 4-byte aligned at all times, but + * it must be 8-byte aligned when calling an externally visible + * function. This is important because this code is reached from an IRQ + * and therefore the stack currently may only be 4-byte aligned. If + * this is the case, the stack must be padded to an 8-byte boundary + * before calling dispatch(). */ + and r4, sp, #4 + sub sp, sp, r4 + + /* Execute a data memory barrier, as per the BCM2835 documentation. */ + bl dmb + + /* Call the C interrupt dispatching code. */ + bl dispatch + + /* Execute a data memory barrier, as per the BCM2835 documentation. */ + bl dmb + + /* Restore the original stack alignment (see note about 8-byte alignment + * above). */ + add sp, sp, r4 + + /* Restore the above-mentioned registers from the SYS mode stack. */ + pop {r0-r4, r12, lr} + + /* [Return From Exception Increment After] */ + /* Load the original SYS-mode CPSR and PC that were saved on the SYS + * mode stack. */ + rfeia sp! + .endfunc diff --git a/system/platforms/arm-rpi/kexec.c b/system/platforms/arm-rpi3/kexec.c similarity index 92% rename from system/platforms/arm-rpi/kexec.c rename to system/platforms/arm-rpi3/kexec.c index 19685647..1ef06e00 100644 --- a/system/platforms/arm-rpi/kexec.c +++ b/system/platforms/arm-rpi3/kexec.c @@ -39,11 +39,13 @@ static const ulong copy_kernel[] = { 0xe4843004, 0xe2511001, 0x1afffffb, - 0xe3a0f902, + 0xe3a0f902 }; - #define COPY_KERNEL_ADDR ((void*)(0x8000 - sizeof(copy_kernel))) +extern void stop_mmu(void); +extern void invalidate_tlbs(void); + /** * Kernel execute - Transfer control to a new kernel. * @@ -68,6 +70,9 @@ syscall kexec(const void *kernel, uint size) /* Copy the assembly stub into a safe location. */ memcpy(COPY_KERNEL_ADDR, copy_kernel, sizeof(copy_kernel)); + + stop_mmu(); + invalidate_tlbs(); /* Enter the assembly stub to copy the new kernel into its final location, * then pass control to it. */ @@ -75,6 +80,12 @@ syscall kexec(const void *kernel, uint size) (( void (*)(const void *, ulong, void *))(COPY_KERNEL_ADDR)) (kernel, (size + 3) / 4, atags_ptr); + kprintf("Returned from copy_kernel...\r\n"); + + while (1) + { + + } /* Control should never reach here. */ restore(im); return SYSERR; diff --git a/system/platforms/arm-rpi3/memory_barrier.S b/system/platforms/arm-rpi3/memory_barrier.S new file mode 100644 index 00000000..ee9bd935 --- /dev/null +++ b/system/platforms/arm-rpi3/memory_barrier.S @@ -0,0 +1,42 @@ +/** + * @file memory_barrier.S + */ +/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ + +.globl dmb + +/** + * @fn void dmb(void) + * + * Executes a data memory barrier operation using the c7 (Cache Operations) + * register of system control coprocessor CP15. + * + * All explicit memory accesses occurring in program order before this operation + * will be globally observed before any memory accesses occurring in program + * order after this operation. This includes both read and write accesses. + * + * This differs from a "data synchronization barrier" in that a data + * synchronization barrier will ensure that all previous explicit memory + * accesses occurring in program order have fully completed before continuing + * and that no subsequent instructions will be executed until that point, even + * if they do not access memory. This is unnecessary for what we need this for. + * + * On the BCM2835 (Raspberry Pi), this is needed before and after accessing + * peripherals, as documented on page 7 of the "BCM2835 ARM Peripherals" + * document. As documented, it is only needed when switching between + * _different_ peripherals. + */ +dmb: + .func dmb + mov r12, #0 + mcr p15, 0, r12, c7, c10, 5 /* Data Memory Barrier */ + mov pc, lr + .endfunc + + +.globl dsb +dsb: + .func dsb + dsb /* Wait for either cache or MMU to finish before continuing */ + bx lr + .endfunc diff --git a/system/platforms/arm-rpi3/mmu.c b/system/platforms/arm-rpi3/mmu.c new file mode 100644 index 00000000..1e9c6c23 --- /dev/null +++ b/system/platforms/arm-rpi3/mmu.c @@ -0,0 +1,44 @@ +#include "mmu.h" +#include +#include + +/* code from Github user dwelch67 + * https://github.com/dwelch67/raspberrypi/tree/master/mmu */ +unsigned int mmu_section(unsigned int vadd, unsigned int padd, unsigned int flags) +{ + unsigned int ra, rb, rc; + + ra = vadd >> 20; + rb = MMUTABLEBASE | (ra << 2); + rc = (padd & 0xFFF00000) | 0xC00 | flags | 2; + PUT32(rb, rc); + + return 0; +} + +/* mmu_init() configures virtual address == physical address */ +/* also configures memory to be cacheable, except for peripheral portion */ +void mmu_init() +{ + unsigned int ra; + for (ra = 0; ; ra += 0x00100000) + { + mmu_section(ra, ra, 0x15C06); + //mmu_section(ra, ra, 0x0 | 0x8); + if (ra >= 0x3F000000) + break; + } + + /* Peripherals not marked (use 0x0000) */ + for ( ; ; ra += 0x00100000) + { + mmu_section(ra, ra, 0x0000); + if (ra == 0x40000000) + break; + } + + // make dma buffer area non-cacheable + mmu_section(dma_buf_space, dma_buf_space, 0x0); + + start_mmu(MMUTABLEBASE); +} diff --git a/system/platforms/arm-rpi3/mmu.h b/system/platforms/arm-rpi3/mmu.h new file mode 100644 index 00000000..8f45f920 --- /dev/null +++ b/system/platforms/arm-rpi3/mmu.h @@ -0,0 +1,30 @@ +#ifndef _MMU_H_ +#define _MMU_H_ + +#define MMUTABLEBASE 0x00004000 + +#ifndef __ASSEMBLER__ + +#include + +/* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0201d/ch03s03s05.html */ +extern void mmu_initialize(void); +extern void start_mmu(unsigned int); +extern void _clean_cache(void); +extern void _flush_cache(void); +extern void _inval_cache(void); +extern void _flush_area(uint32_t); +extern void _inval_area(uint32_t); + +extern uint32_t _getcacheinfo(void); +extern void stop_mmu(void); +extern void invalidate_tlbs(void); +extern unsigned int mmu_section(unsigned int, unsigned int, unsigned int); +extern void mmu_init(void); + +extern void PUT32(unsigned int, unsigned int); +extern unsigned int GET32(unsigned int); + +#endif /* __ASSEMBLER__ */ + +#endif /* _MMU_H_ */ diff --git a/system/platforms/arm-rpi3/mmu_util.S b/system/platforms/arm-rpi3/mmu_util.S new file mode 100755 index 00000000..c7a7bba1 --- /dev/null +++ b/system/platforms/arm-rpi3/mmu_util.S @@ -0,0 +1,196 @@ +/* mmu_util.S + * Contains assembly routines for cache maintenance on the ARM Cortex A53. + * Authors: Rade Latinovich and Patrick J. McGee + * Embedded Xinu, Copyright 2019 + */ +.globl _getcacheinfo +_getcacheinfo: + mrc p15, 1, r0, c0, c0, 0 ;@ Read CCSIDR into r0 + bx lr + +.globl _getcachemaint +_getcachemaint: + mrc p15, 0, r0, c0, c1, 7 ;@ Read ID_MMFR3 (32 bit) into r0 + bx lr + +/* Brief explanation about DMA and Cortex-A53: + * https://stackoverflow.com/questions/42081435/flush-invalidate-range-by-virtual-address-armv8-cache/ + */ + +/* DCCMVAC (clean/flush specific value) + * Input: 32-bit virtual address + * Armv8 architecture reference manual page 5720 */ +.globl _flush_area +_flush_area: + //mcr p15, 0, r0, c7, c10, 1 ;@ Clean line by VA to PoC + mcr p15, 0, r0, c7, c11, 1 ;@ Clean line by VA to PoU + bx lr + +/* DCIMVAC (invalidate specific value) + * Input: 32-bit virtual address */ +.globl _inval_area +_inval_area: + mcr p15, 0, r0, c7, c6, 1 ;@ Invalidate line by VA to PoC + bx lr + +.globl _inval_cache +_inval_cache: + + //mcr p15, 0, r0, c8, c6, 0 ;@ Invalidate entire data TLB + mov r0, #0x0 ;@ Start at zero for first cache section (way) +isec1: + mcr p15, 0, r0, c7, c6, 2 ;@ Invalidate the line by set/way + add r0, r0, #0x10 ;@ Increment by 64 bytes (segment is 16 words, 16*4=64 bytes) + cmp r0, #0x1FC0 ;@ Reached end of set (bits [12:6]) + bne sec1 ;@ If not branch back to set1 + + movt r0, #0x4000 ;@ Use movw and movt to load the full 32-bit constant + movw r0, #0x0000 ;@ Start at 0x40000000 for second cache section (way) +isec2: + mcr p15, 0, r0, c7, c6, 2 ;@ Invalidate the line by set/way + add r0, r0, #0x10 ;@ Increment to next line + + and r1, r0, #0xBFFFFFFF ;@ Clear top way bit because we're checking the lower 16 set bits, for 1FC0 + cmp r1, #0x1FC0 ;@ Reached end of set (bits [12:6]) + bne sec2 ;@ If not branch back to sec2 + + movt r0, #0x8000 + movw r0, #0x0000 ;@ Start at 0x80000000 for third way +isec3: + mcr p15, 0, r0, c7, c6, 2 ;@ Invalidate the line by set/way + add r0, r0, #0x10 ;@ Increment to next line + + and r1, r0, #0x1FFFFFFF + cmp r1, #0x1FC0 ;@ Reached end of set (bits [12:6]) + bne sec3 ;@ If not branch back to sec3 + + movt r0, #0xC000 + movw r0, #0x0000 ;@ Start at 0xC0000000 for fourth way +isec4: + mcr p15, 0, r0, c7, c6, 2 ;@ Invalidate the line by set/way + add r0, r0, #0x10 ;@ Increment to next line + + and r1, r0, #0x3FFFFFFF + cmp r1, #0x1FC0 ;@ Reached end of set (bits [12:6]) + bne sec4 ;@ If not branch back to sec4 + + bx lr + +.globl _flush_cache +_flush_cache: + + /* From Cortex A53 page 330: + The ARMv8-A architecture does not support an operation to invalidate the +entire data cache. If this function is required in software, it must be +constructed by iterating over the cache geometry and executing a series of +individual invalidate by set/way instructions. +The Cortex-A53 processor automatically invalidates caches on reset +unless suppressed with the DBGL1RSTDISABLE or L2RSTDISABLE +pins. It is therefore not necessary for software to invalidate the caches on +startup. + */ + + mcr p15, 0, r0, c8, c6, 0 ;@ Invalidate entire data TLB + mov r0, #0x0 ;@ Start at zero for first cache section (way) +sec1: + mcr p15, 0, r0, c7, c10, 2 ;@ Clean and flush the line by set/way (cache line index held by r0) + //mcr p15, 0, r0, c7, c6, 2 ;@ Invalidate the line by set/way + add r0, r0, #0x10 ;@ Increment by 64 bytes (segment is 16 words, 16*4=64 bytes) + cmp r0, #0x1FC0 ;@ Reached end of set (bits [12:6]) + bne sec1 ;@ If not branch back to set1 + + movt r0, #0x4000 ;@ Use movw and movt to load the full 32-bit constant + movw r0, #0x0000 ;@ Start at 0x40000000 for second cache section (way) +sec2: + mcr p15, 0, r0, c7, c10, 2 ;@ Clean and flush the line by set/way + //mcr p15, 0, r0, c7, c6, 2 ;@ Invalidate the line by set/way + add r0, r0, #0x10 ;@ Increment to next line + + and r1, r0, #0xBFFFFFFF ;@ Clear top way bit because we're checking the lower 16 set bits, for 1FC0 + cmp r1, #0x1FC0 ;@ Reached end of set (bits [12:6]) + bne sec2 ;@ If not branch back to sec2 + + movt r0, #0x8000 + movw r0, #0x0000 ;@ Start at 0x80000000 for third way +sec3: + mcr p15, 0, r0, c7, c10, 2 ;@ Clean and flush the line by set/way + //mcr p15, 0, r0, c7, c6, 2 ;@ Invalidate the line by set/way + add r0, r0, #0x10 ;@ Increment to next line + + and r1, r0, #0x1FFFFFFF + cmp r1, #0x1FC0 ;@ Reached end of set (bits [12:6]) + bne sec3 ;@ If not branch back to sec3 + + movt r0, #0xC000 + movw r0, #0x0000 ;@ Start at 0xC0000000 for fourth way +sec4: + mcr p15, 0, r0, c7, c10, 2 ;@ Clean and flush the line by set/way + //mcr p15, 0, r0, c7, c6, 2 ;@ Invalidate the line by set/way + add r0, r0, #0x10 ;@ Increment to next line + + and r1, r0, #0x3FFFFFFF + cmp r1, #0x1FC0 ;@ Reached end of set (bits [12:6]) + bne sec4 ;@ If not branch back to sec4 + + bx lr + +.globl start_mmu +start_mmu: + mov r2, #0 + mcr p15, 0, r2, c7, c1, 0 ;@ invalidate all instruction caches inner shareable to PoU (point of unification) + mcr p15, 0, r2, c7, c5, 0 ;@ invalidate all instruction caches to PoU + mcr p15, 0, r2, c7, c6, 1 ;@ invalidate d cache line by VA (virtually addressed cache) to PoC (point of coherence + mcr p15, 0, r2, c7, c6, 2 ;@ invalidate d cache line by set/way + mcr p15, 0, r2, c8, c7, 0 ;@ invalidate tlb /* invalidate unified TLB */ + dsb + + mvn r2, #0 + mcr p15, 0, r2, c3, c0, 0 ;@ domain + + orr r0, #0x6A + + orr r0, #0x6A + + mcr p15, 0, r0, c2, c0, 0 ;@ tlb base + mcr p15, 0, r0, c2, c0, 1 ;@ tlb base + + /* SCTLR configuration*/ + mrc p15, 0, r2, c1, c0, 0 +// orr r2, r2, r1 + /* gets rid of the need for a 2nd argument when using start_mmu() */ + /* makes it simpler to use */ + mov r1, #0x1 + orr r1, r1, #0x1000 + orr r1, r1, #0x4 + orr r2, r2, r1 + mcr p15, 0, r2, c1, c0, 0 + + bx lr + + +.globl stop_mmu +stop_mmu: + mrc p15, 0, r2, c1, c0, 0 + bic r2, #0x1000 + bic r2, #0x0004 + bic r2, #0x0001 + mcr p15, 0, r2, c1, c0, 0 + + bx lr + +.globl invalidate_tlbs +invalidate_tlbs: + mov r2, #0 + mcr p15, 0, r2, c8, c7, 0 + dsb + bx lr + +.globl PUT32 +PUT32: + str r1, [r0] + bx lr + +.globl GET32 +GET32: + ldr r0, [r0] + bx lr diff --git a/system/platforms/arm-rpi3/mmu_util.S.old b/system/platforms/arm-rpi3/mmu_util.S.old new file mode 100644 index 00000000..85616840 --- /dev/null +++ b/system/platforms/arm-rpi3/mmu_util.S.old @@ -0,0 +1,57 @@ +.globl start_mmu +start_mmu: + mov r2, #0 +// mcr p15, 0, r2, c7, c7, 0 ;@ invalidate caches /* P.S. not supported in new architecture */ + mcr p15, 0, r2, c7, c1, 0 ;@ invalidate all i caches inner shareable to PoU + mcr p15, 0, r2, c7, c5, 0 ;@ invalidate all i caches to PoU + mcr p15, 0, r2, c7, c6, 1 ;@ invalidate d cache line by VA to PoC + mcr p15, 0, r2, c7, c6, 2 ;@ invalidate d cache line by set/way + mcr p15, 0, r2, c8, c7, 0 ;@ invalidate tlb /* invalidate unified TLB */ + dsb + + mvn r2, #0 + mcr p15, 0, r2, c3, c0, 0 ;@ domain + + mcr p15, 0, r0, c2, c0, 0 ;@ tlb base + mcr p15, 0, r0, c2, c0, 1 ;@ tlb base + + /* SCTLR configuration*/ + mrc p15, 0, r2, c1, c0, 0 +// orr r2, r2, r1 + /* gets rid of the need for a 2nd argument when using start_mmu() */ + /* makes it simpler to use */ + mov r1, #0x1 + orr r1, r1, #0x1000 + orr r1, r1, #0x4 + orr r2, r2, r1 + mcr p15, 0, r2, c1, c0, 0 + + bx lr + + +.globl stop_mmu +stop_mmu: + mrc p15, 0, r2, c1, c0, 0 + bic r2, #0x1000 + bic r2, #0x0004 + bic r2, #0x0001 + mcr p15, 0, r2, c1, c0, 0 + + bx lr + +.globl invalidate_tlbs +invalidate_tlbs: + mov r2, #0 + mcr p15, 0, r2, c8, c7, 0 + dsb + bx lr + +.globl PUT32 +PUT32: + str r1, [r0] + bx lr + +.globl GET32 +GET32: + ldr r0, [r0] + bx lr diff --git a/system/platforms/arm-rpi3/mutex.c b/system/platforms/arm-rpi3/mutex.c new file mode 100644 index 00000000..b45296ca --- /dev/null +++ b/system/platforms/arm-rpi3/mutex.c @@ -0,0 +1,73 @@ +#include +#include + +struct muxent muxtab[NMUTEX]; + +extern void _mutex_acquire(unsigned int *); +extern void _mutex_release(unsigned int *); +extern int _atomic_mutex_check(unsigned int *); +static mutex_t mutex_alloc(void); + +/* Create and return an unlocked mutex */ +mutex_t mutex_create() +{ + mutex_t mux; + + mux = mutex_alloc(); + if (SYSERR == mux) + { + return SYSERR; + } + + muxtab[mux].lock = MUTEX_UNLOCKED; + return mux; +} + +syscall mutex_free(mutex_t mux) +{ + if (isbadmux(mux)) + return SYSERR; + + muxtab[mux].state = MUTEX_FREE; + + return OK; +} + +syscall mutex_acquire(mutex_t mux) +{ + if (isbadmux(mux)) + return SYSERR; + + if (MUTEX_FREE == muxtab[mux].state) + return SYSERR; + + _mutex_acquire(&(muxtab[mux].lock)); + return OK; + +} + +syscall mutex_release(mutex_t mux) +{ + if (isbadmux(mux)) + return SYSERR; + if (MUTEX_FREE == muxtab[mux].state) + return SYSERR; + + _mutex_release(&(muxtab[mux].lock)); + return OK; +} + +static mutex_t mutex_alloc(void) +{ + int i; + + for (i = 0; i < NMUTEX; i++) + { + if (0 == _atomic_mutex_check((unsigned int *)&(muxtab[i].state))) + { + muxtab[i].state = MUTEX_USED; + return i; + } + } + return SYSERR; +} diff --git a/system/platforms/arm-rpi3/mutex.h b/system/platforms/arm-rpi3/mutex.h new file mode 100644 index 00000000..a5bee880 --- /dev/null +++ b/system/platforms/arm-rpi3/mutex.h @@ -0,0 +1,35 @@ +#ifndef _MUTEX_H_ +#define _MUTEX_H_ + +#define MUTEX_FREE 1 +#define MUTEX_USED 2 + +#define MUTEX_LOCKED 0x01 +#define MUTEX_UNLOCKED 0x00 + +#define isbadmux(x) ( (x < 0) || (x > NMUTEX) ) + +#ifndef __ASSEMBLER__ + +#include + +/* 1 for each thread, 1 for each semaphore, plus 50 more for extra */ +#define NMUTEX NTHREAD + NSEM + 50 + +typedef unsigned int mutex_t; + +struct muxent +{ + unsigned char state; + unsigned int lock; +}; + +extern struct muxent muxtab[]; + +mutex_t mutex_create(void); +syscall mutex_free(mutex_t); +syscall mutex_acquire(mutex_t); +syscall mutex_release(mutex_t); +#endif /* __ASSEMBLER__ */ + +#endif /* _MUTEX_H_ */ diff --git a/system/platforms/arm-rpi3/mutex_util.S b/system/platforms/arm-rpi3/mutex_util.S new file mode 100644 index 00000000..3543eed8 --- /dev/null +++ b/system/platforms/arm-rpi3/mutex_util.S @@ -0,0 +1,107 @@ +/* + * file mutex.S + * provides _mutex_acquire _mutex_release _atomic_mutex_check + * + * Written by: Rade Latinovich + Patrick McGee + */ + +#include "mutex.h" + +.globl _mutex_acquire +.globl _mutex_release +.globl _atomic_mutex_check + +/** + * @fn void _mutex_acquire(unsigned int *mutex) + * + * Uses atomic operations to set a mutex lock variable. + * + * @param mutex pointer to mutex lock variable + */ +_mutex_acquire: + .func _mutex_acquire + + push {lr} +loop: + pldw [r0] + + ldrex r1, [r0] /* Load the value of the lock from memory */ + cmp r1, #MUTEX_LOCKED /* IF already locked ,*/ + beq wait /* THEN try again...*/ + + cmp r1, #MUTEX_LOCKED /* IF already locked , */ + beq wait /* THEN try again... */ + + mov r1, #MUTEX_LOCKED /* ELSE unlocked, try to lock.. */ + strex r2, r1, [r0] + cmp r2, #0 /* IF lock acquire failed this time around,*/ + bne loop /* THEN try again back up at the top */ + dmb /* Data Memory Barrier opcode waits for memory accesses */ + /* to complete before returning. */ + pop {lr} + bx lr + +wait: + wfe + b loop + + .endfunc + +/** + * @fn void _mutex_release(unsigned int *mutex) + * + * Sets mutex lock variable to unlocked. + * + * @param mutex pointer to mutex lock variable + */ +_mutex_release: + .func _mutex_release + + mov r1, #MUTEX_UNLOCKED + dmb /* Required before accessing protected resource */ + + str r1, [r0] /* Unlock mutex */ + dsb + + sev + bx lr + + .endfunc + +/** + * @fn int _atomic_mutex_check(unsigned int *) + * + * Tries to atomically check if a mutex lock is available. + * + * @param address of a mutex entries state. + * @return 0 on success, -1 on failure. + */ +.globl _atomic_mutex_check +_atomic_mutex_check: + .func _atomic_mutex_check + + pldw [r0] /* Preload data w/ intent to write */ + ldrex r1, [r0] /* load exclusive the muxtab state */ + cmp r1, #MUTEX_FREE /* IF state == MUTEX_FREE */ + beq _increment /* THEN increment to MUTEX_USED */ + /* OTHERWISE clrex and return */ + clrex + dmb + mov r0, #-1 + bx lr + +_increment: + add r1, r1, #1 /* increments to MUTEX_USED */ + strex r2, r1, [r0] /* strex MUTEX_USED */ + cmp r2, #0 /* IF strex doesnt succeed, */ + bne _atomic_mutex_check /* jump back to the top */ + /* OTHERWISE return as success */ + dmb + mov r0, #0 + bx lr + + .endfunc + + + diff --git a/system/platforms/arm-rpi3/pause.S b/system/platforms/arm-rpi3/pause.S new file mode 100644 index 00000000..ac6aaace --- /dev/null +++ b/system/platforms/arm-rpi3/pause.S @@ -0,0 +1,13 @@ +/** + * @file pause.S + * Platform-dependent code for idling the processor. + */ +/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ + +.globl pause + +pause: + .func pause + wfi /* ARM "wait for interrupt" instruction. */ + mov pc, lr + .endfunc diff --git a/system/platforms/arm-rpi3/platforminit.c b/system/platforms/arm-rpi3/platforminit.c new file mode 100644 index 00000000..0db5bde6 --- /dev/null +++ b/system/platforms/arm-rpi3/platforminit.c @@ -0,0 +1,170 @@ +/** + * @file platforminit.c + */ +/* Embedded Xinu, Copyright (C) 2009, 2013. All rights reserved. */ + +#include +#include +#include +#include +#include "../../../device/uart-pl011/pl011.h" +#include +#include + +#include +#include +#include +#include +#include + +/* Definitions of usable ARM boot tags. ATAG list is a list of parameters passed from + * the bootloader to the kernel. atags_ptr is passed inside start.S as a parameter. */ + +/*to_save_for_later0xB900001F*/ +/* CHANGED SERIAL AND CMDLINE TAGS, SWITCHED ...0006 and ...0009 */ + + +/* Definitions of usable ARM boot tags. ATAG list is a list of parameters passed from + * the bootloader to the kernel. atags_ptr is passed inside start.S as a parameter. */ + +/*to_save_for_later0xB900001F*/ +/* CHANGED SERIAL AND CMDLINE TAGS, SWITCHED ...0006 and ...0009 */ + +enum { + ATAG_NONE = 0x00000000, //Empty tag used to end list + ATAG_CORE = 0x54410001, //First tag used to start list + ATAG_MEM = 0x54410002, //Describes a physical area of memory + ATAG_VIDEOTEXT = 0x54410003, //Describes a VGA text display + ATAG_RAMDISK = 0x54410004, //Describes how the ramdisk will be used in kernel + ATAG_INITRD2 = 0x54410005, //Describes where the compressed ramdisk image is placed in memory + ATAG_SERIAL = 0x54410006, //64 bit board serial number + ATAG_REVISION = 0x54410007, //32 bit board revision number + ATAG_VIDEOLFB = 0x54410008, //Initial values for vesafb-type framebuffers + ATAG_CMDLINE = 0x54410009, //Command line to pass to kernel +}; + +/* Below we only define structures for tags we actually use. */ + +/* ARM boot tag header. */ +struct atag_header { + uint size; /* Size of tag, in words, including the header. */ + uint tag; /* One of the ATAG_* values from above. */ +}; + +/* Description of memory region (ATAG_MEM) */ +struct atag_mem { + uint size; + uint start; +}; + +/* Board serial number (ATAG_SERIAL) */ +struct atag_serialnr { + uint low; + uint high; +}; + +/* Format of ARM boot tag */ +struct atag { + struct atag_header hdr; + union { + struct atag_mem mem; + struct atag_serialnr serialnr; + }; +}; + +/** Physical memory address at which the bootloader placed the ARM boot tags. + *tagata This is set by the code in start.S. Here, initialize it to a dummy value to + * prevent it from being placed in .bss. */ +const struct atag *atags_ptr = (void*)-1; + +/* End of kernel (used for sanity check) */ +extern void *_end; + +/** + * This code is irrelevant to Embedded Xinu and is only used as a means of testing on the RPI 3 boards + */ +/* Initialize GPIO pin 16 as an output */ +void led_init(void) +{ + volatile struct rpi_gpio_regs *regptr; + regptr = (struct rpi_gpio_regs *)(GPIO_REGS_BASE); + regptr->gpfsel[1] &= ~(7 << 18); + regptr->gpfsel[1] |= (1 << 18); +} +/* Set GPIO pin 16 to ON */ +void led_on(void) +{ + volatile struct rpi_gpio_regs *regptr = (struct rpi_gpio_regs *)(GPIO_REGS_BASE); + regptr->gpset[0] = 1 << 16; +} +/* Set GPIO pin 16 to OFF */ +void led_off(void) +{ + volatile struct rpi_gpio_regs *regptr = (struct rpi_gpio_regs *)(GPIO_REGS_BASE); + regptr->gpclr[0] = 1 << 16; +} + +/** + * Initializes platform specific information for the Raspberry Pi hardware. + * @return OK + */ +int platforminit(void) +{ + strlcpy(platform.family, "BCM2837B0", PLT_STRMAX); + strlcpy(platform.name, "Raspberry Pi 3 B+", PLT_STRMAX); + platform.maxaddr = (void *)0x3EFFFFFC; /* Used only if atags are bad */ + platform.clkfreq = 1000000; + platform.serial_low = 0; /* Used only if serial # not found in atags */ + platform.serial_high = 0; /* Used only if serial # not found in atags */ + uint32_t cache_encoding = _getcacheinfo(); /* CCSIDR encoding of L1 cache size */ + switch (cache_encoding){ + case 0x7003E01A: + platform.dcache_size = 8; // 8 KB + break; + case 0x7007E01A: + platform.dcache_size = 16; // 16 KB + break; + case 0x700FE01A: + platform.dcache_size = 32; // 32 KB + break; + case 0x701FE01A: + platform.dcache_size = 64; // 64 KB + break; + default: + platform.dcache_size = 0; + break; + } + + /* Initialize bcm2837 power */ + bcm2837_power_init(); + + /* Initialize the Memory Managament Unit */ + mmu_init(); + + /* Initialize the mutex table */ + for(int i = 0; i < NMUTEX; i++){ + muxtab[i].state = MUTEX_FREE; + muxtab[i].lock = MUTEX_UNLOCKED; + } + + /* Initialize dma buffer space */ + dma_buf_init(); + + /* Initialze the Hardware Random Number Generator */ + random_init(); + + /* Initialize the mutexes for global tables */ + quetab_mutex = mutex_create(); + + register struct thrent *thrptr; + for (int i = 0; i < NTHREAD; i++){ + thrtab_mutex[i] = mutex_create(); + thrptr = &thrtab[i]; + thrptr->core_affinity = -1; + } + + for (int i = 0; i < NSEM; i++) + semtab_mutex[i] = mutex_create(); + + return OK; +} diff --git a/system/platforms/arm-rpi3/preload_data.S b/system/platforms/arm-rpi3/preload_data.S new file mode 100644 index 00000000..711c3d7b --- /dev/null +++ b/system/platforms/arm-rpi3/preload_data.S @@ -0,0 +1,5 @@ +.globl pldw + +pldw: + pldw [r0] + bx lr diff --git a/system/platforms/arm-rpi3/random.c b/system/platforms/arm-rpi3/random.c new file mode 100644 index 00000000..094be910 --- /dev/null +++ b/system/platforms/arm-rpi3/random.c @@ -0,0 +1,16 @@ +#include + +void random_init() +{ + *RNG_STATUS = 0x40000; + *RNG_INT_MASK |= 1; // mask interupts + *RNG_CTRL |= 1; // enable + // wait for it to gain entropy + while(!((*RNG_STATUS)>>24)) asm volatile("nop"); +} + +unsigned int random() +{ +// return *RNG_DATA % (max - min) + min; + return (unsigned int) *RNG_DATA; +} diff --git a/system/platforms/arm-rpi3/random.h b/system/platforms/arm-rpi3/random.h new file mode 100644 index 00000000..acadd506 --- /dev/null +++ b/system/platforms/arm-rpi3/random.h @@ -0,0 +1,14 @@ +#ifndef _RANDOM_H_ +#define _RANDOM_H_ + +#include + +#define RNG_CTRL ((volatile unsigned int*)(PERIPHERALS_BASE+0x00104000)) +#define RNG_STATUS ((volatile unsigned int*)(PERIPHERALS_BASE+0x00104004)) +#define RNG_DATA ((volatile unsigned int*)(PERIPHERALS_BASE+0x00104008)) +#define RNG_INT_MASK ((volatile unsigned int*)(PERIPHERALS_BASE+0x00104010)) + +extern void random_init(void); +extern unsigned int random(void); + +#endif /* _RANDOM_H_ */ diff --git a/system/platforms/arm-rpi3/rpi_gpio.h b/system/platforms/arm-rpi3/rpi_gpio.h new file mode 100644 index 00000000..a90fdca1 --- /dev/null +++ b/system/platforms/arm-rpi3/rpi_gpio.h @@ -0,0 +1,32 @@ +#ifndef _RPI_GPIO_H_ +#define _RPI_GPIO_H_ + +struct rpi_gpio_regs +{ + volatile unsigned int gpfsel[6]; /* GPIO Funciton Select */ + volatile unsigned int do_not_use_a; + volatile unsigned int gpset[2]; /* GPIO Pin Output Set */ + volatile unsigned int do_not_use_b; + volatile unsigned int gpclr[2]; /* GPIO Pin Output Clear */ + volatile unsigned int do_not_use_c; + volatile unsigned int gplev[2]; /* GPIO Pin Level */ + volatile unsigned int do_not_use_d; + volatile unsigned int gpeds[2]; /* GPIO Pin Event Detect Status */ + volatile unsigned int do_not_use_e; + volatile unsigned int gpren[2]; /* GPIO Pin Rising Edge Detect Enable */ + volatile unsigned int do_not_use_f; + volatile unsigned int gpfen[2]; /* GPIO Pin Falling Edge Detect Enable */ + volatile unsigned int do_not_use_g; + volatile unsigned int gphen[2]; /* GPIO Pin High Detect Enable */ + volatile unsigned int do_not_use_h; + volatile unsigned int gplen[2]; /* GPIO Pin Low Detect Enable */ + volatile unsigned int do_not_use_i; + volatile unsigned int gparen[2]; /* GPIO Pin Async. Rising Edge Detect */ + volatile unsigned int do_not_use_j; + volatile unsigned int gpafen[2]; /* GPIO Pin Async. Falling Edge Detect */ + volatile unsigned int do_not_use_k; + volatile unsigned int gppud; /* GPIO Pin Pull-up/down Enable */ + volatile unsigned int gppudclk[2]; /* GPIO Pin Pull-up/down Enable Clock */ +}; + +#endif /* _RPI_GPIO_H_ */ diff --git a/system/platforms/arm-rpi3/setmode.S b/system/platforms/arm-rpi3/setmode.S new file mode 100644 index 00000000..2d183f36 --- /dev/null +++ b/system/platforms/arm-rpi3/setmode.S @@ -0,0 +1,20 @@ +#include + +.globl setmode +setmode: + .func setmode + +/* + mrs r0, cpsr + bic r0, r0, #ARM_MODE_SYS + orr r0, r0, #ARM_MODE_SVC + msr spsr_cxsf, r0 + add r0, pc, #4 + msr ELR_hyp, r0 + eret +*/ + + cpsid if, #ARM_MODE_SYS + bx lr + + .endfunc diff --git a/system/platforms/arm-rpi3/setupCores.S b/system/platforms/arm-rpi3/setupCores.S new file mode 100644 index 00000000..a57d5d66 --- /dev/null +++ b/system/platforms/arm-rpi3/setupCores.S @@ -0,0 +1,51 @@ +#include +#include + +.globl CoreSetup +CoreSetup: + /* change processor to SYSTEM mode */ + mrs r0, cpsr + orr r0, r0, #ARM_MODE_SYS + msr spsr_cxsf, r0 + add r0, pc, #4 + msr ELR_hyp, r0 + eret + + /* set vector addresses */ + ldr r1, =_vectors + mcr p15, 0, r1, c12, c0, 0 /* Write to VBAR */ + + /* get CPUID from MPIDR register and put value in r0 */ + mrc p15, 0, r0, c0, c0, 5 /* MPIDR */ + and r0, r0, #7 /* last 3 bits is CPUID */ + + /* multiply the CPUID by 4 to get the correct index for the arrays */ + mov r1, r0 + mov r2, #4 + mul r1, r1, r2 + + /* core_init_sp array is for the initial stack pointer for each core */ + ldr r2, =core_init_sp + ldr sp, [r2, r1] + + /* move value to non-volatile registers before calling start_mmu */ + mov r4, r1 + + /* call start_mmu so the programmer does not have to manual call it each time they unpark a core */ + mov r0, #MMUTABLEBASE /* MMUTABLEBASE from mmu.h */ + bl start_mmu + + /* corestart array of addresses for the instruction for each core to execute once setup is done */ + ldr r0, =init_args + ldr r0, [r0, r4] + ldr r2, =corestart + ldr pc, [r2, r4] + + +/* Send EVent routine so we can use it in C code.. (unparkcore.c) */ +.globl sev +sev: + .func sev + sev + bx lr + .endfunc diff --git a/system/platforms/arm-rpi3/setupStack.c b/system/platforms/arm-rpi3/setupStack.c new file mode 100644 index 00000000..50cd8e44 --- /dev/null +++ b/system/platforms/arm-rpi3/setupStack.c @@ -0,0 +1,81 @@ +/** + * @file setupStack.c + */ +/* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ + +#include +#include + +/* Length of ARM context record in words (includes r0-r11, cpsr, lr, pc). */ +#define CONTEXT_WORDS 15 + +/* The standard ARMv8 calling convention passes first eight arguments in x0-x7; the + * rest spill onto the stack. */ +#define MAX_REG_ARGS 4 + +/** Set up the context record and arguments on the stack for a new thread + * (ARM version) */ +void *setupStack(void *stackaddr, void *procaddr, + void *retaddr, uint nargs, va_list ap) +{ + uint spilled_nargs; + uint reg_nargs; + uint i; + uint *saddr = stackaddr; + + /* Determine if any arguments will spill onto the stack (outside the context + * record). If so, reserve space for them. */ + if (nargs > MAX_REG_ARGS) { + spilled_nargs = nargs - MAX_REG_ARGS; + reg_nargs = MAX_REG_ARGS; + saddr -= spilled_nargs; + } else { + spilled_nargs = 0; + reg_nargs = nargs; + } + + /* Possibly skip a word to ensure the stack is aligned on a **8-byte** boundary + * after the new thread pops off the context record. */ + if ((uint)saddr & 0x4) + { + --saddr; + } + + + /* Construct the context record for the new thread. */ + saddr -= CONTEXT_WORDS; + + saddr[0] = 0; + + /* Arguments passed in registers (part of context record) */ + for (i = 0; i < reg_nargs; i++) + { + saddr[i] = va_arg(ap, ulong); + } + + for (; i < CONTEXT_WORDS - 3; i++) + { + saddr[i] = 0; + } + + + /* Control bits of program status register + * (SYS mode, IRQs initially enabled) */ + saddr[CONTEXT_WORDS - 3] = ARM_MODE_SYS | ARM_F_BIT; + + /* return address */ + saddr[CONTEXT_WORDS - 2] = (ulong)retaddr; + + /* program counter */ + saddr[CONTEXT_WORDS - 1] = (ulong)procaddr; + + /* Arguments spilled onto stack (not part of context record) */ + for (i = 0; i < spilled_nargs; i++) + { + saddr[CONTEXT_WORDS + i] = va_arg(ap, ulong); + } + + /* Return "top" of stack (lowest address). */ + + return saddr; +} diff --git a/system/platforms/arm-rpi/timer.c b/system/platforms/arm-rpi3/timer.c similarity index 99% rename from system/platforms/arm-rpi/timer.c rename to system/platforms/arm-rpi3/timer.c index aea2d542..dc95d090 100644 --- a/system/platforms/arm-rpi/timer.c +++ b/system/platforms/arm-rpi3/timer.c @@ -18,7 +18,7 @@ /* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ #include -#include "bcm2835.h" +#include "bcm2837.h" /** Layout of the BCM2835 System Timer's registers. */ struct bcm2835_timer_regs { diff --git a/system/platforms/arm-rpi3/unparkcore.c b/system/platforms/arm-rpi3/unparkcore.c new file mode 100644 index 00000000..ad104500 --- /dev/null +++ b/system/platforms/arm-rpi3/unparkcore.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include + +extern void CoreSetup(void) __attribute__((naked)); +typedef void (*fn)(void); +extern void sev(void); + +void printcpsr(void); + +/* array for holding the address of the starting point for each core */ +void *corestart[4]; + +/* array for holding the initial stack pointer for each core */ +/* these values are set in start.S */ +unsigned int core_init_sp[4]; + +void *init_args[4]; + +void unparkcore(int num, void *procaddr, void *args) { + udelay(5); + if (num > 0 && num < 4) + { + corestart[num] = (void *) procaddr; + init_args[num] = args; + sev(); // send event + // this takes the core out of its sleeping state and allows it to + // start running code + *(volatile fn *)(CORE_MBOX_BASE + CORE_MBOX_OFFSET * num) = CoreSetup; + } +} + +void createnullthread(void) +{ + uint cpuid; + cpuid = getcpuid(); + + + /* enable interrupts */ +// enable(); + + while(TRUE) + { + kprintf("CORE %d IS RUNNING\r\n", cpuid); + udelay(250); + } +} + +void printcpsr(void){ + uint mode; + int i; + mode = getmode(); + + kprintf("Printing out CPSR:\r\n"); + // print out bits of cpsr + for (i = 31; i >= 0; i--) + kprintf("%d", (mode >> i) & 1); + +} diff --git a/system/platforms/arm-rpi/usb_dwc_hcd.c b/system/platforms/arm-rpi3/usb_dwc_hcd.c similarity index 94% rename from system/platforms/arm-rpi/usb_dwc_hcd.c rename to system/platforms/arm-rpi3/usb_dwc_hcd.c index 9613c615..54b6950e 100644 --- a/system/platforms/arm-rpi/usb_dwc_hcd.c +++ b/system/platforms/arm-rpi3/usb_dwc_hcd.c @@ -77,7 +77,9 @@ #include #include #include -#include "bcm2835.h" +#include "bcm2837.h" +#include "mmu.h" +#include /** Round a number up to the next multiple of the word size. */ #define WORD_ALIGN(n) (((n) + sizeof(ulong) - 1) & ~(sizeof(ulong) - 1)) @@ -158,9 +160,23 @@ static semaphore chfree_sema; */ static struct usb_xfer_request *channel_pending_xfers[DWC_NUM_CHANNELS]; -/** Aligned buffers for DMA. */ -static uint8_t aligned_bufs[DWC_NUM_CHANNELS][WORD_ALIGN(USB_MAX_PACKET_SIZE)] - __aligned(4); +/* Aligned buffers for DMA. + * In the conception of this driver in Embedded Xinu 2.01 (circa 2013), + * there existed two possibilities for DMA buffer: + * 1. DMA over the hardware if the data is word-aligned + * OR + * 2. DMA manually through a two-dimensional "aligned_bufs" buffer + * and read/write using memcpy() + * + * Because Embedded Xinu 3.0 (2019 port) enables L1 data cache to facilitate + * multicore atomic operations, DMA needs to be guarded to maintain + * cache coherency. ARM Cortex A-53 cache maintenance operations are + * somewhat ambiguous. For example, the invalidate operation (DCIMVAC) + * may also "clean" (flush) the data cache line. Thus, it was an easier + * decision to adhere to only #2 above, and allocate a section in memory + * for it that is uncached (see mmu.c). + * */ +static uint8_t *aligned_bufs[DWC_NUM_CHANNELS]; /* Find index of first set bit in a nonzero word. */ static inline ulong first_set_bit(ulong word) @@ -216,7 +232,7 @@ dwc_power_on(void) int retval; usb_info("Powering on Synopsys DesignWare Hi-Speed " - "USB 2.0 On-The-Go Controller\n"); + "USB 2.0 On-The-Go Controller\r\n"); retval = board_setpower(POWER_USB, TRUE); return (retval == OK) ? USB_STATUS_SUCCESS : USB_STATUS_HARDWARE_ERROR; } @@ -225,7 +241,7 @@ static void dwc_power_off(void) { usb_info("Powering off Synopsys DesignWare Hi-Speed " - "USB 2.0 On-The-Go Controller\n"); + "USB 2.0 On-The-Go Controller\r\n"); board_setpower(POWER_USB, FALSE); } @@ -238,7 +254,7 @@ dwc_power_off(void) static void dwc_soft_reset(void) { - usb_debug("Resetting USB controller\n"); + usb_debug("Resetting USB controller\r\n"); /* Set soft reset flag, then wait until it's cleared. */ regs->core_reset = DWC_SOFT_RESET; @@ -251,10 +267,16 @@ dwc_soft_reset(void) * Set up the DWC OTG USB Host Controller for DMA (direct memory access). This * makes it possible for the Host Controller to directly access in-memory * buffers when performing USB transfers. Beware: all buffers accessed with DMA - * must be 4-byte-aligned. Furthermore, if the L1 data cache is enabled, then + * must be 4-byte-aligned. + * + * Furthermore, if the L1 data cache is enabled, then * it must be explicitly flushed to maintain cache coherency since it is - * internal to the ARM processor. (This is not currently handled by this driver - * because Xinu does not enable the L1 data cache.) + * internal to the ARM processor. XinuPi3 (Embedded Xinu version 3.0 2019) has + * L1 data cache enabled to facilitate multicore atomic operations. Instead of + * setting up the MMU to mark all memory cacheable (except peripherals, of course), + * we flag a section of memory as uncacheable -- this uncached 1MB section + * is used for the DMA buffer (aligned_bufs) for USB, among other buffers + * (for instance, the LAN7800 mailbox buffer). */ static void dwc_setup_dma_mode(void) @@ -269,8 +291,8 @@ dwc_setup_dma_mode(void) * receiving data will fail in virtually impossible to debug ways that cause * memory corruption. This is true even though we are using DMA and not * otherwise interacting with the Host Controller's FIFOs in this driver. */ - usb_debug("%u words of RAM available for dynamic FIFOs\n", regs->hwcfg3 >> 16); - usb_debug("original FIFO sizes: rx 0x%08x, tx 0x%08x, ptx 0x%08x\n", + usb_debug("%u words of RAM available for dynamic FIFOs\r\n", regs->hwcfg3 >> 16); + usb_debug("original FIFO sizes: rx 0x%08x, tx 0x%08x, ptx 0x%08x\r\n", regs->rx_fifo_size, regs->nonperiodic_tx_fifo_size, regs->host_periodic_tx_fifo_size); regs->rx_fifo_size = rx_words; @@ -310,7 +332,7 @@ dwc_power_on_host_port(void) { union dwc_host_port_ctrlstatus hw_status; - usb_debug("Powering on host port.\n"); + usb_debug("Powering on host port.\r\n"); hw_status = dwc_get_host_port_ctrlstatus(); hw_status.powered = 1; regs->host_port_ctrlstatus = hw_status; @@ -325,7 +347,7 @@ dwc_reset_host_port(void) { union dwc_host_port_ctrlstatus hw_status; - usb_debug("Resetting host port\n"); + usb_debug("Resetting host port\r\n"); /* Set the reset flag on the port, then clear it after a certain amount of * time. */ @@ -469,7 +491,7 @@ dwc_host_port_status_changed(void) { root_hub_status_change_request = NULL; usb_debug("Host port status changed; " - "responding to status changed transfer on root hub\n"); + "responding to status changed transfer on root hub\r\n"); *(uint8_t*)req->recvbuf = 0x2; /* 0x2 means Port 1 status changed (bit 0 is used for the hub itself) */ req->actual_size = 1; @@ -729,7 +751,7 @@ dwc_process_root_hub_request(struct usb_xfer_request *req) if (req->endpoint_desc == NULL) { /* Control transfer request to/from default control endpoint. */ - usb_debug("Simulating request to root hub's default endpoint\n"); + usb_debug("Simulating request to root hub's default endpoint\r\n"); req->status = dwc_root_hub_control_msg(req); usb_complete_xfer(req); } @@ -737,7 +759,7 @@ dwc_process_root_hub_request(struct usb_xfer_request *req) { /* Interrupt transfer request from status change endpoint. Assumes that * only one request can be submitted at a time. */ - usb_debug("Posting status change request to root hub\n"); + usb_debug("Posting status change request to root hub\r\n"); root_hub_status_change_request = req; if (host_port_status.wPortChange != 0) { @@ -870,7 +892,7 @@ dwc_channel_start_xfer(uint chan, struct usb_xfer_request *req) switch (req->control_phase) { case 0: /* SETUP phase of control transfer */ - usb_dev_debug(req->dev, "Starting SETUP transaction\n"); + usb_dev_debug(req->dev, "Starting SETUP transaction\r\n"); characteristics.endpoint_direction = USB_DIRECTION_OUT; data = &req->setup_data; transfer.size = sizeof(struct usb_control_setup_data); @@ -878,7 +900,7 @@ dwc_channel_start_xfer(uint chan, struct usb_xfer_request *req) break; case 1: /* DATA phase of control transfer */ - usb_dev_debug(req->dev, "Starting DATA transactions\n"); + usb_dev_debug(req->dev, "Starting DATA transactions\r\n"); characteristics.endpoint_direction = req->setup_data.bmRequestType >> 7; /* We need to carefully take into account that we might be @@ -900,7 +922,7 @@ dwc_channel_start_xfer(uint chan, struct usb_xfer_request *req) break; default: /* STATUS phase of control transfer */ - usb_dev_debug(req->dev, "Starting STATUS transaction\n"); + usb_dev_debug(req->dev, "Starting STATUS transaction\r\n"); /* The direction of the STATUS transaction is opposite the * direction of the DATA transactions, or from device to host if * there were no DATA transactions. */ @@ -984,36 +1006,17 @@ dwc_channel_start_xfer(uint chan, struct usb_xfer_request *req) } } - /* Set up DMA buffer. */ - if (IS_WORD_ALIGNED(data)) - { - /* Can DMA directly from source or to destination if word-aligned. */ - chanptr->dma_address = (uint32_t)data; - } - else + /* Set up DMA buffer. The data must be OR'd with 0xC0000000 for conversion from + * ARM physical address to VideoCore address */ + chanptr->dma_address = (uint32_t) aligned_bufs[chan] | 0xC0000000; + + /* For OUT endpoints, copy the data to send into the DMA buffer. */ + if (characteristics.endpoint_direction == USB_DIRECTION_OUT) { - /* Need to use alternate buffer for DMA, since the actual source or - * destination is not word-aligned. If the attempted transfer size - * overflows this alternate buffer, cap it to the greatest number of - * whole packets that fit. */ - chanptr->dma_address = (uint32_t)aligned_bufs[chan]; - if (transfer.size > sizeof(aligned_bufs[chan])) - { - transfer.size = sizeof(aligned_bufs[chan]) - - (sizeof(aligned_bufs[chan]) % - characteristics.max_packet_size); - req->short_attempt = 1; - } - /* For OUT endpoints, copy the data to send into the DMA buffer. */ - if (characteristics.endpoint_direction == USB_DIRECTION_OUT) - { - memcpy(aligned_bufs[chan], data, transfer.size); - } + memcpy(aligned_bufs[chan], data, transfer.size); } - /* Set pointer to start of next chunk of data to send/receive (may be - * different from the actual DMA address to be used by the hardware if an - * alternate buffer was selected above). */ + /* Set pointer to start of next chunk of data to send/receive */ req->cur_data_ptr = data; /* Calculate the number of packets being set up for this transfer. */ @@ -1036,12 +1039,12 @@ dwc_channel_start_xfer(uint chan, struct usb_xfer_request *req) * can find it. */ channel_pending_xfers[chan] = req; - usb_dev_debug(req->dev, "Setting up transactions on channel %u:\n" + usb_dev_debug(req->dev, "Setting up transactions on channel %u:\r\n" "\t\tmax_packet_size=%u, " - "endpoint_number=%u, endpoint_direction=%s,\n" - "\t\tlow_speed=%u, endpoint_type=%s, device_address=%u,\n\t\t" + "endpoint_number=%u, endpoint_direction=%s,\r\n" + "\t\tlow_speed=%u, endpoint_type=%s, device_address=%u,\r\n\t\t" "size=%u, packet_count=%u, packet_id=%u, split_enable=%u, " - "complete_split=%u\n", + "complete_split=%u\r\n", chan, characteristics.max_packet_size, characteristics.endpoint_number, @@ -1108,7 +1111,7 @@ defer_xfer_thread(struct usb_xfer_request *req) irqmask im; usb_dev_debug(req->dev, - "Waiting for start-of-frame\n"); + "Waiting for start-of-frame\r\n"); im = disable(); chan = dwc_get_free_channel(); @@ -1128,7 +1131,7 @@ defer_xfer_thread(struct usb_xfer_request *req) #endif /* START_SPLIT_INTR_TRANSFERS_ON_SOF */ { usb_dev_debug(req->dev, - "Waiting %u ms to start xfer again\n", interval_ms); + "Waiting %u ms to start xfer again\r\n", interval_ms); sleep(interval_ms); chan = dwc_get_free_channel(); dwc_channel_start_xfer(chan, req); @@ -1171,13 +1174,13 @@ defer_xfer_thread(struct usb_xfer_request *req) static usb_status_t defer_xfer(struct usb_xfer_request *req) { - usb_dev_debug(req->dev, "Deferring transfer\n"); + usb_dev_debug(req->dev, "Deferring transfer\r\n"); if (SYSERR == req->deferer_thread_sema) { req->deferer_thread_sema = semcreate(0); if (SYSERR == req->deferer_thread_sema) { - usb_dev_error(req->dev, "Can't create semaphore\n"); + usb_dev_error(req->dev, "Can't create semaphore\r\n"); return USB_STATUS_OUT_OF_MEMORY; } } @@ -1188,11 +1191,11 @@ defer_xfer(struct usb_xfer_request *req) DEFER_XFER_THREAD_PRIORITY, DEFER_XFER_THREAD_NAME, 1, req); - if (SYSERR == ready(req->deferer_thread_tid, RESCHED_NO)) + if (SYSERR == ready(req->deferer_thread_tid, RESCHED_NO, 0)) { req->deferer_thread_tid = BADTID; usb_dev_error(req->dev, - "Can't create thread to service periodic transfer\n"); + "Can't create thread to service periodic transfer\r\n"); return USB_STATUS_OUT_OF_MEMORY; } } @@ -1225,7 +1228,7 @@ dwc_handle_normal_channel_halted(struct usb_xfer_request *req, uint chan, uint packets_transferred = req->attempted_packets_remaining - packets_remaining; - usb_dev_debug(req->dev, "%u packets transferred on channel %u\n", + usb_dev_debug(req->dev, "%u packets transferred on channel %u\r\n", packets_transferred, chan); if (packets_transferred != 0) @@ -1237,9 +1240,8 @@ dwc_handle_normal_channel_halted(struct usb_xfer_request *req, uint chan, enum usb_direction dir = characteristics.endpoint_direction; enum usb_transfer_type type = characteristics.endpoint_type; - /* Calculate number of bytes transferred and copy data from DMA - * buffer if needed. */ - + /* Calculate number of bytes transferred and + * copy data from DMA buffer. */ if (dir == USB_DIRECTION_IN) { /* The transfer.size field seems to be updated sanely for IN @@ -1247,14 +1249,11 @@ dwc_handle_normal_channel_halted(struct usb_xfer_request *req, uint chan, * impossible to determine the length of short packets...) */ bytes_transferred = req->attempted_bytes_remaining - chanptr->transfer.size; - /* Copy data from DMA buffer if needed */ - if (!IS_WORD_ALIGNED(req->cur_data_ptr)) - { - memcpy(req->cur_data_ptr, - &aligned_bufs[chan][req->attempted_size - - req->attempted_bytes_remaining], - bytes_transferred); - } + + /* Copy data from DMA buffer */ + memcpy(req->cur_data_ptr, + &aligned_bufs[chan][req->attempted_size - req->attempted_bytes_remaining], + bytes_transferred); } else { @@ -1281,7 +1280,7 @@ dwc_handle_normal_channel_halted(struct usb_xfer_request *req, uint chan, } } - usb_dev_debug(req->dev, "Calculated %u bytes transferred\n", + usb_dev_debug(req->dev, "Calculated %u bytes transferred\r\n", bytes_transferred); /* Account for packets and bytes transferred */ @@ -1304,7 +1303,7 @@ dwc_handle_normal_channel_halted(struct usb_xfer_request *req, uint chan, { usb_dev_error(req->dev, "transfer_completed flag not " "set on channel %u as expected " - "(interrupts=0x%08x, transfer=0x%08x).\n", chan, + "(interrupts=0x%08x, transfer=0x%08x).\r\n", chan, interrupts.val, chanptr->transfer.val); return XFER_FAILED; } @@ -1321,7 +1320,7 @@ dwc_handle_normal_channel_halted(struct usb_xfer_request *req, uint chan, { usb_dev_debug(req->dev, "Starting next part of %u-byte transfer " - "after short attempt of %u bytes\n", + "after short attempt of %u bytes\r\n", req->size, req->attempted_size); req->complete_split = 0; req->next_data_pid = chanptr->transfer.packet_id; @@ -1362,7 +1361,7 @@ dwc_handle_normal_channel_halted(struct usb_xfer_request *req, uint chan, /* Transfer is actually complete (or at least, it was an IN transfer * that completed with fewer bytes transferred than requested). */ - usb_dev_debug(req->dev, "Transfer completed on channel %u\n", chan); + usb_dev_debug(req->dev, "Transfer completed on channel %u\r\n", chan); return XFER_COMPLETE; } else @@ -1375,7 +1374,7 @@ dwc_handle_normal_channel_halted(struct usb_xfer_request *req, uint chan, req->complete_split ^= 1; } - usb_dev_debug(req->dev, "Continuing transfer (complete_split=%u)\n", + usb_dev_debug(req->dev, "Continuing transfer (complete_split=%u)\r\n", req->complete_split); return XFER_NEEDS_TRANS_RESTART; } @@ -1392,13 +1391,13 @@ dwc_handle_normal_channel_halted(struct usb_xfer_request *req, uint chan, { /* Start CSPLIT */ req->complete_split = 1; - usb_dev_debug(req->dev, "Continuing transfer (complete_split=%u)\n", + usb_dev_debug(req->dev, "Continuing transfer (complete_split=%u)\r\n", req->complete_split); return XFER_NEEDS_TRANS_RESTART; } else { - usb_dev_error(req->dev, "No packets transferred.\n"); + usb_dev_error(req->dev, "No packets transferred.\r\n"); return XFER_FAILED; } } @@ -1421,9 +1420,9 @@ dwc_handle_channel_halted_interrupt(uint chan) union dwc_host_channel_interrupts interrupts = chanptr->interrupts; enum dwc_intr_status intr_status; - usb_debug("Handling channel %u halted interrupt\n" + usb_debug("Handling channel %u halted interrupt\r\n" "\t\t(interrupts pending: 0x%08x, characteristics=0x%08x, " - "transfer=0x%08x)\n", + "transfer=0x%08x)\r\n", chan, interrupts.val, chanptr->characteristics.val, chanptr->transfer.val); @@ -1439,7 +1438,7 @@ dwc_handle_channel_halted_interrupt(uint chan) /* An error occurred. Complete the transfer immediately with an error * status. */ usb_dev_error(req->dev, "Transfer error on channel %u " - "(interrupts pending: 0x%08x, packet_count=%u)\n", + "(interrupts pending: 0x%08x, packet_count=%u)\r\n", chan, interrupts.val, chanptr->transfer.packet_count); intr_status = XFER_FAILED; } @@ -1448,7 +1447,7 @@ dwc_handle_channel_halted_interrupt(uint chan) /* Restart transactions that fail sporatically due to frame overruns. * TODO: why does this happen? */ usb_dev_debug(req->dev, "Frame overrun on channel %u; " - "restarting transaction\n", chan); + "restarting transaction\r\n", chan); intr_status = XFER_NEEDS_TRANS_RESTART; } else if (interrupts.nyet_response_received) @@ -1458,11 +1457,11 @@ dwc_handle_channel_halted_interrupt(uint chan) * received, restart the entire split transaction. (Apparently, because * of frame overruns or some other reason it's possible for NYETs to be * issued indefinitely until the transaction is retried.) */ - usb_dev_debug(req->dev, "NYET response received on channel %u\n", chan); + usb_dev_debug(req->dev, "NYET response received on channel %u\r\n", chan); if (++req->csplit_retries >= 10) { usb_dev_debug(req->dev, "Restarting split transaction " - "(CSPLIT tried %u times)\n", req->csplit_retries); + "(CSPLIT tried %u times)\r\n", req->csplit_retries); req->complete_split = FALSE; } intr_status = XFER_NEEDS_TRANS_RESTART; @@ -1473,7 +1472,7 @@ dwc_handle_channel_halted_interrupt(uint chan) * send at this time. Try again later. Special case: if the NAK was * sent during a Complete Split transaction, restart with the Start * Split, not the Complete Split. */ - usb_dev_debug(req->dev, "NAK response received on channel %u\n", chan); + usb_dev_debug(req->dev, "NAK response received on channel %u\r\n", chan); intr_status = XFER_NEEDS_DEFERRAL; req->complete_split = FALSE; } @@ -1575,7 +1574,7 @@ dwc_interrupt_handler(void) { /* Start of frame (SOF) interrupt occurred. */ - usb_debug("Received SOF intr (host_frame_number=0x%08x)\n", + usb_debug("Received SOF intr (host_frame_number=0x%08x)\r\n", regs->host_frame_number); if ((regs->host_frame_number & 0x7) != 6) { @@ -1632,7 +1631,7 @@ dwc_interrupt_handler(void) union dwc_host_port_ctrlstatus hw_status = regs->host_port_ctrlstatus; - usb_debug("Port interrupt detected: host_port_ctrlstatus=0x%08x\n", + usb_debug("Port interrupt detected: host_port_ctrlstatus=0x%08x\r\n", hw_status.val); host_port_status.connected = hw_status.connected; @@ -1803,7 +1802,7 @@ dwc_start_xfer_scheduler(void) XFER_SCHEDULER_THREAD_STACK_SIZE, XFER_SCHEDULER_THREAD_PRIORITY, XFER_SCHEDULER_THREAD_NAME, 0); - if (SYSERR == ready(dwc_xfer_scheduler_tid, RESCHED_NO)) + if (SYSERR == ready(dwc_xfer_scheduler_tid, RESCHED_NO, 0)) { semfree(chfree_sema); mailboxFree(hcd_xfer_mailbox); @@ -1819,6 +1818,14 @@ usb_status_t hcd_start(void) { usb_status_t status; + int i; + + /* Allocate an uncached area for the DMA buffer to use, avoiding + * the need for cache maintenance operations. */ + for (i = 0; i < DWC_NUM_CHANNELS; i++) + { + aligned_bufs[i] = dma_buf_alloc(WORD_ALIGN(USB_MAX_PACKET_SIZE)); + } status = dwc_power_on(); if (status != USB_STATUS_SUCCESS) diff --git a/system/platforms/arm-rpi/usb_dwc_regs.h b/system/platforms/arm-rpi3/usb_dwc_regs.h similarity index 100% rename from system/platforms/arm-rpi/usb_dwc_regs.h rename to system/platforms/arm-rpi3/usb_dwc_regs.h diff --git a/system/platforms/arm-rpi/watchdog.c b/system/platforms/arm-rpi3/watchdog.c similarity index 98% rename from system/platforms/arm-rpi/watchdog.c rename to system/platforms/arm-rpi3/watchdog.c index 4b2090fa..9e94f848 100644 --- a/system/platforms/arm-rpi/watchdog.c +++ b/system/platforms/arm-rpi3/watchdog.c @@ -8,7 +8,7 @@ /* Embedded Xinu, Copyright (C) 2013. All rights reserved. */ #include -#include "bcm2835.h" +#include "bcm2837.h" #define PM_RSTC (PM_REGS_BASE + 0x1c) #define PM_WDOG (PM_REGS_BASE + 0x24) diff --git a/system/platforms/e2100l/Makerules b/system/platforms/e2100l/Makerules deleted file mode 100644 index 2f63b959..00000000 --- a/system/platforms/e2100l/Makerules +++ /dev/null @@ -1,22 +0,0 @@ -# This Makefile contains rules to build files in this directory. - -# Name of this component (the directory this file is stored in) -COMP = system/platforms/e2100l - -# Source files for this component - -# Important system components -S_FILES = pause.S -C_FILES = platforminit.c - -# Files for process control -S_FILES += ctxsw.S -C_FILES += setupStack.c - -# Files for preemption and interrupts -S_FILES += clkupdate.S intutils.S intdispatch.S halt.S -C_FILES += dispatch.c exception.c - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/system/platforms/e2100l/ar9130.h b/system/platforms/e2100l/ar9130.h deleted file mode 100644 index 7a46ac9f..00000000 --- a/system/platforms/e2100l/ar9130.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @file ar9130.h - * - * Constants and declarations associated with the Atheros 9130 - * wireless System On A Chip. - * - */ - -#define RST_MISC_INTERRUPT_MASK 0xB8060014 -#define RST_MISC_INTERRUPT_STATUS 0xB8060010 - -#define RST_MISC_IRQ_TIMER (1 << 0) -#define RST_MISC_IRQ_ERROR (1 << 1) -#define RST_MISC_IRQ_GPIO (1 << 2) -#define RST_MISC_IRQ_UART (1 << 3) -#define RST_MISC_IRQ_WATCHDOG (1 << 4) -#define RST_MISC_IRQ_PERF (1 << 5) -#define RST_MISC_IRQ_MBOX (1 << 7) -#define RST_MISC_IRQ_MASK 0x00FF diff --git a/system/platforms/e2100l/clkupdate.S b/system/platforms/e2100l/clkupdate.S deleted file mode 100644 index 81ed69d7..00000000 --- a/system/platforms/e2100l/clkupdate.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/e2100l/ctxsw.S b/system/platforms/e2100l/ctxsw.S deleted file mode 100644 index 4048a664..00000000 --- a/system/platforms/e2100l/ctxsw.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/e2100l/dispatch.c b/system/platforms/e2100l/dispatch.c deleted file mode 100644 index f2922586..00000000 --- a/system/platforms/e2100l/dispatch.c +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @file dispatch.c - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#include -#include -#include -#include -#include "ar9130.h" -#include - -char *interrupts[] = { - "Software interrupt request 0", - "Software interrupt request 1", - "Hardware interrupt request 0, wmac", - "Hardware interrupt request 1, usb", - "Hardware interrupt request 2, eth0", - "Hardware interrupt request 3, eth1", - "Hardware interrupt request 4, misc", - "Hardware interrupt request 5, timer", - "Miscellaneous interrupt request 0, timer", - "Miscellaneous interrupt request 1, error", - "Miscellaneous interrupt request 2, gpio", - "Miscellaneous interrupt request 3, uart", - "Miscellaneous interrupt request 4, watchdog", - "Miscellaneous interrupt request 5, perf", - "Miscellaneous interrupt request 6, reserved", - "Miscellaneous interrupt request 7, mbox", -}; - -/** - * Dispatcher for interrupt requests. - * - * @param cause contents of cause register identifies interrupt - * @param frame pointer to interrupt frame with saved status - * - */ -void dispatch(long cause, long *frame) -{ - long irqcode = 0, irqnum = -1; - irqmask im; - void (*handler) (void); - - irqcode = (cause & CAUSE_IRQ) >> CAUSE_IRQ_SHIFT; - - /* Calculate which interrupt number this is. */ - while (irqcode) - { - irqnum++; - irqcode = irqcode >> 1; - } - -#ifdef IRQ_ATH_MISC - if (IRQ_ATH_MISC == irqnum) - { - ulong *miscStat = (ulong *)RST_MISC_INTERRUPT_STATUS; - ulong *miscMask = (ulong *)RST_MISC_INTERRUPT_MASK; - irqcode = *miscStat & (*miscMask & RST_MISC_IRQ_MASK); - if (!irqcode) - return; /* Spurious AHB interrupt. */ - irqnum = 7; - while (irqcode) - { - irqnum++; - irqcode = irqcode >> 1; - } - } -#endif - - /* Check for registered interrupt handler. */ - if (NULL == (handler = interruptVector[irqnum])) - { - kprintf - ("Xinu Interrupt %d uncaught, %s\r\n", - irqnum, interrupts[irqnum]); - while (1) - ; /* forever */ - } - - im = disable(); /* Disable interrupts for duration of handler */ - exlreset(); /* Reset system-wide exception bit */ - - (*handler) (); /* Call device-specific handler */ - - exlset(); /* Set system-wide exception bit */ - restore(im); -} - -/** - * Enable IRQ number. - * - * @param irqnumber Request number to enable. - * - */ -void enable_irq(irqmask irqnumber) -{ -#ifdef IRQ_ATH_MISC - int irqmisc; - ulong *miscMask = (ulong *)RST_MISC_INTERRUPT_MASK; - if (irqnumber >= 8) - { - irqmisc = irqnumber - 8; - enable_cpuirq(IRQ_ATH_MISC); - *miscMask |= (1 << irqmisc); - } - else - { - enable_cpuirq(irqnumber); - } -#else - enable_cpuirq(irqnumber); -#endif -} - -/** - * Disable IRQ number. - * - * @param irqnumber Request number to enable. - * - */ -void disable_irq(irqmask irqnumber) -{ -#ifdef IRQ_ATH_MISC - int irqmisc; - ulong *miscMask = (ulong *)RST_MISC_INTERRUPT_MASK; - if (irqnumber >= 8) - { - irqmisc = irqnumber - 8; - *miscMask &= ~(1UL << irqmisc); - } - else - { - disable_cpuirq(irqnumber); - } -#else - disable_cpuirq(irqnumber); -#endif -} diff --git a/system/platforms/e2100l/exception.c b/system/platforms/e2100l/exception.c deleted file mode 100644 index 9174fa36..00000000 --- a/system/platforms/e2100l/exception.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/e2100l/halt.S b/system/platforms/e2100l/halt.S deleted file mode 100644 index 46d89066..00000000 --- a/system/platforms/e2100l/halt.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/e2100l/intdispatch.S b/system/platforms/e2100l/intdispatch.S deleted file mode 100644 index fad47b80..00000000 --- a/system/platforms/e2100l/intdispatch.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/e2100l/interrupt.h b/system/platforms/e2100l/interrupt.h deleted file mode 100644 index 79d5dcb9..00000000 --- a/system/platforms/e2100l/interrupt.h +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @file interrupt.h - * - * Constants and declarations associated with interrupt and exception - * processing. - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#ifndef _INTERRUPT_H_ -#define _INTERRUPT_H_ - -#include - -/** Address of interrupt request handler. */ -#define IRQ_ADDR 0x80000180 -/** Address of Xinu-defined trap (exception) vector. */ -#define TRAPVEC_ADDR 0x80001000 -/** Address of Xinu-defined interrupt request vector. */ -#define IRQVEC_ADDR 0x80001080 -/** Address of end of Xinu-defined interrupt tables. */ -#define IRQVEC_END 0x800010C0 - -#ifndef __ASSEMBLER__ -void enable_irq(irqmask); -void disable_irq(irqmask); -#endif - -#endif /* _INTERRUPT_H_ */ diff --git a/system/platforms/e2100l/intutils.S b/system/platforms/e2100l/intutils.S deleted file mode 100644 index 728cec2f..00000000 --- a/system/platforms/e2100l/intutils.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/e2100l/pause.S b/system/platforms/e2100l/pause.S deleted file mode 100644 index 6124b2b2..00000000 --- a/system/platforms/e2100l/pause.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/e2100l/platforminit.c b/system/platforms/e2100l/platforminit.c deleted file mode 100644 index 62b4cf3b..00000000 --- a/system/platforms/e2100l/platforminit.c +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @file platforminit.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include -#include - -extern ulong cpuid; /* Processor id */ - -extern struct platform platform; /* Platform specific configuration */ - -/** - * Determines and stores all platform specific information. - * @return OK if everything is determined successfully - */ -int platforminit(void) -{ - switch (cpuid & PRID_CPU) - { - case PRID_CPU_BCM3302: - strlcpy(platform.family, "Broadcom 3302", PLT_STRMAX); - switch (cpuid & PRID_REV) - { - case PRID_REV_WRT54G: - strlcpy(platform.name, "Linksys WRT54G", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_WRT54G); - platform.minaddr = (void *)KSEG0_BASE; - platform.clkfreq = CLKFREQ_WRT54G; - platform.uart_dll = UART_DLL_WRT54G; - break; - case PRID_REV_WRT54GL: - strlcpy(platform.name, "Linksys WRT54GL", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_WRT54GL); - platform.minaddr = (void *)KSEG0_BASE; - platform.clkfreq = CLKFREQ_WRT54GL; - platform.uart_dll = UART_DLL_WRT54GL; - break; - case PRID_REV_WRT350N: - strlcpy(platform.name, "Linksys WRT350N", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_WRT350N); - platform.minaddr = (void *)KSEG0_BASE; - platform.clkfreq = CLKFREQ_WRT350N; - platform.uart_dll = UART_DLL_WRT350N; - break; - default: - strlcpy(platform.name, "Unknown Platform", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_DEFAULT); - platform.minaddr = (void *)KSEG0_BASE; - platform.clkfreq = CLKFREQ_DEFAULT; - platform.uart_dll = UART_DLL_DEFAULT; - return SYSERR; - } - break; - case PRID_CPU_24K: - strlcpy(platform.family, "MIPS 24K", PLT_STRMAX); - switch (cpuid & PRID_REV) - { - case PRID_REV_WRT160NL: - strlcpy(platform.name, "Linksys WRT160NL", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_WRT160NL); - platform.minaddr = (void *)KSEG0_BASE; - platform.clkfreq = CLKFREQ_WRT160NL; - platform.uart_dll = (CLKFREQ_WRT160NL / 16) / UART_BAUD; - break; - default: - strlcpy(platform.name, "Unknown Platform", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_DEFAULT); - platform.minaddr = (void *)KSEG0_BASE; - platform.clkfreq = CLKFREQ_DEFAULT; - platform.uart_dll = UART_DLL_DEFAULT; - return SYSERR; - } - break; - } - return OK; -} diff --git a/system/platforms/e2100l/setupStack.c b/system/platforms/e2100l/setupStack.c deleted file mode 100644 index bda20ecf..00000000 --- a/system/platforms/e2100l/setupStack.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/mipsel-qemu/Makerules b/system/platforms/mipsel-qemu/Makerules deleted file mode 100644 index c52958c2..00000000 --- a/system/platforms/mipsel-qemu/Makerules +++ /dev/null @@ -1,26 +0,0 @@ -# This Makefile contains rules to build files in this directory. - -# Name of this component (the directory this file is stored in) -COMP = system/platforms/mipsel-qemu - -# Source files for this component - -# Important system components -S_FILES = pause.S -C_FILES = platforminit.c - -# Files for process control -S_FILES += ctxsw.S -C_FILES += setupStack.c - -# Files for preemption and interrupts -S_FILES += clkupdate.S intutils.S intdispatch.S halt.S -C_FILES += dispatch.c exception.c - -# Files for system calls -S_FILES += syscall_entry.S -C_FILES += syscall_dispatch.c - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/system/platforms/mipsel-qemu/clkupdate.S b/system/platforms/mipsel-qemu/clkupdate.S deleted file mode 100644 index 81ed69d7..00000000 --- a/system/platforms/mipsel-qemu/clkupdate.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/mipsel-qemu/ctxsw.S b/system/platforms/mipsel-qemu/ctxsw.S deleted file mode 100644 index 4048a664..00000000 --- a/system/platforms/mipsel-qemu/ctxsw.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/mipsel-qemu/dispatch.c b/system/platforms/mipsel-qemu/dispatch.c deleted file mode 100644 index 393b9196..00000000 --- a/system/platforms/mipsel-qemu/dispatch.c +++ /dev/null @@ -1,169 +0,0 @@ -/** - * @file dispatch.c - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#include -#include -#include -#include -#include "pic8259.h" -#include - -char *interrupts[] = { - "Software interrupt request 0", - "Software interrupt request 1", - "Hardware interrupt request 0, programmable interrupt controller", - "Hardware interrupt request 1", - "Hardware interrupt request 2", - "Hardware interrupt request 3", - "Hardware interrupt request 4", - "Hardware interrupt request 5, timer", - "Interrupt controller request 0, programmable interval timer", - "Interrupt controller request 1, keyboard", - "Interrupt controller request 2", - "Interrupt controller request 3, serial 1", - "Interrupt controller request 4, serial 0", - "Interrupt controller request 5", - "Interrupt controller request 6", - "Interrupt controller request 7", - "Interrupt controller request 8, real-time clock", - "Interrupt controller request 9, ethernet", - "Interrupt controller request 10", - "Interrupt controller request 11", - "Interrupt controller request 12, mouse", - "Interrupt controller request 13", - "Interrupt controller request 14, IDE0", - "Interrupt controller request 15, IDE1" -}; - -/** - * Dispatcher for interrupt requests. - * - * @param cause contents of cause register identifies interrupt - * @param frame pointer to interrupt frame with saved status - * - */ -void dispatch(long cause, long *frame) -{ - long irqcode = 0, irqnum = -1; - irqmask im; - void (*handler) (void); - - irqcode = (cause & CAUSE_IRQ) >> CAUSE_IRQ_SHIFT; - - /* Calculate which interrupt number this is. */ - while (irqcode) - { - irqnum++; - irqcode = irqcode >> 1; - } - -#ifdef PIC8259 - if (IRQ_HW0 == irqnum) - { - uchar *picStat = (uchar *)PIC_MASTER; - irqcode = *picStat; - irqnum = 7; - while (irqcode) - { - irqnum++; - irqcode = irqcode >> 1; - } - if (7 == irqnum) - { - irqnum = 15; - picStat = (uchar *)PIC_SLAVE; - irqcode = *picStat; - while (irqcode) - { - irqnum++; - irqcode = irqcode >> 1; - } - } - } -#endif - - /* Check for registered interrupt handler. */ - if (NULL == (handler = interruptVector[irqnum])) - { - kprintf - ("Xinu Interrupt %d uncaught, %s\r\n", - irqnum, interrupts[irqnum]); - while (1) - ; /* forever */ - } - - im = disable(); /* Disable interrupts for duration of handler */ - exlreset(); /* Reset system-wide exception bit */ - - (*handler) (); /* Call device-specific handler */ - - exlset(); /* Set system-wide exception bit */ - restore(im); -} - -/** - * Enable IRQ number. - * - * @param irqnumber Request number to enable. - * - */ -void enable_irq(irqmask irqnumber) -{ -#ifdef PIC8259 - uint irqmisc; - uchar *picMask = (uchar *)PIC_MASTER_IMR; - if (irqnumber >= 16) - { - picMask = (uchar *)PIC_SLAVE_IMR; - irqmisc = irqnumber - 16; - enable_cpuirq(IRQ_HW0); - *picMask &= ~(1 << irqmisc); - } - else if (irqnumber >= 8) - { - irqmisc = irqnumber - 8; - enable_cpuirq(IRQ_HW0); - *picMask &= ~(1 << irqmisc); - } - else - { - enable_cpuirq(irqnumber); - } -#else - enable_cpuirq(irqnumber); -#endif -} - -/** - * Disable IRQ number. - * - * @param irqnumber Request number to enable. - * - */ -void disable_irq(irqmask irqnumber) -{ -#ifdef PIC8259 - uint irqmisc; - uchar *picMask = (uchar *)PIC_MASTER_IMR; - if (irqnumber >= 16) - { - picMask = (uchar *)PIC_SLAVE_IMR; - irqmisc = irqnumber - 16; - *picMask |= (1 << irqmisc); - } - else if (irqnumber >= 8) - { - irqmisc = irqnumber - 8; - *picMask |= (1 << irqmisc); - } - else - { - disable_cpuirq(irqnumber); - } -#else - disable_cpuirq(irqnumber); -#endif -} diff --git a/system/platforms/mipsel-qemu/exception.c b/system/platforms/mipsel-qemu/exception.c deleted file mode 100644 index 9174fa36..00000000 --- a/system/platforms/mipsel-qemu/exception.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/mipsel-qemu/halt.S b/system/platforms/mipsel-qemu/halt.S deleted file mode 100644 index 46d89066..00000000 --- a/system/platforms/mipsel-qemu/halt.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/mipsel-qemu/intdispatch.S b/system/platforms/mipsel-qemu/intdispatch.S deleted file mode 100644 index fad47b80..00000000 --- a/system/platforms/mipsel-qemu/intdispatch.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/mipsel-qemu/interrupt.h b/system/platforms/mipsel-qemu/interrupt.h deleted file mode 100644 index 5dd52838..00000000 --- a/system/platforms/mipsel-qemu/interrupt.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @file interrupt.h - * - * Constants and declarations associated with interrupt and exception - * processing. - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#ifndef _INTERRUPT_H_ -#define _INTERRUPT_H_ - -#include - -/** Address of interrupt request handler. */ -#define IRQ_ADDR 0x80000180 -/** Address of Xinu-defined trap (exception) vector. */ -#define TRAPVEC_ADDR 0x80000200 -/** Address of Xinu-defined interrupt request vector. */ -#define IRQVEC_ADDR 0x80000280 -/** Address of end of Xinu-defined interrupt tables. */ -#define IRQVEC_END 0x800002E0 - -#ifndef __ASSEMBLER__ -void enable_irq(irqmask); -void disable_irq(irqmask); -#endif - -#endif /* _INTERRUPT_H_ */ diff --git a/system/platforms/mipsel-qemu/intutils.S b/system/platforms/mipsel-qemu/intutils.S deleted file mode 100644 index 728cec2f..00000000 --- a/system/platforms/mipsel-qemu/intutils.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/mipsel-qemu/pause.S b/system/platforms/mipsel-qemu/pause.S deleted file mode 100644 index 6124b2b2..00000000 --- a/system/platforms/mipsel-qemu/pause.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/mipsel-qemu/pic8259.h b/system/platforms/mipsel-qemu/pic8259.h deleted file mode 100644 index 9a95bb67..00000000 --- a/system/platforms/mipsel-qemu/pic8259.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @file pic8259.h - * - * PC-style i8259 programmable interrupt controller. - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#ifndef _PIC8259_H_ -#define _PIC8259_H_ - -#ifdef PIC8259 - -#define PIC_MASTER PIC8259 -#define PIC_MASTER_IMR (PIC_MASTER + 1) -#define PIC_SLAVE (PIC_MASTER + 0x80) -#define PIC_SLAVE_IMR (PIC_SLAVE + 1) -#define PIC_MASTER_ELCR (PIC_MASTER + 0x4B0) -#define PIC_SLAVE_ELCR (PIC_MASTER + 0x4B1) - -#endif /* PIC8259 */ - -/* PIC function prototypes */ - -#endif /* _PIC8259_H_ */ diff --git a/system/platforms/mipsel-qemu/platforminit.c b/system/platforms/mipsel-qemu/platforminit.c deleted file mode 100644 index e7a624be..00000000 --- a/system/platforms/mipsel-qemu/platforminit.c +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @file platforminit.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include -#include -#include - -extern ulong cpuid; /* Processor id */ - -extern struct platform platform; /* Platform specific configuration */ - -/** - * Determines and stores all platform specific information. - * @return OK if everything is determined successfully - */ -int platforminit(void) -{ - strlcpy(platform.family, "MIPS 24K", PLT_STRMAX); - strlcpy(platform.name, "Qemu", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_DEFAULT); - platform.minaddr = (void *)KSEG0_BASE; - platform.clkfreq = CLKFREQ_DEFAULT; - platform.uart_dll = UART_DLL_DEFAULT; -#ifdef PIC8259 - /* Mask off interrupts until needed */ - uchar *pic = (uchar *)PIC_MASTER_IMR; - *pic = 0xFF; - pic = (uchar *)PIC_SLAVE_IMR; - *pic = 0xFF; - /* Set all interrupts to be level-triggered, not edge */ - pic = (uchar *)PIC_MASTER_ELCR; - *pic = 0xFF; - pic = (uchar *)PIC_SLAVE_ELCR; - *pic = 0xFF; -#endif - return OK; -} diff --git a/system/platforms/mipsel-qemu/setupStack.c b/system/platforms/mipsel-qemu/setupStack.c deleted file mode 100644 index bda20ecf..00000000 --- a/system/platforms/mipsel-qemu/setupStack.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/mipsel-qemu/syscall_dispatch.c b/system/platforms/mipsel-qemu/syscall_dispatch.c deleted file mode 100644 index c898bf32..00000000 --- a/system/platforms/mipsel-qemu/syscall_dispatch.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/mipsel-qemu/syscall_entry.S b/system/platforms/mipsel-qemu/syscall_entry.S deleted file mode 100644 index 34ac9af7..00000000 --- a/system/platforms/mipsel-qemu/syscall_entry.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wl330ge/Makerules b/system/platforms/wl330ge/Makerules deleted file mode 100644 index c0b53f28..00000000 --- a/system/platforms/wl330ge/Makerules +++ /dev/null @@ -1,29 +0,0 @@ -# This Makefile contains rules to build files in this directory. - -# Name of this component (the directory this file is stored in) -COMP = system/platforms/wl330ge - -# Source files for this component - -# Important system components -S_FILES = pause.S -C_FILES = platforminit.c - -# Files for process control -S_FILES += ctxsw.S -C_FILES += setupStack.c - -# Files for preemption and interrupts -S_FILES += clkupdate.S intutils.S intdispatch.S halt.S -C_FILES += dispatch.c exception.c - -# Files for JTAG debugging -S_FILES += debugbreak.S debugret.S - -# Files for system calls -S_FILES += syscall_entry.S -C_FILES += syscall_dispatch.c - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/system/platforms/wl330ge/clkupdate.S b/system/platforms/wl330ge/clkupdate.S deleted file mode 100644 index 81ed69d7..00000000 --- a/system/platforms/wl330ge/clkupdate.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wl330ge/ctxsw.S b/system/platforms/wl330ge/ctxsw.S deleted file mode 100644 index 4048a664..00000000 --- a/system/platforms/wl330ge/ctxsw.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wl330ge/debugbreak.S b/system/platforms/wl330ge/debugbreak.S deleted file mode 100644 index 5b354c06..00000000 --- a/system/platforms/wl330ge/debugbreak.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wl330ge/debugret.S b/system/platforms/wl330ge/debugret.S deleted file mode 100644 index 569496ff..00000000 --- a/system/platforms/wl330ge/debugret.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wl330ge/dispatch.c b/system/platforms/wl330ge/dispatch.c deleted file mode 100644 index d1949e17..00000000 --- a/system/platforms/wl330ge/dispatch.c +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @file dispatch.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include - -const char *interrupts[] = { - "Software interrupt request 0", - "Software interrupt request 1", - "Hardware interrupt request 0, eth1", - "Hardware interrupt request 1, serial", - "Hardware interrupt request 2, eth0", - "Hardware interrupt request 3", - "Hardware interrupt request 4", - "Hardware interrupt request 5, timer" -}; - -/** - * Dispatcher for interrupt requests. - * - * @param cause contents of cause register identifies interrupt - * @param frame pointer to interrupt frame with saved status - * - */ -void dispatch(long cause, long *frame) -{ - long irqcode = 0, irqnum = -1; - irqmask im; - void (*handler) (void); - - irqcode = (cause & CAUSE_IRQ) >> CAUSE_IRQ_SHIFT; - - /* Calculate which interrupt number this is. */ - while (irqcode) - { - irqnum++; - irqcode = irqcode >> 1; - } - - /* Check for registered interrupt handler. */ - if (NULL == (handler = interruptVector[irqnum])) - { - kprintf - ("Xinu Interrupt %d uncaught, %s\r\n", - irqnum, interrupts[irqnum]); - while (1) - ; /* forever */ - } - - im = disable(); /* Disable interrupts for duration of handler */ - exlreset(); /* Reset system-wide exception bit */ - - (*handler) (); /* Call device-specific handler */ - - exlset(); /* Set system-wide exception bit */ - restore(im); -} diff --git a/system/platforms/wl330ge/exception.c b/system/platforms/wl330ge/exception.c deleted file mode 100644 index 9174fa36..00000000 --- a/system/platforms/wl330ge/exception.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wl330ge/flash.h b/system/platforms/wl330ge/flash.h deleted file mode 100644 index fdbc2ee2..00000000 --- a/system/platforms/wl330ge/flash.h +++ /dev/null @@ -1,266 +0,0 @@ -/** - * @file flash.h - * This file provides various definitions and prototypes for the flash - * driver and all its affiliates - * - */ -/* Embedded XINU, Copyright (C) 2007. All rights reserved. */ - -#include -#include -#include -#include - -#ifndef _FLASH_H_ -#define _FLASH_H_ - -/* Disk variables */ -#define MAX_LIVE_BLOCKS 8 /**< number of blocks to keep in memory */ -#define FLASH_BLK_SIZE 512 /**< disk blocks are 512 bytes */ - -#define FLASH_BLOCK_FREE 0 /**< block can be allocated */ -#define FLASH_BLOCK_CLEAN 1 /**< block has been read but not writted */ -#define FLASH_BLOCK_DIRTY 2 /**< block has been changed */ - -/* Important disk block sections */ -#define CFE_MIN_BLOCK 0x0000 /**< Physical addr: 0x000000 */ -#define CFE_MAX_BLOCK 0x01FF /**< Physical addr: 0x03ffff */ -#define KERNEL_MIN_BLOCK 0x0200 /**< Physical addr: 0x040000 */ -#define KERNEL_MAX_BLOCK 0x03FF /**< Physical addr: 0x07ffff */ -#define NVRAM_MIN_BLOCK 0x1FC0 /**< Physical addr: 0x3F8000 */ -#define NVRAM_MAX_BLOCK 0x1FFF /**< Physical addr: 0x3fffff */ - -/* Flash control switch values */ -#define FLASH_BLOCK_SIZE 0x0000 /**< get the size of disk blocks */ -#define FLASH_N_BLOCKS 0x0001 /**< get number of disk blocks */ -#define FLASH_SYNC 0x0002 /**< force sync of disk device */ - -/* Flash variables */ -#define FLASH_WIDEMODE 1 -#define MAX_REGIONS 8 - -/* TRX variables */ -#define TRX_MAGIC 0x30524448 - -/* Structures */ -struct trx_header -{ - uint magic; /**< "HDR0" */ - uint len; /**< Length of file including header */ - uint crc; /**< 32-bit CRC from flag_vers to EOF */ - uint flags_vers; /**< 0-15 flags, 16-31 version */ - uint offsets[3]; /**< Partition offsets from header start */ -}; - -/* File structure */ -struct file -{ - uint len; - char *name; - void *data; -}; - -struct flash_region -{ - ulong nblocks; /**< number of blocks within region */ - ulong block_size; /**< size of block in region */ - ulong region_start; /**< beginning of region in memory */ - ulong region_size; /**< size of region in bytes */ -}; - -struct flash_block -{ - ulong start_pos; /**< physical position data starts at */ - ulong size; /**< size of this block */ - uchar state; /**< state of this block */ - void *buffer; /**< buffer for this block */ -}; - -struct flash -{ - device *device; /**< flash entry in dev structure */ - uchar commands; /**< command set the interface uses */ - ulong base; /**< base address for flash memory */ - semaphore lock; /**< lock for execution flash operations */ - ulong size; /**< size (in bytes) of flash memory */ - uchar mode; /**< current mode of flash */ - ushort nregions; /**< number of regions on device */ - struct flash_region regions[MAX_REGIONS]; /**< region info. */ - - ulong log_size; /**< size of logical disk blocks */ - ulong nlog_blocks; /**< number of logical blocks on disk */ - - /** list of open blocks on flash device */ - struct flash_block erase_blocks[MAX_LIVE_BLOCKS]; - uchar curr_block; /**< offset of the oldest block stored */ -}; - -extern struct flash_block bad_block; - -/* - * Common Flash Interface Query commands and macros - */ - -/* put/get 8-bits commands for CFI */ -#define CFI_PUT_8(addr,offset,cmd) \ - *((volatile unsigned char *)((addr)+((offset)< diff --git a/system/platforms/wl330ge/intdispatch.S b/system/platforms/wl330ge/intdispatch.S deleted file mode 100644 index fad47b80..00000000 --- a/system/platforms/wl330ge/intdispatch.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wl330ge/interrupt.h b/system/platforms/wl330ge/interrupt.h deleted file mode 100644 index f204de69..00000000 --- a/system/platforms/wl330ge/interrupt.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @file interrupt.h - * - * Constants and declarations associated with interrupt and exception - * processing. - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#ifndef _INTERRUPT_H_ -#define _INTERRUPT_H_ - -#include - -/** Address of interrupt request handler. */ -#define IRQ_ADDR 0x80000180 -/** Address of Xinu-defined trap (exception) vector. */ -#define TRAPVEC_ADDR 0x80000200 -/** Address of Xinu-defined interrupt request vector. */ -#define IRQVEC_ADDR 0x80000280 -/** Address of end of Xinu-defined interrupt tables. */ -#define IRQVEC_END 0x800002A0 - -#ifndef __ASSEMBLER__ -#define enable_irq enable_cpuirq -#define disable_irq disable_cpuirq -#endif - -#endif /* _INTERRUPT_H_ */ diff --git a/system/platforms/wl330ge/intutils.S b/system/platforms/wl330ge/intutils.S deleted file mode 100644 index 728cec2f..00000000 --- a/system/platforms/wl330ge/intutils.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wl330ge/pause.S b/system/platforms/wl330ge/pause.S deleted file mode 100644 index 6124b2b2..00000000 --- a/system/platforms/wl330ge/pause.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wl330ge/platforminit.c b/system/platforms/wl330ge/platforminit.c deleted file mode 100644 index 62b4cf3b..00000000 --- a/system/platforms/wl330ge/platforminit.c +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @file platforminit.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include -#include - -extern ulong cpuid; /* Processor id */ - -extern struct platform platform; /* Platform specific configuration */ - -/** - * Determines and stores all platform specific information. - * @return OK if everything is determined successfully - */ -int platforminit(void) -{ - switch (cpuid & PRID_CPU) - { - case PRID_CPU_BCM3302: - strlcpy(platform.family, "Broadcom 3302", PLT_STRMAX); - switch (cpuid & PRID_REV) - { - case PRID_REV_WRT54G: - strlcpy(platform.name, "Linksys WRT54G", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_WRT54G); - platform.minaddr = (void *)KSEG0_BASE; - platform.clkfreq = CLKFREQ_WRT54G; - platform.uart_dll = UART_DLL_WRT54G; - break; - case PRID_REV_WRT54GL: - strlcpy(platform.name, "Linksys WRT54GL", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_WRT54GL); - platform.minaddr = (void *)KSEG0_BASE; - platform.clkfreq = CLKFREQ_WRT54GL; - platform.uart_dll = UART_DLL_WRT54GL; - break; - case PRID_REV_WRT350N: - strlcpy(platform.name, "Linksys WRT350N", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_WRT350N); - platform.minaddr = (void *)KSEG0_BASE; - platform.clkfreq = CLKFREQ_WRT350N; - platform.uart_dll = UART_DLL_WRT350N; - break; - default: - strlcpy(platform.name, "Unknown Platform", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_DEFAULT); - platform.minaddr = (void *)KSEG0_BASE; - platform.clkfreq = CLKFREQ_DEFAULT; - platform.uart_dll = UART_DLL_DEFAULT; - return SYSERR; - } - break; - case PRID_CPU_24K: - strlcpy(platform.family, "MIPS 24K", PLT_STRMAX); - switch (cpuid & PRID_REV) - { - case PRID_REV_WRT160NL: - strlcpy(platform.name, "Linksys WRT160NL", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_WRT160NL); - platform.minaddr = (void *)KSEG0_BASE; - platform.clkfreq = CLKFREQ_WRT160NL; - platform.uart_dll = (CLKFREQ_WRT160NL / 16) / UART_BAUD; - break; - default: - strlcpy(platform.name, "Unknown Platform", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_DEFAULT); - platform.minaddr = (void *)KSEG0_BASE; - platform.clkfreq = CLKFREQ_DEFAULT; - platform.uart_dll = UART_DLL_DEFAULT; - return SYSERR; - } - break; - } - return OK; -} diff --git a/system/platforms/wl330ge/setupStack.c b/system/platforms/wl330ge/setupStack.c deleted file mode 100644 index bda20ecf..00000000 --- a/system/platforms/wl330ge/setupStack.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wl330ge/syscall_dispatch.c b/system/platforms/wl330ge/syscall_dispatch.c deleted file mode 100644 index c898bf32..00000000 --- a/system/platforms/wl330ge/syscall_dispatch.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wl330ge/syscall_entry.S b/system/platforms/wl330ge/syscall_entry.S deleted file mode 100644 index 34ac9af7..00000000 --- a/system/platforms/wl330ge/syscall_entry.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt160nl/Makerules b/system/platforms/wrt160nl/Makerules deleted file mode 100644 index 36e3b423..00000000 --- a/system/platforms/wrt160nl/Makerules +++ /dev/null @@ -1,22 +0,0 @@ -# This Makefile contains rules to build files in this directory. - -# Name of this component (the directory this file is stored in) -COMP = system/platforms/wrt160nl - -# Source files for this component - -# Important system components -S_FILES = pause.S -C_FILES = platforminit.c - -# Files for process control -S_FILES += ctxsw.S -C_FILES += setupStack.c - -# Files for preemption and interrupts -S_FILES += clkupdate.S intutils.S intdispatch.S halt.S -C_FILES += dispatch.c exception.c - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/system/platforms/wrt160nl/ar9130.h b/system/platforms/wrt160nl/ar9130.h deleted file mode 100644 index 7a46ac9f..00000000 --- a/system/platforms/wrt160nl/ar9130.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @file ar9130.h - * - * Constants and declarations associated with the Atheros 9130 - * wireless System On A Chip. - * - */ - -#define RST_MISC_INTERRUPT_MASK 0xB8060014 -#define RST_MISC_INTERRUPT_STATUS 0xB8060010 - -#define RST_MISC_IRQ_TIMER (1 << 0) -#define RST_MISC_IRQ_ERROR (1 << 1) -#define RST_MISC_IRQ_GPIO (1 << 2) -#define RST_MISC_IRQ_UART (1 << 3) -#define RST_MISC_IRQ_WATCHDOG (1 << 4) -#define RST_MISC_IRQ_PERF (1 << 5) -#define RST_MISC_IRQ_MBOX (1 << 7) -#define RST_MISC_IRQ_MASK 0x00FF diff --git a/system/platforms/wrt160nl/clkupdate.S b/system/platforms/wrt160nl/clkupdate.S deleted file mode 100644 index 81ed69d7..00000000 --- a/system/platforms/wrt160nl/clkupdate.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt160nl/ctxsw.S b/system/platforms/wrt160nl/ctxsw.S deleted file mode 100644 index 4048a664..00000000 --- a/system/platforms/wrt160nl/ctxsw.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt160nl/dispatch.c b/system/platforms/wrt160nl/dispatch.c deleted file mode 100644 index 91a4ad40..00000000 --- a/system/platforms/wrt160nl/dispatch.c +++ /dev/null @@ -1,137 +0,0 @@ -/** - * @file dispatch.c - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#include -#include -#include -#include -#include "ar9130.h" -#include - -char *interrupts[] = { - "Software interrupt request 0", - "Software interrupt request 1", - "Hardware interrupt request 0, wmac", - "Hardware interrupt request 1, usb", - "Hardware interrupt request 2, eth0", - "Hardware interrupt request 3, eth1", - "Hardware interrupt request 4, misc", - "Hardware interrupt request 5, timer", - "Miscellaneous interrupt request 0, timer", - "Miscellaneous interrupt request 1, error", - "Miscellaneous interrupt request 2, gpio", - "Miscellaneous interrupt request 3, uart", - "Miscellaneous interrupt request 4, watchdog", - "Miscellaneous interrupt request 5, perf", - "Miscellaneous interrupt request 6, reserved", - "Miscellaneous interrupt request 7, mbox", -}; - -/** - * Dispatcher for interrupt requests. - * - * @param cause contents of cause register identifies interrupt - * @param frame pointer to interrupt frame with saved status - * - */ -void dispatch(long cause, long *frame) -{ - long irqcode = 0, irqnum = -1; - irqmask im; - void (*handler) (void); - - irqcode = (cause & CAUSE_IRQ) >> CAUSE_IRQ_SHIFT; - - /* Calculate which interrupt number this is. */ - while (irqcode) - { - irqnum++; - irqcode = irqcode >> 1; - } - -#ifdef IRQ_ATH_MISC - if (IRQ_ATH_MISC == irqnum) - { - ulong *miscStat = (ulong *)RST_MISC_INTERRUPT_STATUS; - irqcode = *miscStat & RST_MISC_IRQ_MASK; - irqnum = 7; - while (irqcode) - { - irqnum++; - irqcode = irqcode >> 1; - } - } -#endif - - /* Check for registered interrupt handler. */ - if (NULL == (handler = interruptVector[irqnum])) - { - kprintf - ("Xinu Interrupt %d uncaught, %s\r\n", - irqnum, interrupts[irqnum]); - while (1) - ; /* forever */ - } - - im = disable(); /* Disable interrupts for duration of handler */ - exlreset(); /* Reset system-wide exception bit */ - - (*handler) (); /* Call device-specific handler */ - - exlset(); /* Set system-wide exception bit */ - restore(im); -} - -/** - * Enable IRQ number. - * - * @param irqnumber Request number to enable. - * - */ -void enable_irq(irqmask irqnumber) -{ -#ifdef IRQ_ATH_MISC - int irqmisc; - ulong *miscMask = (ulong *)RST_MISC_INTERRUPT_MASK; - if (irqnumber >= 8) - { - irqmisc = irqnumber - 8; - enable_cpuirq(IRQ_ATH_MISC); - *miscMask |= (1 << irqmisc); - } - else - { - enable_cpuirq(irqnumber); - } -#else - enable_cpuirq(irqnumber); -#endif -} - -/** - * Disable IRQ number. - * - * @param irqnumber Request number to enable. - * - */ -void disable_irq(irqmask irqnumber) -{ -#ifdef IRQ_ATH_MISC - int irqmisc; - ulong *miscMask = (ulong *)RST_MISC_INTERRUPT_MASK; - if (irqnumber >= 8) - { - irqmisc = irqnumber - 8; - *miscMask &= ~(1UL << irqmisc); - } - else - { - disable_cpuirq(irqnumber); - } -#else - disable_cpuirq(irqnumber); -#endif -} diff --git a/system/platforms/wrt160nl/exception.c b/system/platforms/wrt160nl/exception.c deleted file mode 100644 index 9174fa36..00000000 --- a/system/platforms/wrt160nl/exception.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt160nl/halt.S b/system/platforms/wrt160nl/halt.S deleted file mode 100644 index 46d89066..00000000 --- a/system/platforms/wrt160nl/halt.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt160nl/intdispatch.S b/system/platforms/wrt160nl/intdispatch.S deleted file mode 100644 index fad47b80..00000000 --- a/system/platforms/wrt160nl/intdispatch.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt160nl/interrupt.h b/system/platforms/wrt160nl/interrupt.h deleted file mode 100644 index 8e584b39..00000000 --- a/system/platforms/wrt160nl/interrupt.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @file interrupt.h - * - * Constants and declarations associated with interrupt and exception - * processing. - * - */ -/* Embedded Xinu, Copyright (C) 2008. All rights reserved. */ - -#ifndef _INTERRUPT_H_ -#define _INTERRUPT_H_ - -#include - -/** Address of interrupt request handler. */ -#define IRQ_ADDR 0x80000180 -/** Address of Xinu-defined trap (exception) vector. */ -#define TRAPVEC_ADDR 0x80001000 -/** Address of Xinu-defined interrupt request vector. */ -#define IRQVEC_ADDR 0x80001080 -/** Address of end of Xinu-defined interrupt tables. */ -#define IRQVEC_END 0x800010C0 - -#ifndef __ASSEMBLER__ -void enable_irq(irqmask); -void disable_irq(irqmask); -#endif - -#endif /* _INTERRUPT_H_ */ diff --git a/system/platforms/wrt160nl/intutils.S b/system/platforms/wrt160nl/intutils.S deleted file mode 100644 index 728cec2f..00000000 --- a/system/platforms/wrt160nl/intutils.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt160nl/pause.S b/system/platforms/wrt160nl/pause.S deleted file mode 100644 index 6124b2b2..00000000 --- a/system/platforms/wrt160nl/pause.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt160nl/platforminit.c b/system/platforms/wrt160nl/platforminit.c deleted file mode 100644 index b55d9282..00000000 --- a/system/platforms/wrt160nl/platforminit.c +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @file platforminit.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include -#include - -extern ulong cpuid; /* Processor id */ - -extern struct platform platform; /* Platform specific configuration */ - -/** - * Determines and stores all platform specific information. - * @return OK if everything is determined successfully - */ -int platforminit(void) -{ - strncpy(platform.family, "MIPS 24K", PLT_STRMAX); - strncpy(platform.name, "Linksys WRT160NL", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_WRT160NL); - platform.clkfreq = CLKFREQ_WRT160NL; - platform.uart_dll = (CLKFREQ_WRT160NL / 16) / UART_BAUD; - return OK; -} diff --git a/system/platforms/wrt160nl/setupStack.c b/system/platforms/wrt160nl/setupStack.c deleted file mode 100644 index bda20ecf..00000000 --- a/system/platforms/wrt160nl/setupStack.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt54gl/Makerules b/system/platforms/wrt54gl/Makerules deleted file mode 100644 index dbbed03c..00000000 --- a/system/platforms/wrt54gl/Makerules +++ /dev/null @@ -1,29 +0,0 @@ -# This Makefile contains rules to build files in this directory. - -# Name of this component (the directory this file is stored in) -COMP = system/platforms/wrt54gl - -# Source files for this component - -# Important system components -S_FILES = pause.S -C_FILES = platforminit.c - -# Files for process control -S_FILES += ctxsw.S -C_FILES += setupStack.c - -# Files for preemption and interrupts -S_FILES += clkupdate.S intutils.S intdispatch.S halt.S -C_FILES += dispatch.c exception.c - -# Files for JTAG debugging -S_FILES += debugbreak.S debugret.S - -# Files for system calls -S_FILES += syscall_entry.S -C_FILES += syscall_dispatch.c - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/system/platforms/wrt54gl/clkupdate.S b/system/platforms/wrt54gl/clkupdate.S deleted file mode 100644 index 81ed69d7..00000000 --- a/system/platforms/wrt54gl/clkupdate.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt54gl/ctxsw.S b/system/platforms/wrt54gl/ctxsw.S deleted file mode 100644 index 4048a664..00000000 --- a/system/platforms/wrt54gl/ctxsw.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt54gl/debugbreak.S b/system/platforms/wrt54gl/debugbreak.S deleted file mode 100644 index 5b354c06..00000000 --- a/system/platforms/wrt54gl/debugbreak.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt54gl/debugret.S b/system/platforms/wrt54gl/debugret.S deleted file mode 100644 index 569496ff..00000000 --- a/system/platforms/wrt54gl/debugret.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt54gl/dispatch.c b/system/platforms/wrt54gl/dispatch.c deleted file mode 100644 index d1949e17..00000000 --- a/system/platforms/wrt54gl/dispatch.c +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @file dispatch.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include - -const char *interrupts[] = { - "Software interrupt request 0", - "Software interrupt request 1", - "Hardware interrupt request 0, eth1", - "Hardware interrupt request 1, serial", - "Hardware interrupt request 2, eth0", - "Hardware interrupt request 3", - "Hardware interrupt request 4", - "Hardware interrupt request 5, timer" -}; - -/** - * Dispatcher for interrupt requests. - * - * @param cause contents of cause register identifies interrupt - * @param frame pointer to interrupt frame with saved status - * - */ -void dispatch(long cause, long *frame) -{ - long irqcode = 0, irqnum = -1; - irqmask im; - void (*handler) (void); - - irqcode = (cause & CAUSE_IRQ) >> CAUSE_IRQ_SHIFT; - - /* Calculate which interrupt number this is. */ - while (irqcode) - { - irqnum++; - irqcode = irqcode >> 1; - } - - /* Check for registered interrupt handler. */ - if (NULL == (handler = interruptVector[irqnum])) - { - kprintf - ("Xinu Interrupt %d uncaught, %s\r\n", - irqnum, interrupts[irqnum]); - while (1) - ; /* forever */ - } - - im = disable(); /* Disable interrupts for duration of handler */ - exlreset(); /* Reset system-wide exception bit */ - - (*handler) (); /* Call device-specific handler */ - - exlset(); /* Set system-wide exception bit */ - restore(im); -} diff --git a/system/platforms/wrt54gl/exception.c b/system/platforms/wrt54gl/exception.c deleted file mode 100644 index 9174fa36..00000000 --- a/system/platforms/wrt54gl/exception.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt54gl/halt.S b/system/platforms/wrt54gl/halt.S deleted file mode 100644 index 46d89066..00000000 --- a/system/platforms/wrt54gl/halt.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt54gl/intdispatch.S b/system/platforms/wrt54gl/intdispatch.S deleted file mode 100644 index fad47b80..00000000 --- a/system/platforms/wrt54gl/intdispatch.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt54gl/interrupt.h b/system/platforms/wrt54gl/interrupt.h deleted file mode 100644 index f204de69..00000000 --- a/system/platforms/wrt54gl/interrupt.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @file interrupt.h - * - * Constants and declarations associated with interrupt and exception - * processing. - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#ifndef _INTERRUPT_H_ -#define _INTERRUPT_H_ - -#include - -/** Address of interrupt request handler. */ -#define IRQ_ADDR 0x80000180 -/** Address of Xinu-defined trap (exception) vector. */ -#define TRAPVEC_ADDR 0x80000200 -/** Address of Xinu-defined interrupt request vector. */ -#define IRQVEC_ADDR 0x80000280 -/** Address of end of Xinu-defined interrupt tables. */ -#define IRQVEC_END 0x800002A0 - -#ifndef __ASSEMBLER__ -#define enable_irq enable_cpuirq -#define disable_irq disable_cpuirq -#endif - -#endif /* _INTERRUPT_H_ */ diff --git a/system/platforms/wrt54gl/intutils.S b/system/platforms/wrt54gl/intutils.S deleted file mode 100644 index 728cec2f..00000000 --- a/system/platforms/wrt54gl/intutils.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt54gl/pause.S b/system/platforms/wrt54gl/pause.S deleted file mode 100644 index 6124b2b2..00000000 --- a/system/platforms/wrt54gl/pause.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt54gl/platforminit.c b/system/platforms/wrt54gl/platforminit.c deleted file mode 100644 index 4d757a43..00000000 --- a/system/platforms/wrt54gl/platforminit.c +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @file platforminit.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include -#include - -extern ulong cpuid; /* Processor id */ - -extern struct platform platform; /* Platform specific configuration */ - -/** - * Determines and stores all platform specific information. - * @return OK if everything is determined successfully - */ -int platforminit(void) -{ - strlcpy(platform.family, "Broadcom 3302", PLT_STRMAX); - strlcpy(platform.name, "Linksys WRT54GL", PLT_STRMAX); - platform.maxaddr = (void *)(KSEG0_BASE | MAXADDR_WRT54GL); - platform.minaddr = (void *)KSEG0_BASE; - platform.clkfreq = CLKFREQ_WRT54GL; - platform.uart_dll = UART_DLL_WRT54GL; - return OK; -} diff --git a/system/platforms/wrt54gl/setupStack.c b/system/platforms/wrt54gl/setupStack.c deleted file mode 100644 index bda20ecf..00000000 --- a/system/platforms/wrt54gl/setupStack.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt54gl/syscall_dispatch.c b/system/platforms/wrt54gl/syscall_dispatch.c deleted file mode 100644 index c898bf32..00000000 --- a/system/platforms/wrt54gl/syscall_dispatch.c +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/wrt54gl/syscall_entry.S b/system/platforms/wrt54gl/syscall_entry.S deleted file mode 100644 index 34ac9af7..00000000 --- a/system/platforms/wrt54gl/syscall_entry.S +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/system/platforms/x86/Makerules b/system/platforms/x86/Makerules deleted file mode 100644 index 4b1d2720..00000000 --- a/system/platforms/x86/Makerules +++ /dev/null @@ -1,26 +0,0 @@ -# This Makefile contains rules to build files in the system/platforms/x86 directory. - -# Name of this component (the directory this file is stored in) -COMP = system/platforms/x86 - -# Source files for this component - -# Important system components -S_FILES = startup.S pause.S -C_FILES = platforminit.c - -# Files for process control -S_FILES += ctxsw.S -C_FILES += setupStack.c - -# Files for preemption and interrupts -S_FILES += clkupdate.S intr.S halt.S -C_FILES += xtrap.c - -# Files specific to Intel x86 -S_FILES += parport.S -C_FILES += segment.c evec.c dispatch.c - -# Add the files to the compile source path -DIR = ${TOPDIR}/${COMP} -COMP_SRC += ${S_FILES:%=${DIR}/%} ${C_FILES:%=${DIR}/%} diff --git a/system/platforms/x86/asm-i386/asm.h b/system/platforms/x86/asm-i386/asm.h deleted file mode 100644 index e645c3ea..00000000 --- a/system/platforms/x86/asm-i386/asm.h +++ /dev/null @@ -1,71 +0,0 @@ -/* asm.h - DELAY */ - -#define NBPG 4096 - -#define NID 48 -#define NGD 8 - -#define IRQBASE 32 /* base ivec for IRQ0 */ - -struct idt { - ushort igd_loffset; - ushort igd_segsel; - ulong igd_rsvd : 5; - ulong igd_mbz : 3; - ulong igd_type : 5; - ulong igd_dpl : 2; - ulong igd_present : 1; - ushort 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 { - ushort sd_lolimit; - ushort sd_lobase; - uchar sd_midbase; - ulong sd_perm : 3; - ulong sd_iscode : 1; - ulong sd_isapp : 1; - ulong sd_dpl : 2; - ulong sd_present : 1; - ulong sd_hilimit : 4; - ulong sd_avl : 1; - ulong sd_mbz : 1; /* must be '0' */ - ulong sd_32b : 1; - ulong sd_gran : 1; - uchar sd_hibase; -}; - -#define sd_type sd_perm - -/* System Descriptor Types */ - -#define SDT_INTG 14 /* Interrupt Gate */ - -/* Segment Table Register */ -struct segtr { - ulong len : 16; - ulong addr : 32; -}; - -/* - * Delay units are in microseconds. - */ -#define DELAY(n) \ -{ \ - extern long cpudelay; \ - register char i; \ - register long N = (((n)<<4) >> cpudelay); \ - \ - for ( i = 0; i <= 4; i++ ) \ - { \ - N = (((n) << 4) >> cpudelay); \ - while (--N > 0) ; \ - } \ -} diff --git a/system/platforms/x86/asm-i386/icu.h b/system/platforms/x86/asm-i386/icu.h deleted file mode 100644 index c321c78b..00000000 --- a/system/platforms/x86/asm-i386/icu.h +++ /dev/null @@ -1,11 +0,0 @@ -/* icu.h */ - -#define ICU1 0x20 /* address of primary interrupt control unit */ -#define ICU2 0xA0 /* address of slave interrupt control unit */ - -#define OCR1 ICU1 /* Operation Command Register for ICU1 */ -#define OCR2 ICU2 /* Operation Command Register for ICU2 */ -#define IMR1 (ICU1+1) /* Interrupt Mask Register for ICU1 */ -#define IMR2 (ICU2+1) /* Interrupt Mask Register for ICU2 */ - -#define EOI 0x20 /* end-of-interrupt signal */ diff --git a/system/platforms/x86/asm-i386/xint.S b/system/platforms/x86/asm-i386/xint.S deleted file mode 100644 index 140b46bc..00000000 --- a/system/platforms/x86/asm-i386/xint.S +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Generic exception handler(s) for x86-xinu. Adapted from D.W.Brylow's - * version for the PPC port of XINU - * - */ -#include - -#define EXCEPTION(num) \ - .globl _Xint##num; \ -_Xint##num: \ - cli; \ - pushal; \ - pushl %esp; \ - pushl $num; \ - call dispatch; \ - addl $2*4, %esp; \ - movb $EOI, %al; \ - outb %al, $OCR1; \ - popal; \ - sti; \ - iret; - -/* Create the individual exception handlers */ -EXCEPTION(0x00) -EXCEPTION(0x01) -EXCEPTION(0x02) -EXCEPTION(0x03) -EXCEPTION(0x04) -EXCEPTION(0x05) -EXCEPTION(0x06) -EXCEPTION(0x07) -EXCEPTION(0x08) -EXCEPTION(0x09) -EXCEPTION(0x0A) -EXCEPTION(0x0B) -EXCEPTION(0x0C) -EXCEPTION(0x0D) -EXCEPTION(0x0E) -EXCEPTION(0x0F) -EXCEPTION(0x10) -EXCEPTION(0x11) -EXCEPTION(0x12) -EXCEPTION(0x13) -EXCEPTION(0x14) -EXCEPTION(0x15) -EXCEPTION(0x16) -EXCEPTION(0x17) -EXCEPTION(0x18) -EXCEPTION(0x19) -EXCEPTION(0x1A) -EXCEPTION(0x1B) -EXCEPTION(0x1C) -EXCEPTION(0x1D) -EXCEPTION(0x1E) -EXCEPTION(0x1F) -EXCEPTION(0x20) -EXCEPTION(0x21) -EXCEPTION(0x22) -EXCEPTION(0x23) -EXCEPTION(0x24) -EXCEPTION(0x25) -EXCEPTION(0x26) -EXCEPTION(0x27) -EXCEPTION(0x28) -EXCEPTION(0x29) -EXCEPTION(0x2A) -EXCEPTION(0x2B) -EXCEPTION(0x2C) -EXCEPTION(0x2D) -EXCEPTION(0x2E) -EXCEPTION(0x2F) - diff --git a/system/platforms/x86/clkupdate.S b/system/platforms/x86/clkupdate.S deleted file mode 100644 index e2c62896..00000000 --- a/system/platforms/x86/clkupdate.S +++ /dev/null @@ -1,20 +0,0 @@ -/* clockupdate.s - clock_update */ - -#include - -.text - .globl clkupdate -clkupdate: - movb $EOI, %al /* write end-of-interrupt signal */ - outb %al, $OCR1 /* to interrupt control unit */ - ret - - - .globl clockIRQ -clockIRQ: - cli - pushal - call clkhandler - popal - sti - iret diff --git a/system/platforms/x86/ctxsw.S b/system/platforms/x86/ctxsw.S deleted file mode 100644 index 08e528b0..00000000 --- a/system/platforms/x86/ctxsw.S +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @file ctxsw.s - * - */ -/* Embedded XINU, Copyright (C) 2007. All rights reserved. */ - - .text - .globl ctxsw -newmask: .word 0 - -/*------------------------------------------------------------------------ - * ctxsw - call is ctxsw(&oldsp, &newsp, asid) - *------------------------------------------------------------------------ - */ -ctxsw: - pushl %ebp - movl %esp,%ebp - - pushfl /* save flags */ - pushal /* save general regs */ - - /* save segment registers here, if multiple allowed */ - - movl 8(%ebp),%eax /* &oldsp */ - movl %esp,(%eax) /* save old SP */ - - movl 12(%ebp),%eax /* &newsp */ - movl (%eax),%esp /* restore new SP */ - - /* restore new segment registers here, if multiple allowed */ - - popal /* restore general registers */ - popfl /* restore flags */ - - movl %ebp, %esp - popl %ebp - - ret diff --git a/system/platforms/x86/dispatch.c b/system/platforms/x86/dispatch.c deleted file mode 100644 index def11403..00000000 --- a/system/platforms/x86/dispatch.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include - -extern void clockintr(void); -extern void xtrap(int, int *); - -interrupt (*exctab[NID])(void); - -void dispatch(int exc_num, int *stack_ptr) -{ - if ( exctab[exc_num] != NULL ) - { - /* execute handler */ - (*exctab[exc_num])(); - } - else - { - xtrap(exc_num, stack_ptr); - } -} diff --git a/system/platforms/x86/evec.c b/system/platforms/x86/evec.c deleted file mode 100644 index 1aa1b052..00000000 --- a/system/platforms/x86/evec.c +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -/*#define STKTRACE*/ -/*#define REGDUMP*/ - -/* - * 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. - */ -short girmask; - -extern struct idt idt[NID]; -extern long defevec[]; - -/** - * Set exception vector to point to an exception handler - * @param xnum - * @param handler pointer to handling function - * - */ -void init_evec(void) -{ - int i; - struct idt *pidt; - - for (i = 0; i < NID; i++) - { - /* No handler defined yet */ - exctab[i] = NULL; - - pidt = &idt[i]; - pidt->igd_loffset = (ushort)(defevec[i] & 0x0ffff); - pidt->igd_hoffset = (ushort)(defevec[i] >> 16); - pidt->igd_segsel = 0x8; /* kernel code segment */ - pidt->igd_mbz = 0; - pidt->igd_type = IGDT_TRAPG; - pidt->igd_dpl = 0; - pidt->igd_present = 1; - } -} - -void set_evec(int exc_num, int handler) -{ - struct idt *pidt; - - pidt = &idt[exc_num]; - pidt->igd_loffset = (ushort)(handler & 0x0ffff); - pidt->igd_hoffset = (ushort)(handler >> 16); - pidt->igd_segsel = 0x8; /* kernel code segment */ - pidt->igd_mbz = 0; - pidt->igd_type = IGDT_TRAPG; - pidt->igd_dpl = 0; - pidt->igd_present = 1; - - if ( 32 <= exc_num && exc_num < 48 ) { - /* enable the interrupt in the global IR mask */ - exc_num -= 32; - girmask = (short)(girmask & ~(1 << exc_num)); - } -} - -void set_handler(int exc_num, interrupt (*handler)(void)) -{ - exctab[exc_num] = handler; - - if ( 32 <= exc_num && exc_num < 48 ) { - /* enable the interrupt in the global IR mask */ - exc_num -= 32; - girmask = (short)(girmask & ~(1 << exc_num)); - } -} diff --git a/system/platforms/x86/halt.S b/system/platforms/x86/halt.S deleted file mode 100644 index 15df9373..00000000 --- a/system/platforms/x86/halt.S +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @file halt.s - * - */ -/* Embedded XINU, Copyright (C) 2007. All rights reserved. */ - -.text - .align 4 - .globl halt - -/** - * @fn void halt(void) - * - * Essentially this is a busy wait, however the opcode 'hlt' puts the - * processor in a powersave state (which can be awoken for arbitrary - * reasons) - */ -halt: - hlt - jmp halt diff --git a/system/platforms/x86/interrupt.h b/system/platforms/x86/interrupt.h deleted file mode 100644 index 5c24e303..00000000 --- a/system/platforms/x86/interrupt.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @file interrupt.h - * - * Constants and declarations associated with interrupt and exception - * processing. - * - */ -/* Embedded XINU, Copyright (C) 2007. All rights reserved. */ - -#ifndef _INTERRUPT_H_ -#define _INTERRUPT_H_ - -#include - -#define IRQBASE 32 /* base ivec for IRQ0 */ -#define IRQ0 0 /* programmable interval timer */ -#define IRQ1 1 /* keyboard controller */ -#define IRQ2 2 /* unknown */ -#define IRQ3 3 /* serial port 2 */ -#define IRQ4 4 /* serial port 1 */ -#define IRQ5 5 /* hard disk controller */ -#define IRQ6 6 /* floppy disk controller */ -#define IRQ7 7 /* parallel port / spurious interrupts */ - -#define IGDT_TASK 5 /* task gate IDT descriptor */ -#define IGDT_INTR 14 /* interrupt gate IDT descriptor */ -#define IGDT_TRAPG 15 /* Trap Gate */ - -#define NID 48 - -#ifndef __ASSEMBLER__ - -typedef unsigned long irqmask; /**< machine status for disable/restore */ - -/** Tables of exception/interrupt vectors */ -extern interrupt (*exctab[NID])(void); - -/* Interrrupt enabling function prototypes */ -irqmask disable(void); -irqmask restore(irqmask); -irqmask enable(void); -irqmask enable_irq(irqmask); -irqmask disable_irq(irqmask); - -/* Interrupt configuration function prototypes */ -void init_evec(void); -void set_evec(int, int); -void set_handler(int, interrupt (*)(void)); -void dispatch(int, int *); - -#endif /* __ASSEMBLER__ */ - -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; -}; - -#endif /* _INTERRUPT_H_ */ diff --git a/system/platforms/x86/intr.S b/system/platforms/x86/intr.S deleted file mode 100644 index 00e780b4..00000000 --- a/system/platforms/x86/intr.S +++ /dev/null @@ -1,142 +0,0 @@ -/* intr.s - disable(), restore(), enable(), pause(), halt() */ - - -#include - - .globl enable - .globl disable - .globl restore - .globl restore_intr - .globl pause - .globl getirmask - -/*------------------------------------------------------------------------ - * _Xint? - default exception and interrupt entry points - * NB: These must be contiguous - *------------------------------------------------------------------------ - */ -#include - - .globl defevec -defevec: - .long _Xint0x00 - .long _Xint0x01 - .long _Xint0x02 - .long _Xint0x03 - .long _Xint0x04 - .long _Xint0x05 - .long _Xint0x06 - .long _Xint0x07 - .long _Xint0x08 - .long _Xint0x09 - .long _Xint0x0A - .long _Xint0x0B - .long _Xint0x0C - .long _Xint0x0D - .long _Xint0x0E - .long _Xint0x0F - .long _Xint0x10 - .long _Xint0x11 - .long _Xint0x12 - .long _Xint0x13 - .long _Xint0x14 - .long _Xint0x15 - .long _Xint0x16 - .long _Xint0x17 - .long _Xint0x18 - .long _Xint0x19 - .long _Xint0x1A - .long _Xint0x1B - .long _Xint0x1C - .long _Xint0x1D - .long _Xint0x1E - .long _Xint0x1F - .long _Xint0x20 - .long _Xint0x21 - .long _Xint0x22 - .long _Xint0x23 - .long _Xint0x24 - .long _Xint0x25 - .long _Xint0x26 - .long _Xint0x27 - .long _Xint0x28 - .long _Xint0x29 - .long _Xint0x2A - .long _Xint0x2B - .long _Xint0x2C - .long _Xint0x2D - .long _Xint0x2E - .long _Xint0x2F - - .text - -/*--------------------------------------------------------- - * enable all interrupts - *--------------------------------------------------------- - */ -enable: - cli - movw girmask, %ax - outb %al, $IMR1 - shrw $8, %ax - outb %al, $IMR2 - sti - ret - - -/*--------------------------------------------------------- - * disable() - disable interrupts, save old state in ps - *--------------------------------------------------------- - */ -disable: - cli - pushfl - inb $IMR2, %al - shlw $8, %ax - inb $IMR1, %al /* XINU stores in logical form */ - notw %ax /* but APIC wants negated form */ - movw %ax, %dx - movb $0xff, %al - outb %al, $IMR2 - movb $0xff, %al - outb %al, $IMR1 - popfl - movw %dx, %ax - ret - - -/*--------------------------------------------------------- - * restore(ps) - restore interrupts to value in ps - * STATWORD ps (ulong ps) - *--------------------------------------------------------- - */ -restore: - cli - pushfl - movl 8(%esp), %eax - notw %ax - andw girmask, %ax - outb %al, $IMR1 - shrw $8, %ax - outb %al, $IMR2 - popfl - sti - ret - -restore_intr: - sti - movl 4(%esp), %eax - call *%eax - ret - -/*------------------------------------------------------------------------ - * getirmask(ps) - return current interrupt mask in ps - *------------------------------------------------------------------------ - */ -getirmask: - inb $IMR2, %al - shlw $8, %ax - inb $IMR1, %al - movl 4(%esp), %edx - movw %ax, (%edx) - ret diff --git a/system/platforms/x86/parport.S b/system/platforms/x86/parport.S deleted file mode 100644 index f9a92909..00000000 --- a/system/platforms/x86/parport.S +++ /dev/null @@ -1,18 +0,0 @@ -#include - -.data -PARPORT: .string "Parallel Port: 0x%08x\r\n" - -.text - .globl parport -parport: - cli - pushal - - /* send end-of-interrupt signal */ - movb $EOI, %al - outb %al, $OCR1 - - popal - sti - iret diff --git a/system/platforms/x86/pause.S b/system/platforms/x86/pause.S deleted file mode 100644 index 63e4cf07..00000000 --- a/system/platforms/x86/pause.S +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @file pause.S - * Platform-dependent code for idling the processor - * - */ -/* Embedded XINU, Copyright (C) 2007. All rights reserved. */ - -.text - .align 4 - .globl pause - -/** - * @fn void pause(void) - * - * Enter some kind of powerdown state (if it exists) that suspends - * execution until an interrupt is detected. - */ -pause: - call enable - hlt - ret - diff --git a/system/platforms/x86/platforminit.c b/system/platforms/x86/platforminit.c deleted file mode 100644 index 7bd2ffa8..00000000 --- a/system/platforms/x86/platforminit.c +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @file platforminit.c - * - */ -/* Embedded Xinu, Copyright (C) 2009. All rights reserved. */ - -#include -#include -#include -#include -#include -#include -#include -#include - -extern ulong cpuid; /* Processor id */ - -extern struct platform platform; /* Platform specific configuration */ - -/* prototypes */ -void lidt(void); - -/* interrupt variables */ -extern short girmask; -extern long defevec[]; -extern struct segtr idtr; -extern struct idt idt[NID]; - -/** - * Determines and stores all platform specific information. - * @return OK if everything is determined successfully - */ -int platforminit(void) -{ - int i; - - /* Setup platform data */ - strlcpy(platform.name, "Intel x86", PLT_STRMAX); - platform.maxaddr = (void *)0x1000000; - platform.clkfreq = 1190000; - platform.uart_dll = 1; - - /* Setup Intel 8259a programmable interrupt controller */ - /* 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 */ - - disable(); - - /* Set initial interrupt entry vectors */ - /* Initialize interrupts variables */ - for (i = 0; i < NID; i++) - { - set_evec(i, (long)defevec[i]); - } - - /* girmask masks bus interrupts with default handler */ - girmask = 0xfffb; - lidt(); - - return OK; -} diff --git a/system/platforms/x86/segment.c b/system/platforms/x86/segment.c deleted file mode 100644 index df3edd3b..00000000 --- a/system/platforms/x86/segment.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -extern struct segdesc gdt[NSEGS]; -extern struct segdescreg gdtr; - -/** - * This will insert a segment with the passed values into the descriptor - * table entry. - * @param index index of descriptor to write to - * @param base base address of segment - * @param length length of segment - * @param properties other properties segment has - */ -void insertseg(int index, int base, int limit, int properties) -{ - struct segdesc *seg; - - if (!(0 <= index && index < NSEGS)) - { - return; - } - - seg = &gdt[index]; - - // base split hi/mid/lo; - seg->lobase = base & 0xffff; - seg->midbase = (base >> 16) & 0xff; - seg->hibase = (base >> 24) & 0xff; - - // limit split hi/lo; - /* round up to nearest 4k */ - if (limit != 0xffffffff) - { - limit = (limit + 4095) & ~4095; - } - seg->lolimit = (limit >> 12) & 0xffff; - seg->hilimit = (limit >> 28) & 0xf; - - seg->type = properties & 0xf; - seg->dataseg = (properties >> SEG_DSEG_SHIFT) & 0x1; - seg->dpl = (properties >> SEG_DPL_SHIFT) & 0x3; - seg->present = (properties >> SEG_P_SHIFT) & 0x1; - - seg->avl = (properties >> SEG_AVL_SHIFT) & 0x1; - seg->mbz = 0; - seg->db = (properties >> SEG_DB_SHIFT) & 0x1; - seg->gran = (properties >> SEG_GRAN_SHIFT) & 0x1; -} - -void initialsegs(void) -{ - /* some segment setup */ - insertseg(0, 0x00000000, 0x00000000, 0x00000000); - insertseg(1, 0x00000000, 0xffffffff, SEG_CODE_KERNEL); - insertseg(2, 0x00000000, 0xffffffff, SEG_DATA_KERNEL); - insertseg(3, 0x00000000, 0xffffffff, SEG_DATA_KERNEL); -} - diff --git a/system/platforms/x86/segment.h b/system/platforms/x86/segment.h deleted file mode 100644 index 12b0923b..00000000 --- a/system/platforms/x86/segment.h +++ /dev/null @@ -1,69 +0,0 @@ -/* segment.h - DELAY */ - -#include - -#define NBPG 4096 - -/* segment descriptor data */ -#define NSEGS 8 - -#define SEG_DSEG_SHIFT 4 -#define SEG_DPL_SHIFT 5 -#define SEG_P_SHIFT 7 -#define SEG_AVL_SHIFT 8 -#define SEG_DB_SHIFT 9 -#define SEG_GRAN_SHIFT 10 - -#define SEG_TYPE_DATA_RO 0x0000 -#define SEG_TYPE_DATA_RW 0x0002 -#define SEG_TYPE_CODE_EO 0x0008 -#define SEG_TYPE_CODE_ER 0x000a -#define SEG_DSEG_ON 0x0010 -#define SEG_DPL_KERN 0x0000 -#define SEG_DPL_USER 0x0020 -#define SEG_P_ON 0x0080 -#define SEG_AVL_ON 0x0100 -#define SEG_DB_ON 0x0200 -#define SEG_GRAN_ON 0x0400 - -#define SEG_CODE_KERNEL ( SEG_GRAN_ON | SEG_DB_ON | SEG_P_ON \ - | SEG_DPL_KERN | SEG_DSEG_ON | SEG_TYPE_CODE_ER ) -#define SEG_DATA_KERNEL ( SEG_GRAN_ON | SEG_DB_ON | SEG_P_ON \ - | SEG_DPL_KERN | SEG_DSEG_ON | SEG_TYPE_DATA_RW ) - -struct segdesc -{ - ushort lolimit; - ushort lobase; - uchar midbase; - uchar type : 4, dataseg : 1, dpl : 2, present : 1; - uchar hilimit : 4, avl : 1, mbz : 1, db : 1, gran : 1; - uchar hibase; -}; - -/* Segment Table Register */ -struct segdescreg -{ - ushort limit; - uint base; -}; - -void insertseg(int, int, int, int); - - -#define SDT_INTG 14 /* Interrupt Gate */ -/* - * Delay units are in microseconds. - */ -#define DELAY(n) \ -{ \ - extern int cpudelay; \ - register int i; \ - register long N = (((n)<<4)>>cpudelay); \ - for (i = 0; i <= 4; i++) \ - { \ - N = (((n) << 4) >> cpudelay); \ - while (--N > 0); \ - } \ -} - diff --git a/system/platforms/x86/setupStack.c b/system/platforms/x86/setupStack.c deleted file mode 100644 index 3e1d9801..00000000 --- a/system/platforms/x86/setupStack.c +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @file setupStack.c - */ -/* Embedded Xinu, Copyright (C) 2007, 2013. All rights reserved. */ - -#include -#include - -/** Set up the context record and arguments on the stack for a new thread - * (x86 version) */ -void *setupStack(void *stackaddr, void *procaddr, - void *retaddr, uint nargs, va_list ap) -{ - ulong *saddr = stackaddr; - ulong savsp; /* for remembering stack pointer */ - uint i; - - savsp = (ulong)saddr; - - /* push arguments */ - saddr -= nargs; - for (i = 0; i < nargs; i++) - { - saddr[i] = va_arg(ap, ulong); - } - - *--saddr = (ulong)INITRET; - *--saddr = (ulong)procaddr; - *--saddr = savsp; - savsp = (ulong)saddr; - - /* now we must emulate what ctxsw expects: flags, regs, and old SP */ - /* emulate 386 "pushal" instruction */ - *--saddr = 0; - *--saddr = 0; /* %eax */ - *--saddr = 0; /* %ecx */ - *--saddr = 0; /* %edx */ - *--saddr = 0; /* %ebx */ - *--saddr = 0; /* %esp; "popal" doesn't actually pop it, so 0 is ok */ - *--saddr = savsp; /* %ebp */ - *--saddr = 0; /* %esi */ - *--saddr = 0; /* %edi */ - return saddr; -} diff --git a/system/platforms/x86/startup.S b/system/platforms/x86/startup.S deleted file mode 100644 index affec31b..00000000 --- a/system/platforms/x86/startup.S +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Startup code for standalone system - * Non-relocating version -- for programs which are loaded by boot - * Relocating version for boot - * Small relocating version for "micro" boot - */ - -#define NULLMAGIC 0x0A0AAAA9 - - .data - - .globl gdt - .globl gdtr - .extern memheap - .extern initialsegs - .extern ownerTable - - /* Intel enjoys the GDT to be 16 bit aligned */ - .align 16 -gdt: .space 64 # must be NSEGS * 8 (number of bytes in table) - .align 4 -gdtr: .word 63 # set the gdt limit - .long gdt # gdt base, will be filled later - - .globl idt - .globl idtr -idt: .space 384 # must equal NID*8 (384 == 48 vectors) -idtr: .word 383 # size of idt - 1 (in bytes) - .long idt - - .globl cpudelay - -cpudelay: .long 1 - .text - .align 2 - .extern nulluser - .globl _bootdev - .globl _cyloffset - .globl lidt - .globl startup - -startup: - /* clear stack */ - movl %esp, %ecx - movl $_end, %eax - subl %eax, %ecx - subl $5*4, %ecx - pushl %ecx - pushl $_end - call _asm_bzero - addl $2*4, %esp - - pushl $NULLMAGIC # put the magic number in place - - /* - * Clear Bss section - */ - movl $_end, %ecx # Clear from `edata` to `_end` - subl $edata, %ecx - pushl %ecx - pushl $edata - call _asm_bzero - addl $2*4, %esp - - /* - * Clear all flags - */ - pushl $0 - popf - - /* place the UART in a sane state */ - movl $0x3f8+3, %edx /* UART_LCR */ - movl $0x80, %eax /* UART_LCR_DLAB */ - outb %al, %dx - - movl $0x3f8, %edx /* UART_DLL */ - movl $0x01, %eax /* DLL = 1 for 115200 bps */ - outb %al, %dx - - movl $0x3f8+1, %edx /* UART_DLM */ - movl $0x0, %eax /* DLM = 0 */ - outb %al, %dx - - movl $0x3f8+3, %edx /* UART_LCR */ - movl $0x03, %eax /* UART_LCR_8N1 */ - outb %al, %dx - - call initialsegs - - # save the current stack pointer - movl %esp, %esi - - lgdt gdtr # load the table into the system - - # JSLinux assumes O/S handles protection, so this won't work -# movw $1, %ax # turn on protected mode bit -# lmsw %ax # bam, we're running in protected mode - - - /****************************/ - /* reload segment registers */ - /****************************/ - - /* - * jump to code using the gdt located at the byte 8 for the gdtr - * and located at the address of $gdt1 - */ - ljmp $0x08, $gdt1 /* CS descriptor 1 */ -gdt1: - /* - * load gdt starting at byte 16 into the data segments (ds/es) and the - * same (since we are using flat memory space) into the stack segment. - */ - movl $0x10, %eax /* DS descriptor 2 */ - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %ss - - movl $0x18, %eax /* TLS descriptor 3 */ - movw %ax, %gs - - # Restore the stack point post-segment init - movl %esi, %esp - - # find where the stack starts and mark the beginning of heap mem - movl %esp, %ebx -heapat: - movl 0(%ebx), %eax - addl $4, %ebx - testl $NULLMAGIC, %eax - jne heapat - - addl $4, %ebx - leal memheap, %edx - movl %ebx, 0(%edx) - - /* set monitor coprocessor bit in CR0 */ - movl %CR0, %eax - orl $0x0002, %eax - movl %eax, %CR0 - - /* set O/S extended exception support and restore bits in CR4 */ - movl %CR4, %eax - orl $0x0600, %eax - movl %eax, %CR4 - - /* stack pointer is base pointer (prepair for C code) */ - movl %esp, %ebp /* preparing for C code */ - - finit /* Initialize the floating point unit */ - - movl $0x01, %eax - cpuid - pushl %esp - pushl %eax - call nulluser /* C code, go! */ - - jmp halt - - .data -_bootdev: .long 0 -_cyloffset: .long 0 -savearea: .long 0,0 # sp & bp to return to - .text - - .globl inb -inb: - movl 4(%esp), %edx - xorl %eax, %eax - inb %dx, %al - ret - - .globl inw -inw: - movl 4(%esp), %edx - xorl %eax, %eax - inw %dx, %ax - ret - - .globl outb -outb: - movl 4(%esp), %edx - movl 8(%esp), %eax - outb %al, %dx - ret - - .globl outw -outw: - movl 4(%esp), %edx - movl 8(%esp), %eax - outw %ax, %dx - ret - - # - # _asm_bzero (base, count) - # - .globl _asm_bzero -_asm_bzero: - pushl %edi - movl 8(%esp),%edi - movl 12(%esp),%ecx - movb $0x00,%al - cld - rep - stosb - popl %edi - ret - - # - # bcopy(src, dst, count) - # - - .globl _asm_bcopy -_asm_bcopy: - pushl %esi - pushl %edi - movl 12(%esp),%esi - movl 16(%esp),%edi - movl 20(%esp),%ecx - cld - rep - movsb - popl %edi - popl %esi - ret - - # insw(port,addr,cnt) - .globl insw -insw: - pushl %edi - movw 8(%esp),%dx - movl 12(%esp),%edi - movl 16(%esp),%ecx - cld - .byte 0x66,0xf2,0x6d # rep insw - movl %edi,%eax - popl %edi - ret - - # outsw(port,addr,cnt) - .globl outsw -outsw: - pushl %esi - movw 8(%esp),%dx - movl 12(%esp),%esi - movl 16(%esp),%ecx - cld - .byte 0x66,0xf2,0x6f # rep outsw - movl %esi,%eax - popl %esi - ret - - # - # lidt() - load interrupt descriptor table from idtr - # -lidt: - lidt idtr - ret - -#Return: -# CF clear if successful -# AX = extended memory between 1M and 16M, in K (max 3C00h = 15MB) -# BX = extended memory above 16M, in 64K blocks -# CX = configured memory 1M to 16M, in K -# DX = configured memory above 16M, in 64K blocks CF set on error diff --git a/system/platforms/x86/xtrap.c b/system/platforms/x86/xtrap.c deleted file mode 100644 index 9b97fe38..00000000 --- a/system/platforms/x86/xtrap.c +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @file xtrap.c - * - */ -/* Embedded XINU, Copyright (C) 2007. All rights reserved. */ - -#include -#include -#include -#include -#include - -extern void halt(void); - -#define TRAPS 16 - -char *trap_names[TRAPS] = -{ - "divide by zero", - "debug exception", - "non-maskable interrupt", - "breakpoint", - "overflow", - "bounds check failure", - "invalid opcode", - "coprocessor not available", - "double fault", - "coprocessor segment overrun", - "invalid TSS", - "segment not present", - "stack fault", - "general protection violation", - "page fault", - "coprocessor error" -}; - -/** - * Generic XINU Trap (Interrupt) Handler. - * - * @param cause the contents of the cause register used to decode the trap - * @param frame pointer to the interrupt frame with saved status - * - */ -void xtrap(long cause, long *frame) -{ - int offset = 0; - - if ( (8 == cause) || (10 <= cause && cause <= 14) ) - { - offset = 1; - } - - kprintf("XINU Trap/Exception 0x%02x", cause); - - if (cause < TRAPS) { kprintf(" (%s)", trap_names[cause]); } - - kprintf(": Process %d (\"%s\")\r\n", thrcurrent, thrtab[thrcurrent].name); - - kprintf(" errno: 0x%08x ", *(frame-2)); - kprintf("stkptr: 0x%08x\r\n", *(frame-1)); - kprintf(" edi: 0x%08x ", *(frame+0)); - kprintf(" esi: 0x%08x ", *(frame+1)); - kprintf(" ebp: 0x%08x ", *(frame+2)); - kprintf(" esp: 0x%08x\r\n", *(frame+3)); - kprintf(" ebx: 0x%08x ", *(frame+4)); - kprintf(" edx: 0x%08x ", *(frame+5)); - kprintf(" ecx: 0x%08x ", *(frame+6)); - kprintf(" eax: 0x%08x\r\n", *(frame+7)); - kprintf(" ebp: 0x%08x ", *(frame+8)); - - kprintf(" eip: 0x%08x ", *(frame+offset+9)); - kprintf(" cs: 0x%08x ", *(frame+offset+10)); - kprintf("eflags: 0x%08x\r\n", *(frame+offset+11)); - - if ( 1 == offset ) - { - kprintf(" errno: 0x%08x\r\n", *(frame+9)); - } - - kprintf("girmask: 0x%04x\r\n", getirmask()); - - halt(); - - kprintf("did not halt."); - while (1) - { - } -} diff --git a/system/queinit.c b/system/queinit.c index 43c41aed..3d5c66a8 100644 --- a/system/queinit.c +++ b/system/queinit.c @@ -23,6 +23,9 @@ qid_typ queinit(void) { return SYSERR; } + + quetab_acquire(); + q = nextqid; nextqid += 2; quetab[quehead(q)].next = quetail(q); @@ -31,5 +34,8 @@ qid_typ queinit(void) quetab[quetail(q)].next = EMPTY; quetab[quetail(q)].prev = quehead(q); quetab[quetail(q)].key = MINKEY; + + quetab_release(); + return q; } diff --git a/system/queue.c b/system/queue.c index 305a6c77..d6c316d3 100644 --- a/system/queue.c +++ b/system/queue.c @@ -7,6 +7,7 @@ #include #include #include +#include struct queent quetab[NQENT]; /**< global thread queue table */ @@ -27,6 +28,8 @@ tid_typ enqueue(tid_typ tid, qid_typ q) return SYSERR; } + quetab_acquire(); + tail = quetail(q); prev = quetab[tail].prev; @@ -34,6 +37,9 @@ tid_typ enqueue(tid_typ tid, qid_typ q) quetab[tid].prev = prev; quetab[prev].next = tid; quetab[tail].prev = tid; + + quetab_release(); + return tid; } @@ -48,6 +54,7 @@ tid_typ dequeue(qid_typ q) { int tid; + if (isbadqid(q)) { return SYSERR; @@ -58,10 +65,28 @@ tid_typ dequeue(qid_typ q) } tid = getfirst(q); + + quetab_acquire(); if (!isbadtid(tid)) { quetab[tid].prev = EMPTY; quetab[tid].next = EMPTY; } + quetab_release(); return tid; } + +void quetab_acquire() +{ + for (int i = 0; i < NQENT; i++) + { + pldw(&quetab[i]); + } + mutex_acquire(quetab_mutex); +} + +void quetab_release() +{ + dmb(); + mutex_release(quetab_mutex); +} diff --git a/system/ready.c b/system/ready.c index 01a48955..35551347 100644 --- a/system/ready.c +++ b/system/ready.c @@ -6,6 +6,7 @@ #include #include +#include /** * @ingroup threads @@ -17,21 +18,35 @@ */ int ready(tid_typ tid, bool resch) { - register struct thrent *thrptr; + register struct thrent *thrptr; - if (isbadtid(tid)) - { - return SYSERR; - } + if (isbadtid(tid)){ + return SYSERR; + } - thrptr = &thrtab[tid]; - thrptr->state = THRREADY; + thrtab_acquire(tid); - insert(tid, readylist, thrptr->prio); + thrptr = &thrtab[tid]; + thrptr->state = THRREADY; - if (resch == RESCHED_YES) - { - resched(); - } - return OK; + /* if core affinity is not set, + * set affinity to core currently running this code (most likely 0) */ + unsigned int cpuid; + cpuid = getcpuid(); + if (-1 == thrptr->core_affinity) + { + core_affinity[tid] = core; + } + + thrtab_release(tid); + + if (SYSERR == insert(tid, readylist[thrptr->core_affinity], thrptr->prio)){ + return SYSERR; + } + + if ((resch == RESCHED_YES) && (thrptr->core_affinity == cpuid)){ + resched(); + } + + return OK; } diff --git a/system/receive.c b/system/receive.c index fe671b52..a0d16cf3 100644 --- a/system/receive.c +++ b/system/receive.c @@ -17,16 +17,31 @@ message receive(void) register struct thrent *thrptr; irqmask im; message msg; + unsigned int cpuid; im = disable(); - thrptr = &thrtab[thrcurrent]; + + cpuid = getcpuid(); + + thrptr = &thrtab[thrcurrent[cpuid]]; if (FALSE == thrptr->hasmsg) { /* if no message, wait for one */ - thrptr->state = THRRECV; + thrtab_acquire(thrcurrent[cpuid]); + + thrptr->state = THRRECV; + + thrtab_release(thrcurrent[cpuid]); + resched(); } + + thrtab_acquire(thrcurrent[cpuid]); + msg = thrptr->msg; /* retrieve message */ thrptr->hasmsg = FALSE; /* reset message flag */ + + thrtab_release(thrcurrent[cpuid]); + restore(im); return msg; } diff --git a/system/recvclr.c b/system/recvclr.c index dac2d00e..ad162c31 100644 --- a/system/recvclr.c +++ b/system/recvclr.c @@ -17,9 +17,15 @@ message recvclr(void) register struct thrent *thrptr; irqmask im; message msg; + unsigned int cpuid; im = disable(); - thrptr = &thrtab[thrcurrent]; + + cpuid = getcpuid(); + + thrtab_acquire(thrcurrent[cpuid]); + + thrptr = &thrtab[thrcurrent[cpuid]]; if (thrptr->hasmsg) { msg = thrptr->msg; @@ -29,6 +35,9 @@ message recvclr(void) msg = NOMSG; } thrptr->hasmsg = FALSE; /* reset message flag */ + + thrtab_release(thrcurrent[cpuid]); + restore(im); return msg; } diff --git a/system/recvtime.c b/system/recvtime.c index e9a75760..b8603cfa 100644 --- a/system/recvtime.c +++ b/system/recvtime.c @@ -21,22 +21,31 @@ message recvtime(int maxwait) register struct thrent *thrptr; irqmask im; message msg; + unsigned int cpuid; + + cpuid = getcpuid(); if (maxwait < 0) { return SYSERR; } im = disable(); - thrptr = &thrtab[thrcurrent]; + thrptr = &thrtab[thrcurrent[cpuid]]; if (FALSE == thrptr->hasmsg) { #if RTCLOCK - if (SYSERR == insertd(thrcurrent, sleepq, maxwait)) + if (SYSERR == insertd(thrcurrent[cpuid], sleepq, maxwait)) { restore(im); return SYSERR; } - thrtab[thrcurrent].state = THRTMOUT; + + thrtab_acquire(thrcurrent[cpuid]); + + thrtab[thrcurrent[cpuid]].state = THRTMOUT; + + thrtab_release(thrcurrent[cpuid]); + resched(); #else restore(im); @@ -44,6 +53,8 @@ message recvtime(int maxwait) #endif } + thrtab_acquire(thrcurrent[cpuid]); + if (thrptr->hasmsg) { msg = thrptr->msg; /* retrieve message */ @@ -53,6 +64,9 @@ message recvtime(int maxwait) { msg = TIMEOUT; } + + thrtab_release(thrcurrent[cpuid]); + restore(im); return msg; } diff --git a/system/resched.c b/system/resched.c index 44539efa..fa1749f0 100644 --- a/system/resched.c +++ b/system/resched.c @@ -23,41 +23,52 @@ int resdefer; /* >0 if rescheduling deferred */ */ int resched(void) { - uchar asid; /* address space identifier */ - struct thrent *throld; /* old thread entry */ - struct thrent *thrnew; /* new thread entry */ - - if (resdefer > 0) - { /* if deferred, increase count & return */ - resdefer++; - return (OK); - } - - throld = &thrtab[thrcurrent]; - - throld->intmask = disable(); - - if (THRCURR == throld->state) - { - if (nonempty(readylist) && (throld->prio > firstkey(readylist))) - { - restore(throld->intmask); - return OK; - } - throld->state = THRREADY; - insert(thrcurrent, readylist, throld->prio); - } - - /* get highest priority thread from ready list */ - thrcurrent = dequeue(readylist); - thrnew = &thrtab[thrcurrent]; - thrnew->state = THRCURR; - - /* change address space identifier to thread id */ - asid = thrcurrent & 0xff; - ctxsw(&throld->stkptr, &thrnew->stkptr, asid); - - /* old thread returns here when resumed */ - restore(throld->intmask); - return OK; + uchar asid; /* address space identifier */ + struct thrent *throld; /* old thread entry */ + struct thrent *thrnew; /* new thread entry */ + unsigned int cpuid; + + if (resdefer > 0) + { /* if deferred, increase count & return */ + resdefer++; + return (OK); + } + + cpuid = getcpuid(); + + thrtab_acquire(thrcurrent[cpuid]); + throld = &thrtab[thrcurrent[cpuid]]; + throld->intmask = disable(); + + if (THRCURR == throld->state) + { + quetab_acquire(); + if (nonempty(readylist[cpuid]) && (throld->prio > firstkey(readylist[cpuid]))) + { + quetab_release(); + thrtab_release(thrcurrent[cpuid]); + restore(throld->intmask); + return OK; + } + quetab_release(); + throld->state = THRREADY; + insert(thrcurrent[cpuid], readylist[cpuid], throld->prio); + } + + thrtab_release(thrcurrent[cpuid]); + + /* get highest priority thread from ready list */ + thrcurrent[cpuid] = dequeue(readylist[cpuid]); + thrtab_acquire(thrcurrent[cpuid]); + thrnew = &thrtab[thrcurrent[cpuid]]; + thrnew->state = THRCURR; + thrtab_release(thrcurrent[cpuid]); + + /* change address space identifier to thread id */ + asid = thrcurrent[cpuid] & 0xff; + ctxsw(&throld->stkptr, &thrnew->stkptr, asid); + + /* old thread returns here when resumed */ + restore(throld->intmask); + return OK; } diff --git a/system/semcreate.c b/system/semcreate.c index 7c03cc07..08a70583 100644 --- a/system/semcreate.c +++ b/system/semcreate.c @@ -5,6 +5,7 @@ #include #include +#include static semaphore semalloc(void); @@ -33,14 +34,18 @@ semaphore semcreate(int count) return SYSERR; } + im = disable(); /* Disable interrupts. */ sem = semalloc(); /* Allocate semaphore. */ if (SYSERR != sem) /* If semaphore was allocated, set count. */ { + semtab_acquire(sem); semtab[sem].count = count; + semtab_release(sem); } /* Restore interrupts and return either the semaphore or SYSERR. */ restore(im); + return sem; } @@ -61,9 +66,23 @@ static semaphore semalloc(void) nextsem = (nextsem + 1) % NSEM; if (SFREE == semtab[nextsem].state) { + semtab_acquire(nextsem); semtab[nextsem].state = SUSED; + semtab_release(nextsem); return nextsem; } } return SYSERR; } + +void semtab_acquire(semaphore sem) +{ + pldw(&semtab[sem]); + mutex_acquire(semtab_mutex[sem]); +} + +void semtab_release(semaphore sem) +{ + dmb(); + mutex_release(semtab_mutex[sem]); +} diff --git a/system/semfree.c b/system/semfree.c index bc5bd8d3..f9855dd7 100644 --- a/system/semfree.c +++ b/system/semfree.c @@ -32,7 +32,8 @@ syscall semfree(semaphore sem) restore(im); return SYSERR; } - + + semtab_acquire(sem); semptr = &semtab[sem]; while (nonempty(semptr->queue)) { @@ -42,6 +43,8 @@ syscall semfree(semaphore sem) semptr->count = 0; semptr->state = SFREE; + semtab_release(sem); + restore(im); return OK; } diff --git a/system/send.c b/system/send.c index c1ca8f56..1f235617 100644 --- a/system/send.c +++ b/system/send.c @@ -31,9 +31,14 @@ syscall send(tid_typ tid, message msg) restore(im); return SYSERR; } + + thrtab_acquire(tid); + thrptr->msg = msg; /* deposit message */ thrptr->hasmsg = TRUE; /* raise message flag */ + thrtab_release(tid); + /* if receiver waits, start it */ if (THRRECV == thrptr->state) { diff --git a/system/signal.c b/system/signal.c index e19f0235..e8277697 100644 --- a/system/signal.c +++ b/system/signal.c @@ -25,6 +25,7 @@ syscall signal(semaphore sem) { register struct sement *semptr; + int count; irqmask im; im = disable(); @@ -33,11 +34,18 @@ syscall signal(semaphore sem) restore(im); return SYSERR; } + + semtab_acquire(sem); semptr = &semtab[sem]; - if ((semptr->count++) < 0) + count = semptr->count++; + semtab_release(sem); + + if (count < 0) { - ready(dequeue(semptr->queue), RESCHED_YES); + ready(dequeue(semptr->queue), RESCHED_NO); + resched(); } + restore(im); return OK; } diff --git a/system/signaln.c b/system/signaln.c index 76d1178e..b6be3ad6 100644 --- a/system/signaln.c +++ b/system/signaln.c @@ -27,6 +27,7 @@ syscall signaln(semaphore sem, int count) { register struct sement *semptr; + int c; irqmask im; im = disable(); @@ -36,13 +37,18 @@ syscall signaln(semaphore sem, int count) return SYSERR; } semptr = &semtab[sem]; + for (; count > 0; count--) { - if ((semptr->count++) < 0) + semtab_acquire(sem); + c = semptr->count++; + semtab_release(sem); + if (c < 0) { ready(dequeue(semptr->queue), RESCHED_NO); } } + resched(); restore(im); return OK; diff --git a/system/sleep.c b/system/sleep.c index f4eda9c9..f53fc124 100644 --- a/system/sleep.c +++ b/system/sleep.c @@ -29,18 +29,23 @@ syscall sleep(uint ms) #if RTCLOCK irqmask im; int ticks = 0; + unsigned int cpuid; + + cpuid = getcpuid(); ticks = (ms * CLKTICKS_PER_SEC) / 1000; im = disable(); if (ticks > 0) { - if (SYSERR == insertd(thrcurrent, sleepq, ticks)) + if (SYSERR == insertd(thrcurrent[cpuid], sleepq, ticks)) { restore(im); return SYSERR; } - thrtab[thrcurrent].state = THRSLEEP; + thrtab_acquire(thrcurrent[cpuid]); + thrtab[thrcurrent[cpuid]].state = THRSLEEP; + thrtab_release(thrcurrent[cpuid]); } resched(); diff --git a/system/stkget.c b/system/stkget.c index 9a8c4e63..0a1b1571 100644 --- a/system/stkget.c +++ b/system/stkget.c @@ -76,5 +76,6 @@ void *stkget(uint nbytes) memlist.length -= nbytes; restore(im); + return (void *)((ulong)fits + nbytes - sizeof(int)); } diff --git a/system/suspend.c b/system/suspend.c index 34b464de..c270f280 100644 --- a/system/suspend.c +++ b/system/suspend.c @@ -35,11 +35,15 @@ syscall suspend(tid_typ tid) if (THRREADY == thrptr->state) { getitem(tid); /* removes from queue */ + thrtab_acquire(tid); thrptr->state = THRSUSP; + thrtab_release(tid); } else { + thrtab_acquire(tid); thrptr->state = THRSUSP; + thrtab_release(tid); resched(); } prio = thrptr->prio; diff --git a/system/udelay.c b/system/udelay.c index a1ee6a32..98e9de79 100644 --- a/system/udelay.c +++ b/system/udelay.c @@ -14,6 +14,10 @@ * clkcount() being implemented by the platform-specific code. However it does * assume that the platform clock frequency is an even multiple of 1000000. */ +/* TODO: udelay divisor was previously 1000000... should be 1000 on Pi 3 B+. + * Thus, this is not platform-independent. + */ + /** * @ingroup timer * @@ -27,7 +31,7 @@ void udelay(ulong us) { /* delay = Number of timer ticks to wait for */ - ulong delay = (platform.clkfreq / 1000000) * us; + ulong delay = (platform.clkfreq / 1000) * us; /* start = Starting tick count */ ulong start = clkcount(); @@ -43,7 +47,7 @@ void udelay(ulong us) /* Normal case: Wait until tick count is greater than target or has * wrapped around to less than start. */ while (((count = clkcount()) < target) && (count >= start)) - ; + ; } else { diff --git a/system/unsleep.c b/system/unsleep.c index 5f458346..20e2ffa4 100644 --- a/system/unsleep.c +++ b/system/unsleep.c @@ -39,12 +39,16 @@ syscall unsleep(tid_typ tid) return SYSERR; } + quetab_acquire(); + next = quetab[tid].next; if (next < NTHREAD) { quetab[next].key += quetab[tid].key; } + quetab_release(); + getitem(tid); restore(im); return OK; diff --git a/system/wait.c b/system/wait.c index 6be9fb25..a941a079 100644 --- a/system/wait.c +++ b/system/wait.c @@ -27,23 +27,37 @@ syscall wait(semaphore sem) { register struct sement *semptr; register struct thrent *thrptr; + int c; + unsigned int cpuid; irqmask im; + cpuid = getcpuid(); + im = disable(); if (isbadsem(sem)) { restore(im); return SYSERR; } - thrptr = &thrtab[thrcurrent]; + thrptr = &thrtab[thrcurrent[cpuid]]; + + semtab_acquire(sem); semptr = &semtab[sem]; - if (--(semptr->count) < 0) + c = --(semptr->count); + semtab_release(sem); + + if (c < 0) { + thrtab_acquire(thrcurrent[cpuid]); + thrptr->state = THRWAIT; thrptr->sem = sem; - enqueue(thrcurrent, semptr->queue); - resched(); + thrtab_release(thrcurrent[cpuid]); + enqueue(thrcurrent[cpuid], semptr->queue); + + resched(); } + restore(im); return OK; } diff --git a/test/Makerules b/test/Makerules index 30a6afff..fbb22fe9 100644 --- a/test/Makerules +++ b/test/Makerules @@ -4,8 +4,11 @@ COMP = test # Source files for this component -C_FILES = testhelper.c test_arp.c test_mailbox.c test_semaphore3.c test_bigargs.c test_memory.c test_semaphore4.c test_bufpool.c test_messagePass.c test_semaphore.c test_deltaQueue.c test_netaddr.c test_snoop.c test_ether.c test_netif.c test_ethloop.c test_nvram.c test_system.c test_ip.c test_preempt.c test_tlb.c test_libCtype.c test_procQueue.c test_ttydriver.c test_libLimits.c test_raw.c test_udp.c test_libStdio.c test_recursion.c test_umemory.c test_libStdlib.c test_schedule.c test_libString.c test_semaphore2.c - +C_FILES = testhelper.c test_mailbox.c test_semaphore3.c test_bigargs.c test_memory.c test_semaphore4.c test_bufpool.c +C_FILES += test_messagePass.c test_semaphore.c test_deltaQueue.c test_netaddr.c test_snoop.c test_ether.c test_netif.c test_ethloop.c +C_FILES += test_nvram.c test_system.c test_ip.c test_preempt.c test_tlb.c test_libCtype.c test_procQueue.c test_ttydriver.c test_libLimits.c +C_FILES += test_raw.c test_udp.c test_libStdio.c test_recursion.c test_umemory.c test_libStdlib.c test_schedule.c test_libString.c +C_FILES += test_semaphore2.c test_semaphore_core.c test_boundedbuffer.c test_arp.c S_FILES = diff --git a/test/test_arp.c b/test/test_arp.c index efa439a9..12c2065d 100644 --- a/test/test_arp.c +++ b/test/test_arp.c @@ -15,6 +15,7 @@ #include #include #include +#include #if NETHER @@ -238,7 +239,7 @@ thread test_arp(bool verbose) tids[i] = tid; entry->waiting[i] = tid; entry->count++; - ready(tid, RESCHED_NO); + ready(tid, RESCHED_NO, CORE_ZERO); } recvclr(); arpNotify(entry, ARP_MSG_RESOLVED); @@ -288,7 +289,7 @@ thread test_arp(bool verbose) tids[i] = tid; entry->waiting[i] = tid; entry->count++; - ready(tid, RESCHED_NO); + ready(tid, RESCHED_NO, CORE_ZERO); } recvclr(); if (SYSERR == arpFree(entry)) @@ -751,7 +752,7 @@ thread test_arp(bool verbose) tid = ready(create ((void *)lookupTest, INITSTK, INITPRIO, "lookupTest", 4, - request, wait, data, phdr.caplen), RESCHED_NO); + request, wait, data, phdr.caplen), RESCHED_NO, CORE_ZERO); i = arpLookup(netptr, &praddr, &addrbuf); if ((SYSERR == i) || (TIMEOUT == i)) { @@ -798,7 +799,7 @@ thread test_arp(bool verbose) tid = ready(create ((void *)lookupTest, INITSTK, INITPRIO, "lookupTest", 4, - request, wait, data, phdr.caplen), RESCHED_NO); + request, wait, data, phdr.caplen), RESCHED_NO, CORE_ZERO); i = arpLookup(netptr, &praddr, &addrbuf); if ((SYSERR == i) || (TIMEOUT == i)) { diff --git a/test/test_bigargs.c b/test/test_bigargs.c index 37ade46f..c3607fa6 100644 --- a/test/test_bigargs.c +++ b/test/test_bigargs.c @@ -2,6 +2,7 @@ #include #include #include +#include static void bigargs(uchar a, uchar b, uchar c, uchar d, uchar e, uchar f, uchar *testArray) @@ -21,7 +22,7 @@ thread test_bigargs(bool verbose) uchar testArray[20]; ready(create((void *)bigargs, INITSTK, 31, "BIGARGS", - 7, 10, 20, 30, 40, 50, 60, testArray), RESCHED_YES); + 7, 10, 20, 30, 40, 50, 60, testArray), RESCHED_YES, CORE_ZERO); if ((10 == testArray[0]) && (20 == testArray[1]) diff --git a/test/test_boundedbuffer.c b/test/test_boundedbuffer.c new file mode 100644 index 00000000..e0114154 --- /dev/null +++ b/test/test_boundedbuffer.c @@ -0,0 +1,128 @@ +/** + * @file: test_boundedbuffer.c + * @provides test_boundedbuffer + * + * @usage A producer-consumer problem test for the mutex for multicore rpi3 + * + * This code is straight from Dinosaur Book, essentially... slightly modified + */ + +/* producer() runs on one core, + * consumer() runs on another core, + * and print_bb_status() runs on a third core, + * effectively each acting as their own separate "process" */ + +#include +#include +#include + +#define BUFFER_SIZE 10 + +void test_boundedbuffer(void); +extern void unparkcore(unsigned int, void *); +extern void led_test(void); +extern void udelay(unsigned long); +extern void pld(unsigned int *); +extern void dsb(void); +static void producer(void); +static void consumer(void); +static void print_bb_status(void); + +/* these are static so that they are not visible to the outside xinu world + * and dont interfere with any other variable names, just in case */ +static mutex_t bb_mutex = MUTEX_UNLOCKED; + +static unsigned int buffer[BUFFER_SIZE]; +static unsigned int in = 0; +static unsigned int out = 0; + +void test_boundedbuffer() +{ + kprintf("---------------------------------\r\n"); + kprintf("\tBOUNDED BUFFER TEST\r\n"); + kprintf("---------------------------------\r\n"); + unparkcore(1, (void *) producer); + unparkcore(2, (void *) consumer); + unparkcore(3, (void *) print_bb_status); + led_test(); +} + +static void producer() +{ + + udelay(2500); + kprintf("producer() starting...\r\n"); + + unsigned int next_produced = 1; + while (1) + { + + // do nothing while buffer is full + while (((in + 1) % BUFFER_SIZE) == out) + pld(&out); + + udelay(1000 + (clkticks % 1000)); // using clock to generate "random" durations of delay + + mutex_acquire(&bb_mutex); + // do stuff + + buffer[in] = next_produced; + in = (in + 1) % BUFFER_SIZE; + next_produced = (next_produced + 1) % BUFFER_SIZE; + + dsb(); + + mutex_release(&bb_mutex); + } +} + +static void consumer() +{ + udelay(2500); + kprintf("consumer() starting...\r\n"); + + unsigned int consumed; + while (1) + { + + // do nothing while buffer is empty + // + // preloadData is necessary otherwise cache coherency becomes an issue + // aka consumer() will read "outdated" value of "in" variable and will get stuck in loop + while (in == out) + pld(&in); + + udelay(1000 + (clkticks % 1000)); // using clock to generate "random" durations of delay + + mutex_acquire(&bb_mutex); + + consumed = buffer[out]; + consumed += 1; + out = (out + 1) % BUFFER_SIZE; + + // for cache coherency issue mentioned above.. + dsb(); + + // consume item now... + + mutex_release(&bb_mutex); + } +} + +static void print_bb_status() +{ + + int i; + while (1) + { + + udelay(500); + + mutex_acquire(&bb_mutex); + // print buffer & info + kprintf("in=%d, out=%d\r\n", in, out); + for (i = 0; i < BUFFER_SIZE; i++) + kprintf("%d: %d\r\n", i, buffer[i]); + mutex_release(&bb_mutex); + } +} diff --git a/test/test_mailbox.c b/test/test_mailbox.c index 468a4660..a370274d 100644 --- a/test/test_mailbox.c +++ b/test/test_mailbox.c @@ -6,6 +6,7 @@ #include #include #include +#include /* function prototypes */ static int producer(mailbox); @@ -207,7 +208,7 @@ thread test_mailbox(bool verbose) consumertid = create((void *)consumer, INITSTK, prio + 1, "consumer", 1, testbox1); - ready(consumertid, RESCHED_YES); + ready(consumertid, RESCHED_YES, CORE_ZERO); thrptr = &thrtab[consumertid]; @@ -233,7 +234,7 @@ thread test_mailbox(bool verbose) create((void *)producer, INITSTK, prio + 1, "producer", 1, testbox1); - ready(producertid, RESCHED_YES); + ready(producertid, RESCHED_YES, CORE_ZERO); thrptr = &thrtab[producertid]; diff --git a/test/test_messagePass.c b/test/test_messagePass.c index b9bfdd40..7d58e3f8 100644 --- a/test/test_messagePass.c +++ b/test/test_messagePass.c @@ -6,6 +6,7 @@ #include #include #include +#include static thread recvthread(bool); @@ -94,7 +95,7 @@ thread test_messagePass(bool verbose) testPrint(verbose, "Receive timeout"); recvtid = create((void *)recvthread, INITSTK, getprio(gettid()), "recvthread", 1, verbose); - if ((SYSERR == recvtid) || (SYSERR == ready(recvtid, RESCHED_YES))) + if ((SYSERR == recvtid) || (SYSERR == ready(recvtid, RESCHED_YES, CORE_ZERO))) { passed = FALSE; testFail(verbose, "\nunable to create receiver thread"); diff --git a/test/test_preempt.c b/test/test_preempt.c index 8071cb29..76175401 100644 --- a/test/test_preempt.c +++ b/test/test_preempt.c @@ -3,6 +3,7 @@ #include #include #include +#include thread spin(void) { @@ -21,12 +22,17 @@ thread test_preempt(bool verbose) bool passed = TRUE; tid_typ thrspin; + uint cpuid; + cpuid = getcpuid(); + + thrtab_acquire(thrcurrent[cpuid]); /* This is the first "subtest" of this suite */ thrspin = - create(spin, INITSTK, thrtab[thrcurrent].prio, "test_spin", 0); + create(spin, INITSTK, thrtab[thrcurrent[cpuid]].prio, "test_spin", 0); + thrtab_release(thrcurrent[cpuid]); /* Make spin ... spin */ - ready(thrspin, RESCHED_YES); + ready(thrspin, RESCHED_YES, CORE_ZERO); /* If this next line runs, we're good */ kill(thrspin); diff --git a/test/test_recursion.c b/test/test_recursion.c index cf0d9abc..9a968902 100644 --- a/test/test_recursion.c +++ b/test/test_recursion.c @@ -2,6 +2,7 @@ #include #include #include +#include #define TIMES 5 @@ -42,13 +43,13 @@ thread test_recursion(bool verbose) disable(); ready(atid = create((void *)t5, INITSTK, 31, "RECURSION-A", - 3, TIMES, testArray, &index), 0); + 3, TIMES, testArray, &index), 0, CORE_ZERO); ready(btid = create((void *)t5, INITSTK, 32, "RECURSION-B", - 3, TIMES, testArray, &index), 0); + 3, TIMES, testArray, &index), 0, CORE_ZERO); ready(ctid = create((void *)t5, INITSTK, 34, "RECURSION-C", - 3, TIMES, testArray, &index), 0); + 3, TIMES, testArray, &index), 0, CORE_ZERO); ready(dtid = create((void *)t5, INITSTK, 32, "RECURSION-D", - 3, TIMES, testArray, &index), 0); + 3, TIMES, testArray, &index), 0, CORE_ZERO); /* Run the tests by yielding the processor */ yield(); diff --git a/test/test_schedule.c b/test/test_schedule.c index 05ca27ed..7e037630 100644 --- a/test/test_schedule.c +++ b/test/test_schedule.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #define TIMES 5 @@ -39,13 +41,13 @@ thread test_schedule(bool verbose) /* disable interrupts so we execute in known order */ disable(); ready(atid = create((void *)t4, INITSTK, 31, "PRIORITY-A", - 3, TIMES, testArray, &shared), 0); + 3, TIMES, testArray, &shared), 0, CORE_ZERO); ready(btid = create((void *)t4, INITSTK, 32, "PRIORITY-B", - 3, TIMES, testArray, &shared), 0); + 3, TIMES, testArray, &shared), 0, CORE_ZERO); ready(ctid = create((void *)t4, INITSTK, 34, "PRIORITY-C", - 3, TIMES, testArray, &shared), 0); + 3, TIMES, testArray, &shared), 0, CORE_ZERO); ready(dtid = create((void *)t4, INITSTK, 32, "PRIORITY-D", - 3, TIMES, testArray, &shared), 0); + 3, TIMES, testArray, &shared), 0, CORE_ZERO); /* Run the tests by yielding the processor */ yield(); @@ -81,6 +83,8 @@ thread test_schedule(bool verbose) for (i = 0; i < 4 * TIMES; i++) { + kprintf("\r"); + kprintf("\r\nExpectedResults[%d]: %d (%s), TestResults[%d]: %d", i, expectedResults[i], thrtab[i].name, i, testArray[i]); if (expectedResults[i] != testArray[i]) { passed = FALSE; diff --git a/test/test_semaphore.c b/test/test_semaphore.c index af22cce7..f51b6fe3 100644 --- a/test/test_semaphore.c +++ b/test/test_semaphore.c @@ -3,6 +3,7 @@ #include #include #include +#include #if NSEM @@ -89,7 +90,7 @@ thread test_semaphore(bool verbose) ready(atid = create((void *)test_semWaiter, INITSTK, 31, - "SEMAPHORE-A", 3, s, 1, &testResult), RESCHED_YES); + "SEMAPHORE-A", 3, s, 1, &testResult), RESCHED_YES, CORE_ZERO); testPrint(verbose, "Wait on semaphore: "); if (test_checkProcState(atid, THRWAIT, verbose) diff --git a/test/test_semaphore2.c b/test/test_semaphore2.c index aa45f636..6328b1f5 100644 --- a/test/test_semaphore2.c +++ b/test/test_semaphore2.c @@ -3,6 +3,7 @@ #include #include #include +#include #if NSEM @@ -42,10 +43,10 @@ thread test_semaphore2(bool verbose) ready(atid = create((void *)test_semWaiter, INITSTK, 32, - "SEMAPHORE-A", 3, s, 1, &testResult), RESCHED_NO); + "SEMAPHORE-A", 3, s, 1, &testResult), RESCHED_NO, CORE_ZERO); ready(btid = create((void *)test_semWaiter, INITSTK, 31, - "SEMAPHORE-B", 3, s, 1, &testResult), RESCHED_NO); + "SEMAPHORE-B", 3, s, 1, &testResult), RESCHED_NO, CORE_ZERO); /* Both processes should run and immediately wait. A should wait first * because it has higher priority. */ diff --git a/test/test_semaphore3.c b/test/test_semaphore3.c index ddc125bf..944ae864 100644 --- a/test/test_semaphore3.c +++ b/test/test_semaphore3.c @@ -3,6 +3,7 @@ #include #include #include +#include #if NSEM extern bool test_checkSemCount(semaphore s, short c); @@ -42,10 +43,10 @@ thread test_semaphore3(bool verbose) * thread B before it is even able to wait on the semaphore. */ ready(atid = create((void *)test_semWaiter, INITSTK, 32, - "SEMAPHORE-A", 3, s, 1, &testResult), RESCHED_NO); + "SEMAPHORE-A", 3, s, 1, &testResult), RESCHED_NO, CORE_ZERO); ready(btid = create((void *)test_semWaiter, INITSTK, 31, - "SEMAPHORE-B", 3, s, 1, &testResult), RESCHED_YES); + "SEMAPHORE-B", 3, s, 1, &testResult), RESCHED_YES, CORE_ZERO); testPrint(verbose, "Wait on semaphore: "); /* Process A should be admitted, but B should wait. */ diff --git a/test/test_semaphore4.c b/test/test_semaphore4.c index 647bd2ce..2bef0ceb 100644 --- a/test/test_semaphore4.c +++ b/test/test_semaphore4.c @@ -3,6 +3,7 @@ #include #include #include +#include #if NSEM extern bool test_checkSemCount(semaphore s, short c); @@ -40,7 +41,7 @@ thread test_semaphore4(bool verbose) ready(atid = create((void *)test_semWaiter, INITSTK, 31, - "SEMAPHORE-A", 3, s, 1, &testResult), RESCHED_YES); + "SEMAPHORE-A", 3, s, 1, &testResult), RESCHED_YES, CORE_ZERO); testPrint(verbose, "Wait on semaphore: "); if (test_checkProcState(atid, THRWAIT) diff --git a/test/test_semaphore_core.c b/test/test_semaphore_core.c new file mode 100644 index 00000000..4f691b04 --- /dev/null +++ b/test/test_semaphore_core.c @@ -0,0 +1,34 @@ +#include +#include +#include + +void led_test(void); + +extern void createnullthread(void); + +extern void led_init(void); +extern void led_on(void); +extern void led_off(void); +extern void udelay(unsigned int); + + +void testallcores(void) +{ + unparkcore(1, (void *)createnullthread, NULL); + unparkcore(2, (void *)createnullthread, NULL); + unparkcore(3, (void *)createnullthread, NULL); + led_test(); +} + +void led_test() +{ + led_init(); + led_off(); + while(1) + { + udelay(1000); + led_on(); + udelay(1000); + led_off(); + } +} diff --git a/test/test_system.c b/test/test_system.c index db9c68f8..9cee6888 100644 --- a/test/test_system.c +++ b/test/test_system.c @@ -3,6 +3,7 @@ #include #include #include +#include /** * Example of a test program for the Xinu testsuite. Beyond this file you @@ -14,8 +15,10 @@ thread test_system(bool verbose) /* the failif macro depends on 'passed' and 'verbose' vars */ bool passed = TRUE; + int cpuid = getcpuid(); + testPrint(verbose, "Checking gettid()"); - failif((thrcurrent != gettid()), + failif((thrcurrent[cpuid] != gettid()), "gettid() does not return thrcurrent"); testPrint(verbose, "Checking getprio()"); diff --git a/test/testhelper.c b/test/testhelper.c index 5bfbf518..6240fdeb 100644 --- a/test/testhelper.c +++ b/test/testhelper.c @@ -45,7 +45,7 @@ void testPass(bool verbose, const char *msg) { if (TRUE == verbose) { - printf("\033[60G[\033[1;32mPASS\033[0;39m] %s\n", msg); + kprintf("\033[60G[\033[1;32mPASS\033[0;39m] %s\n", msg); } } @@ -53,7 +53,7 @@ void testFail(bool verbose, const char *msg) { if (TRUE == verbose) { - printf("\033[60G[\033[1;31mFAIL\033[0;39m] %s\n", msg); + kprintf("\033[60G[\033[1;31mFAIL\033[0;39m] %s\n", msg); } } @@ -61,7 +61,7 @@ void testSkip(bool verbose, const char *msg) { if (TRUE == verbose) { - printf("\033[60G[\033[1;33mSKIP\033[0;39m] %s\n", msg); + kprintf("\033[60G[\033[1;33mSKIP\033[0;39m] %s\n", msg); } } @@ -69,6 +69,6 @@ void testPrint(bool verbose, const char *msg) { if (TRUE == verbose) { - printf(" %s", msg); + kprintf(" %s", msg); } }