mirror of https://github.com/zrafa/xinu-avr.git
commit
6f0cd91423
312 changed files with 26551 additions and 0 deletions
@ -0,0 +1,20 @@
|
||||
Portions of this software are covered by the following copyright: |
||||
|
||||
Copyright (c) 2012, 2015 Douglas E. Comer and CRC Press, Inc. |
||||
All rights reserved. |
||||
|
||||
Redistribution and use in source and binary forms are permitted |
||||
provided that this notice is preserved and that due credit is given |
||||
to the copyright holders. The names of the copyright holders |
||||
may not be used to endorse or promote products derived from this |
||||
software without specific prior written permission. This software |
||||
is provided `as is'' without express or implied warranty. The author |
||||
assumes no liability for damages incidental or consequential, nor is the |
||||
software warranted for correctness or suitability for any purpose. |
||||
Portions of this software are documented in the book: |
||||
|
||||
Operating System Design -- The Xinu Approach, CRC Press, |
||||
Boca Raton, FL, Linksys version 2012, Second Edition 2015. |
||||
|
||||
This software may not be sold or published in printed form without written |
||||
permission from the copyright holders. |
||||
@ -0,0 +1,34 @@
|
||||
## What is Xinu? |
||||
Xinu stands for Xinu Is Not Unix -- although it shares concepts and even names with Unix, the internal design differs completely. Xinu is a small, elegant operating system that supports dynamic process creation, dynamic memory allocation, network communication, local and remote file systems, a shell, and device-independent I/O functions. The small size makes Xinu suitable for embedded environments. |
||||
|
||||
## What is Xinu for STM32 |
||||
Xinu for STM32 is a port of the ARM version of Xinu. The STM32 family of 32-bit microcontrollers is a popular SoC based on the Arm Cortex-M processor. |
||||
Besides porting the original version, Xinu for STM32 is extended with the following specific Cortex-M* features: |
||||
|
||||
* Shadowed Stack Pointer: Two stack pointers are available. The MSP is used |
||||
for the OS Kernel and interrupt handlers. The PSP is used by application |
||||
tasks. |
||||
* PendSV exception for scheduling: If Xinu decides that context switching is needed, |
||||
it sets the pending status of the PendSV, and delays the context-switching |
||||
request until all other IRQ handlers have completed their processing before |
||||
carrying out the PendSV exception |
||||
|
||||
## Supported Peripherals (currently) |
||||
* UART (Serial) |
||||
* GPIO |
||||
* SPI |
||||
|
||||
## Tested boards |
||||
1. STM32F103* - https://stm32-base.org/boards/STM32F103RCT6-STM32-Mini-V2.0 |
||||
2. Qemu for STM32 - https://github.com/beckus/qemu_stm32 |
||||
|
||||
## How to build and run |
||||
Xinu for STM32 uses simple Makefiles. The source code should be compiled with a cross compiler (i.e. Ubuntu's standard package: GCC cross compiler for ARM Cortex-A/R/M processors) |
||||
STM32Flash (https://sourceforge.net/projects/stm32flash) can be used for flashing the compiled code to the device's flash ROM. Use `qemu make` to run Xinu for STM32 in Qemu. Please note that this version of qemu should be manually build (see https://github.com/beckus/qemu_stm32) |
||||
|
||||
|
||||
## Screenshots |
||||
 |
||||
|
||||
More general information about Xinu can be found at https://xinu.cs.purdue.edu/ |
||||
|
||||
@ -0,0 +1,318 @@
|
||||
#-------------------------------------------------------------------------------# |
||||
# # |
||||
# Definitions generated by build-make on dom may 17 23:40:51 -03 2020 # |
||||
# # |
||||
#-------------------------------------------------------------------------------# |
||||
|
||||
SRC_CFILES = |
||||
SRC_SFILES = |
||||
|
||||
|
||||
|
||||
#------------------------------------------------------------------ |
||||
# |
||||
# Directory ../system |
||||
# |
||||
#------------------------------------------------------------------ |
||||
|
||||
SYSTEM_SFILES = \ |
||||
intr.S start.S |
||||
|
||||
SYSTEM_CFILES = \ |
||||
ascdate.c blink_avr.c bufinit.c chprio.c clkhandler.c \ |
||||
clkinit.c close.c conf.c control.c create.c \ |
||||
debug.c evec.c exit.c freebuf.c freemem.c \ |
||||
getbuf.c getc.c getdev.c getitem.c getmem.c \ |
||||
getpid.c getprio.c getstk.c getticks.c gettime.c \ |
||||
init.c initialize.c insert.c insertd.c ioerr.c \ |
||||
ionull.c kill.c kprintf.c main.c mark.c \ |
||||
meminit.c mkbufpool.c newqueue.c open.c panic.c \ |
||||
platinit.c ptclear.c ptcount.c ptcreate.c ptdelete.c \ |
||||
ptinit.c ptrecv.c ptreset.c ptsend.c putc.c \ |
||||
queue.c read.c ready.c receive.c recvclr.c \ |
||||
recvtime.c resched.c resume.c seek.c semcount.c \ |
||||
semcreate.c semdelete.c semreset.c send.c serial_avr.c \ |
||||
signal.c signaln.c sleep.c suspend.c syscall.c \ |
||||
unsleep.c userret.c wait.c wakeup.c write.c \ |
||||
xdone.c yield.c |
||||
|
||||
SRC_CFILES += ${SYSTEM_CFILES} |
||||
SRC_SFILES += ${SYSTEM_SFILES} |
||||
SYSTEM_CFULL += ${SYSTEM_CFILES:%=../system/%} |
||||
SYSTEM_SFULL += ${SYSTEM_SFILES:%=../system/%} |
||||
SRC_CFULL += ${SYSTEM_CFULL} |
||||
SRC_SFULL += ${SYSTEM_SFULL} |
||||
|
||||
|
||||
#------------------------------------------------------------------ |
||||
# |
||||
# Directory ../lib |
||||
# |
||||
#------------------------------------------------------------------ |
||||
|
||||
LIB_CFILES = \ |
||||
ctype_.c doprnt.c doscan.c messages.c userland.c |
||||
|
||||
SRC_CFILES += ${LIB_CFILES} |
||||
LIB_CFULL += ${LIB_CFILES:%=../lib/%} |
||||
SRC_CFULL += ${LIB_CFULL} |
||||
|
||||
|
||||
#------------------------------------------------------------------ |
||||
# |
||||
# Directory ../device/nam |
||||
# |
||||
#------------------------------------------------------------------ |
||||
|
||||
DEVICE_NAM_CFILES = \ |
||||
mount.c naminit.c nammap.c namopen.c |
||||
|
||||
SRC_CFILES += ${DEVICE_NAM_CFILES} |
||||
DEVICE_NAM_CFULL += ${DEVICE_NAM_CFILES:%=../device/nam/%} |
||||
SRC_CFULL += ${DEVICE_NAM_CFULL} |
||||
|
||||
|
||||
#------------------------------------------------------------------ |
||||
# |
||||
# Directory ../shell |
||||
# |
||||
#------------------------------------------------------------------ |
||||
|
||||
SHELL_CFILES = \ |
||||
addargs.c lexan.c shell.c |
||||
|
||||
SRC_CFILES += ${SHELL_CFILES} |
||||
SHELL_CFULL += ${SHELL_CFILES:%=../shell/%} |
||||
SRC_CFULL += ${SHELL_CFULL} |
||||
|
||||
|
||||
#-------------------------------------------------------------------------------# |
||||
# # |
||||
# Rules For Generating Object Files # |
||||
# # |
||||
#-------------------------------------------------------------------------------# |
||||
|
||||
OBJ_TMP = ${patsubst %.s,%.o,$(SRC_SFILES)} # substitute .s => .o |
||||
OBJ_SFILES = ${patsubst %.S,%.o,$(OBJ_TMP)} # substitute .S => .o |
||||
OBJ_CFILES = ${patsubst %.c,%.o,$(SRC_CFILES)} # substitute .c => .o |
||||
OBJ_LIST = ${OBJ_CFILES} ${OBJ_SFILES} |
||||
OBJ_FILES = ${OBJ_LIST:%=binaries/%} |
||||
SRC_FULL = ${SRC_CFULL} ${SRC_SFULL} |
||||
|
||||
#------------------------------------------------------------------ |
||||
# Rules for files in directory ../system |
||||
#------------------------------------------------------------------ |
||||
|
||||
binaries/intr.o: ../system/intr.S |
||||
${CC} ${CFLAGS} -o binaries/intr.o ../system/intr.S |
||||
binaries/start.o: ../system/start.S |
||||
${CC} ${CFLAGS} -o binaries/start.o ../system/start.S |
||||
binaries/ascdate.o: ../system/ascdate.c |
||||
${CC} ${CFLAGS} -o binaries/ascdate.o ../system/ascdate.c |
||||
binaries/blink_avr.o: ../system/blink_avr.c |
||||
${CC} ${CFLAGS} -o binaries/blink_avr.o ../system/blink_avr.c |
||||
binaries/bufinit.o: ../system/bufinit.c |
||||
${CC} ${CFLAGS} -o binaries/bufinit.o ../system/bufinit.c |
||||
binaries/chprio.o: ../system/chprio.c |
||||
${CC} ${CFLAGS} -o binaries/chprio.o ../system/chprio.c |
||||
binaries/clkhandler.o: ../system/clkhandler.c |
||||
${CC} ${CFLAGS} -o binaries/clkhandler.o ../system/clkhandler.c |
||||
binaries/clkinit.o: ../system/clkinit.c |
||||
${CC} ${CFLAGS} -o binaries/clkinit.o ../system/clkinit.c |
||||
binaries/close.o: ../system/close.c |
||||
${CC} ${CFLAGS} -o binaries/close.o ../system/close.c |
||||
binaries/conf.o: ../system/conf.c |
||||
${CC} ${CFLAGS} -o binaries/conf.o ../system/conf.c |
||||
binaries/control.o: ../system/control.c |
||||
${CC} ${CFLAGS} -o binaries/control.o ../system/control.c |
||||
binaries/create.o: ../system/create.c |
||||
${CC} ${CFLAGS} -o binaries/create.o ../system/create.c |
||||
binaries/debug.o: ../system/debug.c |
||||
${CC} ${CFLAGS} -o binaries/debug.o ../system/debug.c |
||||
binaries/evec.o: ../system/evec.c |
||||
${CC} ${CFLAGS} -o binaries/evec.o ../system/evec.c |
||||
binaries/exit.o: ../system/exit.c |
||||
${CC} ${CFLAGS} -o binaries/exit.o ../system/exit.c |
||||
binaries/freebuf.o: ../system/freebuf.c |
||||
${CC} ${CFLAGS} -o binaries/freebuf.o ../system/freebuf.c |
||||
binaries/freemem.o: ../system/freemem.c |
||||
${CC} ${CFLAGS} -o binaries/freemem.o ../system/freemem.c |
||||
binaries/getbuf.o: ../system/getbuf.c |
||||
${CC} ${CFLAGS} -o binaries/getbuf.o ../system/getbuf.c |
||||
binaries/getc.o: ../system/getc.c |
||||
${CC} ${CFLAGS} -o binaries/getc.o ../system/getc.c |
||||
binaries/getdev.o: ../system/getdev.c |
||||
${CC} ${CFLAGS} -o binaries/getdev.o ../system/getdev.c |
||||
binaries/getitem.o: ../system/getitem.c |
||||
${CC} ${CFLAGS} -o binaries/getitem.o ../system/getitem.c |
||||
binaries/getmem.o: ../system/getmem.c |
||||
${CC} ${CFLAGS} -o binaries/getmem.o ../system/getmem.c |
||||
binaries/getpid.o: ../system/getpid.c |
||||
${CC} ${CFLAGS} -o binaries/getpid.o ../system/getpid.c |
||||
binaries/getprio.o: ../system/getprio.c |
||||
${CC} ${CFLAGS} -o binaries/getprio.o ../system/getprio.c |
||||
binaries/getstk.o: ../system/getstk.c |
||||
${CC} ${CFLAGS} -o binaries/getstk.o ../system/getstk.c |
||||
binaries/getticks.o: ../system/getticks.c |
||||
${CC} ${CFLAGS} -o binaries/getticks.o ../system/getticks.c |
||||
binaries/gettime.o: ../system/gettime.c |
||||
${CC} ${CFLAGS} -o binaries/gettime.o ../system/gettime.c |
||||
binaries/init.o: ../system/init.c |
||||
${CC} ${CFLAGS} -o binaries/init.o ../system/init.c |
||||
binaries/initialize.o: ../system/initialize.c |
||||
${CC} ${CFLAGS} -o binaries/initialize.o ../system/initialize.c |
||||
binaries/insert.o: ../system/insert.c |
||||
${CC} ${CFLAGS} -o binaries/insert.o ../system/insert.c |
||||
binaries/insertd.o: ../system/insertd.c |
||||
${CC} ${CFLAGS} -o binaries/insertd.o ../system/insertd.c |
||||
binaries/ioerr.o: ../system/ioerr.c |
||||
${CC} ${CFLAGS} -o binaries/ioerr.o ../system/ioerr.c |
||||
binaries/ionull.o: ../system/ionull.c |
||||
${CC} ${CFLAGS} -o binaries/ionull.o ../system/ionull.c |
||||
binaries/kill.o: ../system/kill.c |
||||
${CC} ${CFLAGS} -o binaries/kill.o ../system/kill.c |
||||
binaries/kprintf.o: ../system/kprintf.c |
||||
${CC} ${CFLAGS} -o binaries/kprintf.o ../system/kprintf.c |
||||
binaries/main.o: ../system/main.c |
||||
${CC} ${CFLAGS} -o binaries/main.o ../system/main.c |
||||
binaries/mark.o: ../system/mark.c |
||||
${CC} ${CFLAGS} -o binaries/mark.o ../system/mark.c |
||||
binaries/meminit.o: ../system/meminit.c |
||||
${CC} ${CFLAGS} -o binaries/meminit.o ../system/meminit.c |
||||
binaries/mkbufpool.o: ../system/mkbufpool.c |
||||
${CC} ${CFLAGS} -o binaries/mkbufpool.o ../system/mkbufpool.c |
||||
binaries/newqueue.o: ../system/newqueue.c |
||||
${CC} ${CFLAGS} -o binaries/newqueue.o ../system/newqueue.c |
||||
binaries/open.o: ../system/open.c |
||||
${CC} ${CFLAGS} -o binaries/open.o ../system/open.c |
||||
binaries/panic.o: ../system/panic.c |
||||
${CC} ${CFLAGS} -o binaries/panic.o ../system/panic.c |
||||
binaries/platinit.o: ../system/platinit.c |
||||
${CC} ${CFLAGS} -o binaries/platinit.o ../system/platinit.c |
||||
binaries/ptclear.o: ../system/ptclear.c |
||||
${CC} ${CFLAGS} -o binaries/ptclear.o ../system/ptclear.c |
||||
binaries/ptcount.o: ../system/ptcount.c |
||||
${CC} ${CFLAGS} -o binaries/ptcount.o ../system/ptcount.c |
||||
binaries/ptcreate.o: ../system/ptcreate.c |
||||
${CC} ${CFLAGS} -o binaries/ptcreate.o ../system/ptcreate.c |
||||
binaries/ptdelete.o: ../system/ptdelete.c |
||||
${CC} ${CFLAGS} -o binaries/ptdelete.o ../system/ptdelete.c |
||||
binaries/ptinit.o: ../system/ptinit.c |
||||
${CC} ${CFLAGS} -o binaries/ptinit.o ../system/ptinit.c |
||||
binaries/ptrecv.o: ../system/ptrecv.c |
||||
${CC} ${CFLAGS} -o binaries/ptrecv.o ../system/ptrecv.c |
||||
binaries/ptreset.o: ../system/ptreset.c |
||||
${CC} ${CFLAGS} -o binaries/ptreset.o ../system/ptreset.c |
||||
binaries/ptsend.o: ../system/ptsend.c |
||||
${CC} ${CFLAGS} -o binaries/ptsend.o ../system/ptsend.c |
||||
binaries/putc.o: ../system/putc.c |
||||
${CC} ${CFLAGS} -o binaries/putc.o ../system/putc.c |
||||
binaries/queue.o: ../system/queue.c |
||||
${CC} ${CFLAGS} -o binaries/queue.o ../system/queue.c |
||||
binaries/read.o: ../system/read.c |
||||
${CC} ${CFLAGS} -o binaries/read.o ../system/read.c |
||||
binaries/ready.o: ../system/ready.c |
||||
${CC} ${CFLAGS} -o binaries/ready.o ../system/ready.c |
||||
binaries/receive.o: ../system/receive.c |
||||
${CC} ${CFLAGS} -o binaries/receive.o ../system/receive.c |
||||
binaries/recvclr.o: ../system/recvclr.c |
||||
${CC} ${CFLAGS} -o binaries/recvclr.o ../system/recvclr.c |
||||
binaries/recvtime.o: ../system/recvtime.c |
||||
${CC} ${CFLAGS} -o binaries/recvtime.o ../system/recvtime.c |
||||
binaries/resched.o: ../system/resched.c |
||||
${CC} ${CFLAGS} -o binaries/resched.o ../system/resched.c |
||||
binaries/resume.o: ../system/resume.c |
||||
${CC} ${CFLAGS} -o binaries/resume.o ../system/resume.c |
||||
binaries/seek.o: ../system/seek.c |
||||
${CC} ${CFLAGS} -o binaries/seek.o ../system/seek.c |
||||
binaries/semcount.o: ../system/semcount.c |
||||
${CC} ${CFLAGS} -o binaries/semcount.o ../system/semcount.c |
||||
binaries/semcreate.o: ../system/semcreate.c |
||||
${CC} ${CFLAGS} -o binaries/semcreate.o ../system/semcreate.c |
||||
binaries/semdelete.o: ../system/semdelete.c |
||||
${CC} ${CFLAGS} -o binaries/semdelete.o ../system/semdelete.c |
||||
binaries/semreset.o: ../system/semreset.c |
||||
${CC} ${CFLAGS} -o binaries/semreset.o ../system/semreset.c |
||||
binaries/send.o: ../system/send.c |
||||
${CC} ${CFLAGS} -o binaries/send.o ../system/send.c |
||||
binaries/serial_avr.o: ../system/serial_avr.c |
||||
${CC} ${CFLAGS} -o binaries/serial_avr.o ../system/serial_avr.c |
||||
binaries/signal.o: ../system/signal.c |
||||
${CC} ${CFLAGS} -o binaries/signal.o ../system/signal.c |
||||
binaries/signaln.o: ../system/signaln.c |
||||
${CC} ${CFLAGS} -o binaries/signaln.o ../system/signaln.c |
||||
binaries/sleep.o: ../system/sleep.c |
||||
${CC} ${CFLAGS} -o binaries/sleep.o ../system/sleep.c |
||||
binaries/suspend.o: ../system/suspend.c |
||||
${CC} ${CFLAGS} -o binaries/suspend.o ../system/suspend.c |
||||
binaries/syscall.o: ../system/syscall.c |
||||
${CC} ${CFLAGS} -o binaries/syscall.o ../system/syscall.c |
||||
binaries/unsleep.o: ../system/unsleep.c |
||||
${CC} ${CFLAGS} -o binaries/unsleep.o ../system/unsleep.c |
||||
binaries/userret.o: ../system/userret.c |
||||
${CC} ${CFLAGS} -o binaries/userret.o ../system/userret.c |
||||
binaries/wait.o: ../system/wait.c |
||||
${CC} ${CFLAGS} -o binaries/wait.o ../system/wait.c |
||||
binaries/wakeup.o: ../system/wakeup.c |
||||
${CC} ${CFLAGS} -o binaries/wakeup.o ../system/wakeup.c |
||||
binaries/write.o: ../system/write.c |
||||
${CC} ${CFLAGS} -o binaries/write.o ../system/write.c |
||||
binaries/xdone.o: ../system/xdone.c |
||||
${CC} ${CFLAGS} -o binaries/xdone.o ../system/xdone.c |
||||
binaries/yield.o: ../system/yield.c |
||||
${CC} ${CFLAGS} -o binaries/yield.o ../system/yield.c |
||||
|
||||
#------------------------------------------------------------------ |
||||
# Rules for files in directory ../lib |
||||
#------------------------------------------------------------------ |
||||
|
||||
binaries/ctype_.o: ../lib/ctype_.c |
||||
${CC} ${CFLAGS} -o binaries/ctype_.o ../lib/ctype_.c |
||||
binaries/doprnt.o: ../lib/doprnt.c |
||||
${CC} ${CFLAGS} -o binaries/doprnt.o ../lib/doprnt.c |
||||
binaries/doscan.o: ../lib/doscan.c |
||||
${CC} ${CFLAGS} -o binaries/doscan.o ../lib/doscan.c |
||||
binaries/messages.o: ../lib/messages.c |
||||
${CC} ${CFLAGS} -o binaries/messages.o ../lib/messages.c |
||||
binaries/userland.o: ../lib/userland.c |
||||
${CC} ${CFLAGS} -o binaries/userland.o ../lib/userland.c |
||||
|
||||
#------------------------------------------------------------------ |
||||
# Rules for files in directory ../device/nam |
||||
#------------------------------------------------------------------ |
||||
|
||||
binaries/mount.o: ../device/nam/mount.c |
||||
${CC} ${CFLAGS} -o binaries/mount.o ../device/nam/mount.c |
||||
binaries/naminit.o: ../device/nam/naminit.c |
||||
${CC} ${CFLAGS} -o binaries/naminit.o ../device/nam/naminit.c |
||||
binaries/nammap.o: ../device/nam/nammap.c |
||||
${CC} ${CFLAGS} -o binaries/nammap.o ../device/nam/nammap.c |
||||
binaries/namopen.o: ../device/nam/namopen.c |
||||
${CC} ${CFLAGS} -o binaries/namopen.o ../device/nam/namopen.c |
||||
|
||||
#------------------------------------------------------------------ |
||||
# Rules for files in directory ../shell |
||||
#------------------------------------------------------------------ |
||||
|
||||
binaries/addargs.o: ../shell/addargs.c |
||||
${CC} ${CFLAGS} -o binaries/addargs.o ../shell/addargs.c |
||||
binaries/lexan.o: ../shell/lexan.c |
||||
${CC} ${CFLAGS} -o binaries/lexan.o ../shell/lexan.c |
||||
binaries/shell.o: ../shell/shell.c |
||||
${CC} ${CFLAGS} -o binaries/shell.o ../shell/shell.c |
||||
|
||||
objs: ${OBJ_FILES} |
||||
|
||||
list_obj: |
||||
@echo ${OBJ_FILES} |
||||
|
||||
list_csrc: |
||||
@echo ${SRC_CFILES} |
||||
|
||||
list_ssrc: |
||||
@echo ${SRC_SFILES} |
||||
|
||||
# Export variables for recursive make calls (such as the library) |
||||
|
||||
export |
||||
|
||||
@ -0,0 +1 @@
|
||||
****DAC_OUT_PUT1 : Result of conversion DAC channel 1**** |
||||
@ -0,0 +1 @@
|
||||
****DAC_OUT_PUT2 : Result of conversion DAC channel 2**** |
||||
@ -0,0 +1,199 @@
|
||||
#########################################################################
|
||||
# #
|
||||
# #
|
||||
# Makefile for STM32 version of the Xinu operating system #
|
||||
# #
|
||||
# includes: .deps and .defs #
|
||||
# #
|
||||
# #
|
||||
#########################################################################
|
||||
|
||||
COMPILER_ROOT = avr-
|
||||
PNAME = ATMEGA328P
|
||||
PLAT = Platform_$(PNAME)
|
||||
TOPDIR = ..
|
||||
|
||||
CC = ${COMPILER_ROOT}gcc
|
||||
LD = ${COMPILER_ROOT}gcc
|
||||
OBJCOPY = ${COMPILER_ROOT}objcopy
|
||||
OBJDUMP = ${COMPILER_ROOT}objdump
|
||||
QEMU = /home/lechnerm/rafa/xinu/qemu_stm32/arm-softmmu/qemu-system-arm
|
||||
XINU = $(TOPDIR)/compile/xinu.elf
|
||||
XINUBIN = $(TOPDIR)/compile/xinu.bin
|
||||
XINUHEX = $(TOPDIR)/compile/xinu.hex
|
||||
XINUBOOT = $(TOPDIR)/compile/xinu
|
||||
BUILDMAKE = $(TOPDIR)/compile/bin/build-make
|
||||
MKVERS = $(TOPDIR)/compile/bin/mkvers
|
||||
|
||||
MAKEDEP = $(CC) -M -MG
|
||||
|
||||
DEPSFILE = .deps
|
||||
DEFSFILE = .defs
|
||||
VERSIONFILE = version
|
||||
LDSCRIPT = ld.script
|
||||
MKVERS = $(TOPDIR)/compile/bin/mkvers
|
||||
|
||||
|
||||
# RAFA -s $(TOPDIR)/device/ram \
|
||||
REBUILDFLAGS = -s $(TOPDIR)/system debug.c \
|
||||
#-s $(TOPDIR)/device/gpio \
|
||||
#-s $(TOPDIR)/device/spi \
|
||||
-s $(TOPDIR)/device/tty \
|
||||
#
|
||||
REBUILDFLAGS = -s $(TOPDIR)/system \
|
||||
-s $(TOPDIR)/lib \
|
||||
-s $(TOPDIR)/device/nam \
|
||||
-s $(TOPDIR)/shell 'xsh_rdstest*'
|
||||
|
||||
INCLUDE = -I$(TOPDIR)/include
|
||||
# RAFA DEFS = -DBSDURG -DVERSION=\""`cat $(VERSIONFILE)`"\"
|
||||
DEFS = -DVERSION=\""Rafa"\"
|
||||
|
||||
# Compiler flags
|
||||
# CFLAGS = -mcpu=cortex-m3 -mno-unaligned-access -mthumb -fno-builtin -fno-stack-protector -nostdlib -c -Wall -O ${DEFS} ${INCLUDE}
|
||||
# CFLAGS = -DF_CPU=16000000UL -mmcu=atmega328p -mrelax -fno-builtin -fno-stack-protector -nostdlib -c -Wall -Os ${DEFS} ${INCLUDE}
|
||||
CFLAGS = -DF_CPU=16000000UL -mmcu=atmega328p -fno-builtin -c -Wall -Os ${DEFS} ${INCLUDE}
|
||||
SFLAGS = ${INCLUDE}
|
||||
|
||||
# Loader flags
|
||||
|
||||
# RAFA LDFLAGS = -Wl,--wrap,malloc,--wrap,free,--wrap,realloc,--wrap,fdevopen
|
||||
# LDFLAGS = -mmcu=atmega328p -nostartfiles -T ld.script -Wl,-Map,xinu.map
|
||||
LDFLAGS = -mmcu=atmega328p -Wl,-Map,xinu.map
|
||||
|
||||
all: xinu |
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
# Handle generation of a new version string when initialize is recompiled
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
newversion: |
||||
@echo creating new version
|
||||
@$(MKVERS) $(PNAME) > version
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
# Include generic make targets and rules from the file generated by build-make
|
||||
#--------------------------------------------------------------------------------
|
||||
-include $(DEFSFILE) |
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
# Add files that require special rules and place start.o at the front
|
||||
#--------------------------------------------------------------------------------
|
||||
# RAFA quitamos el start.S y start.o porque intentaremos el startup de avr
|
||||
LD_LIST = binaries/start.o $(filter-out binaries/start.o,$(OBJ_FILES))
|
||||
# LD_LIST = $(filter-out binaries/start.o,$(OBJ_FILES))
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Rules for files that need special handling
|
||||
#------------------------------------------------------------
|
||||
|
||||
# Define variables for the Configuration file and generated files
|
||||
|
||||
CONFFILE = $(TOPDIR)/config/Configuration
|
||||
CONFH = $(TOPDIR)/include/conf.h
|
||||
CONFC = $(TOPDIR)/system/conf.c
|
||||
|
||||
# Define variables for the config program and its sources
|
||||
|
||||
CONFPGM = $(TOPDIR)/config/config
|
||||
CONFL = $(TOPDIR)/config/config.l
|
||||
CONFY = $(TOPDIR)/config/config.y
|
||||
|
||||
# Set up the required build directory structure
|
||||
|
||||
BLDDIRS = binaries
|
||||
export
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
# Specific additional rules and exceptions
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
xinu: Makefile rebuild $(BLDDIRS) $(DEFSFILE) $(DEPSFILE) $(CONFH) $(CONFC) $(LD_LIST) |
||||
@echo;echo 'Loading object files to produce xinu'
|
||||
# RAFA original : @$(LD) $(LDFLAGS) $(LD_LIST) -o $(XINU) -L/usr/lib/gcc/arm-none-eabi/6.3.1/ --print-memory-usage
|
||||
@$(LD) $(LDFLAGS) $(LD_LIST) -o $(XINU)
|
||||
@echo "Creating Binary..."
|
||||
@$(OBJCOPY) -O binary $(XINU) $(XINUBIN)
|
||||
|
||||
examine-all: |
||||
$(OBJDUMP) -D $(XINU) | less
|
||||
|
||||
examine-header: |
||||
$(OBJDUMP) -x $(XINU) | less
|
||||
|
||||
flash: |
||||
avr-objcopy -O ihex -R .eeprom $(XINU) $(XINUHEX)
|
||||
avrdude -p atmega328p -c arduino -P /dev/ttyUSB0 -b 57600 -D -U flash:w:$(XINUHEX):i
|
||||
# avrdude -p atmega328p -c arduino -P /dev/ttyUSB0 -b 115200 -D -U flash:w:$(FIRMWARE):i
|
||||
|
||||
|
||||
qemu: |
||||
$(QEMU) -serial stdio -M stm32-f103c8 -kernel $(XINUBIN)
|
||||
monitor: |
||||
$(QEMU) -monitor stdio -serial stdio -M stm32-f103c8 -kernel $(XINUBIN)
|
||||
|
||||
$(BLDDIRS): |
||||
@mkdir -p $(BLDDIRS)
|
||||
|
||||
objects: $(LD_LIST) |
||||
|
||||
$(CONFH): $(CONFFILE) $(CONFPGM) |
||||
@echo making $(CONFH)
|
||||
@make configure
|
||||
|
||||
$(CONFC): $(CONFFILE) $(CONFPGM) |
||||
@echo making $(CONFC)
|
||||
@make configure
|
||||
|
||||
$(CONFPGM): $(CONFL) $(CONFY) |
||||
@echo making the config program
|
||||
@make -C $(TOPDIR)/config clean all install
|
||||
|
||||
configure: |
||||
@echo forcing a rebuild of conf.h and conf.c
|
||||
@make newversion
|
||||
@(cd $(TOPDIR)/config; make install)
|
||||
|
||||
clean: |
||||
@echo removing .o files
|
||||
@rm -f ${LD_LIST}
|
||||
@echo removing configuration files ...
|
||||
@rm -f $(CONFH) $(CONFC)
|
||||
@(cd $(TOPDIR)/config; make clean)
|
||||
@echo removing xinu ...
|
||||
@rm -f $(XINU)
|
||||
@rm -f $(XINUBIN)
|
||||
@rm -f $(XINUBOOT)
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
# Locations of source directories and exceptions (.c and .[sS] files to exclude)
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
$(DEFSFILE): |
||||
@rm -f $(DEFSFILE)
|
||||
@echo "" > $(DEFSFILE)
|
||||
@make rebuild
|
||||
|
||||
$(DEPSFILE): |
||||
@rm -f $(DEPSFILE)
|
||||
@echo "" > $(DEPSFILE)
|
||||
@make depend
|
||||
|
||||
rebuild: $(CONFC) |
||||
@echo Rebuilding the $(DEFSFILE) file
|
||||
@$(BUILDMAKE) $(REBUILDFLAGS) > $(DEFSFILE)
|
||||
|
||||
defclean: |
||||
rm -f $(DEFSFILE)
|
||||
echo "" > $(DEFSFILE)
|
||||
|
||||
depend: $(DEFSFILE) |
||||
@echo;echo Making all dependencies in $(DEPSFILE)
|
||||
@$(MAKEDEP) ${INCLUDE} ${SRC_FULL} > $(DEPSFILE)
|
||||
@echo;echo Finished making dependencies
|
||||
|
||||
depclean: |
||||
rm -f $(DEPSFILE)
|
||||
echo "" > $(DEPSFILE)
|
||||
|
||||
-include $(DEPSFILE) |
||||
@ -0,0 +1,710 @@
|
||||
#!/bin/sh |
||||
######################################################################### |
||||
# # |
||||
# build-make - build entries for a makefile # |
||||
# # |
||||
# use: build-make dir_spec... # |
||||
# # |
||||
# where each dir_spec, which specifies one of the source # |
||||
# directories to include has the form: # |
||||
# # |
||||
# -s source_dir_path [pattern...] # |
||||
# # |
||||
# Build-make generates rules for a Makefile that will compile # |
||||
# the source files from the specified set of source directories. # |
||||
# Build-make is run in the directory that will hold the Makefile, # |
||||
# and assumes .o files will be placed in the ./binaries # |
||||
# directory in the same file as the Makefile. # |
||||
# # |
||||
# # |
||||
# A directory specification begins with a -s srgument that is # |
||||
# followed by a source directory name (a relative path is # |
||||
# recommended, but not required), and a list of zero or more # |
||||
# patterns. The patterns are used to specify which files # |
||||
# from source directory should be omitted from consideration. # |
||||
# Build-make starts by making a list of all C and assembly # |
||||
# language files in the directory (i.e. files that match *.c and # |
||||
# *.[Ss]). It then uses the set of patterns (if any are present) # |
||||
# to decide which of the files to exclude from further # |
||||
# processing. A pattern can contain literal characters plus one # |
||||
# asterisk, which indicates a wild card match. For example, # |
||||
# 'xxx', 'xxx*', '*xxx', 'xxx*yyy' are legal forms of patterns. # |
||||
# Note: any pattern argument that contains an asterisk must be # |
||||
# enclosed in quotes on the command line to prevent the shell # |
||||
# from interpreting it. For example, to omit files that start # |
||||
# with 'debug', one would specify: 'debug*' in quotes. Omitting # |
||||
# files has two purposes. First, it allows files to be left in # |
||||
# the soruce directory that are not normally needed (e.g., # |
||||
# debug.c). Second, a programmer can specify a set of files # |
||||
# for which standard compilation rules are insufficient. Of # |
||||
# course, if a programmer omits a file, the programmer must # |
||||
# insert a compilation rule into the Makefile. # |
||||
# # |
||||
# Build-make does not create a complete Makefile. Instead, # |
||||
# build-make writes text output to stdout and allows the # |
||||
# programmer to use the output to construct a Makefile. # |
||||
# Typically, a programmer runs: # |
||||
# # |
||||
# build-make > Makedefs # |
||||
# # |
||||
# and then inserts the line # |
||||
# # |
||||
# include Makedefs # |
||||
# # |
||||
# into a Makefile. Doing so allows the Makedefs to be recreated # |
||||
# easily if the contents of the source directories change. # |
||||
# # |
||||
# Build-make generates two variables: SOURCE_FILES that contains # |
||||
# a list of all source file names, and OBJECT_FILES that lists # |
||||
# all the object files. it also generates a list of rules # |
||||
# for generating object files. For example, a rule might # |
||||
# be: # |
||||
# # |
||||
# binaries/aaa.o: ../../system/aaa.c # |
||||
# $(CC) $(CFLAGS) -o binaries/aaa.o ../../system/aaa.c # |
||||
# # |
||||
######################################################################### |
||||
|
||||
MSG1='use is: build-make dir_spec...' |
||||
MSG2=' where dir_spec is -s source_dir_path [pattern...]' |
||||
|
||||
# |
||||
# Define prefixes shared by this script and the awk program |
||||
# |
||||
PRE_ERR='+ERROR:' |
||||
PRE_DIR='+DIR:' |
||||
PRE_OMIT='+OMIT:' |
||||
PRE_CFILE='+CFILE:' |
||||
PRE_SFILE='+SFILE:' |
||||
|
||||
export PRE_ERR PRE_DIR PRE_OMIT PRE_CFILE PRE_SFILE |
||||
|
||||
TMP1=".,BUILDM1-$$" |
||||
TMP2=".,BUILDM2-$$" |
||||
trap "rm -f $TMP1 $TMP2; exit" 1 2 3 |
||||
|
||||
# |
||||
# Parse arguments and generate input to the script below |
||||
# |
||||
|
||||
if test $# -lt 2; then |
||||
echo "$MSG1" >&2 |
||||
echo "$MSG2" >&2 |
||||
exit 1 |
||||
fi |
||||
|
||||
# iterate through dirspecs |
||||
|
||||
( |
||||
> $TMP1 |
||||
> $TMP2 |
||||
|
||||
while test $# -gt 0; do |
||||
|
||||
# parse -s and get directory name |
||||
|
||||
if test $# -lt 2; then |
||||
echo "$PRE_ERR" |
||||
echo "$MSG1" >&2 |
||||
echo "$MSG2" >&2 |
||||
exit 1 |
||||
fi |
||||
|
||||
case "x$1" in |
||||
x-s) DIR="$2" |
||||
# verify that directory exists |
||||
if test -d $DIR; then |
||||
echo "$PRE_DIR$DIR" |
||||
else |
||||
echo "$PRE_ERR" |
||||
echo "cannot find a source directory named $DIR" >&2 |
||||
exit 1 |
||||
fi |
||||
shift; shift |
||||
;; |
||||
*) echo 'expecting -s at start of directory specification' >&2 |
||||
echo "$PRE_ERR" |
||||
echo "$MSG1" >&2 |
||||
echo "$MSG2" >&2 |
||||
;; |
||||
esac |
||||
|
||||
# |
||||
# See if DIR contains any .c or .[sS] files |
||||
# |
||||
if test "x$DIR" = "x."; then |
||||
CFILES=`ls *.c 2>$TMP1` |
||||
SFILES=`ls *.[sS] 2>$TMP2` |
||||
else |
||||
CFILES=`ls $DIR/*.c 2>$TMP1` |
||||
SFILES=`ls $DIR/*.[sS] 2>$TMP2` |
||||
fi |
||||
|
||||
if test -s $TMP1 -a -s $TMP2; then |
||||
(echo;echo "Warning: directory $DIR does not contain any .c or .[sS] files to compile";echo) >&2 |
||||
fi |
||||
rm -f $TMP1 $TMP2 |
||||
|
||||
# arguments up to the next -s as patterns that specify omitted files |
||||
|
||||
LOOKING=true |
||||
while $LOOKING; do |
||||
if test $# -eq 0; then |
||||
LOOKING=false |
||||
elif test "x$1" = "x-s"; then |
||||
LOOKING=false |
||||
else |
||||
echo "$PRE_OMIT$1" |
||||
shift |
||||
fi |
||||
done |
||||
|
||||
# output .s and .S files for this directory |
||||
|
||||
if test "x$SFILES" != "x"; then |
||||
for i in $SFILES; do |
||||
echo "$PRE_SFILE$i" |
||||
done |
||||
fi |
||||
|
||||
# output .c files for this directory |
||||
|
||||
if test "x$CFILES" != "x"; then |
||||
for i in $CFILES; do |
||||
echo "$PRE_CFILE$i" |
||||
done |
||||
fi |
||||
|
||||
done |
||||
) | |
||||
|
||||
gawk ' |
||||
|
||||
######################################################################### |
||||
# # |
||||
# # |
||||
# Start of awk script # |
||||
# # |
||||
# # |
||||
######################################################################### |
||||
|
||||
#################### |
||||
# |
||||
# function ftmlist - format a list of file names |
||||
# |
||||
# args are: number of names, array of names, maximum name length, |
||||
# directory name, prefix to use |
||||
# |
||||
#################### |
||||
|
||||
function fmtlist(n,items,maxl,dname, pfix) { |
||||
|
||||
if (n <= 0) { |
||||
return; |
||||
} |
||||
|
||||
if (doneheading == 0) { |
||||
printf("\n\n%s\n%s\n%sDirectory %s\n%s\n%s\n",hdr4, hdr5, hdr6, dname, hdr5, hdr4); |
||||
doneheading = 1; |
||||
} |
||||
fmt2 = sprintf("\n%%-%ds\\\n",maxwid-1); |
||||
printf(fmt2, pfix " ="); |
||||
|
||||
namwid = maxl + 2; |
||||
# |
||||
# compute number of names per line allowing 2 blanks between them |
||||
# and not taking more than actwid characters |
||||
# |
||||
nperline = int( (actwid+2)/(maxl+2) ); |
||||
extrabl = actwid-(nperline*maxl + 2*(nperline-1))+1; |
||||
cnt = 1; |
||||
fmt = sprintf("%%-%ds",maxl); |
||||
for (i=1; i<=n ; i++) { |
||||
if (cnt > nperline) { |
||||
for (b=1; b<=extrabl; b++) { |
||||
printf(" "); |
||||
} |
||||
printf("\\\n"); |
||||
cnt = 1; |
||||
} |
||||
if (cnt == 1) { |
||||
printf("%s", tb); |
||||
} else { |
||||
printf(" "); |
||||
} |
||||
printf(fmt, items[i]); |
||||
cnt++; |
||||
} |
||||
printf("\n"); |
||||
return; |
||||
} |
||||
|
||||
#################### |
||||
# |
||||
# function isomitted - check a file name against the list of omitted patters |
||||
# for the current directory and report 1 if the file |
||||
# name is omitted |
||||
# |
||||
# arg: file name to check |
||||
# |
||||
# globals used: nomits, omits[] list of omitted patterns (1 through nomits) |
||||
# |
||||
#################### |
||||
|
||||
function isomitted(io_fname) { |
||||
|
||||
io_flen = length(io_fname); |
||||
|
||||
# |
||||
# Iterate through all omit patterns for the current directory |
||||
# |
||||
|
||||
for (io_j=1; io_j <= nomits; io_j++) { |
||||
|
||||
# Get pattern to check |
||||
io_omit = omits[io_j]; |
||||
|
||||
# length of omit pattern |
||||
io_olen = length(io_omit); |
||||
|
||||
# Find where "*" occurs in the pattern and set prefix length |
||||
|
||||
io_plen = index(io_omit, "*") - 1; |
||||
|
||||
if (io_plen < 0) { # No * in the pattern, so check exact match |
||||
|
||||
if (io_fname == io_omit) { |
||||
return 1; |
||||
} else { |
||||
continue; |
||||
} |
||||
|
||||
} |
||||
|
||||
# At least one * occurs in the pattern |
||||
|
||||
if (io_olen == 1) { # Pattern is just a *, so omit everything |
||||
return 1; |
||||
} |
||||
|
||||
if (io_plen > 1) { # if fixed prefix exists, check for match |
||||
|
||||
# A file name shorter than the prefix is not omitted |
||||
|
||||
if (io_flen < io_plen) { |
||||
continue; |
||||
} |
||||
|
||||
# If prefix does not match, name is not omitted |
||||
|
||||
if ( substr(io_omit, 1, io_plen) != substr(io_fname, 1, io_plen) ) { |
||||
continue; |
||||
} |
||||
} |
||||
|
||||
# Prefix has matched; check suffix |
||||
|
||||
io_slen = io_olen - io_plen -1; |
||||
|
||||
if (io_slen <= 0) { # If no suffix, pattern matches |
||||
return 1; |
||||
} |
||||
|
||||
# A file name shorter than the suffix is not omitted |
||||
|
||||
if (io_flen < io_slen) { |
||||
continue; |
||||
} |
||||
|
||||
# If suffix in omit pattern exactly matches the suffix of the |
||||
# file name, this file name is omitted |
||||
|
||||
if ( substr(io_omit, io_olen - (io_slen - 1)) == \ |
||||
substr(io_fname, length(io_fname) - (io_slen - 1)) ) { |
||||
return 1; |
||||
} |
||||
|
||||
} |
||||
|
||||
# The file name does not match any omitted pattern, so keep it |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
#################### |
||||
# |
||||
# getbasename - extract the basename from a path name and return it |
||||
# |
||||
# arg: path name |
||||
# |
||||
#################### |
||||
|
||||
function getbasename(gb_path) { |
||||
|
||||
for (gb_pos = length(gb_path); gb_pos > 0; gb_pos--) { |
||||
if (substr(gb_path, gb_pos, 1) == "/") { |
||||
break; |
||||
} |
||||
} |
||||
if (gb_pos > 0) { |
||||
return substr(gb_path, gb_pos+1); |
||||
} else { |
||||
return gb_path; |
||||
} |
||||
} |
||||
|
||||
|
||||
#################### |
||||
# |
||||
# Initialize variables for the awk script |
||||
# |
||||
#################### |
||||
|
||||
BEGIN { |
||||
ndirs = 0; # Number of directories found so far |
||||
maxwid = 81; # Maximum width of formatted line |
||||
actwid = maxwid - 10; # Actual width for names (line width minus 8 for tab indent and |
||||
# 2 for " \" at the end of the line) |
||||
|
||||
tb = " "; # Tab character |
||||
plen_err = length("'$PRE_ERR'"); |
||||
plen_dir = length("'$PRE_DIR'"); |
||||
plen_omt = length("'$PRE_OMIT'"); |
||||
plen_cfl = length("'$PRE_CFILE'"); |
||||
plen_sfl = length("'$PRE_SFILE'"); |
||||
|
||||
|
||||
hdr1 = "#-------------------------------------------------------------------------------#"; |
||||
hdr2 = "# #"; |
||||
hdr3 = "# Definitions generated by build-make on '"`date`"' #"; |
||||
hdr4 = "#------------------------------------------------------------------"; |
||||
hdr5 = "#"; |
||||
hdr6 = "# "; |
||||
hdr7 = "# Rules For Generating Object Files #"; |
||||
hdr8 = "# Rules for files in directory "; |
||||
|
||||
msg1 = "SRC_CFILES ="; |
||||
msg2 = "SRC_SFILES ="; |
||||
msg3 = "OBJ_FILES ="; |
||||
} |
||||
|
||||
# |
||||
# Skip blank lines in input |
||||
# |
||||
/^ *$/ { |
||||
next; |
||||
} |
||||
|
||||
# |
||||
# Handle errors |
||||
# |
||||
/^\'${PRE_ERR}'/ { |
||||
exit(1); |
||||
} |
||||
|
||||
# |
||||
# Start a new directory |
||||
# |
||||
|
||||
/^\'$PRE_DIR'/ { |
||||
|
||||
ndirs++; |
||||
dirs[ndirs] = substr($0,plen_dir+1); |
||||
|
||||
# Initialize counts for this directory |
||||
|
||||
ncfiles[ndirs] = 0; |
||||
nsfiles[ndirs] = 0; |
||||
nomits = 0; |
||||
next; |
||||
} |
||||
|
||||
# |
||||
# Collect list of omitted files for this directory (must occur in the input before |
||||
# any C or S files for the directory) |
||||
# |
||||
|
||||
/^\'$PRE_OMIT'/ { |
||||
|
||||
nomits++; |
||||
omits[nomits] = substr($0,plen_omt+1); |
||||
next; |
||||
} |
||||
|
||||
# |
||||
# Handle a C file from the current directory |
||||
# |
||||
|
||||
/^\'$PRE_CFILE'/ { |
||||
|
||||
fullname = substr($0,plen_cfl+1); |
||||
basename = getbasename(fullname); |
||||
|
||||
# Skip omitted files |
||||
|
||||
if (isomitted(basename) > 0) { |
||||
next; |
||||
} |
||||
|
||||
ncfiles[ndirs]++; |
||||
cpath[ndirs "%" ncfiles[ndirs]] = fullname; |
||||
cfile[ndirs "%" ncfiles[ndirs]] = basename; |
||||
|
||||
next; |
||||
} |
||||
|
||||
# |
||||
# Handle as S file from the current directory |
||||
# |
||||
|
||||
/^\'$PRE_SFILE'/ { |
||||
|
||||
fullname = substr($0,plen_sfl+1); |
||||
basename = getbasename(fullname); |
||||
|
||||
# Skip omitted files |
||||
|
||||
if (isomitted(basename) > 0) { |
||||
next; |
||||
} |
||||
|
||||
nsfiles[ndirs]++; |
||||
spath[ndirs "%" nsfiles[ndirs]] = fullname; |
||||
sfile[ndirs "%" nsfiles[ndirs]] = basename; |
||||
|
||||
next; |
||||
} |
||||
|
||||
|
||||
# |
||||
# Any other input line is unexpected |
||||
# |
||||
|
||||
{ |
||||
print "Error: unexpected input line ->", $0; |
||||
exit 1; |
||||
} |
||||
|
||||
END { |
||||
################################################################# |
||||
# # |
||||
# Do all the work of formatting and printing the makefile # |
||||
# rules. Start by printing an initial comment block and the # |
||||
# variable initializtion statements. # |
||||
# # |
||||
################################################################# |
||||
|
||||
printf("%s\n%s\n%s\n%s\n%s\n\n",hdr1, hdr2, hdr3, hdr2, hdr1); |
||||
printf("%s\n%s\n\n",msg1, msg2, msg3); |
||||
|
||||
totlen = 0; # max over valid source file names in all directories |
||||
|
||||
################################################################# |
||||
# # |
||||
# Iterate over all directories and generate a unique prefix # |
||||
# to be used on make variables for each directory # |
||||
# # |
||||
################################################################# |
||||
|
||||
totlen = 0; # max file name length across all directories |
||||
|
||||
for (d=1; d<=ndirs; d++) { |
||||
|
||||
# Generate a unique variable name prefix for this directory |
||||
|
||||
dirpath = dirs[d]; |
||||
strt = 1; |
||||
str = toupper(dirpath); |
||||
finish = length(str); |
||||
ch = substr(str,strt,1); |
||||
while ( (ch == ".") || (ch == "/") ) { |
||||
strt++; |
||||
if (strt > finish) { |
||||
break; |
||||
} |
||||
ch = substr(str,strt,1); |
||||
} |
||||
if (strt > finish) { |
||||
if (substr(str,1,1) == ".") { |
||||
prefix = "DOT"; |
||||
} else { |
||||
prefix = "SLASH"; |
||||
} |
||||
for (i=2; i<=finish; i++) { |
||||
if (substr(str,i,1) == ".") { |
||||
prefix = prefix "_DOT"; |
||||
} else { |
||||
prefix = prefix "_SLASH"; |
||||
} |
||||
} |
||||
} else { |
||||
prefix = ""; |
||||
for (i=strt; i<=finish; i++) { |
||||
ch = substr(str,i,1); |
||||
if (ch == "/") { |
||||
prefix = prefix "_"; |
||||
} else { |
||||
prefix = prefix ch; |
||||
} |
||||
} |
||||
} |
||||
pref[d] = prefix; |
||||
|
||||
doneheading = 0; |
||||
|
||||
# |
||||
# Compute the maximum length of a file name in this directory |
||||
# and update the max length across all directories |
||||
# |
||||
|
||||
maxlen = 0; # max file name length for this directory |
||||
|
||||
# Check S files first |
||||
|
||||
for (i = 1; i <= nsfiles[d]; i++) { |
||||
srcsfiles[i] = sfile[d "%" i] |
||||
l = length(srcsfiles[i]); |
||||
if (l > maxlen) { |
||||
maxlen = l; |
||||
} |
||||
} |
||||
if (maxlen > totlen) { # update global max across all directories |
||||
totlen = maxlen; |
||||
} |
||||
|
||||
# Check C files |
||||
|
||||
for (i = 1; i <= ncfiles[d]; i++) { |
||||
srccfiles[i] = cfile[d "%" i] |
||||
l = length(srccfiles[i]); |
||||
if (l > maxlen) { |
||||
maxlen = l; |
||||
} |
||||
} |
||||
if (maxlen > totlen) { # update global max across all directories |
||||
totlen = maxlen; |
||||
} |
||||
|
||||
# Format the list of S files for this directory |
||||
|
||||
fmtlist(nsfiles[d], srcsfiles, maxlen, dirs[d], pref[d] "_SFILES"); |
||||
|
||||
# Format the list of C files for this directory |
||||
|
||||
fmtlist(ncfiles[d], srccfiles, maxlen, dirs[d], pref[d] "_CFILES"); |
||||
|
||||
printf("\n"); |
||||
|
||||
# |
||||
# Generate assignments for Makefile variables |
||||
# |
||||
|
||||
nasn = 0; |
||||
|
||||
# |
||||
# Generate assignments for variables SRC_CFILES and SRC_SFILES |
||||
# |
||||
if (ncfiles[d] > 0) { |
||||
nasn++; |
||||
asnl[nasn] = "SRC_CFILES"; |
||||
asnr[nasn] = sprintf("+= ${%s_CFILES}", pref[d]); |
||||
} |
||||
if (nsfiles[d] > 0) { |
||||
nasn++; |
||||
asnl[nasn] = "SRC_SFILES"; |
||||
asnr[nasn] = sprintf("+= ${%s_SFILES}", pref[d]); |
||||
} |
||||
|
||||
# |
||||
# Generate assignments for variables prefix_CFULL and prefix_SFULL |
||||
# |
||||
|
||||
if (ncfiles[d] > 0) { |
||||
nasn++; |
||||
asnl[nasn] = sprintf("%s_CFULL", prefix); |
||||
asnr[nasn] = sprintf("+= ${%s_CFILES:%%=%s/%%}", pref[d], dirs[d]); |
||||
} |
||||
if (nsfiles[d] > 0) { |
||||
nasn++; |
||||
asnl[nasn] = sprintf("%s_SFULL", prefix); |
||||
asnr[nasn] = sprintf("+= ${%s_SFILES:%%=%s/%%}", pref[d], dirs[d]); |
||||
} |
||||
|
||||
# |
||||
# Generate assignments for variables SRC_CFULL and SRC_SFULL |
||||
# |
||||
|
||||
if (ncfiles[d] > 0) { |
||||
nasn++; |
||||
asnl[nasn] = "SRC_CFULL"; |
||||
asnr[nasn] = sprintf("+= ${%s_CFULL}", pref[d]); |
||||
} |
||||
if (nsfiles[d] > 0) { |
||||
nasn++; |
||||
asnl[nasn] = "SRC_SFULL"; |
||||
asnr[nasn] = sprintf("+= ${%s_SFULL}", pref[d]); |
||||
} |
||||
wid = 0; |
||||
for (i=1; i<=nasn; i++) { |
||||
n = length(asnl[i]); |
||||
if (n > wid) { |
||||
wid = n; |
||||
} |
||||
} |
||||
fmt3 = sprintf("%%-%ds %%s\n", wid); |
||||
for (i=1; i<=nasn; i++) { |
||||
printf(fmt3, asnl[i], asnr[i]); |
||||
} |
||||
} |
||||
|
||||
printf("\n\n%s\n%s\n%s\n%s\n%s\n\n", hdr1, hdr2, hdr7, hdr2, hdr1); |
||||
|
||||
printf("OBJ_TMP = ${patsubst %%.s,%%.o,$(SRC_SFILES)} # substitute .s => .o\n"); |
||||
printf("OBJ_SFILES = ${patsubst %%.S,%%.o,$(OBJ_TMP)} # substitute .S => .o\n"); |
||||
printf("OBJ_CFILES = ${patsubst %%.c,%%.o,$(SRC_CFILES)} # substitute .c => .o\n"); |
||||
printf("OBJ_LIST = ${OBJ_CFILES} ${OBJ_SFILES}\n"); |
||||
printf("OBJ_FILES = ${OBJ_LIST:%%=binaries/%%}\n"); |
||||
printf("SRC_FULL = ${SRC_CFULL} ${SRC_SFULL}\n"); |
||||
|
||||
fmt4c = sprintf("%%-%ds%%s\n\t${CC} ${CFLAGS} -o %%s %%s\n",9+totlen+3); |
||||
fmt4s = sprintf("%%-%ds%%s\n\t${CC} ${CFLAGS} -o %%s %%s\n",9+totlen+3); |
||||
for (d=1; d<=ndirs; d++) { |
||||
needheadings = 1; |
||||
|
||||
# print dependencies for .s files |
||||
|
||||
for (i = 1; i <= nsfiles[d]; i++) { |
||||
if (needheadings > 0) { |
||||
printf("\n%s\n%s%s\n%s\n\n", hdr4, hdr8, dirs[d], hdr4); |
||||
needheadings = 0; |
||||
} |
||||
fname = sfile[d "%" i]; |
||||
tmpobj = "binaries/" substr(fname, 1, length(fname)-2) ".o"; |
||||
tmpsrc = dirs[d] "/" fname; |
||||
printf(fmt4s, tmpobj ":", tmpsrc, tmpobj, tmpsrc); |
||||
} |
||||
|
||||
# print dependencies for .c files |
||||
|
||||
for (i = 1; i <= ncfiles[d]; i++) { |
||||
if (needheadings > 0) { |
||||
printf("\n%s\n%s%s\n%s\n\n", hdr4, hdr8, dirs[d], hdr4); |
||||
needheadings = 0; |
||||
} |
||||
fname = cfile[d "%" i]; |
||||
tmpobj = "binaries/" substr(fname, 1, length(fname)-2) ".o"; |
||||
tmpsrc = dirs[d] "/" fname; |
||||
printf(fmt4c, tmpobj ":", tmpsrc, tmpobj, tmpsrc); |
||||
} |
||||
|
||||
} |
||||
printf("\nobjs: ${OBJ_FILES}\n"); |
||||
|
||||
printf("\nlist_obj:\n\t@echo ${OBJ_FILES}\n"); |
||||
|
||||
printf("\nlist_csrc:\n\t@echo ${SRC_CFILES}\n"); |
||||
|
||||
printf("\nlist_ssrc:\n\t@echo ${SRC_SFILES}\n"); |
||||
|
||||
printf("\n# Export variables for recursive make calls (such as the library)\n\nexport\n\n"); |
||||
} ' |
||||
@ -0,0 +1,27 @@
|
||||
#!/bin/sh |
||||
# |
||||
# Generate a new version string to be printed at startup |
||||
# |
||||
# Use is: mkvers platform_name |
||||
|
||||
VERS_NUM_FILE=.vers_num |
||||
|
||||
case $# in |
||||
1) PLAT="$1" |
||||
;; |
||||
*) echo 'use is: mkvers platform_name' >&2 |
||||
exit 1 |
||||
;; |
||||
esac |
||||
|
||||
if test -s $VERS_NUM_FILE; then |
||||
OLD_VERS=`cat $VERS_NUM_FILE` |
||||
VERS=`expr $OLD_VERS + 1` |
||||
else |
||||
VERS=1 |
||||
fi |
||||
echo $VERS > $VERS_NUM_FILE |
||||
if test "x$USER" = "x"; then |
||||
USER=`who am i | sed 's/ .*//'` |
||||
fi |
||||
echo "Xinu for $PLAT -- version #$VERS ($USER) `date`" |
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,189 @@
|
||||
#########################################################################
|
||||
# #
|
||||
# #
|
||||
# Makefile for STM32 version of the Xinu operating system #
|
||||
# #
|
||||
# includes: .deps and .defs #
|
||||
# #
|
||||
# #
|
||||
#########################################################################
|
||||
|
||||
COMPILER_ROOT = avr-
|
||||
PNAME = ATMEGA328P
|
||||
PLAT = Platform_$(PNAME)
|
||||
TOPDIR = ..
|
||||
|
||||
CC = ${COMPILER_ROOT}gcc
|
||||
LD = ${COMPILER_ROOT}gcc
|
||||
OBJCOPY = ${COMPILER_ROOT}objcopy
|
||||
OBJDUMP = ${COMPILER_ROOT}objdump
|
||||
QEMU = /home/lechnerm/rafa/xinu/qemu_stm32/arm-softmmu/qemu-system-arm
|
||||
XINU = $(TOPDIR)/compile/xinu.elf
|
||||
XINUBIN = $(TOPDIR)/compile/xinu.bin
|
||||
XINUBOOT = $(TOPDIR)/compile/xinu
|
||||
BUILDMAKE = $(TOPDIR)/compile/bin/build-make
|
||||
MKVERS = $(TOPDIR)/compile/bin/mkvers
|
||||
|
||||
MAKEDEP = $(CC) -M -MG
|
||||
|
||||
DEPSFILE = .deps
|
||||
DEFSFILE = .defs
|
||||
VERSIONFILE = version
|
||||
# RAFA LDSCRIPT = ld.script
|
||||
MKVERS = $(TOPDIR)/compile/bin/mkvers
|
||||
REBUILDFLAGS = -s $(TOPDIR)/system debug.c \
|
||||
-s $(TOPDIR)/lib \
|
||||
-s $(TOPDIR)/device/tty \
|
||||
-s $(TOPDIR)/device/nam \
|
||||
# RAFA -s $(TOPDIR)/device/ram \
|
||||
-s $(TOPDIR)/device/gpio \
|
||||
-s $(TOPDIR)/device/spi \
|
||||
#
|
||||
-s $(TOPDIR)/shell 'xsh_rdstest*'
|
||||
|
||||
INCLUDE = -I$(TOPDIR)/include
|
||||
DEFS = -DBSDURG -DVERSION=\""`cat $(VERSIONFILE)`"\"
|
||||
|
||||
# Compiler flags
|
||||
# CFLAGS = -mcpu=cortex-m3 -mno-unaligned-access -mthumb -fno-builtin -fno-stack-protector -nostdlib -c -Wall -O ${DEFS} ${INCLUDE}
|
||||
CFLAGS = -DF_CPU=16000000UL -mmcu=atmega328p -mrelax -fno-builtin -fno-stack-protector -nostdlib -c -Wall -Os ${DEFS} ${INCLUDE}
|
||||
SFLAGS = ${INCLUDE}
|
||||
|
||||
# Loader flags
|
||||
|
||||
# RAFA LDFLAGS = -dn -m armelf -Map xinu.map -T ld.script
|
||||
LDFLAGS = -Wl,--wrap,malloc,--wrap,free,--wrap,realloc,--wrap,fdevopen
|
||||
|
||||
all: xinu |
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
# Handle generation of a new version string when initialize is recompiled
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
newversion: |
||||
@echo creating new version
|
||||
@$(MKVERS) $(PNAME) > version
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
# Include generic make targets and rules from the file generated by build-make
|
||||
#--------------------------------------------------------------------------------
|
||||
-include $(DEFSFILE) |
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
# Add files that require special rules and place start.o at the front
|
||||
#--------------------------------------------------------------------------------
|
||||
# RAFA quitamos el start.S y start.o porque intentaremos el startup de avr
|
||||
# RAFA LD_LIST = binaries/start.o $(filter-out binaries/start.o,$(OBJ_FILES))
|
||||
LD_LIST = $(filter-out binaries/start.o,$(OBJ_FILES))
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Rules for files that need special handling
|
||||
#------------------------------------------------------------
|
||||
|
||||
# Define variables for the Configuration file and generated files
|
||||
|
||||
CONFFILE = $(TOPDIR)/config/Configuration
|
||||
CONFH = $(TOPDIR)/include/conf.h
|
||||
CONFC = $(TOPDIR)/system/conf.c
|
||||
|
||||
# Define variables for the config program and its sources
|
||||
|
||||
CONFPGM = $(TOPDIR)/config/config
|
||||
CONFL = $(TOPDIR)/config/config.l
|
||||
CONFY = $(TOPDIR)/config/config.y
|
||||
|
||||
# Set up the required build directory structure
|
||||
|
||||
BLDDIRS = binaries
|
||||
export
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
# Specific additional rules and exceptions
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
xinu: Makefile rebuild $(BLDDIRS) $(DEFSFILE) $(DEPSFILE) $(CONFH) $(CONFC) $(LD_LIST) |
||||
@echo;echo 'Loading object files to produce xinu'
|
||||
# RAFA original : @$(LD) $(LDFLAGS) $(LD_LIST) -o $(XINU) -L/usr/lib/gcc/arm-none-eabi/6.3.1/ --print-memory-usage
|
||||
@$(LD) $(LDFLAGS) -T ld.script $(LD_LIST) -o $(XINU)
|
||||
@echo "Creating Binary..."
|
||||
@$(OBJCOPY) -O binary $(XINU) $(XINUBIN)
|
||||
|
||||
examine-all: |
||||
$(OBJDUMP) -D $(XINU) | less
|
||||
|
||||
examine-header: |
||||
$(OBJDUMP) -x $(XINU) | less
|
||||
|
||||
flash: |
||||
stm32flash -w $(XINUBIN) -v /dev/ttyUSB0
|
||||
|
||||
qemu: |
||||
$(QEMU) -serial stdio -M stm32-f103c8 -kernel $(XINUBIN)
|
||||
monitor: |
||||
$(QEMU) -monitor stdio -serial stdio -M stm32-f103c8 -kernel $(XINUBIN)
|
||||
|
||||
$(BLDDIRS): |
||||
@mkdir -p $(BLDDIRS)
|
||||
|
||||
objects: $(LD_LIST) |
||||
|
||||
$(CONFH): $(CONFFILE) $(CONFPGM) |
||||
@echo making $(CONFH)
|
||||
@make configure
|
||||
|
||||
$(CONFC): $(CONFFILE) $(CONFPGM) |
||||
@echo making $(CONFC)
|
||||
@make configure
|
||||
|
||||
$(CONFPGM): $(CONFL) $(CONFY) |
||||
@echo making the config program
|
||||
@make -C $(TOPDIR)/config clean all install
|
||||
|
||||
configure: |
||||
@echo forcing a rebuild of conf.h and conf.c
|
||||
@make newversion
|
||||
@(cd $(TOPDIR)/config; make install)
|
||||
|
||||
clean: |
||||
@echo removing .o files
|
||||
@rm -f ${LD_LIST}
|
||||
@echo removing configuration files ...
|
||||
@rm -f $(CONFH) $(CONFC)
|
||||
@(cd $(TOPDIR)/config; make clean)
|
||||
@echo removing xinu ...
|
||||
@rm -f $(XINU)
|
||||
@rm -f $(XINUBIN)
|
||||
@rm -f $(XINUBOOT)
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
# Locations of source directories and exceptions (.c and .[sS] files to exclude)
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
$(DEFSFILE): |
||||
@rm -f $(DEFSFILE)
|
||||
@echo "" > $(DEFSFILE)
|
||||
@make rebuild
|
||||
|
||||
$(DEPSFILE): |
||||
@rm -f $(DEPSFILE)
|
||||
@echo "" > $(DEPSFILE)
|
||||
@make depend
|
||||
|
||||
rebuild: $(CONFC) |
||||
@echo Rebuilding the $(DEFSFILE) file
|
||||
@$(BUILDMAKE) $(REBUILDFLAGS) > $(DEFSFILE)
|
||||
|
||||
defclean: |
||||
rm -f $(DEFSFILE)
|
||||
echo "" > $(DEFSFILE)
|
||||
|
||||
depend: $(DEFSFILE) |
||||
@echo;echo Making all dependencies in $(DEPSFILE)
|
||||
@$(MAKEDEP) ${INCLUDE} ${SRC_FULL} > $(DEPSFILE)
|
||||
@echo;echo Finished making dependencies
|
||||
|
||||
depclean: |
||||
rm -f $(DEPSFILE)
|
||||
echo "" > $(DEPSFILE)
|
||||
|
||||
-include $(DEPSFILE) |
||||
@ -0,0 +1 @@
|
||||
~/rafa/stm32flash/stm32flash -w xinu.bin -S 0x8000000 -v -g 0x8000000 -b 115200 /dev/ttyUSB0 |
||||
@ -0,0 +1,135 @@
|
||||
/* Linker script for ATMEL(R) AVR(R) ATmega328P. */ |
||||
|
||||
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") |
||||
OUTPUT_ARCH(avr:5) |
||||
|
||||
/* The beginning and end of the program ROM area. */ |
||||
/* Leave 4 bytes for the 32-bit checksum plus 0x10 extra bytes free. */ |
||||
_rom_begin = 0x00000000; |
||||
_rom_end = 0x00007FEC; |
||||
|
||||
/* The beginning and end (i.e., top) of the stack */ |
||||
/* Set up a stack with a size of (1/2)K */ |
||||
_stack_begin = 0x800500; |
||||
_stack_end = 0x8008FF; /* RAFA, en atmega328 el fin de la RAM */ |
||||
|
||||
/* The end of the 2K RAM stack */ |
||||
__initial_stack_pointer = 0x8008FF; |
||||
|
||||
MEMORY |
||||
{ |
||||
ROM(rx) : ORIGIN = 0, LENGTH = 32K |
||||
RAM(rw!x) : ORIGIN = 0x800100, LENGTH = 2K |
||||
} |
||||
|
||||
SECTIONS |
||||
{ |
||||
. = 0x0; |
||||
. = ALIGN(2); |
||||
|
||||
.text : |
||||
{ |
||||
/* RAFA _*/ |
||||
text = ABSOLUTE(.); /* text: beginning of text segment */ |
||||
|
||||
*(.vectors) |
||||
KEEP(*(.vectors)) |
||||
|
||||
/*Init sections were here*/ |
||||
/* From this point on, we don't bother about wether the insns are |
||||
below or above the 16 bits boundary. */ |
||||
*(.init0) /* Start here after reset. */ |
||||
__ctors_end = .; |
||||
KEEP (*(.init0)) |
||||
*(.init1) |
||||
KEEP (*(.init1)) |
||||
*(.init2) /* Clear __zero_reg__, set up stack pointer. */ |
||||
KEEP (*(.init2)) |
||||
*(.init3) |
||||
KEEP (*(.init3)) |
||||
*(.init4) /* Initialize data and BSS. */ |
||||
KEEP (*(.init4)) |
||||
*(.init5) |
||||
KEEP (*(.init5)) |
||||
*(.init6) /* C++ constructors. */ |
||||
KEEP (*(.init6)) |
||||
*(.init7) |
||||
KEEP (*(.init7)) |
||||
*(.init8) |
||||
KEEP (*(.init8)) |
||||
*(.init9) /* Call main(). */ |
||||
KEEP (*(.init9)) |
||||
|
||||
*(.def_isr) |
||||
KEEP(*(.def_isr)) |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*(.progmem*) |
||||
. = ALIGN(2); |
||||
*(.text) |
||||
. = ALIGN(2); |
||||
*(.text*) |
||||
. = ALIGN(2); |
||||
etext = ABSOLUTE(.) ; /* etext: end of text */ |
||||
|
||||
|
||||
} > ROM |
||||
|
||||
.text : |
||||
{ |
||||
. = ALIGN(0x10); |
||||
} > ROM = 0xAAAA |
||||
|
||||
.= 0x800100; |
||||
. = ALIGN(2); |
||||
|
||||
/* The ROM-to-RAM initialized data section */ |
||||
.data : |
||||
{ |
||||
data = ABSOLUTE(.); /* data: beginning of data segment */ |
||||
__data = ABSOLUTE(.); /* data: beginning of data segment */ |
||||
|
||||
_data_begin = .; |
||||
*(.data) |
||||
. = ALIGN(2); |
||||
KEEP (*(.data)) |
||||
*(.data*) |
||||
. = ALIGN(2); |
||||
KEEP (*(.data*)) |
||||
*(.rodata) /* Do *NOT* move this! Include .rodata here if gcc is used with -fdata-sections. */ |
||||
. = ALIGN(2); |
||||
KEEP (*(.rodata)) |
||||
*(.rodata*) |
||||
. = ALIGN(2); |
||||
KEEP (*(.rodata*)) |
||||
__data_end = .; |
||||
|
||||
__data_start = .; |
||||
__data_load_start = .; |
||||
__bss_start = .; |
||||
|
||||
} > RAM AT > ROM |
||||
|
||||
/* The uninitialized (zero-cleared) data section */ |
||||
.bss : |
||||
{ |
||||
__bss = ABSOLUTE(.); /* bss: beginning of bss segment */ |
||||
|
||||
*(.bss) |
||||
. = ALIGN(2); |
||||
KEEP (*(.bss)) |
||||
*(.bss*) |
||||
. = ALIGN(2); |
||||
KEEP (*(.bss*)) |
||||
|
||||
__bss_end = ABSOLUTE(.); /* _end: end of image */ |
||||
|
||||
} > RAM |
||||
|
||||
_rom_data_begin = LOADADDR(.data); |
||||
__data_load = LOADADDR(.data); |
||||
} |
||||
@ -0,0 +1,135 @@
|
||||
/* Linker script for ATMEL(R) AVR(R) ATmega328P. */ |
||||
|
||||
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") |
||||
OUTPUT_ARCH(avr:5) |
||||
|
||||
/* The beginning and end of the program ROM area. */ |
||||
/* Leave 4 bytes for the 32-bit checksum plus 0x10 extra bytes free. */ |
||||
_rom_begin = 0x00000000; |
||||
_rom_end = 0x00007FEC; |
||||
|
||||
/* The beginning and end (i.e., top) of the stack */ |
||||
/* Set up a stack with a size of (1/2)K */ |
||||
_stack_begin = 0x800500; |
||||
_stack_end = 0x8008FF; /* RAFA, en atmega328 el fin de la RAM */ |
||||
|
||||
/* The end of the 2K RAM stack */ |
||||
__initial_stack_pointer = 0x8008FF; |
||||
|
||||
MEMORY |
||||
{ |
||||
ROM(rx) : ORIGIN = 0, LENGTH = 32K |
||||
RAM(rw!x) : ORIGIN = 0x800100, LENGTH = 2K |
||||
} |
||||
|
||||
SECTIONS |
||||
{ |
||||
. = 0x0; |
||||
/* RAFA . = ALIGN(2); */ |
||||
|
||||
/* ISR vectors */ |
||||
.isr_vector : |
||||
{ |
||||
*(.isr_vector) |
||||
. = ALIGN(0x10); |
||||
KEEP(*(.isr_vector)) |
||||
} > ROM = 0xAAAA |
||||
|
||||
/* Startup code */ |
||||
.startup : |
||||
{ |
||||
*(.startup) |
||||
. = ALIGN(0x10); |
||||
KEEP(*(.startup)) |
||||
} > ROM = 0xAAAA |
||||
|
||||
/* Program code (text), read-only data and static ctors */ |
||||
.text : |
||||
{ |
||||
/* RAFA _*/ |
||||
text = ABSOLUTE(.); /* text: beginning of text segment */ |
||||
|
||||
__muluhisi3 = .; |
||||
start = .; |
||||
__do_copy_data = .; |
||||
__do_clear_bss = .; |
||||
_/* _data_end = .; */ |
||||
__data_load_start = .; |
||||
__bss_end = .; |
||||
__bss_start = .; |
||||
__data_start = .; |
||||
|
||||
/* FIN DE RAFA */ |
||||
_ctors_begin = .; |
||||
*(.ctors) |
||||
. = ALIGN(2); |
||||
KEEP (*(SORT(.ctors))) |
||||
_ctors_end = .; |
||||
*(.progmem*) |
||||
. = ALIGN(2); |
||||
*(.trampolines*) |
||||
. = ALIGN(2); |
||||
*(.text) |
||||
. = ALIGN(2); |
||||
*(.text*) |
||||
. = ALIGN(2); |
||||
etext = ABSOLUTE(.) ; /* etext: end of text */ |
||||
|
||||
} > ROM |
||||
|
||||
.text : |
||||
{ |
||||
. = ALIGN(0x10); |
||||
} > ROM = 0xAAAA |
||||
|
||||
.= 0x800100; |
||||
. = ALIGN(2); |
||||
|
||||
/* The ROM-to-RAM initialized data section */ |
||||
.data : |
||||
{ |
||||
data = ABSOLUTE(.); /* data: beginning of data segment */ |
||||
|
||||
_data_begin = .; |
||||
*(.data) |
||||
/* rafa . = ALIGN(2); */ |
||||
. = ALIGN(1); |
||||
KEEP (*(.data)) |
||||
*(.data*) |
||||
/* RAafa . = ALIGN(2); todos los demas tambien */ |
||||
. = ALIGN(1); |
||||
KEEP (*(.data*)) |
||||
*(.rodata) /* Do *NOT* move this! Include .rodata here if gcc is used with -fdata-sections. */ |
||||
. = ALIGN(1); |
||||
KEEP (*(.rodata)) |
||||
*(.rodata*) |
||||
. = ALIGN(1); |
||||
KEEP (*(.rodata*)) |
||||
_data_end = .; |
||||
|
||||
edata = ABSOLUTE(.) ; /* edata: end of data */ |
||||
} > RAM AT > ROM |
||||
|
||||
/* The uninitialized (zero-cleared) data section */ |
||||
.bss : |
||||
{ |
||||
bss = ABSOLUTE(.); /* bss: beginning of bss segment */ |
||||
|
||||
_bss_begin = .; |
||||
*(.bss) |
||||
. = ALIGN(1); |
||||
KEEP (*(.bss)) |
||||
*(.bss*) |
||||
. = ALIGN(1); |
||||
KEEP (*(.bss*)) |
||||
_bss_end = .; |
||||
|
||||
ebss = ABSOLUTE(.) ; /* ebss: end of bss */ |
||||
|
||||
end = ABSOLUTE(.); /* end: end of image */ |
||||
_end = ABSOLUTE(.); /* _end: end of image */ |
||||
|
||||
} > RAM |
||||
|
||||
_rom_data_begin = LOADADDR(.data); |
||||
} |
||||
@ -0,0 +1,105 @@
|
||||
/* Linker script for ATMEL(R) AVR(R) ATmega328P. */ |
||||
|
||||
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") |
||||
OUTPUT_ARCH(avr:5) |
||||
|
||||
/* The beginning and end of the program ROM area. */ |
||||
/* Leave 4 bytes for the 32-bit checksum plus 0x10 extra bytes free. */ |
||||
_rom_begin = 0x00000000; |
||||
_rom_end = 0x00007FEC; |
||||
|
||||
/* The beginning and end (i.e., top) of the stack */ |
||||
/* Set up a stack with a size of (1/2)K */ |
||||
_stack_begin = 0x800500; |
||||
_stack_end = 0x800800; |
||||
|
||||
/* The end of the 2K RAM stack */ |
||||
__initial_stack_pointer = 0x800800; |
||||
|
||||
MEMORY |
||||
{ |
||||
ROM(rx) : ORIGIN = 0, LENGTH = 32K - 0x14 |
||||
RAM(rw!x) : ORIGIN = 0x800100, LENGTH = 0x0800 |
||||
} |
||||
|
||||
SECTIONS |
||||
{ |
||||
. = 0x0; |
||||
. = ALIGN(2); |
||||
|
||||
/* ISR vectors */ |
||||
.isr_vector : |
||||
{ |
||||
*(.isr_vector) |
||||
. = ALIGN(0x10); |
||||
KEEP(*(.isr_vector)) |
||||
} > ROM = 0xAAAA |
||||
|
||||
/* Startup code */ |
||||
.startup : |
||||
{ |
||||
*(.startup) |
||||
. = ALIGN(0x10); |
||||
KEEP(*(.startup)) |
||||
} > ROM = 0xAAAA |
||||
|
||||
/* Program code (text), read-only data and static ctors */ |
||||
.text : |
||||
{ |
||||
_ctors_begin = .; |
||||
*(.ctors) |
||||
. = ALIGN(2); |
||||
KEEP (*(SORT(.ctors))) |
||||
_ctors_end = .; |
||||
*(.progmem*) |
||||
. = ALIGN(2); |
||||
*(.trampolines*) |
||||
. = ALIGN(2); |
||||
*(.text) |
||||
. = ALIGN(2); |
||||
*(.text*) |
||||
. = ALIGN(2); |
||||
} > ROM |
||||
|
||||
.text : |
||||
{ |
||||
. = ALIGN(0x10); |
||||
} > ROM = 0xAAAA |
||||
|
||||
.= 0x800100; |
||||
. = ALIGN(2); |
||||
|
||||
/* The ROM-to-RAM initialized data section */ |
||||
.data : |
||||
{ |
||||
_data_begin = .; |
||||
*(.data) |
||||
. = ALIGN(2); |
||||
KEEP (*(.data)) |
||||
*(.data*) |
||||
. = ALIGN(2); |
||||
KEEP (*(.data*)) |
||||
*(.rodata) /* Do *NOT* move this! Include .rodata here if gcc is used with -fdata-sections. */ |
||||
. = ALIGN(2); |
||||
KEEP (*(.rodata)) |
||||
*(.rodata*) |
||||
. = ALIGN(2); |
||||
KEEP (*(.rodata*)) |
||||
_data_end = .; |
||||
} > RAM AT > ROM |
||||
|
||||
/* The uninitialized (zero-cleared) data section */ |
||||
.bss : |
||||
{ |
||||
_bss_begin = .; |
||||
*(.bss) |
||||
. = ALIGN(2); |
||||
KEEP (*(.bss)) |
||||
*(.bss*) |
||||
. = ALIGN(2); |
||||
KEEP (*(.bss*)) |
||||
_bss_end = .; |
||||
} > RAM |
||||
|
||||
_rom_data_begin = LOADADDR(.data); |
||||
} |
||||
@ -0,0 +1,149 @@
|
||||
/* Linker script for ATMEL(R) AVR(R) ATmega328P. */ |
||||
|
||||
OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") |
||||
OUTPUT_ARCH(avr:5) |
||||
|
||||
/* The beginning and end of the program ROM area. */ |
||||
/* Leave 4 bytes for the 32-bit checksum plus 0x10 extra bytes free. */ |
||||
_rom_begin = 0x00000000; |
||||
_rom_end = 0x00007FEC; |
||||
|
||||
/* The beginning and end (i.e., top) of the stack */ |
||||
/* Set up a stack with a size of (1/2)K */ |
||||
_stack_begin = 0x800500; |
||||
_stack_end = 0x8008FF; /* RAFA, en atmega328 el fin de la RAM */ |
||||
|
||||
/* The end of the 2K RAM stack */ |
||||
__initial_stack_pointer = 0x8008FF; |
||||
|
||||
MEMORY |
||||
{ |
||||
ROM(rx) : ORIGIN = 0, LENGTH = 32K |
||||
RAM(rw!x) : ORIGIN = 0x800100, LENGTH = 2K |
||||
} |
||||
|
||||
SECTIONS |
||||
{ |
||||
. = 0x0; |
||||
. = ALIGN(2); |
||||
|
||||
.text : |
||||
{ |
||||
/* RAFA _*/ |
||||
text = ABSOLUTE(.); /* text: beginning of text segment */ |
||||
|
||||
*(.vectors) |
||||
KEEP(*(.vectors)) |
||||
|
||||
/*Init sections were here*/ |
||||
/* From this point on, we don't bother about wether the insns are |
||||
below or above the 16 bits boundary. */ |
||||
*(.init0) /* Start here after reset. */ |
||||
KEEP (*(.init0)) |
||||
*(.init1) |
||||
KEEP (*(.init1)) |
||||
*(.init2) /* Clear __zero_reg__, set up stack pointer. */ |
||||
KEEP (*(.init2)) |
||||
*(.init3) |
||||
KEEP (*(.init3)) |
||||
*(.init4) /* Initialize data and BSS. */ |
||||
KEEP (*(.init4)) |
||||
*(.init5) |
||||
KEEP (*(.init5)) |
||||
*(.init6) /* C++ constructors. */ |
||||
KEEP (*(.init6)) |
||||
*(.init7) |
||||
KEEP (*(.init7)) |
||||
*(.init8) |
||||
KEEP (*(.init8)) |
||||
*(.init9) /* Call main(). */ |
||||
KEEP (*(.init9)) |
||||
|
||||
*(.def_isr) |
||||
KEEP(*(.def_isr)) |
||||
|
||||
|
||||
|
||||
__muluhisi3 = .; |
||||
start = .; |
||||
__do_copy_data = .; |
||||
__do_clear_bss = .; |
||||
_/* _data_end = .; */ |
||||
__data_load_start = .; |
||||
__bss_end = .; |
||||
__bss_start = .; |
||||
__data_start = .; |
||||
|
||||
/* FIN DE RAFA */ |
||||
_ctors_begin = .; |
||||
*(.ctors) |
||||
. = ALIGN(2); |
||||
KEEP (*(SORT(.ctors))) |
||||
_ctors_end = .; |
||||
*(.progmem*) |
||||
. = ALIGN(2); |
||||
*(.trampolines*) |
||||
. = ALIGN(2); |
||||
*(.text) |
||||
. = ALIGN(2); |
||||
*(.text*) |
||||
. = ALIGN(2); |
||||
etext = ABSOLUTE(.) ; /* etext: end of text */ |
||||
|
||||
} > ROM |
||||
|
||||
.text : |
||||
{ |
||||
. = ALIGN(0x10); |
||||
} > ROM = 0xAAAA |
||||
|
||||
.= 0x800100; |
||||
. = ALIGN(2); |
||||
|
||||
/* The ROM-to-RAM initialized data section */ |
||||
.data : |
||||
{ |
||||
data = ABSOLUTE(.); /* data: beginning of data segment */ |
||||
|
||||
_data_begin = .; |
||||
*(.data) |
||||
. = ALIGN(2); |
||||
KEEP (*(.data)) |
||||
*(.data*) |
||||
. = ALIGN(2); |
||||
KEEP (*(.data*)) |
||||
*(.rodata) /* Do *NOT* move this! Include .rodata here if gcc is used with -fdata-sections. */ |
||||
. = ALIGN(2); |
||||
KEEP (*(.rodata)) |
||||
*(.rodata*) |
||||
. = ALIGN(2); |
||||
KEEP (*(.rodata*)) |
||||
_data_end = .; |
||||
__data_end = .; |
||||
|
||||
edata = ABSOLUTE(.) ; /* edata: end of data */ |
||||
} > RAM AT > ROM |
||||
|
||||
/* The uninitialized (zero-cleared) data section */ |
||||
.bss : |
||||
{ |
||||
bss = ABSOLUTE(.); /* bss: beginning of bss segment */ |
||||
|
||||
_bss_begin = .; |
||||
*(.bss) |
||||
. = ALIGN(2); |
||||
KEEP (*(.bss)) |
||||
*(.bss*) |
||||
. = ALIGN(2); |
||||
KEEP (*(.bss*)) |
||||
_bss_end = .; |
||||
|
||||
ebss = ABSOLUTE(.) ; /* ebss: end of bss */ |
||||
|
||||
end = ABSOLUTE(.); /* end: end of image */ |
||||
_end = ABSOLUTE(.); /* _end: end of image */ |
||||
|
||||
} > RAM |
||||
|
||||
_rom_data_begin = LOADADDR(.data); |
||||
} |
||||
@ -0,0 +1,55 @@
|
||||
/* Xinu for STM32 |
||||
* |
||||
* Original license applies |
||||
* Modifications for STM32 by Robin Krens |
||||
* Please see LICENSE and AUTHORS |
||||
* |
||||
* $LOG$ |
||||
* 2019/11/11 - ROBIN KRENS |
||||
* Initial version |
||||
* |
||||
* $DESCRIPTION$ |
||||
* |
||||
* */ |
||||
|
||||
/* OUTPUT_ARCH(arm) */ |
||||
ENTRY(start) |
||||
|
||||
physbase = 0x08000000; |
||||
|
||||
MEMORY |
||||
{ |
||||
/* FLASH (xr) : ORIGIN = 0x08000000, LENGTH = 512K */ |
||||
FLASH (xr) : ORIGIN = 0x8000000, LENGTH = 128K |
||||
/* SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K */ |
||||
SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K |
||||
} |
||||
|
||||
SECTIONS |
||||
{ |
||||
. = 0x0; /* Image starts here */ |
||||
.text : ALIGN(4) { |
||||
text = ABSOLUTE(.); /* text: beginning of text segment */ |
||||
*(.text .text.*) /* asm text, then C text */ |
||||
*(.rodata .rodata.*) /* asm and C read-only data */ |
||||
etext = ABSOLUTE(.) ; /* etext: end of text */ |
||||
} |
||||
. = 0x20000000; |
||||
.data : AT(etext) |
||||
{ |
||||
data = ABSOLUTE(.); /* data: beginning of data segment */ |
||||
*(.data .data.*) |
||||
edata = ABSOLUTE(.) ; /* edata: end of data */ |
||||
} |
||||
.bss ALIGN(4) : |
||||
{ |
||||
bss = ABSOLUTE(.); /* bss: beginning of bss segment */ |
||||
*(.bss .bss.*) |
||||
*(COMMON) /* extra sections that are common */ |
||||
ebss = ABSOLUTE(.) ; /* ebss: end of bss */ |
||||
. = ALIGN(8); */ |
||||
end = ABSOLUTE(.); /* end: end of image */ |
||||
_end = ABSOLUTE(.); /* _end: end of image */ |
||||
. = ALIGN(8); |
||||
} |
||||
} |
||||
@ -0,0 +1 @@
|
||||
Xinu for ATMEGA328P -- version #280 (lechnerm) dom may 17 23:40:51 -03 2020 |
||||
@ -0,0 +1,119 @@
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* Configuration - Xinu device configuration specification file */ |
||||
/* */ |
||||
/* This file becomes input to the config program, which generates */ |
||||
/* conf.h and conf.c */ |
||||
/* */ |
||||
/* Entries for a device specify the functions that handle each of the */ |
||||
/* high-level I/O operations as follows: */ |
||||
/* */ |
||||
/* -i init -o open -c close */ |
||||
/* -r read -w write -s seek */ |
||||
/* -g getc -p putc -n control */ |
||||
/* -intr int_hndlr -csr csr -irq irq */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
/* Type Declarations for both real- and pseudo- device types */ |
||||
|
||||
/* type of a null device */ |
||||
null: |
||||
on nothing |
||||
-i ionull -o ionull -c ionull |
||||
-r ionull -g ionull -p ionull |
||||
-w ionull -s ioerr |
||||
|
||||
/* type of a gpio device */ |
||||
/* RAFA |
||||
gpio: |
||||
on standard_gpio |
||||
-i gpioinit -o ionull -c ionull |
||||
-r gpioread -g ionull -p ionull |
||||
-w gpiowrite -s ioerr -n gpiocontrol |
||||
-intr gpiohandler |
||||
FIN DE RAFA */ |
||||
|
||||
/* type of a tty device */ |
||||
tty: |
||||
/* RAFA |
||||
on uart |
||||
-i ttyinit -o ionull -c ionull |
||||
-r ttyread -g ttygetc -p ttyputc |
||||
-w ttywrite -s ioerr -n ttycontrol |
||||
-intr ttyhandler |
||||
FIN DE RAFA */ |
||||
on uart |
||||
-i ionull -o ionull -c ionull |
||||
-r ionull -g ionull -p ionull |
||||
-w ionull -s ioerr -n ionull |
||||
-intr ionull |
||||
|
||||
/* type of ram disk */ |
||||
/* RAFA |
||||
ram: |
||||
on mem |
||||
-i raminit -o ramopen -c ramclose |
||||
-r ramread -g ioerr -p ioerr |
||||
-w ramwrite -s ioerr -n ioerr |
||||
-intr ionull |
||||
FIN DE RAFA */ |
||||
|
||||
/* type of namespace device */ |
||||
nam: |
||||
on top |
||||
-i naminit -o namopen -c ioerr |
||||
-r ioerr -g ioerr -p ioerr |
||||
-w ioerr -s ioerr -n ioerr |
||||
-intr ioerr |
||||
|
||||
/* RAFA |
||||
spi: |
||||
on standard_spi |
||||
-i spiinit -o ioerr -c ioerr |
||||
-r ioerr -g ioerr -p spiputc |
||||
-w ioerr -s ioerr -n ioerr |
||||
-intr ioerr |
||||
FIN DE RAFA */ |
||||
|
||||
%% |
||||
|
||||
/* Actual device declarations that each give the name of a device that */ |
||||
/* will be present in the system */ |
||||
|
||||
/* Define the console device to be a tty and specify CSR*/ |
||||
CONSOLE is tty on uart csr 0x40013800 -irq 53 |
||||
|
||||
/* Define the console device to be a tty and specify CSR*/ |
||||
/* RAFA GPIO0 is gpio on standard_gpio csr 0x40010800 -irq 99 */ |
||||
/* Define the console device to be a tty and specify CSR*/ |
||||
/* RAFA GPIO1 is gpio on standard_gpio csr 0x40010C00 -irq 99 */ |
||||
/* Define the console device to be a tty and specify CSR*/ |
||||
/* RAFA GPIO2 is gpio on standard_gpio csr 0x40011000 -irq 99 */ |
||||
/* Define the console device to be a tty and specify CSR*/ |
||||
/* RAFA GPIO3 is gpio on standard_gpio csr 0x40011400 -irq 99 */ |
||||
|
||||
/* Define a null device */ |
||||
NULLDEV is null on nothing |
||||
|
||||
/* Define a namespace device */ |
||||
NAMESPACE is nam on top |
||||
|
||||
/* Define a SPI device */ |
||||
/* RAFA SPI1 is spi on standard_spi */ |
||||
|
||||
/* Define a ram disk device */ |
||||
/* RAFA RAM0 is ram on mem */ |
||||
|
||||
%% |
||||
|
||||
/* Configuration and Size Constants */ |
||||
|
||||
#define NPROC 4 /* number of user processes */ |
||||
#define NSEM 4 /* number of semaphores */ |
||||
#define IRQBASE 32 /* base ivec for IRQ0 */ |
||||
#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 CLKFREQ 200000000 /* 200 MHz clock */ |
||||
|
||||
// #define LF_DISK_DEV RAM0 |
||||
@ -0,0 +1,106 @@
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* Configuration - Xinu device configuration specification file */ |
||||
/* */ |
||||
/* This file becomes input to the config program, which generates */ |
||||
/* conf.h and conf.c */ |
||||
/* */ |
||||
/* Entries for a device specify the functions that handle each of the */ |
||||
/* high-level I/O operations as follows: */ |
||||
/* */ |
||||
/* -i init -o open -c close */ |
||||
/* -r read -w write -s seek */ |
||||
/* -g getc -p putc -n control */ |
||||
/* -intr int_hndlr -csr csr -irq irq */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
/* Type Declarations for both real- and pseudo- device types */ |
||||
|
||||
/* type of a null device */ |
||||
null: |
||||
on nothing |
||||
-i ionull -o ionull -c ionull |
||||
-r ionull -g ionull -p ionull |
||||
-w ionull -s ioerr |
||||
|
||||
/* type of a gpio device */ |
||||
gpio: |
||||
on standard_gpio |
||||
-i gpioinit -o ionull -c ionull |
||||
-r gpioread -g ionull -p ionull |
||||
-w gpiowrite -s ioerr -n gpiocontrol |
||||
-intr gpiohandler |
||||
|
||||
/* type of a tty device */ |
||||
tty: |
||||
on uart |
||||
-i ttyinit -o ionull -c ionull |
||||
-r ttyread -g ttygetc -p ttyputc |
||||
-w ttywrite -s ioerr -n ttycontrol |
||||
-intr ttyhandler |
||||
|
||||
/* type of ram disk */ |
||||
ram: |
||||
on mem |
||||
-i raminit -o ramopen -c ramclose |
||||
-r ramread -g ioerr -p ioerr |
||||
-w ramwrite -s ioerr -n ioerr |
||||
-intr ionull |
||||
|
||||
/* type of namespace device */ |
||||
nam: |
||||
on top |
||||
-i naminit -o namopen -c ioerr |
||||
-r ioerr -g ioerr -p ioerr |
||||
-w ioerr -s ioerr -n ioerr |
||||
-intr ioerr |
||||
|
||||
spi: |
||||
on standard_spi |
||||
-i spiinit -o ioerr -c ioerr |
||||
-r ioerr -g ioerr -p spiputc |
||||
-w ioerr -s ioerr -n ioerr |
||||
-intr ioerr |
||||
|
||||
%% |
||||
|
||||
/* Actual device declarations that each give the name of a device that */ |
||||
/* will be present in the system */ |
||||
|
||||
/* Define the console device to be a tty and specify CSR*/ |
||||
CONSOLE is tty on uart csr 0x40013800 -irq 53 |
||||
|
||||
/* Define the console device to be a tty and specify CSR*/ |
||||
GPIO0 is gpio on standard_gpio csr 0x40010800 -irq 99 |
||||
/* Define the console device to be a tty and specify CSR*/ |
||||
GPIO1 is gpio on standard_gpio csr 0x40010C00 -irq 99 |
||||
/* Define the console device to be a tty and specify CSR*/ |
||||
GPIO2 is gpio on standard_gpio csr 0x40011000 -irq 99 |
||||
/* Define the console device to be a tty and specify CSR*/ |
||||
GPIO3 is gpio on standard_gpio csr 0x40011400 -irq 99 |
||||
|
||||
/* Define a null device */ |
||||
NULLDEV is null on nothing |
||||
|
||||
/* Define a namespace device */ |
||||
NAMESPACE is nam on top |
||||
|
||||
/* Define a SPI device */ |
||||
SPI1 is spi on standard_spi |
||||
|
||||
/* Define a ram disk device */ |
||||
RAM0 is ram on mem |
||||
|
||||
%% |
||||
|
||||
/* Configuration and Size Constants */ |
||||
|
||||
#define NPROC 10 /* number of user processes */ |
||||
#define NSEM 10 /* number of semaphores */ |
||||
#define IRQBASE 32 /* base ivec for IRQ0 */ |
||||
#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 CLKFREQ 200000000 /* 200 MHz clock */ |
||||
|
||||
#define LF_DISK_DEV RAM0 |
||||
@ -0,0 +1,111 @@
|
||||
This is the Xinu config program that allows one to specify a set of |
||||
device drivers. |
||||
|
||||
Input: the program reads specifications from an input file, usually |
||||
|
||||
Configuration |
||||
|
||||
|
||||
Output: the program produces two ouput files, usually |
||||
|
||||
conf.h - configuration constants and declarations |
||||
for device drivers and the device |
||||
switch table |
||||
|
||||
conf.c - initialization code for data strcutures |
||||
declared in conf.h |
||||
|
||||
|
||||
The input file consists of three sections, with %% used as a sparator |
||||
between sections: |
||||
|
||||
---------------------------------------------------------------------------- |
||||
|
||||
/* Comments can appear anywhere in the input file; use */ |
||||
/* the C style of slash-star ... star-slash. */ |
||||
/* The config program ignores whitespace and comments. */ |
||||
|
||||
|
||||
device type declarations |
||||
|
||||
%% |
||||
|
||||
device declarations |
||||
|
||||
%% |
||||
|
||||
Other constants added to conf.h (typically, #defines) |
||||
|
||||
---------------------------------------------------------------------------- |
||||
|
||||
|
||||
**************************** Type Declarations ***************************** |
||||
|
||||
|
||||
The type declaration section consists of a series of entries of the form: |
||||
|
||||
type_name: on hardware_name [options] |
||||
|
||||
where |
||||
|
||||
type_name a name for the type |
||||
: a required punctuation, usually appended onto the |
||||
type name |
||||
on a keyword |
||||
hardware_name any string used to allow a type name to have |
||||
two implementations |
||||
options multiple options can be specified, and each |
||||
consists of a flag and the name of a |
||||
driver function or hardware parameter |
||||
(the minus sign in front of a flag |
||||
can be omitted): |
||||
|
||||
-i initialization_function |
||||
-o open_function |
||||
-r read_function |
||||
-w write_function |
||||
-s seek_function |
||||
-c close_function |
||||
-g getc_function |
||||
-p putc_function |
||||
-n control_function |
||||
-intr interrupt_handler |
||||
-csr CSR address |
||||
-irq Interrupt request number |
||||
|
||||
Example: |
||||
|
||||
|
||||
eth: on quark_eth |
||||
-i ethinit -o ioerr -c ioerr |
||||
-r ethread -g ioerr -p ioerr |
||||
-w ethwrite -s ioerr -n ethcontrol |
||||
-intr ethdispatch |
||||
|
||||
|
||||
*************************** Device Declarations **************************** |
||||
|
||||
|
||||
The device declaration section consists of one entry per device in the form: |
||||
|
||||
device_name is type_name on hardware_name [options] |
||||
|
||||
where |
||||
|
||||
device_name a name for the device (by convention, Xinu |
||||
uses upper-case device names) |
||||
is a keyword |
||||
type_name the name of a type defined above |
||||
on a keyword |
||||
hardware_name must match one of the hardware names used with |
||||
when the type was defined |
||||
options the same as the options above -- any values used |
||||
on a device declaration override the |
||||
values defined for the type. Typically, |
||||
a type does not have specific hardware |
||||
parameters, so they must be filled in. |
||||
|
||||
Example: |
||||
|
||||
|
||||
ETHER is eth on quark_eth csr 0001770 -irq 0053 |
||||
@ -0,0 +1,41 @@
|
||||
#
|
||||
# Make the Xinu configuration program
|
||||
#
|
||||
|
||||
COMPILER_ROOT = /usr/bin/
|
||||
|
||||
CC = ${COMPILER_ROOT}gcc
|
||||
LEX = ${COMPILER_ROOT}flex
|
||||
YACC = ${COMPILER_ROOT}bison -y # Flag enables yacc-compatible filenames
|
||||
CFLAGS =
|
||||
LFLAGS = -lfl
|
||||
|
||||
#
|
||||
# Name of the configuration program
|
||||
#
|
||||
|
||||
CONFIG = config
|
||||
|
||||
all: conf.h conf.c |
||||
|
||||
${CONFIG}: lex.yy.c y.tab.c |
||||
$(CC) ${CFLAGS} -o $@ y.tab.c ${LFLAGS}
|
||||
|
||||
lex.yy.c: config.l |
||||
$(LEX) config.l
|
||||
|
||||
y.tab.c: config.y |
||||
$(YACC) config.y
|
||||
|
||||
clean: |
||||
rm -f config lex.yy.c y.tab.c
|
||||
|
||||
conf.h: config Configuration |
||||
./config Configuration conf.c conf.h
|
||||
|
||||
conf.c: config Configuration |
||||
./config Configuration conf.c conf.h
|
||||
|
||||
install: conf.h conf.c |
||||
cp -p conf.h ../include
|
||||
cp -p conf.c ../system
|
||||
@ -0,0 +1,44 @@
|
||||
/* conf.c (GENERATED FILE; DO NOT EDIT) */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
|
||||
extern devcall ioerr(void); |
||||
extern devcall ionull(void); |
||||
|
||||
/* Device independent I/O switch */ |
||||
|
||||
typedef unsigned int size_t; |
||||
#include <avr/pgmspace.h> |
||||
const struct dentry devtab[] PROGMEM = |
||||
{ |
||||
/**
|
||||
* Format of entries is: |
||||
* dev-number, minor-number, dev-name, |
||||
* init, open, close, |
||||
* read, write, seek, |
||||
* getc, putc, control, |
||||
* dev-csr-address, intr-handler, irq |
||||
*/ |
||||
|
||||
/* CONSOLE is tty */ |
||||
{ 0, 0, "CONSOLE", |
||||
(void *)ionull, (void *)ionull, (void *)ionull, |
||||
(void *)ionull, (void *)ionull, (void *)ioerr, |
||||
(void *)ionull, (void *)ionull, (void *)ionull, |
||||
(void *)0x40013800, (void *)ionull, 53 }, |
||||
|
||||
/* NULLDEV is null */ |
||||
{ 1, 0, "NULLDEV", |
||||
(void *)ionull, (void *)ionull, (void *)ionull, |
||||
(void *)ionull, (void *)ionull, (void *)ioerr, |
||||
(void *)ionull, (void *)ionull, (void *)ioerr, |
||||
(void *)0x0, (void *)ioerr, 0 }, |
||||
|
||||
/* NAMESPACE is nam */ |
||||
{ 2, 0, "NAMESPACE", |
||||
(void *)naminit, (void *)namopen, (void *)ioerr, |
||||
(void *)ioerr, (void *)ioerr, (void *)ioerr, |
||||
(void *)ioerr, (void *)ioerr, (void *)ioerr, |
||||
(void *)0x0, (void *)ioerr, 0 } |
||||
}; |
||||
@ -0,0 +1,50 @@
|
||||
/* conf.h (GENERATED FILE; DO NOT EDIT) */ |
||||
|
||||
/* Device switch table declarations */ |
||||
|
||||
/* Device table entry */ |
||||
struct dentry { |
||||
int32 dvnum; |
||||
int32 dvminor; |
||||
char dvname[16]; |
||||
devcall (*dvinit) (struct dentry *); |
||||
devcall (*dvopen) (struct dentry *, char *, char *); |
||||
devcall (*dvclose)(struct dentry *); |
||||
devcall (*dvread) (struct dentry *, void *, uint32); |
||||
devcall (*dvwrite)(struct dentry *, void *, uint32); |
||||
devcall (*dvseek) (struct dentry *, int32); |
||||
devcall (*dvgetc) (struct dentry *); |
||||
devcall (*dvputc) (struct dentry *, char); |
||||
devcall (*dvcntl) (struct dentry *, int32, int32, int32); |
||||
void *dvcsr; |
||||
void (*dvintr)(void); |
||||
byte dvirq; |
||||
}; |
||||
|
||||
extern const struct dentry devtab[]; /* one entry per device */ |
||||
|
||||
/* Device name definitions */ |
||||
|
||||
#define CONSOLE 0 /* type tty */ |
||||
#define NULLDEV 1 /* type null */ |
||||
#define NAMESPACE 2 /* type nam */ |
||||
|
||||
/* Control block sizes */ |
||||
|
||||
#define Nnull 1 |
||||
#define Ntty 1 |
||||
#define Nnam 1 |
||||
|
||||
#define NDEVS 3 |
||||
|
||||
|
||||
/* Configuration and Size Constants */ |
||||
|
||||
#define NPROC 4 /* number of user processes */ |
||||
#define NSEM 4 /* number of semaphores */ |
||||
#define IRQBASE 32 /* base ivec for IRQ0 */ |
||||
#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 CLKFREQ 200000000 /* 200 MHz clock */ |
||||
|
||||
// #define LF_DISK_DEV RAM0
|
||||
@ -0,0 +1,40 @@
|
||||
%{ |
||||
extern int linectr; |
||||
extern int brkcount; |
||||
int skipping; |
||||
%} |
||||
OCT 0[0-7]* |
||||
DEC [1-9][0-9]* |
||||
HEX 0x[0-9a-fA-F]+ |
||||
ID [a-z_A-Z][a-z_A-Z0-9]* |
||||
%% |
||||
"/*" { skipping = 1; } |
||||
"*/" { skipping = 0; } |
||||
"%%" { if (! skipping) |
||||
if (++brkcount >= 2) |
||||
{ return 0; /* EOF */ } |
||||
else |
||||
{ return DEFBRK; } } |
||||
":" { if (! skipping) return COLON; } |
||||
{OCT} { if (! skipping) return INTEGER; } |
||||
{DEC} { if (! skipping) return INTEGER; } |
||||
{HEX} { if (! skipping) return INTEGER; } |
||||
is { if (! skipping) return IS; } |
||||
on { if (! skipping) return ON; } |
||||
"=" ; |
||||
-?intr { if (! skipping) return INTR; } |
||||
-?csr { if (! skipping) return CSR; } |
||||
-?irq { if (! skipping) return IRQ; } |
||||
-?i { if (! skipping) return INIT; } |
||||
-?o { if (! skipping) return OPEN; } |
||||
-?c { if (! skipping) return CLOSE; } |
||||
-?r { if (! skipping) return READ; } |
||||
-?g { if (! skipping) return GETC; } |
||||
-?p { if (! skipping) return PUTC; } |
||||
-?w { if (! skipping) return WRITE; } |
||||
-?s { if (! skipping) return SEEK; } |
||||
-?n { if (! skipping) return CONTROL; } |
||||
[ \t]+ ; |
||||
"\n" { linectr++; } |
||||
{ID} { if (! skipping) return IDENT; } |
||||
. { if (! skipping) return yytext[0]; } |
||||
@ -0,0 +1,754 @@
|
||||
/* config.y - yacc input file for the Xinu config program */ |
||||
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* This file contains the yacc grammar and semantic functions */ |
||||
/* that read a Xinu Configuration file and generate output files */ |
||||
/* conf.h and conf.c that are then compiled along with the rest of */ |
||||
/* Xinu. */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
%token DEFBRK IFBRK COLON OCTAL INTEGER IDENT CSR IRQ INTR INIT OPEN |
||||
CLOSE READ WRITE SEEK CONTROL IS ON GETC PUTC |
||||
%{ |
||||
#include <stdlib.h> |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include <ctype.h> |
||||
|
||||
extern char *yytext; |
||||
/* |
||||
Work-around for the type conflict that results from unmatched versions |
||||
of flex and bison (lex and yacc). The idea is to force the new flex |
||||
style so the output file (lex.yy.c) treats yyleng as an int (as was |
||||
done by oldest lex versions) instead of a size_t. We override the |
||||
new flex typedef of yy_size_t. |
||||
*/ |
||||
#ifndef YY_TYPEDEF_YY_SIZE_T |
||||
#define YY_TYPEDEF_YY_SIZE_T |
||||
typedef int yy_size_t; |
||||
#endif |
||||
/* End work-around */ |
||||
extern int yyleng; |
||||
|
||||
|
||||
/********************************************************************************/ |
||||
/* */ |
||||
/* Start of Definitions */ |
||||
/* */ |
||||
/********************************************************************************/ |
||||
|
||||
#define NIL (struct dev_ent *)0x00 |
||||
|
||||
#define CONFC "conf.c" /* Name of .c output */ |
||||
#define CONFH "conf.h" /* Name of .h output */ |
||||
#define CONFHREF "<conf.h>" /* How conf.h referenced */ |
||||
#define INFILE "Configuration" /* Name of input file */ |
||||
// RAFA #define MAXNAME 16 /* Max length of names */ |
||||
#define MAXNAME 16 /* Max length of names */ |
||||
|
||||
// RAFA #define NDEVS 250 /* Max devices */ |
||||
// RAFA #define NTYPES 250 /* Max device types */ |
||||
#define NDEVS 5 /* Max devices */ |
||||
#define NTYPES 5 /* Max device types */ |
||||
|
||||
int linectr = 1; |
||||
|
||||
FILE *confc; |
||||
FILE *confh; |
||||
|
||||
int brkcount = 0; /* Count of %% separators till now in */ |
||||
/* the input file */ |
||||
char *doing = "device type declarations"; |
||||
|
||||
struct dev_ent { /* Entry for a device or device type */ |
||||
char name[MAXNAME]; /* device name (unused in a type) */ |
||||
char tname[MAXNAME]; /* Type name */ |
||||
char ison[MAXNAME]; /* Name is "on" XXX */ |
||||
int tindex; /* Index in dtypes (unused in a type) */ |
||||
int csr; /* Control Status Register addr */ |
||||
int irq; /* interrupt request */ |
||||
char intr[MAXNAME]; /* interrupt function name */ |
||||
char init[MAXNAME]; /* init function name */ |
||||
char open[MAXNAME]; /* open function name */ |
||||
char close[MAXNAME]; /* close function name */ |
||||
char read[MAXNAME]; /* read function name */ |
||||
char write[MAXNAME]; /* write function name */ |
||||
char control[MAXNAME]; /* control function name */ |
||||
char seek[MAXNAME]; /* seek function name */ |
||||
char getc[MAXNAME]; /* getc function name */ |
||||
char putc[MAXNAME]; /* putc function name */ |
||||
int minor; /* In a device, the minor device */ |
||||
/* assigned to the device 0,1,... */ |
||||
/* in a type, the next minor number */ |
||||
/* to assign */ |
||||
}; |
||||
struct dev_ent dtypes[NTYPES];/* Table of all device types */ |
||||
int ntypes = 0; /* Number of device types found */ |
||||
|
||||
struct dev_ent devs[NDEVS]; /* Table of all devices */ |
||||
int ndevs = 0; /* Number of devices found */ |
||||
|
||||
char *devstab[] = { |
||||
"/* Device table entry */", |
||||
"struct\tdentry\t{", |
||||
"\tint32 dvnum;", |
||||
"\tint32 dvminor;", |
||||
// RAFA "\tchar *dvname;", |
||||
"\tchar dvname[16];", |
||||
"\tdevcall (*dvinit) (struct dentry *);", |
||||
"\tdevcall (*dvopen) (struct dentry *, char *, char *);", |
||||
"\tdevcall (*dvclose)(struct dentry *);", |
||||
"\tdevcall (*dvread) (struct dentry *, void *, uint32);", |
||||
"\tdevcall (*dvwrite)(struct dentry *, void *, uint32);", |
||||
"\tdevcall (*dvseek) (struct dentry *, int32);", |
||||
"\tdevcall (*dvgetc) (struct dentry *);", |
||||
"\tdevcall (*dvputc) (struct dentry *, char);", |
||||
"\tdevcall (*dvcntl) (struct dentry *, int32, int32, int32);", |
||||
"\tvoid *dvcsr;", |
||||
"\tvoid (*dvintr)(void);", |
||||
"\tbyte dvirq;", |
||||
"};\n", |
||||
"extern const struct dentry devtab[]; /* one entry per device */", |
||||
NULL |
||||
}; |
||||
|
||||
char saveattrid[MAXNAME]; /* Holds the IDENT from an attribute */ |
||||
|
||||
/********************************************************************************/ |
||||
/* */ |
||||
/* Function prototypes */ |
||||
/* */ |
||||
/********************************************************************************/ |
||||
|
||||
void addattr(int, int); |
||||
int addton(char *); |
||||
int config_atoi(char *, int); |
||||
void devisid(char *); |
||||
void devonid(char *); |
||||
void getattrid(char *); |
||||
void newdev(char *); |
||||
int newtype(char *); |
||||
void yyerror(char *); |
||||
|
||||
|
||||
%} |
||||
|
||||
%% |
||||
/************************************************************************/ |
||||
/* */ |
||||
/* Grammar rules for the entire Configuration */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
configuration: devtypes DEFBRK devices |
||||
; |
||||
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* Grammar rules for device types */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
devtypes: /* nothing */ { doing = "device definitions"; } |
||||
| devtypes devtype |
||||
; |
||||
|
||||
devtype: tname COLON dev_tlist |
||||
; |
||||
|
||||
tname: IDENT { $$ = newtype(yytext); } |
||||
; |
||||
|
||||
dev_tlist: theader attr_list |
||||
| dev_tlist theader attr_list |
||||
; |
||||
|
||||
theader: ON tonid { $$ = $2; } |
||||
; |
||||
|
||||
tonid: IDENT { $$ = addton(yytext); } |
||||
; |
||||
|
||||
attr_list: /* nothing */ |
||||
| attr_list attr |
||||
; |
||||
|
||||
attr: CSR number { addattr(CSR, $2); } |
||||
| IRQ number { addattr(IRQ, $2); } |
||||
| INTR id { addattr(INTR, 0); } |
||||
| OPEN id { addattr(OPEN, 0); } |
||||
| CLOSE id { addattr(CLOSE, 0); } |
||||
| INIT id { addattr(INIT, 0); } |
||||
| GETC id { addattr(GETC, 0); } |
||||
| PUTC id { addattr(PUTC, 0); } |
||||
| READ id { addattr(READ, 0); } |
||||
| WRITE id { addattr(WRITE, 0); } |
||||
| SEEK id { addattr(SEEK, 0); } |
||||
| CONTROL id { addattr(CONTROL, 0); } |
||||
; |
||||
|
||||
id: IDENT { $$ = 0; getattrid(yytext); } |
||||
; |
||||
|
||||
number: INTEGER { $$ = config_atoi(yytext, yyleng); } |
||||
; |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* Grammar rules for device definitions */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
devices: /* nothing */ { doing = "interface types"; } |
||||
| devices device |
||||
; |
||||
|
||||
device: dheader attr_list |
||||
; |
||||
|
||||
dheader: dname devis devon |
||||
; |
||||
|
||||
dname: IDENT { newdev(yytext); } |
||||
; |
||||
|
||||
devis: IS devisid |
||||
; |
||||
|
||||
devisid: IDENT { devisid(yytext); } |
||||
; |
||||
|
||||
devon: ON devonid |
||||
; |
||||
|
||||
devonid: IDENT { devonid(yytext); } |
||||
; |
||||
|
||||
%% |
||||
|
||||
#include "lex.yy.c" |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* main - main program: parse arguments, invoke the parser, and */ |
||||
/* write the conf.h and conf.c files */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
|
||||
int main(int argc, char **argv) { |
||||
int n, i, j, l, fcount; |
||||
struct dev_ent *s; |
||||
int verbose = 0; |
||||
char *p; |
||||
int c; |
||||
|
||||
if ( argc > 1 && (strncmp("-v", argv[1], 2) == 0) ) { |
||||
argc--; |
||||
argv++; |
||||
verbose++; |
||||
} |
||||
|
||||
if ( argc > 4 ) { |
||||
fprintf(stderr, "use: config [-v] [input_file] [conf.c] [conf.h]\n"); |
||||
exit(1); |
||||
} |
||||
|
||||
if (verbose) { printf("Opening input file...\n"); } |
||||
|
||||
if (argc >= 2) { |
||||
if (freopen(argv[1], "r", stdin) == NULL) { |
||||
fprintf(stderr, "Can't open %s\n", argv[1]); |
||||
exit(1); |
||||
} |
||||
} |
||||
else { /* try to open Configuration file */ |
||||
if (freopen(INFILE, "r", stdin) == NULL) { |
||||
fprintf(stderr, "Can't open %s\n", INFILE); |
||||
exit(1); |
||||
} |
||||
} |
||||
|
||||
/****************************************************************/ |
||||
/* */ |
||||
/* Parse the Configuration file */ |
||||
/* */ |
||||
/****************************************************************/ |
||||
|
||||
|
||||
if (verbose) { printf("Parsing configuration specs...\n"); } |
||||
|
||||
if ( (n = yyparse()) != 0 ) { exit(n); } |
||||
|
||||
/* Open conf.h and conf.c for writing */ |
||||
|
||||
if (verbose) { printf("Opening output files...\n"); } |
||||
|
||||
if (argc >= 3) { |
||||
if ( (confc = fopen(argv[2],"w") ) == NULL) { |
||||
fprintf(stderr, "Can't write on %s\n", argv[2]); |
||||
exit(1); |
||||
} |
||||
} |
||||
else { /* try to open conf.c file */ |
||||
if ( (confc = fopen(CONFC,"w") ) == NULL) { |
||||
fprintf(stderr, "Can't write on %s\n", CONFC); |
||||
exit(1); |
||||
} |
||||
} |
||||
|
||||
if (argc >= 4) { |
||||
if ( (confh = fopen(argv[3],"w") ) == NULL) { |
||||
fprintf(stderr, "Can't write on %s\n", argv[3]); |
||||
exit(1); |
||||
} |
||||
} |
||||
else { /* try to open conf.h file */ |
||||
if ( (confh = fopen(CONFH,"w") ) == NULL) { |
||||
fprintf(stderr, "Can't write on %s\n", CONFH); |
||||
exit(1); |
||||
} |
||||
} |
||||
|
||||
/****************************************************************/ |
||||
/* */ |
||||
/* produce conf.h */ |
||||
/* */ |
||||
/****************************************************************/ |
||||
|
||||
|
||||
fprintf(confh, "/* conf.h (GENERATED FILE; DO NOT EDIT) */\n\n"); |
||||
|
||||
if (verbose) { printf("Writing output...\n"); } |
||||
|
||||
fprintf(confh, "/* Device switch table declarations */\n\n"); |
||||
|
||||
for (i = 0; (p = devstab[i]) != NULL; i++) { |
||||
fprintf(confh, "%s\n", p); |
||||
} |
||||
|
||||
fprintf(confh, "\n"); |
||||
|
||||
/* write device declarations and definitions */ |
||||
|
||||
fprintf(confh, "/* Device name definitions */\n\n"); |
||||
for (i = 0; i<ndevs; i++) { |
||||
s = &devs[i]; |
||||
fprintf(confh, "#define %-20s%2d\t/* type %-8s */\n", |
||||
s->name, i, s->tname); |
||||
} |
||||
fprintf(confh, "\n"); |
||||
|
||||
/* write count of device types */ |
||||
|
||||
fprintf(confh, "/* Control block sizes */\n\n"); |
||||
for (i = 0; i < ntypes; i++) { |
||||
s = &dtypes[i]; |
||||
if (s->minor > 0) { |
||||
fprintf(confh, "#define\tN%s\t%d\n", |
||||
s->tname, s->minor); |
||||
} |
||||
} |
||||
|
||||
fprintf(confh, "\n"); |
||||
|
||||
if (ndevs > 0) { fprintf(confh, "#define NDEVS %d\n", ndevs); } |
||||
|
||||
/* Copy definitions to output */ |
||||
|
||||
if (brkcount >= 4 && verbose) { |
||||
printf("Copying definitions to %s...\n", CONFH); |
||||
} |
||||
|
||||
if (brkcount >= 2) { |
||||
while ( (c = input()) > 0) { /* lex input function */ |
||||
putc(c, confh); |
||||
} |
||||
} |
||||
fclose(confh); |
||||
|
||||
|
||||
/****************************************************************/ |
||||
/* */ |
||||
/* produce conf.c */ |
||||
/* */ |
||||
/****************************************************************/ |
||||
|
||||
|
||||
fprintf(confc, "/* conf.c (GENERATED FILE; DO NOT EDIT) */\n\n"); |
||||
fprintf(confc, "#include <xinu.h>\n\n"); |
||||
fprintf(confc, "\n"); |
||||
|
||||
fprintf(confc, "extern\tdevcall\tioerr(void);\n"); |
||||
fprintf(confc, "extern\tdevcall\tionull(void);\n\n"); |
||||
|
||||
/* produce devtab (giant I/O switch table) */ |
||||
fprintf(confc, "/* Device independent I/O switch */\n\n"); |
||||
if (ndevs > 0) |
||||
{ |
||||
// RAFA fprintf(confc, "const struct dentry devtab[NDEVS] =\n{\n"); |
||||
fprintf(confc, "typedef unsigned int size_t;\n"); |
||||
fprintf(confc, "#include <avr/pgmspace.h>\n"); |
||||
fprintf(confc, "const struct dentry devtab[] PROGMEM =\n{\n"); |
||||
// RAFA fprintf(confc, "const struct dentry devtab[] PROGMEM =\n{\n"); |
||||
fprintf(confc, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n\n", |
||||
"/**", |
||||
" * Format of entries is:", |
||||
" * dev-number, minor-number, dev-name,", |
||||
" * init, open, close,", |
||||
" * read, write, seek,", |
||||
" * getc, putc, control,", |
||||
" * dev-csr-address, intr-handler, irq", |
||||
" */"); |
||||
} |
||||
|
||||
for (i=0; i<ndevs; i++) { |
||||
s = &devs[i]; |
||||
fprintf(confc, "/* %s is %s */\n", s->name, s->tname); |
||||
fprintf(confc, "\t{ %d, %d, \"%s\",\n", i, s->minor, s->name); |
||||
fprintf(confc, "\t (void *)%s, (void *)%s, (void *)%s,\n", |
||||
s->init, s->open, s->close); |
||||
fprintf(confc, "\t (void *)%s, (void *)%s, (void *)%s,\n", |
||||
s->read, s->write, s->seek); |
||||
fprintf(confc, "\t (void *)%s, (void *)%s, (void *)%s,\n", |
||||
s->getc, s->putc, s->control); |
||||
fprintf(confc, "\t (void *)0x%x, (void *)%s, %d }", |
||||
s->csr, s->intr, s->irq); |
||||
if (i< ndevs-1) { |
||||
fprintf(confc, ",\n\n"); |
||||
} else { |
||||
fprintf(confc, "\n};"); |
||||
} |
||||
} |
||||
|
||||
/* we must guarantee conf.c written later than conf.h for make */ |
||||
fprintf(confc, "\n"); |
||||
fclose(confc); |
||||
|
||||
/* finish up and write report for user if requested */ |
||||
if (verbose) { |
||||
printf("Configuration complete. Number of devs=%d:\n", ndevs); |
||||
for (i=0; i<ndevs; i++) { |
||||
s = &devs[i]; |
||||
printf("Device %s (on %s)\n", s->name, s->ison); |
||||
printf(" csr=0x%04x, irq=0x%04x, minor=%d\n", |
||||
s->csr, s->irq, s->minor); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* addattr - add a new attribute spec to current type/device description*/ |
||||
/* tok: token type (attribute type) */ |
||||
/* val: symbol number of value */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
void addattr(int tok, int val) { |
||||
struct dev_ent *s; |
||||
char *c; |
||||
|
||||
if (brkcount == 0) { |
||||
/* Doing types */ |
||||
s = &dtypes[ntypes-1]; |
||||
} else { |
||||
/* Doing devices */ |
||||
s = &devs[ndevs-1]; |
||||
} |
||||
|
||||
switch (tok) { |
||||
case CSR: s->csr = val; break; |
||||
case IRQ: s->irq = val; break; |
||||
case INTR: strcpy(s->intr, saveattrid); break; |
||||
case READ: strcpy(s->read, saveattrid); break; |
||||
case WRITE: strcpy(s->write,saveattrid); break; |
||||
case GETC: strcpy(s->getc, saveattrid); break; |
||||
case PUTC: strcpy(s->putc, saveattrid); break; |
||||
case OPEN: strcpy(s->open, saveattrid); break; |
||||
case CLOSE: strcpy(s->close,saveattrid); break; |
||||
case INIT: strcpy(s->init, saveattrid); break; |
||||
case SEEK: strcpy(s->seek, saveattrid); break; |
||||
case CONTROL: strcpy(s->control,saveattrid); break; |
||||
default: fprintf(stderr, "Internal error 1\n"); |
||||
} |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* addton -- add an "on XXX" to the current type */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
int addton(char *tonid) { |
||||
int currtype; /* The current type */ |
||||
|
||||
if (strlen(tonid) >= MAXNAME) { |
||||
fprintf(stderr,"string %s is too long on line %d\n", |
||||
tonid, linectr); |
||||
exit(1); |
||||
} |
||||
currtype = ntypes - 1; |
||||
strcpy(dtypes[currtype].ison, tonid); |
||||
|
||||
return currtype; |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* config_atoi - convert an ascii string of text to an integer, */ |
||||
/* honoring octal, decimal, and hex */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
int config_atoi(char *p, int len) { |
||||
int base, rv; |
||||
|
||||
if (*p == '0') |
||||
{ |
||||
++p; |
||||
--len; |
||||
if (*p == 'x' || *p == 'X') |
||||
{ |
||||
++p; --len; /* skip 'x' */ |
||||
base = 16; |
||||
} |
||||
else |
||||
{ |
||||
base = 8; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
base = 10; |
||||
} |
||||
|
||||
rv = 0; |
||||
for (; len > 0; ++p, --len) |
||||
{ |
||||
rv *= base; |
||||
if (isdigit(*p)) { rv += *p - '0'; } |
||||
else if (isupper(*p)) { rv += *p - 'A' + 10; } |
||||
else { rv += *p - 'a' + 10; } |
||||
} |
||||
|
||||
return rv; |
||||
} |
||||
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* devisid -- add an "is XXX" to the current device */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
void devisid(char *tname) { |
||||
int currdev; /* The current device */ |
||||
int i; |
||||
|
||||
if (strlen(tname) >= MAXNAME) { |
||||
fprintf(stderr,"string %s is too long on line %d\n", |
||||
tname, linectr); |
||||
exit(1); |
||||
} |
||||
/* Verify the type exists */ |
||||
|
||||
for (i=0; i<ntypes; i++) { |
||||
if (strcmp(tname, dtypes[i].tname) == 0) { |
||||
break; |
||||
} |
||||
} |
||||
if (i >= ntypes) { |
||||
fprintf(stderr, "Illegal type name %s on line %d\n", |
||||
tname, linectr); |
||||
exit(1); |
||||
} |
||||
currdev = ndevs - 1; |
||||
strcpy(devs[currdev].tname, tname); |
||||
|
||||
return; |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* devonid -- add an "on XXX" to the current device, lookup the type, */ |
||||
/* and copy attributes into the device from the type */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
void devonid(char *onname) { |
||||
int currdev; /* The current device */ |
||||
int i; |
||||
struct dev_ent *dptr; /* Pointer to current device */ |
||||
struct dev_ent *tptr; /* Pointer to a type */ |
||||
char tmp[MAXNAME]; /* Holds the device name during */ |
||||
/* copy */ |
||||
|
||||
if (strlen(onname) >= MAXNAME) { |
||||
fprintf(stderr,"string %s is too long on line %d\n", |
||||
onname, linectr); |
||||
exit(1); |
||||
} |
||||
if (ndevs <=0) { |
||||
fprintf(stderr,"Internal error 3\n"); |
||||
exit(1); |
||||
} |
||||
currdev = ndevs - 1; |
||||
dptr = &devs[currdev]; |
||||
|
||||
strcpy(dptr->ison, onname); |
||||
|
||||
/* Lookup the device type */ |
||||
|
||||
for (i=0; i<ntypes; i++) { |
||||
tptr = &dtypes[i]; |
||||
if ( (strcmp(dptr->tname,tptr->tname) == 0 ) && |
||||
(strcmp(dptr->ison, tptr->ison) == 0 ) ){ |
||||
|
||||
/* The specified type matches the ith entry, so */ |
||||
/* set all attributes equal to the ones in the */ |
||||
/* type definition. */ |
||||
|
||||
strcpy(tmp, dptr->name); |
||||
bcopy (tptr, dptr, sizeof(struct dev_ent)); |
||||
/* Increment the minor device number for the */ |
||||
/* next time the type is used */ |
||||
tptr->minor++; |
||||
strcpy(dptr->name, tmp); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
fprintf(stderr, "Ileagal device specification on line %d\n", linectr); |
||||
exit(1); |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* getattrid -- pick up and save the attribute string from an id */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
void getattrid(char *str) { |
||||
|
||||
if (strlen(str) >= MAXNAME) { |
||||
fprintf(stderr,"atribute string %s is too long on line %d\n", |
||||
str, linectr); |
||||
exit(1); |
||||
} |
||||
strcpy(saveattrid, str); |
||||
return; |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* newdev -- allocate an entry in devs, initialize, and fill in the name*/ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
void newdev(char *name) { |
||||
|
||||
struct dev_ent *dptr; /* Ptr. to an entry in devs */ |
||||
int i; |
||||
|
||||
if (ndevs >= NDEVS) { |
||||
fprintf(stderr,"Too many devices on line %d", linectr); |
||||
exit(1); |
||||
} |
||||
if (strlen(name) >= MAXNAME) { |
||||
fprintf(stderr,"Device name %s is too long on line %d\n", |
||||
name, linectr); |
||||
exit(1); |
||||
} |
||||
|
||||
/* Verify that the device name is unique */ |
||||
|
||||
for (i=0; i<ndevs; i++) { |
||||
if (strcmp(name, devs[i].name) == 0) { |
||||
fprintf(stderr, "Duplicate device name %s on line %d\n", |
||||
name, linectr); |
||||
exit(1); |
||||
} |
||||
} |
||||
|
||||
dptr = &devs[ndevs]; |
||||
|
||||
/* Initialize fields in the entry */ |
||||
|
||||
bzero((void *)dptr, sizeof(struct dev_ent)); |
||||
strcpy(dptr->name, name); |
||||
ndevs++; |
||||
return; |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* newtype -- allocate an entry in the type array and fill in the name */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
int newtype(char *name) { |
||||
|
||||
struct dev_ent *dptr; /* Ptr. to an entry in dtypes */ |
||||
int i; /* Index into the type table */ |
||||
|
||||
if (ntypes >= NTYPES) { |
||||
fprintf(stderr,"Too many types on line %d", linectr); |
||||
exit(1); |
||||
} |
||||
if (strlen(name) >= MAXNAME) { |
||||
fprintf(stderr,"Type name %s is too long on line %d\n", |
||||
name, linectr); |
||||
exit(1); |
||||
} |
||||
|
||||
/* Verify that the type name is unique */ |
||||
|
||||
for (i=0; i<ntypes; i++) { |
||||
if (strcmp(name, dtypes[i].tname) == 0) { |
||||
fprintf(stderr, "Duplicate type name %s on line %d\n", |
||||
name, linectr); |
||||
exit(1); |
||||
} |
||||
} |
||||
|
||||
dptr = &dtypes[ntypes]; |
||||
|
||||
/* Initialize fields in the entry */ |
||||
|
||||
bzero((void *)dptr, sizeof(struct dev_ent)); |
||||
strcpy(dptr->tname, name); |
||||
strncpy(dptr->intr, "ioerr", 5); |
||||
strncpy(dptr->init, "ioerr", 5); |
||||
strncpy(dptr->open, "ioerr", 5); |
||||
strncpy(dptr->close, "ioerr", 5); |
||||
strncpy(dptr->read, "ioerr", 5); |
||||
strncpy(dptr->write, "ioerr", 5); |
||||
strncpy(dptr->control, "ioerr", 5); |
||||
strncpy(dptr->seek, "ioerr", 5); |
||||
strncpy(dptr->getc, "ioerr", 5); |
||||
strncpy(dptr->putc, "ioerr", 5); |
||||
|
||||
return ntypes++; |
||||
} |
||||
|
||||
|
||||
/************************************************************************/ |
||||
/* */ |
||||
/* yyerror - print an error message with the line number */ |
||||
/* */ |
||||
/************************************************************************/ |
||||
|
||||
void yyerror(char *s) { |
||||
|
||||
fprintf(stderr, "Syntax error in %s on line %d\n", doing, linectr); |
||||
} |
||||
@ -0,0 +1,35 @@
|
||||
/* ethcontrol.c - ethcontrol */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ethcontrol - implement control function for a quark ethernet device |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall ethcontrol ( |
||||
struct dentry *devptr, /* entry in device switch table */ |
||||
int32 func, /* control function */ |
||||
int32 arg1, /* argument 1, if needed */ |
||||
int32 arg2 /* argument 2, if needed */ |
||||
) |
||||
{ |
||||
struct ethcblk *ethptr; /* Ethertab entry pointer */ |
||||
int32 retval = OK; /* Return value of cntl function*/ |
||||
|
||||
ethptr = ðertab[devptr->dvminor]; |
||||
|
||||
switch (func) { |
||||
|
||||
/* Get MAC address */ |
||||
|
||||
case ETH_CTRL_GET_MAC: |
||||
memcpy((byte *)arg1, ethptr->devAddress, |
||||
ETH_ADDR_LEN); |
||||
break; |
||||
|
||||
default: |
||||
return SYSERR; |
||||
} |
||||
|
||||
return retval; |
||||
} |
||||
@ -0,0 +1,123 @@
|
||||
/* ethhandler.c - ethhandler */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ethhandler - TI AM335X Ethernet Interrupt Handler |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
interrupt ethhandler ( |
||||
uint32 xnum /* IRQ number */ |
||||
) |
||||
{ |
||||
struct eth_a_csreg *csrptr; /* Ethernet CSR pointer */ |
||||
struct eth_a_tx_desc *tdescptr; /* Tx desc pointer */ |
||||
struct eth_a_rx_desc *rdescptr; /* Rx desc pointer */ |
||||
struct ethcblk *ethptr = ðertab[0]; /* Ethernet ctl blk ptr */ |
||||
|
||||
csrptr = (struct eth_a_csreg *)ethptr->csr; |
||||
|
||||
if(xnum == ETH_AM335X_TXINT) { /* Transmit interrupt */ |
||||
|
||||
/* Get pointer to first desc in queue */ |
||||
|
||||
tdescptr = (struct eth_a_tx_desc *)ethptr->txRing + |
||||
ethptr->txHead; |
||||
|
||||
/* Defer scheduling until all descs are processed */ |
||||
|
||||
resched_cntl(DEFER_START); |
||||
|
||||
while(semcount(ethptr->osem) < (int32)ethptr->txRingSize) { |
||||
|
||||
/* If desc owned by DMA, check if we need to */ |
||||
/* Restart the transmission */ |
||||
|
||||
if(tdescptr->stat & ETH_AM335X_TDS_OWN) { |
||||
if(csrptr->stateram->tx_hdp[0] == 0) { |
||||
csrptr->stateram->tx_hdp[0] = |
||||
(uint32)tdescptr; |
||||
} |
||||
break; |
||||
} |
||||
|
||||
/* Acknowledge the interrupt */ |
||||
|
||||
csrptr->stateram->tx_cp[0] = (uint32)tdescptr; |
||||
|
||||
/* Increment the head index of the queue */ |
||||
/* And go to the next descriptor in queue */ |
||||
|
||||
ethptr->txHead++; |
||||
tdescptr++; |
||||
if(ethptr->txHead >= ethptr->txRingSize) { |
||||
ethptr->txHead = 0; |
||||
tdescptr = (struct eth_a_tx_desc *) |
||||
ethptr->txRing; |
||||
} |
||||
|
||||
/* Signal the output semaphore */ |
||||
|
||||
signal(ethptr->osem); |
||||
} |
||||
|
||||
/* Acknowledge the transmit interrupt */ |
||||
|
||||
csrptr->cpdma->eoi_vector = 0x2; |
||||
|
||||
/* Resume rescheduling */ |
||||
|
||||
resched_cntl(DEFER_STOP); |
||||
} |
||||
else if(xnum == ETH_AM335X_RXINT) { /* Receive interrupt */ |
||||
|
||||
/* Get the pointer to last desc in the queue */ |
||||
|
||||
rdescptr = (struct eth_a_rx_desc *)ethptr->rxRing + |
||||
ethptr->rxTail; |
||||
|
||||
/* Defer scheduling until all descriptors are processed */ |
||||
|
||||
resched_cntl(DEFER_START); |
||||
|
||||
while(semcount(ethptr->isem) < (int32)ethptr->rxRingSize) { |
||||
|
||||
/* Check if we need to restart the DMA */ |
||||
|
||||
if(rdescptr->stat & ETH_AM335X_RDS_OWN) { |
||||
if(csrptr->stateram->rx_hdp[0] == 0) { |
||||
csrptr->stateram->rx_hdp[0] = |
||||
(uint32)rdescptr; |
||||
} |
||||
break; |
||||
} |
||||
|
||||
/* Acknowledge the interrupt */ |
||||
|
||||
csrptr->stateram->rx_cp[0] = (uint32)rdescptr; |
||||
|
||||
/* Increment the tail index of the queue */ |
||||
/* And go to the next descriptor in the queue */ |
||||
|
||||
ethptr->rxTail++; |
||||
rdescptr++; |
||||
if(ethptr->rxTail >= ethptr->rxRingSize) { |
||||
ethptr->rxTail = 0; |
||||
rdescptr = (struct eth_a_rx_desc *) |
||||
ethptr->rxRing; |
||||
} |
||||
|
||||
/* Signal the input semaphore */ |
||||
|
||||
signal(ethptr->isem); |
||||
} |
||||
|
||||
/* Acknowledge the receive interrupt */ |
||||
|
||||
csrptr->cpdma->eoi_vector = 0x1; |
||||
|
||||
/* Resume rescheduling */ |
||||
|
||||
resched_cntl(DEFER_STOP); |
||||
} |
||||
} |
||||
@ -0,0 +1,403 @@
|
||||
/* ethinit.c - ethinit, eth_phy_read, eth_phy_write */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
struct eth_a_csreg eth_a_regs; |
||||
|
||||
struct ethcblk ethertab[1]; |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* eth_phy_read - read a PHY register |
||||
*----------------------------------------------------------------------- |
||||
*/ |
||||
int32 eth_phy_read ( |
||||
volatile struct eth_a_mdio *mdio,/* MDIO CSR pointer */ |
||||
byte regadr, /* PHY Register number */ |
||||
byte phyadr, /* PHY address */ |
||||
uint32 *value /* Pointer to value */ |
||||
) |
||||
{ |
||||
|
||||
/* Ethernet PHY has only 32 registers */ |
||||
|
||||
if(regadr > 31) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Only 32 possible PHY addresses */ |
||||
|
||||
if(phyadr > 31) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Wait for the previous access to complete */ |
||||
|
||||
while( (mdio->useraccess0 & ETH_AM335X_MDIOUA_GO) != 0 ); |
||||
|
||||
/* Start the access */ |
||||
|
||||
mdio->useraccess0 = (ETH_AM335X_MDIOUA_GO) | |
||||
(regadr << 21) | |
||||
(phyadr << 16); |
||||
|
||||
/* Wait until the access is complete */ |
||||
|
||||
while( (mdio->useraccess0 & ETH_AM335X_MDIOUA_GO) != 0 ); |
||||
|
||||
/* Check if the access was successful */ |
||||
|
||||
if( (mdio->useraccess0 & ETH_AM335X_MDIOUA_ACK) == 0 ) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Copy the value read */ |
||||
|
||||
(*value) = mdio->useraccess0 & ETH_AM335X_MDIOUA_DM; |
||||
|
||||
return OK; |
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* eth_phy_write - write a PHY register |
||||
*----------------------------------------------------------------------- |
||||
*/ |
||||
int32 eth_phy_write ( |
||||
volatile struct eth_a_mdio *mdio, /* MDIO CSR pointer */ |
||||
byte regadr, /* PHY register number */ |
||||
byte phyadr, /* PHY address */ |
||||
uint32 value /* Value to be written */ |
||||
) |
||||
{ |
||||
|
||||
/* There are only 32 PHY registers */ |
||||
|
||||
if(regadr > 31) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* There are only 32 possible PHY addresses */ |
||||
|
||||
if(phyadr > 31) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Wait for the previous access to complete */ |
||||
|
||||
while( (mdio->useraccess0 & ETH_AM335X_MDIOUA_GO) != 0); |
||||
|
||||
/* Start the access */ |
||||
|
||||
mdio->useraccess0 = ETH_AM335X_MDIOUA_GO | |
||||
ETH_AM335X_MDIOUA_WR | |
||||
(regadr << 21) | |
||||
(phyadr << 16) | |
||||
(value & 0xffff); |
||||
|
||||
/* Wait for the access to complete */ |
||||
|
||||
while( (mdio->useraccess0 & ETH_AM335X_MDIOUA_GO) != 0); |
||||
|
||||
return OK; |
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* eth_phy_reset - Reset an Ethernet PHY |
||||
*----------------------------------------------------------------------- |
||||
*/ |
||||
int32 eth_phy_reset ( |
||||
volatile struct eth_a_mdio *mdio, /* MDIO CSR pointer */ |
||||
byte phyadr /* PHY Address */ |
||||
) |
||||
{ |
||||
uint32 phyreg; /* Variable to hold ETH PHY register value */ |
||||
int32 retries;/* Number of retries */ |
||||
int32 retval; /* Return value of functions called here */ |
||||
|
||||
/* Read the PHY Control Register */ |
||||
|
||||
retval = eth_phy_read(mdio, ETH_PHY_CTLREG, phyadr, &phyreg); |
||||
if(retval == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Set the Reset bit and write the register */ |
||||
|
||||
phyreg |= ETH_PHY_CTLREG_RESET; |
||||
eth_phy_write(mdio, ETH_PHY_CTLREG, phyadr, phyreg); |
||||
|
||||
/* Check if Reset operation is complete */ |
||||
|
||||
for(retries = 0; retries < 10; retries++) { |
||||
if(eth_phy_read(mdio, ETH_PHY_CTLREG, phyadr, &phyreg) == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
if((phyreg & ETH_PHY_CTLREG_RESET) == 0) { |
||||
break; |
||||
} |
||||
else { |
||||
retries++; |
||||
DELAY(ETH_AM335X_INIT_DELAY); |
||||
continue; |
||||
} |
||||
} |
||||
if(retries >= 3) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Check if the Link is established */ |
||||
|
||||
for(retries = 0; retries < 10; retries++) { |
||||
if(eth_phy_read(mdio, ETH_PHY_STATREG, phyadr, &phyreg) == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
if(phyreg & ETH_PHY_STATREG_LINK) { |
||||
break; |
||||
} |
||||
else { |
||||
retries++; |
||||
DELAY(ETH_AM335X_INIT_DELAY); |
||||
continue; |
||||
} |
||||
} |
||||
if(retries >= 3) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
return OK; |
||||
} |
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* ethinit - initialize the TI AM335X ethernet hardware |
||||
*----------------------------------------------------------------------- |
||||
*/ |
||||
int32 ethinit ( |
||||
struct dentry *devptr |
||||
) |
||||
{ |
||||
struct ethcblk *ethptr; /* Ethernet control blk pointer */ |
||||
struct eth_a_tx_desc *tdescptr;/* Tx descriptor pointer */ |
||||
struct eth_a_rx_desc *rdescptr;/* Rx descriptor pointer */ |
||||
struct netpacket *pktptr; /* Packet pointer */ |
||||
struct eth_a_csreg *csrptr; /* Ethernet CSR pointer */ |
||||
uint32 phyreg; /* Variable to store PHY reg val*/ |
||||
int32 retval; /* Return value */ |
||||
int32 i; /* Index variable */ |
||||
|
||||
/* Get the Ethernet control block address */ |
||||
/* from the device table entry */ |
||||
|
||||
ethptr = ðertab[devptr->dvminor]; |
||||
|
||||
/* Store the address of CSRs in the Ethernet control block */ |
||||
|
||||
csrptr = ð_a_regs; |
||||
ethptr->csr = csrptr; |
||||
|
||||
/* Initialize the addresses of all the submodules */ |
||||
|
||||
csrptr->ale = (struct eth_a_ale *)ETH_AM335X_ALE_ADDR; |
||||
csrptr->cpdma = (struct eth_a_cpdma *)ETH_AM335X_CPDMA_ADDR; |
||||
csrptr->sl = (struct eth_a_sl *)ETH_AM335X_SL1_ADDR; |
||||
csrptr->stateram = (struct eth_a_stateram *) |
||||
ETH_AM335X_STATERAM_ADDR; |
||||
csrptr->ss = (struct eth_a_ss *)ETH_AM335X_SS_ADDR; |
||||
csrptr->wr = (struct eth_a_wr *)ETH_AM335X_WR_ADDR; |
||||
csrptr->mdio = (struct eth_a_mdio *)ETH_AM335X_MDIO_ADDR; |
||||
|
||||
/* Reset all the submodules */ |
||||
|
||||
csrptr->cpdma->reset = 1; |
||||
while(csrptr->cpdma->reset == 1); |
||||
|
||||
csrptr->sl->reset = 1; |
||||
while(csrptr->sl->reset == 1); |
||||
|
||||
csrptr->wr->reset = 1; |
||||
while(csrptr->wr->reset == 1) ; |
||||
|
||||
csrptr->ss->reset = 1; |
||||
while(csrptr->ss->reset == 1) ; |
||||
|
||||
/* Enable MDIO */ |
||||
|
||||
csrptr->mdio->ctrl |= ETH_AM335X_MDIOCTL_EN; |
||||
|
||||
/* Reset the PHY */ |
||||
|
||||
retval = eth_phy_reset(csrptr->mdio, 0); |
||||
if(retval == SYSERR) { |
||||
kprintf("Cannot reset Ethernet PHY\n"); |
||||
return SYSERR; |
||||
} |
||||
|
||||
retval = eth_phy_read(csrptr->mdio, ETH_PHY_CTLREG, 0, &phyreg); |
||||
if(retval == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
if( (phyreg & ETH_PHY_CTLREG_SM) == ETH_PHY_10M ) { |
||||
kprintf("Ethernet Link is Up. Speed is 10Mbps\n"); |
||||
} |
||||
else if( (phyreg & ETH_PHY_CTLREG_SM) == ETH_PHY_100M ) { |
||||
kprintf("Ethernet Link is Up. Speed is 100Mbps\n"); |
||||
} |
||||
else if( (phyreg & ETH_PHY_CTLREG_SM) == ETH_PHY_1000M ) { |
||||
kprintf("Ethernet Link is Up. Speed is 1000Mbps\n"); |
||||
} |
||||
else { |
||||
return SYSERR; |
||||
} |
||||
|
||||
if(phyreg & ETH_PHY_CTLREG_FD) { |
||||
kprintf("Link is Full Duplex\n"); |
||||
csrptr->sl->macctrl |= ETH_AM335X_SLCTL_FD; |
||||
} |
||||
else { |
||||
kprintf("Link is Half Duplex\n"); |
||||
} |
||||
|
||||
/* Read the device MAC address */ |
||||
for(i = 0; i < 2; i++) { |
||||
ethptr->devAddress[4+i] = *((byte *)(0x44e10630+i)); |
||||
} |
||||
for(i = 0; i < 4; i++) { |
||||
ethptr->devAddress[i] = *((byte *)(0x44e10634+i)); |
||||
} |
||||
|
||||
kprintf("MAC Address is: "); |
||||
for(i = 0; i < 5; i++) { |
||||
kprintf("%02X:", ethptr->devAddress[i]); |
||||
} |
||||
kprintf("%02X\n", ethptr->devAddress[5]); |
||||
|
||||
/* Initialize the rx ring size field */ |
||||
ethptr->rxRingSize = ETH_AM335X_RX_RING_SIZE; |
||||
|
||||
/* Allocate memory for the rx ring */ |
||||
ethptr->rxRing = (void*)getmem(sizeof(struct eth_a_rx_desc)* |
||||
ethptr->rxRingSize); |
||||
if((int32)ethptr->rxRing == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Zero out the rx ring */ |
||||
memset((char*)ethptr->rxRing, NULLCH, |
||||
sizeof(struct eth_a_rx_desc)*ethptr->rxRingSize); |
||||
|
||||
/* Allocate memory for rx buffers */ |
||||
ethptr->rxBufs = (void*)getmem(ETH_BUF_SIZE * |
||||
ethptr->rxRingSize); |
||||
if((int32)ethptr->rxBufs == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Zero out the rx buffers */ |
||||
memset((char *)ethptr->rxBufs, NULLCH, ETH_BUF_SIZE * |
||||
ethptr->rxRingSize); |
||||
|
||||
/* Initialize the rx ring */ |
||||
|
||||
rdescptr = (struct eth_a_rx_desc *)ethptr->rxRing; |
||||
pktptr = (struct netpacket *)ethptr->rxBufs; |
||||
|
||||
for(i = 0; i < ethptr->rxRingSize; i++) { |
||||
rdescptr->next = rdescptr + 1; |
||||
rdescptr->buffer = (uint32)pktptr->net_ethdst; |
||||
rdescptr->buflen = ETH_BUF_SIZE; |
||||
rdescptr->bufoff = 0; |
||||
rdescptr->stat = ETH_AM335X_RDS_OWN; |
||||
rdescptr++; |
||||
pktptr++; |
||||
} |
||||
(--rdescptr)->next = NULL; |
||||
|
||||
ethptr->rxHead = 0; |
||||
ethptr->rxTail = 0; |
||||
ethptr->isem = semcreate(0); |
||||
if((int32)ethptr->isem == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* initialize the tx ring size */ |
||||
ethptr->txRingSize = ETH_AM335X_TX_RING_SIZE; |
||||
|
||||
/* Allocate memory for tx ring */ |
||||
ethptr->txRing = (void*)getmem(sizeof(struct eth_a_tx_desc)* |
||||
ethptr->txRingSize); |
||||
if((int32)ethptr->txRing == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Zero out the tx ring */ |
||||
memset((char*)ethptr->txRing, NULLCH, |
||||
sizeof(struct eth_a_tx_desc)*ethptr->txRingSize); |
||||
|
||||
/* Allocate memory for tx buffers */ |
||||
ethptr->txBufs = (void*)getmem(ETH_BUF_SIZE * |
||||
ethptr->txRingSize); |
||||
if((int32)ethptr->txBufs == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Zero out the tx buffers */ |
||||
memset((char*)ethptr->txBufs, NULLCH, ETH_BUF_SIZE * |
||||
ethptr->txRingSize); |
||||
|
||||
/* Initialize the tx ring */ |
||||
|
||||
tdescptr = (struct eth_a_tx_desc *)ethptr->txRing; |
||||
pktptr = (struct netpacket *)ethptr->txBufs; |
||||
|
||||
for(i = 0; i < ethptr->txRingSize; i++) { |
||||
tdescptr->next = NULL; |
||||
tdescptr->buffer = (uint32)pktptr->net_ethdst; |
||||
tdescptr->buflen = ETH_BUF_SIZE; |
||||
tdescptr->bufoff = 0; |
||||
tdescptr->stat = (ETH_AM335X_TDS_SOP | |
||||
ETH_AM335X_TDS_EOP | |
||||
ETH_AM335X_TDS_DIR | |
||||
ETH_AM335X_TDS_P1); |
||||
tdescptr++; |
||||
pktptr++; |
||||
} |
||||
|
||||
ethptr->txHead = 0; |
||||
ethptr->txTail = 0; |
||||
ethptr->osem = semcreate(ethptr->txRingSize); |
||||
if((int32)ethptr->osem == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Enable the ALE and put it into bypass mode */ |
||||
csrptr->ale->ctrl = (ETH_AM335X_ALECTL_EN | |
||||
ETH_AM335X_ALECTL_BY); |
||||
|
||||
/* Put the ports 0, 1 in forwarding state */ |
||||
csrptr->ale->portctl[0] = ETH_AM335X_ALEPCTL_FWD; |
||||
csrptr->ale->portctl[1] = ETH_AM335X_ALEPCTL_FWD; |
||||
|
||||
/* Start the rx and tx processes in DMA */ |
||||
csrptr->cpdma->tx_ctrl = 1; |
||||
csrptr->cpdma->rx_ctrl = 1; |
||||
|
||||
/* Initialize the head desc pointers for tx and rx */ |
||||
csrptr->stateram->tx_hdp[0] = 0; |
||||
csrptr->stateram->rx_hdp[0] = (uint32)ethptr->rxRing; |
||||
|
||||
/* Enable Rx and Tx in MAC */ |
||||
csrptr->sl->macctrl |= ETH_AM335X_SLCTL_EN; |
||||
|
||||
/* Set interrupt vectors */ |
||||
set_evec(ETH_AM335X_TXINT, (uint32)devptr->dvintr); |
||||
set_evec(ETH_AM335X_RXINT, (uint32)devptr->dvintr); |
||||
|
||||
/* Enable the CPDMA interrupts */ |
||||
csrptr->cpdma->tx_intmask_set = 0x1; |
||||
csrptr->cpdma->rx_intmask_set = 0x1; |
||||
|
||||
/* Route the interrupts to core 0 */ |
||||
csrptr->wr->c0_tx_en = 0x1; |
||||
csrptr->wr->c0_rx_en = 0x1; |
||||
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,69 @@
|
||||
/* ethread.c - ethread */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ethread - read an incoming packet on TI AM335X Ethernet |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
int32 ethread ( |
||||
struct dentry *devptr, |
||||
void *buf, |
||||
uint32 count |
||||
) |
||||
{ |
||||
struct ethcblk *ethptr; /* Ethernet ctl blk ptr */ |
||||
struct eth_a_csreg *csrptr; /* Ethernet CSR pointer */ |
||||
struct eth_a_rx_desc *rdescptr;/* Rx Desc. pointer */ |
||||
struct eth_a_rx_desc *prev; /* Prev Rx desc pointer */ |
||||
uint32 retval; /* Num of bytes returned*/ |
||||
|
||||
ethptr = ðertab[devptr->dvminor]; |
||||
|
||||
/* Get the pointer to Ethernet CSR */ |
||||
csrptr = (struct eth_a_csreg *)ethptr->csr; |
||||
|
||||
/* Wait for a packet */ |
||||
wait(ethptr->isem); |
||||
|
||||
/* Get pointer to the descriptor */ |
||||
rdescptr = (struct eth_a_rx_desc *)ethptr->rxRing + |
||||
ethptr->rxHead; |
||||
|
||||
/* Read the packet length */ |
||||
retval = rdescptr->packlen; |
||||
if(retval > count) { |
||||
retval = count; |
||||
} |
||||
|
||||
/* Copy the packet into user provided buffer */ |
||||
memcpy((char *)buf, (char *)rdescptr->buffer, retval); |
||||
|
||||
/* Initialize the descriptor for next packet */ |
||||
rdescptr->stat = ETH_AM335X_RDS_OWN; |
||||
rdescptr->bufoff = 0; |
||||
rdescptr->buflen = ETH_BUF_SIZE; |
||||
rdescptr->packlen = 0; |
||||
rdescptr->next = NULL; |
||||
|
||||
/* Insert the descriptor into Rx queue */ |
||||
prev = (struct eth_a_rx_desc *)csrptr->stateram->rx_hdp[0]; |
||||
if(prev == NULL) { |
||||
kprintf("hdp 0, adding %x\n", rdescptr); |
||||
csrptr->stateram->rx_hdp[0] = (uint32)rdescptr; |
||||
} |
||||
else { |
||||
while(prev->next != NULL) { |
||||
prev = prev->next; |
||||
} |
||||
prev->next = rdescptr; |
||||
} |
||||
|
||||
/* Increment the head index of rx ring */ |
||||
ethptr->rxHead++; |
||||
if(ethptr->rxHead >= ethptr->rxRingSize) { |
||||
ethptr->rxHead = 0; |
||||
} |
||||
|
||||
return retval; |
||||
} |
||||
@ -0,0 +1,84 @@
|
||||
/* ethwrite.c - ethwrite */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ethwrite - enqueue a packet for transmission on TI AM335X Ethernet |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
int32 ethwrite ( |
||||
struct dentry *devptr, |
||||
void *buf, |
||||
uint32 count |
||||
) |
||||
{ |
||||
struct ethcblk *ethptr; /* Ether entry pointer */ |
||||
struct eth_a_csreg *csrptr; /* Ethernet CSR pointer */ |
||||
struct eth_a_tx_desc *tdescptr;/* Tx Desc. pointer */ |
||||
struct eth_a_tx_desc *prev; /* Prev. Desc. pointer */ |
||||
|
||||
ethptr = ðertab[devptr->dvminor]; |
||||
|
||||
/* Get the pointer to the Ethernet CSR */ |
||||
csrptr = (struct eth_a_csreg *)ethptr->csr; |
||||
|
||||
/* Wait for an empty slot in the queue */ |
||||
wait(ethptr->osem); |
||||
|
||||
/* Get the pointer to the next descriptor */ |
||||
tdescptr = (struct eth_a_tx_desc *)ethptr->txRing + |
||||
ethptr->txTail; |
||||
|
||||
/* Adjust count if greater than max. possible packet size */ |
||||
if(count > PACKLEN) { |
||||
count = PACKLEN; |
||||
} |
||||
|
||||
/* Initialize the descriptor */ |
||||
tdescptr->next = NULL; |
||||
tdescptr->buflen = count; |
||||
tdescptr->bufoff = 0; |
||||
tdescptr->packlen = count; |
||||
tdescptr->stat = (ETH_AM335X_TDS_SOP | /* Start of packet */ |
||||
ETH_AM335X_TDS_EOP | /* End of packet */ |
||||
ETH_AM335X_TDS_OWN | /* Own flag set for DMA */ |
||||
ETH_AM335X_TDS_DIR | /* Directed packet */ |
||||
ETH_AM335X_TDS_P1); /* Output port is port1 */ |
||||
|
||||
/* Copy the packet into the Tx buffer */ |
||||
memcpy((char *)tdescptr->buffer, buf, count); |
||||
|
||||
/* TODO Figure out why we need this hack */ |
||||
/* This ethernet device does not send packets smaller than 60 */ |
||||
/* bytes; So pad a small packet to make it 60 bytes long */ |
||||
|
||||
if(count < 60) { |
||||
memset((char *)tdescptr->buffer+count, 0, 60-count); |
||||
tdescptr->buflen = 60; |
||||
tdescptr->packlen = 60; |
||||
} |
||||
|
||||
/* Insert the descriptor into Tx queue */ |
||||
|
||||
if(csrptr->stateram->tx_hdp[0] == 0) { |
||||
/* Tx queue is empty, this desc. will be the first */ |
||||
csrptr->stateram->tx_hdp[0] = (uint32)tdescptr; |
||||
} |
||||
else { |
||||
/* Tx queue not empty, insert at end */ |
||||
prev = (struct eth_a_tx_desc *) |
||||
csrptr->stateram->tx_hdp[0]; |
||||
while(prev->next != NULL) { |
||||
prev = prev->next; |
||||
} |
||||
prev->next = tdescptr; |
||||
} |
||||
|
||||
/* Increment the tail index of the Tx ring */ |
||||
ethptr->txTail++; |
||||
if(ethptr->txTail >= ethptr->txRingSize) { |
||||
ethptr->txTail = 0; |
||||
} |
||||
|
||||
return count; |
||||
} |
||||
@ -0,0 +1,40 @@
|
||||
/* lfdballoc.c - lfdballoc */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
#define DFILL '+' /* character used to fill a disk block */ |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lfdballoc - Allocate a new data block from free list on disk |
||||
* (assumes directory mutex held) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
dbid32 lfdballoc ( |
||||
struct lfdbfree *dbuff /* Addr. of buffer to hold data block */ |
||||
) |
||||
{ |
||||
dbid32 dnum; /* ID of next d-block on the free list */ |
||||
int32 retval; /* Return value */ |
||||
|
||||
/* Get the ID of first data block on the free list */ |
||||
|
||||
dnum = Lf_data.lf_dir.lfd_dfree; |
||||
if (dnum == LF_DNULL) { /* Ran out of free data blocks */ |
||||
panic("out of data blocks"); |
||||
} |
||||
retval = read(Lf_data.lf_dskdev, (char *)dbuff, dnum); |
||||
if (retval == SYSERR) { |
||||
panic("lfdballoc cannot read disk block\n\r"); |
||||
} |
||||
|
||||
/* Unlink d-block from in-memory directory */ |
||||
|
||||
Lf_data.lf_dir.lfd_dfree = dbuff->lf_nextdb; |
||||
write(Lf_data.lf_dskdev, (char *)&Lf_data.lf_dir, LF_AREA_DIR); |
||||
Lf_data.lf_dirdirty = FALSE; |
||||
|
||||
/* Fill data block to erase old data */ |
||||
|
||||
memset((char *)dbuff, DFILL, LF_BLKSIZ); |
||||
return dnum; |
||||
} |
||||
@ -0,0 +1,25 @@
|
||||
/* lfdbfree.c - lfdbfree */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lfdbfree - Free a data block given its block number (assumes |
||||
* directory mutex is held) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
status lfdbfree( |
||||
did32 diskdev, /* ID of disk device to use */ |
||||
dbid32 dnum /* ID of data block to free */ |
||||
) |
||||
{ |
||||
struct lfdir *dirptr; /* Pointer to directory */ |
||||
struct lfdbfree buf; /* Buffer to hold data block */ |
||||
|
||||
dirptr = &Lf_data.lf_dir; |
||||
buf.lf_nextdb = dirptr->lfd_dfree; |
||||
dirptr->lfd_dfree = dnum; |
||||
write(diskdev, (char *)&buf, dnum); |
||||
write(diskdev, (char *)dirptr, LF_AREA_DIR); |
||||
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,42 @@
|
||||
/* lfflush.c - lfflush */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lfflush - Flush directory, data block, and index block for an open |
||||
* file (assumes file mutex is held) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
status lfflush ( |
||||
struct lflcblk *lfptr /* Ptr to file pseudo device */ |
||||
) |
||||
{ |
||||
|
||||
if (lfptr->lfstate == LF_FREE) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Write the directory if it has changed */ |
||||
|
||||
if (Lf_data.lf_dirdirty) { |
||||
write(Lf_data.lf_dskdev, (char *)&Lf_data.lf_dir, |
||||
LF_AREA_DIR); |
||||
Lf_data.lf_dirdirty = FALSE; |
||||
} |
||||
|
||||
/* Write data block if it has changed */ |
||||
|
||||
if (lfptr->lfdbdirty) { |
||||
write(Lf_data.lf_dskdev, lfptr->lfdblock, lfptr->lfdnum); |
||||
lfptr->lfdbdirty = FALSE; |
||||
} |
||||
|
||||
/* Write i-block if it has changed */ |
||||
|
||||
if (lfptr->lfibdirty) { |
||||
lfibput(Lf_data.lf_dskdev, lfptr->lfinum, &lfptr->lfiblock); |
||||
lfptr->lfibdirty = FALSE; |
||||
} |
||||
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,61 @@
|
||||
/* lfgetmode.c - lfgetmode */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lfgetmode - Parse mode argument and generate integer of mode bits |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
int32 lfgetmode ( |
||||
char *mode /* String of mode characters */ |
||||
) |
||||
{ |
||||
int32 mbits; /* Mode bits to return */ |
||||
char ch; /* Next char in mode string */ |
||||
|
||||
mbits = 0; |
||||
|
||||
/* Mode string specifies: */ |
||||
/* r - read */ |
||||
/* w - write */ |
||||
/* o - old (file must exist) */ |
||||
/* n - new (create a new file) */ |
||||
|
||||
while ( (ch = *mode++) != NULLCH) { |
||||
switch (ch) { |
||||
|
||||
case 'r': if (mbits&LF_MODE_R) { |
||||
return SYSERR; |
||||
} |
||||
mbits |= LF_MODE_R; |
||||
continue; |
||||
|
||||
case 'w': if (mbits&LF_MODE_W) { |
||||
return SYSERR; |
||||
} |
||||
mbits |= LF_MODE_W; |
||||
continue; |
||||
|
||||
case 'o': if (mbits&LF_MODE_O || mbits&LF_MODE_N) { |
||||
return SYSERR; |
||||
} |
||||
mbits |= LF_MODE_O; |
||||
break; |
||||
|
||||
case 'n': if (mbits&LF_MODE_O || mbits&LF_MODE_N) { |
||||
return SYSERR; |
||||
} |
||||
mbits |= LF_MODE_N; |
||||
break; |
||||
|
||||
default: return SYSERR; |
||||
} |
||||
} |
||||
|
||||
/* If neither read nor write specified, allow both */ |
||||
|
||||
if ( (mbits&LF_MODE_RW) == 0 ) { |
||||
mbits |= LF_MODE_RW; |
||||
} |
||||
return mbits; |
||||
} |
||||
@ -0,0 +1,33 @@
|
||||
/* lfiballoc.c - lfiballoc */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lfiballoc - Allocate a new index block from free list on disk |
||||
* (assumes directory mutex held) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
ibid32 lfiballoc (void) |
||||
{ |
||||
ibid32 ibnum; /* ID of next block on the free list */ |
||||
struct lfiblk iblock; /* Buffer to hold an index block */ |
||||
|
||||
/* Get ID of first index block on free list */ |
||||
|
||||
ibnum = Lf_data.lf_dir.lfd_ifree; |
||||
if (ibnum == LF_INULL) { /* Ran out of free index blocks */ |
||||
panic("out of index blocks"); |
||||
} |
||||
lfibget(Lf_data.lf_dskdev, ibnum, &iblock); |
||||
|
||||
/* Unlink index block from the directory free list */ |
||||
|
||||
Lf_data.lf_dir.lfd_ifree = iblock.ib_next; |
||||
|
||||
/* Write a copy of the directory to disk after the change */ |
||||
|
||||
write(Lf_data.lf_dskdev, (char *) &Lf_data.lf_dir, LF_AREA_DIR); |
||||
Lf_data.lf_dirdirty = FALSE; |
||||
|
||||
return ibnum; |
||||
} |
||||
@ -0,0 +1,22 @@
|
||||
/* lfibclear.c - lfibclear */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lfibclear -- Clear an in-core copy of an index block |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
void lfibclear( |
||||
struct lfiblk *ibptr, /* Address of i-block in memory */ |
||||
int32 offset /* File offset for this i-block */ |
||||
) |
||||
{ |
||||
int32 i; /* Index for data block array */ |
||||
|
||||
ibptr->ib_offset = offset; /* Assign specified file offset */ |
||||
for (i=0 ; i<LF_IBLEN ; i++) { /* Clear each data block pointer*/ |
||||
ibptr->ib_dba[i] = LF_DNULL; |
||||
} |
||||
ibptr->ib_next = LF_INULL; /* Set next ptr to null */ |
||||
return; |
||||
} |
||||
@ -0,0 +1,31 @@
|
||||
/* lfibget.c - lfibget */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lfibget - Get an index block from disk given its number (assumes |
||||
* mutex is held) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
void lfibget( |
||||
did32 diskdev, /* Device ID of disk to use */ |
||||
ibid32 inum, /* ID of index block to fetch */ |
||||
struct lfiblk *ibuff /* Buffer to hold index block */ |
||||
)
|
||||
{ |
||||
char *from, *to; /* Pointers used in copying */ |
||||
int32 i; /* Loop index used during copy */ |
||||
char dbuff[LF_BLKSIZ]; /* Buffer to hold disk block */ |
||||
|
||||
/* Read disk block that contains the specified index block */ |
||||
|
||||
read(diskdev, dbuff, ib2sect(inum)); |
||||
|
||||
/* Copy specified index block to caller's ibuff */ |
||||
|
||||
from = dbuff + ib2disp(inum); |
||||
to = (char *)ibuff; |
||||
for (i=0 ; i<sizeof(struct lfiblk) ; i++) |
||||
*to++ = *from++; |
||||
return; |
||||
} |
||||
@ -0,0 +1,43 @@
|
||||
/* lfibput.c - lfibput */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lfibput - Write an index block to disk given its ID (assumes |
||||
* mutex is held) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
status lfibput( |
||||
did32 diskdev, /* ID of disk device */ |
||||
ibid32 inum, /* ID of index block to write */ |
||||
struct lfiblk *ibuff /* Buffer holding the index blk */ |
||||
) |
||||
{ |
||||
dbid32 diskblock; /* ID of disk sector (block) */ |
||||
char *from, *to; /* Pointers used in copying */ |
||||
int32 i; /* Loop index used during copy */ |
||||
char dbuff[LF_BLKSIZ]; /* Temp. buffer to hold d-block */ |
||||
|
||||
/* Compute disk block number and offset of index block */ |
||||
|
||||
diskblock = ib2sect(inum); |
||||
to = dbuff + ib2disp(inum); |
||||
from = (char *)ibuff; |
||||
|
||||
/* Read disk block */ |
||||
|
||||
if (read(diskdev, dbuff, diskblock) == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Copy index block into place */ |
||||
|
||||
for (i=0 ; i<sizeof(struct lfiblk) ; i++) { |
||||
*to++ = *from++; |
||||
} |
||||
|
||||
/* Write the block back to disk */ |
||||
|
||||
write(diskdev, dbuff, diskblock); |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,38 @@
|
||||
/* lflclose.c - lflclose.c */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lflclose - Close a file by flushing output and freeing device entry |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall lflclose ( |
||||
struct dentry *devptr /* Entry in device switch table */ |
||||
) |
||||
{ |
||||
struct lflcblk *lfptr; /* Ptr to open file table entry */ |
||||
|
||||
/* Obtain exclusive use of the file */ |
||||
|
||||
lfptr = &lfltab[devptr->dvminor]; |
||||
wait(lfptr->lfmutex); |
||||
|
||||
/* If file is not open, return an error */ |
||||
|
||||
if (lfptr->lfstate != LF_USED) { |
||||
signal(lfptr->lfmutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Write index or data blocks to disk if they have changed */ |
||||
|
||||
if (Lf_data.lf_dirdirty || lfptr->lfdbdirty || lfptr->lfibdirty) { |
||||
lfflush(lfptr); |
||||
} |
||||
|
||||
/* Set device state to FREE and return to caller */ |
||||
|
||||
lfptr->lfstate = LF_FREE; |
||||
signal(lfptr->lfmutex); |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,47 @@
|
||||
/* lflcontrol.c - lflcontrol */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lflcontrol - Provide control functions for a local file pseudo-device |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall lflcontrol ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
int32 func, /* A control function */ |
||||
int32 arg1, /* Argument #1 */ |
||||
int32 arg2 /* Argument #2 */ |
||||
) |
||||
{ |
||||
struct lflcblk *lfptr; /* Ptr to open file table entry */ |
||||
int32 retval; /* Return value from func. call */ |
||||
|
||||
/* Obtain exclusive use of the file */ |
||||
|
||||
lfptr = &lfltab[devptr->dvminor]; |
||||
wait(lfptr->lfmutex); |
||||
|
||||
/* If file is not open, return an error */ |
||||
|
||||
if (lfptr->lfstate != LF_USED) { |
||||
signal(lfptr->lfmutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
switch (func) { |
||||
|
||||
/* Truncate a file */ |
||||
|
||||
case LF_CTL_TRUNC: |
||||
wait(Lf_data.lf_mutex); |
||||
retval = lftruncate(lfptr); |
||||
signal(Lf_data.lf_mutex); |
||||
signal(lfptr->lfmutex); |
||||
return retval;
|
||||
|
||||
default: |
||||
kprintf("lfcontrol: function %d not valid\n\r", func); |
||||
signal(lfptr->lfmutex); |
||||
return SYSERR; |
||||
} |
||||
} |
||||
@ -0,0 +1,52 @@
|
||||
/* lflgetc.c - lfgetc */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lflgetc - Read the next byte from an open local file |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall lflgetc ( |
||||
struct dentry *devptr /* Entry in device switch table */ |
||||
) |
||||
{ |
||||
struct lflcblk *lfptr; /* Ptr to open file table entry */ |
||||
struct ldentry *ldptr; /* Ptr to file's entry in the */ |
||||
/* in-memory directory */ |
||||
int32 onebyte; /* Next data byte in the file */ |
||||
|
||||
/* Obtain exclusive use of the file */ |
||||
|
||||
lfptr = &lfltab[devptr->dvminor]; |
||||
wait(lfptr->lfmutex); |
||||
|
||||
/* If file is not open, return an error */ |
||||
|
||||
if (lfptr->lfstate != LF_USED) { |
||||
signal(lfptr->lfmutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Return EOF for any attempt to read beyond the end-of-file */ |
||||
|
||||
ldptr = lfptr->lfdirptr; |
||||
if (lfptr->lfpos >= ldptr->ld_size) { |
||||
signal(lfptr->lfmutex); |
||||
return EOF; |
||||
} |
||||
|
||||
/* If byte pointer is beyond the current data block, set up */ |
||||
/* a new data block */ |
||||
|
||||
if (lfptr->lfbyte >= &lfptr->lfdblock[LF_BLKSIZ]) { |
||||
lfsetup(lfptr); |
||||
} |
||||
|
||||
/* Extract the next byte from block, update file position, and */ |
||||
/* return the byte to the caller */ |
||||
|
||||
onebyte = 0xff & *lfptr->lfbyte++; |
||||
lfptr->lfpos++; |
||||
signal(lfptr->lfmutex); |
||||
return onebyte; |
||||
} |
||||
@ -0,0 +1,46 @@
|
||||
/* lflinit.c - lflinit */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
struct lflcblk lfltab[Nlfl]; /* Pseudo-device control blocks */ |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lflinit - Initialize control blocks for local file pseudo-devices |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall lflinit ( |
||||
struct dentry *devptr /* Entry in device switch table */ |
||||
) |
||||
{ |
||||
struct lflcblk *lfptr; /* Ptr. to control block entry */ |
||||
int32 i; /* Walks through name array */ |
||||
|
||||
lfptr = &lfltab[ devptr->dvminor ]; |
||||
|
||||
/* Initialize control block entry */ |
||||
|
||||
lfptr->lfstate = LF_FREE; /* Device is currently unused */ |
||||
lfptr->lfdev = devptr->dvnum; /* Set device ID */ |
||||
lfptr->lfmutex = semcreate(1); /* Create the mutex semaphore */ |
||||
|
||||
/* Initialize the directory and file position */ |
||||
|
||||
lfptr->lfdirptr = (struct ldentry *) NULL; |
||||
lfptr->lfpos = 0; |
||||
for (i=0; i<LF_NAME_LEN; i++) { |
||||
lfptr->lfname[i] = NULLCH; |
||||
} |
||||
|
||||
/* Zero the in-memory index block and data block */ |
||||
|
||||
lfptr->lfinum = LF_INULL; |
||||
memset((char *) &lfptr->lfiblock, NULLCH, sizeof(struct lfiblk)); |
||||
lfptr->lfdnum = 0; |
||||
memset((char *) &lfptr->lfdblock, NULLCH, LF_BLKSIZ); |
||||
|
||||
/* Start with the byte beyond the current data block */ |
||||
|
||||
lfptr->lfbyte = &lfptr->lfdblock[LF_BLKSIZ]; |
||||
lfptr->lfibdirty = lfptr->lfdbdirty = FALSE; |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,64 @@
|
||||
/* lflputc.c - lfputc */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lflputc - Write a single byte to an open local file |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall lflputc ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char ch /* Character (byte) to write */ |
||||
) |
||||
{ |
||||
struct lflcblk *lfptr; /* Ptr to open file table entry */ |
||||
struct ldentry *ldptr; /* Ptr to file's entry in the */ |
||||
/* in-memory directory */ |
||||
|
||||
/* Obtain exclusive use of the file */ |
||||
|
||||
lfptr = &lfltab[devptr->dvminor]; |
||||
wait(lfptr->lfmutex); |
||||
|
||||
/* If file is not open, return an error */ |
||||
|
||||
if (lfptr->lfstate != LF_USED) { |
||||
signal(lfptr->lfmutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Return SYSERR for an attempt to skip bytes beyond the byte */ |
||||
/* that is currently the end of the file */ |
||||
|
||||
ldptr = lfptr->lfdirptr; |
||||
if (lfptr->lfpos > ldptr->ld_size) { |
||||
signal(lfptr->lfmutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* If pointer is outside current block, set up new block */ |
||||
|
||||
if (lfptr->lfbyte >= &lfptr->lfdblock[LF_BLKSIZ]) { |
||||
|
||||
/* Set up block for current file position */ |
||||
|
||||
lfsetup(lfptr); |
||||
} |
||||
|
||||
/* If appending a byte to the file, increment the file size. */ |
||||
/* Note: comparison might be equal, but should not be greater.*/ |
||||
|
||||
if (lfptr->lfpos >= ldptr->ld_size) { |
||||
ldptr->ld_size++; |
||||
Lf_data.lf_dirdirty = TRUE; |
||||
} |
||||
|
||||
/* Place byte in buffer and mark buffer "dirty" */ |
||||
|
||||
*lfptr->lfbyte++ = ch; |
||||
lfptr->lfpos++; |
||||
lfptr->lfdbdirty = TRUE; |
||||
|
||||
signal(lfptr->lfmutex); |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,39 @@
|
||||
/* lflread.c - lflread */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lflread - Read from a previously opened local file |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall lflread ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *buff, /* Buffer to hold bytes */ |
||||
int32 count /* Max bytes to read */ |
||||
) |
||||
{ |
||||
uint32 numread; /* Number of bytes read */ |
||||
int32 nxtbyte; /* Character or SYSERR/EOF */ |
||||
|
||||
if (count < 0) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Iterate and use lflgetc to read individual bytes */ |
||||
|
||||
for (numread=0 ; numread < count ; numread++) { |
||||
nxtbyte = lflgetc(devptr); |
||||
if (nxtbyte == SYSERR) { |
||||
return SYSERR; |
||||
} else if (nxtbyte == EOF) { /* EOF before finished */ |
||||
if (numread == 0) { |
||||
return EOF; |
||||
} else { |
||||
return numread; |
||||
} |
||||
} else { |
||||
*buff++ = (char) (0xff & nxtbyte); |
||||
} |
||||
} |
||||
return numread; |
||||
} |
||||
@ -0,0 +1,41 @@
|
||||
/* lflseek.c - lflseek */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lflseek - Seek to a specified position in a file |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall lflseek ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
uint32 offset /* Byte position in the file */ |
||||
) |
||||
{ |
||||
struct lflcblk *lfptr; /* Ptr to open file table entry */ |
||||
|
||||
/* If file is not open, return an error */ |
||||
|
||||
lfptr = &lfltab[devptr->dvminor]; |
||||
wait(lfptr->lfmutex); |
||||
if (lfptr->lfstate != LF_USED) { |
||||
signal(lfptr->lfmutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Verify offset is within current file size */ |
||||
|
||||
if (offset > lfptr->lfdirptr->ld_size) { |
||||
signal(lfptr->lfmutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Record new offset and invalidate byte pointer (i.e., force */ |
||||
/* the index and data blocks to be replaced if a successive */ |
||||
/* call is made to read or write) */ |
||||
|
||||
lfptr->lfpos = offset; |
||||
lfptr->lfbyte = &lfptr->lfdblock[LF_BLKSIZ]; |
||||
|
||||
signal(lfptr->lfmutex); |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,29 @@
|
||||
/* lflwrite.c - lflwrite */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lflwrite -- Write data to a previously opened local disk file |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall lflwrite ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *buff, /* Buffer holding data to write */ |
||||
int32 count /* Number of bytes to write */ |
||||
) |
||||
{ |
||||
int32 i; /* Number of bytes written */ |
||||
|
||||
if (count < 0) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Iteratate and write one byte at a time */ |
||||
|
||||
for (i=0; i<count; i++) { |
||||
if (lflputc(devptr, *buff++) == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
} |
||||
return count; |
||||
} |
||||
@ -0,0 +1,40 @@
|
||||
/* lfscheck.c - lfscheck */ |
||||
|
||||
#include <xinu.h> |
||||
#include <ramdisk.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lfscheck - Check a directory to verify it contains a Xinu file system |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
status lfscheck ( |
||||
struct lfdir *dirptr /* Ptr to an in-core directory */ |
||||
) |
||||
{ |
||||
uint32 reverse; /* LFS_ID in reverse byte order */ |
||||
|
||||
/* Verify the File System ID, all 0's and all 1's fields */ |
||||
|
||||
if ( (dirptr->lfd_fsysid != LFS_ID) || |
||||
(dirptr->lfd_allzeros != 0x00000000) || |
||||
(dirptr->lfd_allones != 0xffffffff) ) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Check the reverse-order File System ID field */ |
||||
|
||||
reverse = ((LFS_ID>>24) & 0x000000ff) |
|
||||
((LFS_ID>> 8) & 0x0000ff00) | |
||||
((LFS_ID<< 8) & 0x00ff0000) | |
||||
((LFS_ID<<24) & 0xff000000) ; |
||||
|
||||
if (dirptr->lfd_revid != reverse) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Extra sanity check - verify file count is positive */ |
||||
if (dirptr->lfd_nfiles < 0){ |
||||
return SYSERR; |
||||
} |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,65 @@
|
||||
/* lfckfmt.c - lfckfmt */ |
||||
|
||||
#include <xinu.h> |
||||
#include <ramdisk.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lfckfmt - Check the format of an initially-created disk |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
status lfsckfmt ( |
||||
did32 disk /* ID of an open disk device */ |
||||
) |
||||
{ |
||||
uint32 ibsectors; /* Number of sectors of i-blocks*/ |
||||
struct lfdir dir; /* Buffer to hold the directory */ |
||||
uint32 dblks; /* Total free data blocks */ |
||||
struct lfiblk iblock; /* Space for one i-block */ |
||||
struct lfdbfree dblock; /* Data block on the free list */ |
||||
int32 lfiblks; /* Total free index blocks */ |
||||
int32 retval; |
||||
ibid32 nextib; |
||||
dbid32 nextdb; |
||||
|
||||
/* Read directory */ |
||||
|
||||
retval = read(disk,(char *)&dir, LF_AREA_DIR); |
||||
if (retval == SYSERR) { |
||||
panic("cannot read directory"); |
||||
} |
||||
kprintf("Have read directory from disk device %d\n\r", |
||||
disk); |
||||
|
||||
/* Check to see if directory contains a Xinu file system */ |
||||
|
||||
if (lfscheck(&dir) == SYSERR) { |
||||
panic("directory does not contain a Xinu file system"); |
||||
} |
||||
kprintf("Directory corresponds to a local Xinu file system\n"); |
||||
|
||||
/* Follow index block list */ |
||||
|
||||
lfiblks = 0; |
||||
nextib = dir.lfd_ifree; |
||||
kprintf("initial index block is %d\n\r", nextib); |
||||
while (nextib != LF_INULL) { |
||||
lfiblks++; |
||||
lfibget(disk, nextib, &iblock); |
||||
nextib = iblock.ib_next; |
||||
} |
||||
ibsectors = (lfiblks + 6) /7; |
||||
kprintf("Found %d index blocks (%d sectors)\n\r", lfiblks, ibsectors); |
||||
|
||||
/* Follow data block list */ |
||||
|
||||
dblks = 0; |
||||
nextdb = dir.lfd_dfree; |
||||
kprintf("initial data block is %d\n\r", nextdb); |
||||
while (nextdb != LF_DNULL) { |
||||
dblks++; |
||||
read(disk, (char *)&dblock, nextdb); |
||||
nextdb = dblock.lf_nextdb; |
||||
} |
||||
kprintf("Found %d data blocks\n\r", dblks); |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,74 @@
|
||||
/* lfscreate.c - lfscreate */ |
||||
|
||||
#include <xinu.h> |
||||
#include <ramdisk.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lfscreate - Create an initially-empty file system on a disk |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
status lfscreate ( |
||||
did32 disk, /* ID of an open disk device */ |
||||
ibid32 lfiblks, /* Num. of index blocks on disk */ |
||||
uint32 dsiz /* Total size of disk in bytes */ |
||||
) |
||||
{ |
||||
uint32 sectors; /* Number of sectors to use */ |
||||
uint32 ibsectors; /* Number of sectors of i-blocks*/ |
||||
uint32 ibpersector; /* Number of i-blocks per sector*/ |
||||
struct lfdir dir; /* Buffer to hold the directory */ |
||||
uint32 dblks; /* Total free data blocks */ |
||||
struct lfiblk iblock; /* Space for one i-block */ |
||||
struct lfdbfree dblock; /* Data block on the free list */ |
||||
dbid32 dbindex; /* Index for data blocks */ |
||||
int32 retval; /* Return value from func call */ |
||||
int32 i; /* Loop index */ |
||||
|
||||
/* Compute total sectors on disk */ |
||||
|
||||
sectors = dsiz / LF_BLKSIZ; /* Truncate to full sector */ |
||||
|
||||
/* Compute number of sectors comprising i-blocks */ |
||||
|
||||
ibpersector = LF_BLKSIZ / sizeof(struct lfiblk); |
||||
ibsectors = (lfiblks+(ibpersector-1)) / ibpersector;/* Round up */ |
||||
lfiblks = ibsectors * ibpersector; |
||||
if (ibsectors > sectors/2) { /* Invalid arguments */ |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Create an initial directory */ |
||||
|
||||
memset((char *)&dir, NULLCH, sizeof(struct lfdir)); |
||||
dir.lfd_nfiles = 0; |
||||
dbindex= (dbid32)(ibsectors + 1); |
||||
dir.lfd_dfree = dbindex; |
||||
dblks = sectors - ibsectors - 1; |
||||
retval = write(disk,(char *)&dir, LF_AREA_DIR); |
||||
if (retval == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Create list of free i-blocks on disk */ |
||||
|
||||
lfibclear(&iblock, 0); |
||||
for (i=0; i<lfiblks-1; i++) { |
||||
iblock.ib_next = (ibid32)(i + 1); |
||||
lfibput(disk, i, &iblock); |
||||
} |
||||
iblock.ib_next = LF_INULL; |
||||
lfibput(disk, i, &iblock); |
||||
|
||||
/* Create list of free data blocks on disk */ |
||||
|
||||
memset((char*)&dblock, NULLCH, LF_BLKSIZ); |
||||
for (i=0; i<dblks-1; i++) { |
||||
dblock.lf_nextdb = dbindex + 1; |
||||
write(disk, (char *)&dblock, dbindex); |
||||
dbindex++; |
||||
} |
||||
dblock.lf_nextdb = LF_DNULL; |
||||
write(disk, (char *)&dblock, dbindex); |
||||
close(disk); |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,122 @@
|
||||
/* lfsetup.c - lfsetup */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lfsetup - Set a file's index block and data block for the current |
||||
* file position (assumes file mutex held) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
status lfsetup ( |
||||
struct lflcblk *lfptr /* Pointer to slave file device */ |
||||
) |
||||
{ |
||||
dbid32 dnum; /* Data block to fetch */ |
||||
ibid32 ibnum; /* I-block number during search */ |
||||
struct ldentry *ldptr; /* Ptr to file entry in dir. */ |
||||
struct lfiblk *ibptr; /* Ptr to in-memory index block */ |
||||
uint32 newoffset; /* Computed data offset for */ |
||||
/* next index block */ |
||||
int32 dindex; /* Index into array in an index */ |
||||
/* block */ |
||||
|
||||
|
||||
/* Obtain exclusive access to the directory */ |
||||
|
||||
wait(Lf_data.lf_mutex); |
||||
|
||||
/* Get pointers to in-memory directory, file's entry in the */ |
||||
/* directory, and the in-memory index block */ |
||||
|
||||
ldptr = lfptr->lfdirptr; |
||||
ibptr = &lfptr->lfiblock; |
||||
|
||||
/* If existing index block or data block changed, write to disk */ |
||||
|
||||
if (lfptr->lfibdirty || lfptr->lfdbdirty) { |
||||
lfflush(lfptr); |
||||
} |
||||
ibnum = lfptr->lfinum; /* Get ID of curr. index block */ |
||||
|
||||
/* If there is no index block in memory (e.g., because the file */ |
||||
/* was just opened), either load the first index block of */ |
||||
/* the file or allocate a new first index block */ |
||||
|
||||
if (ibnum == LF_INULL) { |
||||
|
||||
/* Check directory entry to see if index block exists */ |
||||
|
||||
ibnum = ldptr->ld_ilist; |
||||
if (ibnum == LF_INULL) { /* Empty file - get new i-block*/ |
||||
ibnum = lfiballoc(); |
||||
lfibclear(ibptr, 0); |
||||
ldptr->ld_ilist = ibnum; |
||||
lfptr->lfibdirty = TRUE; |
||||
} else { /* Nonempty - read first i-block*/ |
||||
lfibget(Lf_data.lf_dskdev, ibnum, ibptr); |
||||
} |
||||
lfptr->lfinum = ibnum; |
||||
|
||||
/* Otherwise, if current file position has been moved to an */ |
||||
/* offset before the current index block, start at the */ |
||||
/* beginning of the index list for the file */ |
||||
|
||||
} else if (lfptr->lfpos < ibptr->ib_offset) { |
||||
|
||||
/* Load initial index block for the file (we know that */ |
||||
/* at least one index block exists) */ |
||||
|
||||
ibnum = ldptr->ld_ilist; |
||||
lfibget(Lf_data.lf_dskdev, ibnum, ibptr); |
||||
lfptr->lfinum = ibnum; |
||||
} |
||||
|
||||
/* At this point, an index block is in memory, but may cover */ |
||||
/* an offset less than the current file position. Loop until */ |
||||
/* the index block covers the current file position. */ |
||||
|
||||
while ((lfptr->lfpos & ~LF_IMASK) > ibptr->ib_offset ) { |
||||
ibnum = ibptr->ib_next; |
||||
if (ibnum == LF_INULL) { |
||||
/* Allocate new index block to extend file */ |
||||
ibnum = lfiballoc(); |
||||
ibptr->ib_next = ibnum; |
||||
lfibput(Lf_data.lf_dskdev, lfptr->lfinum, ibptr); |
||||
lfptr->lfinum = ibnum; |
||||
newoffset = ibptr->ib_offset + LF_IDATA; |
||||
lfibclear(ibptr, newoffset); |
||||
lfptr->lfibdirty = TRUE; |
||||
} else { |
||||
lfibget(Lf_data.lf_dskdev, ibnum, ibptr); |
||||
lfptr->lfinum = ibnum; |
||||
} |
||||
lfptr->lfdnum = LF_DNULL; /* Invalidate old data block */ |
||||
} |
||||
|
||||
/* At this point, the index block in lfiblock covers the */ |
||||
/* current file position (i.e., position lfptr->lfpos). The */ |
||||
/* next step consists of loading the correct data block. */ |
||||
|
||||
dindex = (lfptr->lfpos & LF_IMASK) >> 9; |
||||
|
||||
/* If data block index does not match current data block, read */ |
||||
/* the correct data block from disk */ |
||||
|
||||
dnum = lfptr->lfiblock.ib_dba[dindex]; |
||||
if (dnum == LF_DNULL) { /* Allocate new data block */ |
||||
dnum = lfdballoc((struct lfdbfree *)&lfptr->lfdblock); |
||||
lfptr->lfiblock.ib_dba[dindex] = dnum; |
||||
lfptr->lfibdirty = TRUE; |
||||
} else if ( dnum != lfptr->lfdnum) { |
||||
read(Lf_data.lf_dskdev, (char *)lfptr->lfdblock, dnum); |
||||
lfptr->lfdbdirty = FALSE; |
||||
} |
||||
lfptr->lfdnum = dnum; |
||||
|
||||
/* Use current file offset to set the pointer to the next byte */ |
||||
/* within the data block */ |
||||
|
||||
lfptr->lfbyte = &lfptr->lfdblock[lfptr->lfpos & LF_DMASK]; |
||||
signal(Lf_data.lf_mutex); |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,32 @@
|
||||
/* lfsinit.c - lfsinit */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
struct lfdata Lf_data; |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lfsinit - Initialize the local file system master device |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall lfsinit ( |
||||
struct dentry *devptr /* Entry in device switch table */ |
||||
) |
||||
{ |
||||
/* Assign ID of disk device that will be used */ |
||||
|
||||
Lf_data.lf_dskdev = LF_DISK_DEV; |
||||
|
||||
/* Create a mutual exclusion semaphore */ |
||||
|
||||
Lf_data.lf_mutex = semcreate(1); |
||||
|
||||
/* Zero directory area (for debugging) */ |
||||
|
||||
memset((char *)&Lf_data.lf_dir, NULLCH, sizeof(struct lfdir)); |
||||
|
||||
/* Initialize directory to "not present" in memory */ |
||||
|
||||
Lf_data.lf_dirpresent = Lf_data.lf_dirdirty = FALSE; |
||||
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,185 @@
|
||||
/* lfsopen.c - lfsopen */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lfsopen - Open a file and allocate a local file pseudo-device |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall lfsopen ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *name, /* Name of file to open */ |
||||
char *mode /* Mode chars: 'r' 'w' 'o' 'n' */ |
||||
) |
||||
{ |
||||
struct lfdir *dirptr; /* Ptr to in-memory directory */ |
||||
char *from, *to; /* Ptrs used during copy */ |
||||
char *nam, *cmp; /* Ptrs used during comparison */ |
||||
int32 i; /* General loop index */ |
||||
did32 lfnext; /* Minor number of an unused */ |
||||
/* file pseudo-device */ |
||||
struct ldentry *ldptr; /* Ptr to an entry in directory */ |
||||
struct lflcblk *lfptr; /* Ptr to open file table entry */ |
||||
bool8 found; /* Was the name found? */ |
||||
int32 retval; /* Value returned from function */ |
||||
int32 mbits; /* Mode bits */ |
||||
|
||||
/* Check length of name file (leaving space for NULLCH */ |
||||
|
||||
from = name; |
||||
for (i=0; i< LF_NAME_LEN; i++) { |
||||
if (*from++ == NULLCH) { |
||||
break; |
||||
} |
||||
} |
||||
if (i >= LF_NAME_LEN) { /* Name is too long */ |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Parse mode argument and convert to binary */ |
||||
|
||||
mbits = lfgetmode(mode); |
||||
if (mbits == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* If named file is already open, return SYSERR */ |
||||
|
||||
lfnext = SYSERR; |
||||
for (i=0; i<Nlfl; i++) { /* Search file pseudo-devices */ |
||||
lfptr = &lfltab[i]; |
||||
if (lfptr->lfstate == LF_FREE) { |
||||
if (lfnext == SYSERR) { |
||||
lfnext = i; /* Record index */ |
||||
} |
||||
continue; |
||||
} |
||||
|
||||
/* Compare requested name to name of open file */ |
||||
|
||||
nam = name; |
||||
cmp = lfptr->lfname; |
||||
while(*nam != NULLCH) { |
||||
if (*nam != *cmp) { |
||||
break; |
||||
} |
||||
nam++; |
||||
cmp++; |
||||
} |
||||
|
||||
/* See if comparison succeeded */ |
||||
|
||||
if ( (*nam==NULLCH) && (*cmp == NULLCH) ) { |
||||
return SYSERR; |
||||
} |
||||
} |
||||
if (lfnext == SYSERR) { /* No slave file devices are available */ |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Obtain copy of directory if not already present in memory */ |
||||
|
||||
dirptr = &Lf_data.lf_dir; |
||||
wait(Lf_data.lf_mutex); |
||||
if (! Lf_data.lf_dirpresent) { |
||||
retval = read(Lf_data.lf_dskdev,(char *)dirptr,LF_AREA_DIR); |
||||
if (retval == SYSERR ) { |
||||
signal(Lf_data.lf_mutex); |
||||
return SYSERR; |
||||
} |
||||
if (lfscheck(dirptr) == SYSERR ) { |
||||
kprintf("Disk does not contain a Xinu file system\n"); |
||||
signal(Lf_data.lf_mutex); |
||||
return SYSERR; |
||||
} |
||||
Lf_data.lf_dirpresent = TRUE; |
||||
} |
||||
|
||||
/* Search directory to see if file exists */ |
||||
|
||||
found = FALSE; |
||||
for (i=0; i<dirptr->lfd_nfiles; i++) { |
||||
ldptr = &dirptr->lfd_files[i]; |
||||
nam = name; |
||||
cmp = ldptr->ld_name; |
||||
while(*nam != NULLCH) { |
||||
if (*nam != *cmp) { |
||||
break; |
||||
} |
||||
nam++; |
||||
cmp++; |
||||
} |
||||
if ( (*nam==NULLCH) && (*cmp==NULLCH) ) { /* Name found */ |
||||
found = TRUE; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
/* Case #1 - file is not in directory (i.e., does not exist) */ |
||||
|
||||
if (! found) { |
||||
if (mbits & LF_MODE_O) { /* File *must* exist */ |
||||
signal(Lf_data.lf_mutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Take steps to create new file and add to directory */ |
||||
|
||||
/* Verify that space remains in the directory */ |
||||
|
||||
if (dirptr->lfd_nfiles >= LF_NUM_DIR_ENT) { |
||||
signal(Lf_data.lf_mutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Allocate next dir. entry & initialize to empty file */ |
||||
|
||||
ldptr = &dirptr->lfd_files[dirptr->lfd_nfiles++]; |
||||
ldptr->ld_size = 0; |
||||
from = name; |
||||
to = ldptr->ld_name; |
||||
while ( (*to++ = *from++) != NULLCH ) { |
||||
; |
||||
} |
||||
ldptr->ld_ilist = LF_INULL; |
||||
|
||||
/* Case #2 - file is in directory (i.e., already exists) */ |
||||
|
||||
} else if (mbits & LF_MODE_N) { /* File must not exist */ |
||||
signal(Lf_data.lf_mutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Initialize the local file pseudo-device */ |
||||
|
||||
lfptr = &lfltab[lfnext]; |
||||
lfptr->lfstate = LF_USED; |
||||
lfptr->lfdirptr = ldptr; /* Point to directory entry */ |
||||
lfptr->lfmode = mbits & LF_MODE_RW; |
||||
|
||||
/* File starts at position 0 */ |
||||
|
||||
lfptr->lfpos = 0; |
||||
|
||||
to = lfptr->lfname; |
||||
from = name; |
||||
while ( (*to++ = *from++) != NULLCH ) { |
||||
; |
||||
} |
||||
|
||||
/* Neither index block nor data block are initially valid */ |
||||
|
||||
lfptr->lfinum = LF_INULL; |
||||
lfptr->lfdnum = LF_DNULL; |
||||
|
||||
/* Initialize byte pointer to address beyond the end of the */ |
||||
/* buffer (i.e., invalid pointer triggers setup) */ |
||||
|
||||
lfptr->lfbyte = &lfptr->lfdblock[LF_BLKSIZ]; |
||||
lfptr->lfibdirty = FALSE; |
||||
lfptr->lfdbdirty = FALSE; |
||||
|
||||
signal(Lf_data.lf_mutex); |
||||
|
||||
return lfptr->lfdev; |
||||
} |
||||
@ -0,0 +1,104 @@
|
||||
/* lftruncate.c - lftruncate */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* lftruncate - Truncate a file by freeing its index and data blocks |
||||
* (assumes directory mutex held) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
status lftruncate ( |
||||
struct lflcblk *lfptr /* Ptr to file's cntl blk entry */ |
||||
) |
||||
{ |
||||
struct ldentry *ldptr; /* Pointer to file's dir. entry */ |
||||
struct lfiblk iblock; /* Buffer for one index block */ |
||||
ibid32 ifree; /* Start of index blk free list */ |
||||
ibid32 firstib; /* First index blk of the file */ |
||||
ibid32 nextib; /* Walks down list of the */ |
||||
/* file's index blocks */ |
||||
dbid32 nextdb; /* Next data block to free */ |
||||
int32 i; /* Moves through data blocks in */ |
||||
/* a given index block */ |
||||
|
||||
ldptr = lfptr->lfdirptr; /* Get pointer to dir. entry */ |
||||
if (ldptr->ld_size == 0) { /* File is already empty */ |
||||
return OK; |
||||
} |
||||
|
||||
/* Clean up the open local file first */ |
||||
|
||||
if ( (lfptr->lfibdirty) || (lfptr->lfdbdirty) ) { |
||||
lfflush(lfptr); |
||||
} |
||||
lfptr->lfpos = 0; |
||||
lfptr->lfinum = LF_INULL; |
||||
lfptr->lfdnum = LF_DNULL; |
||||
lfptr->lfbyte = &lfptr->lfdblock[LF_BLKSIZ]; |
||||
|
||||
/* Obtain ID of first index block on free list */ |
||||
|
||||
ifree = Lf_data.lf_dir.lfd_ifree; |
||||
|
||||
/* Record file's first i-block and clear directory entry */ |
||||
|
||||
firstib = ldptr->ld_ilist; |
||||
ldptr->ld_ilist = LF_INULL; |
||||
ldptr->ld_size = 0; |
||||
Lf_data.lf_dirdirty = TRUE; |
||||
|
||||
/* Walk along index block list, disposing of each data block */ |
||||
/* and clearing the corresponding pointer. A note on loop */ |
||||
/* termination: last pointer is set to ifree below. */ |
||||
|
||||
for (nextib=firstib; nextib!=ifree; nextib=iblock.ib_next) { |
||||
|
||||
/* Obtain a copy of current index block from disk */ |
||||
|
||||
lfibget(Lf_data.lf_dskdev, nextib, &iblock); |
||||
|
||||
/* Free each data block in the index block */ |
||||
|
||||
for (i=0; i<LF_IBLEN; i++) { /* For each d-block */ |
||||
|
||||
/* Free the data block */ |
||||
|
||||
nextdb = iblock.ib_dba[i]; |
||||
if (nextdb != LF_DNULL) { |
||||
lfdbfree(Lf_data.lf_dskdev, nextdb); |
||||
} |
||||
|
||||
/* Clear entry in i-block for this d-block */ |
||||
|
||||
iblock.ib_dba[i] = LF_DNULL; |
||||
} |
||||
|
||||
/* Clear offset (just to make debugging easier) */ |
||||
|
||||
iblock.ib_offset = 0; |
||||
|
||||
/* For the last index block on the list, make it point */ |
||||
/* to the current free list */ |
||||
|
||||
if (iblock.ib_next == LF_INULL) { |
||||
iblock.ib_next = ifree; |
||||
} |
||||
|
||||
/* Write cleared i-block back to disk */ |
||||
|
||||
lfibput(Lf_data.lf_dskdev, nextib, &iblock); |
||||
} |
||||
|
||||
/* Last index block on the file list now points to first node */ |
||||
/* on the current free list. Once we make the free list */ |
||||
/* point to the first index block on the file list, the */ |
||||
/* entire set of index blocks will be on the free list */ |
||||
|
||||
Lf_data.lf_dir.lfd_ifree = firstib; |
||||
|
||||
/* Indicate that directory has changed and return */ |
||||
|
||||
Lf_data.lf_dirdirty = TRUE; |
||||
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,64 @@
|
||||
/* gpiocontrol.c - gpiocontrol */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
#define OFFSETMODE(x) (x * 4) |
||||
#define OFFSETCFG(x) ((x * 4) + 2) |
||||
#define OFFSETMODE2(x) ((x - 8) * 4) |
||||
#define OFFSETCFG2(x) (((x - 8) * 4) + 2) |
||||
|
||||
static int setmode(struct dentry * devptr, uint32 mode, uint32 pin)
|
||||
{
|
||||
struct gpio_csreg * csrptr; |
||||
csrptr = (struct gpio_csreg *)(devptr->dvcsr); |
||||
|
||||
if (pin < 8) { |
||||
csrptr->crl &= ~(0x3 << OFFSETMODE(pin)); // clear
|
||||
csrptr->crl |= (mode << OFFSETMODE(pin));
|
||||
} |
||||
|
||||
else { |
||||
csrptr->crh &= ~(0x3 << OFFSETMODE2(pin)); // clear
|
||||
csrptr->crh |= (mode << OFFSETMODE2(pin));
|
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static int setcnf(struct dentry * devptr, uint32 mode, uint32 pin)
|
||||
{ |
||||
struct gpio_csreg * csrptr; |
||||
csrptr = (struct gpio_csreg *)(devptr->dvcsr); |
||||
|
||||
if (pin < 8) { |
||||
csrptr->crl &= ~(0x3 << OFFSETCFG(pin)); // clear
|
||||
csrptr->crl |= (mode << OFFSETCFG(pin));
|
||||
} |
||||
else { |
||||
csrptr->crh &= ~(0x3 << OFFSETCFG2(pin)); // clear
|
||||
csrptr->crh |= (mode << OFFSETCFG2(pin));
|
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* gpiocontrol - Control a gpio device pin settings |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall gpiocontrol(struct dentry * devptr, int32 func, int32 mode, int32 pin) { |
||||
|
||||
switch(func) { |
||||
|
||||
case SETMODE:
|
||||
setmode(devptr, mode, pin); |
||||
break; |
||||
case SETCFG: |
||||
setcnf(devptr, mode, pin); |
||||
break; |
||||
|
||||
default: |
||||
break; |
||||
|
||||
} |
||||
return OK; |
||||
|
||||
} |
||||
@ -0,0 +1,85 @@
|
||||
/* gpiohandler.c - gpiohandler */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* gpiohandler - Handle an interrupt for a gpio device |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
void gpiohandler( |
||||
uint32 xnum /* IRQ number */ |
||||
) |
||||
{ |
||||
struct gpio_csreg *csrptr; /* GPIO CSR pointer */ |
||||
gpiointhook gphookfn; /* The inerrupt function */ |
||||
|
||||
/* Clear all interrupts */ |
||||
|
||||
// if(xnum == GPIO0_INT_A) {
|
||||
// csrptr = (struct gpio_csreg *)(GPIO0_BASE);
|
||||
// gphookfn = gpiotab[0].gphookfn;
|
||||
// if(gphookfn != NULL)
|
||||
// gphookfn(xnum, csrptr->irqstatus0);
|
||||
// csrptr->irqstatus0 = 0xFFFFFFFF;
|
||||
// return;
|
||||
// }
|
||||
// if(xnum == GPIO0_INT_B) {
|
||||
// csrptr = (struct gpio_csreg *)(GPIO0_BASE);
|
||||
// gphookfn = gpiotab[0].gphookfn;
|
||||
// if(gphookfn != NULL)
|
||||
// gphookfn(xnum, csrptr->irqstatus1);
|
||||
// csrptr->irqstatus1 = 0xFFFFFFFF;
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if(xnum == GPIO1_INT_A) {
|
||||
// csrptr = (struct gpio_csreg *)(GPIO1_BASE);
|
||||
// gphookfn = gpiotab[1].gphookfn;
|
||||
// if(gphookfn != NULL)
|
||||
// gphookfn(xnum, csrptr->irqstatus0);
|
||||
// csrptr->irqstatus0 = 0xFFFFFFFF;
|
||||
// return;
|
||||
// }
|
||||
// if(xnum == GPIO1_INT_B) {
|
||||
// csrptr = (struct gpio_csreg *)(GPIO1_BASE);
|
||||
// gphookfn = gpiotab[1].gphookfn;
|
||||
// if(gphookfn != NULL)
|
||||
// gphookfn(xnum, csrptr->irqstatus1);
|
||||
// csrptr->irqstatus1 = 0xFFFFFFFF;
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if(xnum == GPIO2_INT_A) {
|
||||
// csrptr = (struct gpio_csreg *)(GPIO2_BASE);
|
||||
// gphookfn = gpiotab[2].gphookfn;
|
||||
// if(gphookfn != NULL)
|
||||
// gphookfn(xnum, csrptr->irqstatus0);
|
||||
// csrptr->irqstatus0 = 0xFFFFFFFF;
|
||||
// return;
|
||||
// }
|
||||
// if(xnum == GPIO2_INT_B) {
|
||||
// csrptr = (struct gpio_csreg *)(GPIO2_BASE);
|
||||
// gphookfn = gpiotab[2].gphookfn;
|
||||
// if(gphookfn != NULL)
|
||||
// gphookfn(xnum, csrptr->irqstatus1);
|
||||
// csrptr->irqstatus1 = 0xFFFFFFFF;
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if(xnum == GPIO3_INT_A) {
|
||||
// csrptr = (struct gpio_csreg *)(GPIO3_BASE);
|
||||
// gphookfn = gpiotab[3].gphookfn;
|
||||
// if(gphookfn != NULL)
|
||||
// gphookfn(xnum, csrptr->irqstatus0);
|
||||
// csrptr->irqstatus0 = 0xFFFFFFFF;
|
||||
// return;
|
||||
// }
|
||||
// if(xnum == GPIO3_INT_B) {
|
||||
// csrptr = (struct gpio_csreg *)(GPIO3_BASE);
|
||||
// gphookfn = gpiotab[3].gphookfn;
|
||||
// if(gphookfn != NULL)
|
||||
// gphookfn(xnum, csrptr->irqstatus1);
|
||||
// csrptr->irqstatus1 = 0xFFFFFFFF;
|
||||
// return;
|
||||
// }
|
||||
} |
||||
@ -0,0 +1,42 @@
|
||||
/* gpioinit.c - gpioinit */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
struct gpiocblk gpiotab[NGPIO]; |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* gpioinit - Initialize settings for a gpio device |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall gpioinit( |
||||
struct dentry *devptr /* Entry in device switch table */ |
||||
) |
||||
{ |
||||
//struct gpio_csreg * csrptr;
|
||||
struct clock_csreg * clockptr; |
||||
//struct gpiocblk * gpioptr;
|
||||
//csrptr = (struct gpio_csreg *)(devptr->dvcsr);
|
||||
clockptr = (struct clock_csreg *)CLOCK_BASE; |
||||
//gpioptr = &gpiotab[devptr->dvminor];
|
||||
|
||||
/* Enable clock on GPIO */ |
||||
switch (devptr->dvminor) { |
||||
case 0: |
||||
clockptr->apb2enr |= (1 << IOPAEN); |
||||
break; |
||||
case 1: |
||||
clockptr->apb2enr |= (1 << IOPBEN); |
||||
break; |
||||
case 2: |
||||
clockptr->apb2enr |= (1 << IOPCEN); |
||||
break; |
||||
case 3: |
||||
clockptr->apb2enr |= (1 << IOPDEN); |
||||
break; |
||||
default: |
||||
kprintf("Failed to recognize GPIO device"); |
||||
return SYSERR; |
||||
}
|
||||
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,27 @@
|
||||
/* gpioread.c - gpioread */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* gpioread - Read aspecified set of GPIO pins |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall gpioread( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *value, /* Pointer to a 32bit buffer */ |
||||
int32 pinmask /* Pins from which to read */ |
||||
) |
||||
{ |
||||
// struct gpio_csreg *csrptr; /* Pointer to GPIO CSRs */
|
||||
//
|
||||
// /* Obtain the address of the CSR from the device switch table */
|
||||
//
|
||||
// csrptr = (struct gpio_csreg *)(devptr->dvcsr);
|
||||
//
|
||||
// /* Access the GPIO pins, use the mask to select a subset, and */
|
||||
// /* store the result in the specified buffer */
|
||||
//
|
||||
// *((uint32 *)value) = csrptr->datain & pinmask;
|
||||
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,25 @@
|
||||
/* gpioselect.h - pin multiplexing and control for the BBB ZCZ package */ |
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* gpioselect - Configure modes for GPIO pins |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall gpioselect(
|
||||
uint32 pinreg, /* Pin to be affected */ |
||||
uint32 pinmode, /* Multiplexed pin function */
|
||||
uint32 pinsettings /* Settings for the pin */ |
||||
)
|
||||
{ |
||||
// volatile uint32* confreg; /* Pin configuration register */
|
||||
//
|
||||
// /* Pick up the pin configuration register address */
|
||||
//
|
||||
// confreg = &(((uint32*)PINMUXBASE)[pinreg]);
|
||||
//
|
||||
// /* Apply the specified settings to the pin */
|
||||
//
|
||||
// *confreg = pinmode|pinsettings;
|
||||
//
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,31 @@
|
||||
/* gpiowrite.c - gpiowrite */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* gpiowrite - Write value of gpio pins |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall gpiowrite( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *value, /* Pointer to 32-bit buffer */ |
||||
int32 pin /* Pins to be written written */ |
||||
) |
||||
{ |
||||
struct gpio_csreg * csrptr; |
||||
uint8 val; |
||||
|
||||
csrptr = (struct gpio_csreg *)(devptr->dvcsr); |
||||
val = (uint8)value; |
||||
|
||||
if (val == 0) { |
||||
csrptr->odr &= ~(1 << pin); |
||||
return 0; |
||||
} |
||||
else if (val == 1) { |
||||
csrptr->odr |= (1 << pin); |
||||
return 0; |
||||
} |
||||
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,14 @@
|
||||
/* ramclose.c - ramclose */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* Ramclose - Close a ram disk |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall ramclose ( |
||||
struct dentry *devptr /* Entry in device switch table */ |
||||
) |
||||
{ |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,19 @@
|
||||
/* raminit.c - raminit */ |
||||
|
||||
#include <xinu.h> |
||||
#include <ramdisk.h> |
||||
|
||||
struct ramdisk Ram; |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* raminit - Initialize the remote disk system device |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall raminit ( |
||||
struct dentry *devptr /* Entry in device switch table */ |
||||
) |
||||
{ |
||||
memcpy(Ram.disk, "hopeless", 8); |
||||
memcpy( &Ram.disk[8], Ram.disk, RM_BLKSIZ * RM_BLKS - 8); |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,19 @@
|
||||
/* ramopen.c - ramopen */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ramopen - Open a ram disk |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
|
||||
devcall ramopen ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *name, /* Unused for a ram disk */ |
||||
char *mode /* Unused for a ram disk */ |
||||
) |
||||
{ |
||||
/* No action -- just return the device descriptor */ |
||||
|
||||
return devptr->dvnum; |
||||
} |
||||
@ -0,0 +1,21 @@
|
||||
/* ramread.c - ramread */ |
||||
|
||||
#include <xinu.h> |
||||
#include <ramdisk.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ramread - Read a block from a ram disk |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall ramread ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *buff, /* Buffer to hold disk block */ |
||||
int32 blk /* Block number of block to read*/ |
||||
) |
||||
{ |
||||
int32 bpos; /* Byte position of blk */ |
||||
|
||||
bpos = RM_BLKSIZ * blk; |
||||
memcpy(buff, &Ram.disk[bpos], RM_BLKSIZ); |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,21 @@
|
||||
/* ramwrite.c - ramwrite */ |
||||
|
||||
#include <xinu.h> |
||||
#include <ramdisk.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ramwrite - Write a block to a ram disk |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall ramwrite ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *buff, /* Buffer containing a block */ |
||||
int32 blk /* Block number to write */ |
||||
) |
||||
{ |
||||
int32 bpos; /* Byte position of blk */ |
||||
|
||||
bpos = RM_BLKSIZ * blk; |
||||
memcpy(&Ram.disk[bpos], buff, RM_BLKSIZ); |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,58 @@
|
||||
/* ttycontrol.c - ttycontrol */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ttycontrol - Control a tty device by setting modes |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall ttycontrol( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
int32 func, /* Function to perform */ |
||||
int32 arg1, /* Argument 1 for request */ |
||||
int32 arg2 /* Argument 2 for request */ |
||||
) |
||||
{ |
||||
struct ttycblk *typtr; /* Pointer to tty control block */ |
||||
char ch; /* Character for lookahead */ |
||||
|
||||
typtr = &ttytab[devptr->dvminor]; |
||||
|
||||
/* Process the request */ |
||||
|
||||
switch ( func ) { |
||||
|
||||
case TC_NEXTC: |
||||
wait(typtr->tyisem); |
||||
ch = *typtr->tyitail; |
||||
signal(typtr->tyisem); |
||||
return (devcall)ch; |
||||
|
||||
case TC_MODER: |
||||
typtr->tyimode = TY_IMRAW; |
||||
return (devcall)OK; |
||||
|
||||
case TC_MODEC: |
||||
typtr->tyimode = TY_IMCOOKED; |
||||
return (devcall)OK; |
||||
|
||||
case TC_MODEK: |
||||
typtr->tyimode = TY_IMCBREAK; |
||||
return (devcall)OK; |
||||
|
||||
case TC_ICHARS: |
||||
return(semcount(typtr->tyisem)); |
||||
|
||||
case TC_ECHO: |
||||
typtr->tyiecho = TRUE; |
||||
return (devcall)OK; |
||||
|
||||
case TC_NOECHO: |
||||
typtr->tyiecho = FALSE; |
||||
return (devcall)OK; |
||||
|
||||
default: |
||||
return (devcall)SYSERR; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,41 @@
|
||||
/* ttygetc.c - ttygetc */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ttygetc - Read one character from a tty device (interrupts disabled) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall ttygetc( |
||||
struct dentry *devptr /* Entry in device switch table */ |
||||
) |
||||
{ |
||||
char ch; /* Character to return */ |
||||
struct ttycblk *typtr; /* Pointer to ttytab entry */ |
||||
|
||||
typtr = &ttytab[devptr->dvminor]; |
||||
|
||||
/* Wait for a character in the buffer and extract one character */ |
||||
|
||||
|
||||
// struct sentry * semptr;
|
||||
// semptr = &semtab[typtr->tyisem];
|
||||
// while(--(semptr->scount) < 0);
|
||||
wait(typtr->tyisem); |
||||
ch = *typtr->tyihead++; |
||||
|
||||
/* Wrap around to beginning of buffer, if needed */ |
||||
|
||||
if (typtr->tyihead >= &typtr->tyibuff[TY_IBUFLEN]) { |
||||
typtr->tyihead = typtr->tyibuff; |
||||
} |
||||
|
||||
/* In cooked mode, check for the EOF character */ |
||||
|
||||
if ( (typtr->tyimode == TY_IMCOOKED) && (typtr->tyeof) && |
||||
(ch == typtr->tyeofch) ) { |
||||
return (devcall)EOF; |
||||
} |
||||
|
||||
return (devcall)ch; |
||||
} |
||||
@ -0,0 +1,267 @@
|
||||
/* ttyhandle_in.c - ttyhandle_in, erase1, eputc, echoch */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
local void erase1(struct ttycblk *, struct uart_csreg *); |
||||
local void echoch(char, struct ttycblk *, struct uart_csreg *); |
||||
local void eputc(char, struct ttycblk *, struct uart_csreg *); |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ttyhandle_in - Handle one arriving char (interrupts disabled) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
void ttyhandle_in ( |
||||
struct ttycblk *typtr, /* Pointer to ttytab entry */ |
||||
struct uart_csreg *csrptr /* Address of UART's CSR */ |
||||
) |
||||
{ |
||||
char ch; /* Next char from device */ |
||||
int32 avail; /* Chars available in buffer */ |
||||
|
||||
ch = csrptr->dr; |
||||
|
||||
/* Compute chars available */ |
||||
|
||||
avail = semcount(typtr->tyisem); |
||||
if (avail < 0) { /* One or more processes waiting*/ |
||||
avail = 0; |
||||
} |
||||
|
||||
/* Handle raw mode */ |
||||
|
||||
if (typtr->tyimode == TY_IMRAW) { |
||||
if (avail >= TY_IBUFLEN) { /* No space => ignore input */ |
||||
return; |
||||
} |
||||
|
||||
/* Place char in buffer with no editing */ |
||||
|
||||
*typtr->tyitail++ = ch; |
||||
|
||||
/* Wrap buffer pointer */ |
||||
|
||||
if (typtr->tyitail >= &typtr->tyibuff[TY_IBUFLEN]) { |
||||
typtr->tyitail = typtr->tyibuff; |
||||
} |
||||
|
||||
/* Signal input semaphore and return */ |
||||
signal(typtr->tyisem); |
||||
return; |
||||
} |
||||
|
||||
/* Handle cooked and cbreak modes (common part) */ |
||||
|
||||
if ( (ch == TY_RETURN) && typtr->tyicrlf ) { |
||||
ch = TY_NEWLINE; |
||||
} |
||||
|
||||
/* If flow control is in effect, handle ^S and ^Q */ |
||||
|
||||
if (typtr->tyoflow) { |
||||
if (ch == typtr->tyostart) { /* ^Q starts output */ |
||||
typtr->tyoheld = FALSE; |
||||
ttykickout(csrptr); |
||||
return; |
||||
} else if (ch == typtr->tyostop) { /* ^S stops output */ |
||||
typtr->tyoheld = TRUE; |
||||
return; |
||||
} |
||||
} |
||||
|
||||
typtr->tyoheld = FALSE; /* Any other char starts output */ |
||||
|
||||
if (typtr->tyimode == TY_IMCBREAK) { /* Just cbreak mode */ |
||||
|
||||
/* If input buffer is full, send bell to user */ |
||||
|
||||
if (avail >= TY_IBUFLEN) { |
||||
eputc(typtr->tyifullc, typtr, csrptr); |
||||
} else { /* Input buffer has space for this char */ |
||||
*typtr->tyitail++ = ch; |
||||
|
||||
/* Wrap around buffer */ |
||||
|
||||
if (typtr->tyitail>=&typtr->tyibuff[TY_IBUFLEN]) { |
||||
typtr->tyitail = typtr->tyibuff; |
||||
} |
||||
if (typtr->tyiecho) { /* Are we echoing chars?*/ |
||||
echoch(ch, typtr, csrptr); |
||||
} |
||||
signal(typtr->tyisem); |
||||
} |
||||
return; |
||||
|
||||
} else { /* Just cooked mode (see common code above) */ |
||||
|
||||
/* Line kill character arrives - kill entire line */ |
||||
|
||||
if (ch == typtr->tyikillc && typtr->tyikill) { |
||||
typtr->tyitail -= typtr->tyicursor; |
||||
if (typtr->tyitail < typtr->tyibuff) { |
||||
typtr->tyitail += TY_IBUFLEN; |
||||
} |
||||
typtr->tyicursor = 0; |
||||
eputc(TY_RETURN, typtr, csrptr); |
||||
eputc(TY_NEWLINE, typtr, csrptr); |
||||
return; |
||||
} |
||||
|
||||
/* Erase (backspace) character */ |
||||
|
||||
if ( ((ch==typtr->tyierasec) || (ch==typtr->tyierasec2)) |
||||
&& typtr->tyierase) { |
||||
if (typtr->tyicursor > 0) { |
||||
typtr->tyicursor--; |
||||
erase1(typtr, csrptr); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
/* End of line */ |
||||
|
||||
if ( (ch == TY_NEWLINE) || (ch == TY_RETURN) ) { |
||||
if (typtr->tyiecho) { |
||||
echoch(ch, typtr, csrptr); |
||||
} |
||||
*typtr->tyitail++ = ch; |
||||
if (typtr->tyitail>=&typtr->tyibuff[TY_IBUFLEN]) { |
||||
typtr->tyitail = typtr->tyibuff; |
||||
} |
||||
/* Make entire line (plus \n or \r) available */ |
||||
signaln(typtr->tyisem, typtr->tyicursor + 1); |
||||
typtr->tyicursor = 0; /* Reset for next line */ |
||||
return; |
||||
} |
||||
|
||||
/* Character to be placed in buffer - send bell if */ |
||||
/* buffer has overflowed */ |
||||
|
||||
avail = semcount(typtr->tyisem); |
||||
if (avail < 0) { |
||||
avail = 0; |
||||
} |
||||
if ((avail + typtr->tyicursor) >= TY_IBUFLEN-1) { |
||||
eputc(typtr->tyifullc, typtr, csrptr); |
||||
return; |
||||
} |
||||
|
||||
/* EOF character: recognize at beginning of line, but */ |
||||
/* print and ignore otherwise. */ |
||||
|
||||
if (ch == typtr->tyeofch && typtr->tyeof) { |
||||
if (typtr->tyiecho) { |
||||
echoch(ch, typtr, csrptr); |
||||
} |
||||
if (typtr->tyicursor != 0) { |
||||
return; |
||||
} |
||||
*typtr->tyitail++ = ch; |
||||
signal(typtr->tyisem); |
||||
return; |
||||
} |
||||
|
||||
|
||||
/* Echo the character */ |
||||
|
||||
if (typtr->tyiecho) { |
||||
echoch(ch, typtr, csrptr); |
||||
} |
||||
|
||||
/* Insert in the input buffer */ |
||||
|
||||
typtr->tyicursor++; |
||||
*typtr->tyitail++ = ch; |
||||
|
||||
/* Wrap around if needed */ |
||||
|
||||
if (typtr->tyitail >= &typtr->tyibuff[TY_IBUFLEN]) { |
||||
typtr->tyitail = typtr->tyibuff; |
||||
} |
||||
return; |
||||
} |
||||
} |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* erase1 - Erase one character honoring erasing backspace |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
local void erase1( |
||||
struct ttycblk *typtr, /* Ptr to ttytab entry */ |
||||
struct uart_csreg *csrptr /* Address of UART's CSRs */ |
||||
) |
||||
{ |
||||
char ch; /* Character to erase */ |
||||
|
||||
if ( (--typtr->tyitail) < typtr->tyibuff) { |
||||
typtr->tyitail += TY_IBUFLEN; |
||||
} |
||||
|
||||
/* Pick up char to erase */ |
||||
|
||||
ch = *typtr->tyitail; |
||||
if (typtr->tyiecho) { /* Are we echoing? */ |
||||
if (ch < TY_BLANK || ch == 0177) { /* Nonprintable */ |
||||
if (typtr->tyevis) { /* Visual cntl chars */ |
||||
eputc(TY_BACKSP, typtr, csrptr); |
||||
if (typtr->tyieback) { /* Erase char */ |
||||
eputc(TY_BLANK, typtr, csrptr); |
||||
eputc(TY_BACKSP, typtr, csrptr); |
||||
} |
||||
} |
||||
eputc(TY_BACKSP, typtr, csrptr);/* Bypass up arr*/ |
||||
if (typtr->tyieback) { |
||||
eputc(TY_BLANK, typtr, csrptr); |
||||
eputc(TY_BACKSP, typtr, csrptr); |
||||
} |
||||
} else { /* A normal character that is printable */ |
||||
eputc(TY_BACKSP, typtr, csrptr); |
||||
if (typtr->tyieback) { /* erase the character */ |
||||
eputc(TY_BLANK, typtr, csrptr); |
||||
eputc(TY_BACKSP, typtr, csrptr); |
||||
} |
||||
} |
||||
} |
||||
return; |
||||
} |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* echoch - Echo a character with visual and output crlf options |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
local void echoch( |
||||
char ch, /* Character to echo */ |
||||
struct ttycblk *typtr, /* Ptr to ttytab entry */ |
||||
struct uart_csreg *csrptr /* Address of UART's CSRs */ |
||||
) |
||||
{ |
||||
if ((ch==TY_NEWLINE || ch==TY_RETURN) && typtr->tyecrlf) { |
||||
eputc(TY_RETURN, typtr, csrptr); |
||||
eputc(TY_NEWLINE, typtr, csrptr); |
||||
} else if ( (ch<TY_BLANK||ch==0177) && typtr->tyevis) { |
||||
eputc(TY_UPARROW, typtr, csrptr);/* print ^x */ |
||||
eputc(ch+0100, typtr, csrptr); /* Make it printable */ |
||||
} else { |
||||
eputc(ch, typtr, csrptr); |
||||
} |
||||
} |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* eputc - Put one character in the echo queue |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
local void eputc( |
||||
char ch, /* Character to echo */ |
||||
struct ttycblk *typtr, /* Ptr to ttytab entry */ |
||||
struct uart_csreg *csrptr /* Address of UART's CSRs */ |
||||
) |
||||
{ |
||||
*typtr->tyetail++ = ch; |
||||
|
||||
/* Wrap around buffer, if needed */ |
||||
|
||||
if (typtr->tyetail >= &typtr->tyebuff[TY_EBUFLEN]) { |
||||
typtr->tyetail = typtr->tyebuff; |
||||
} |
||||
ttykickout(csrptr); |
||||
return; |
||||
} |
||||
@ -0,0 +1,83 @@
|
||||
/* ttyhandle_out.c - ttyhandle_out */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ttyhandle_out - Handle an output on a tty device by sending more |
||||
* characters to the device FIFO (interrupts disabled) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
void ttyhandle_out( |
||||
struct ttycblk *typtr, /* Ptr to ttytab entry */ |
||||
struct uart_csreg *csrptr /* Address of UART's CSRs */ |
||||
) |
||||
{ |
||||
|
||||
int32 ochars; /* Number of output chars sent */ |
||||
/* to the UART */ |
||||
int32 avail; /* Available chars in output buf*/ |
||||
int32 uspace; /* Space left in onboard UART */ |
||||
/* output FIFO */ |
||||
//uint32 ier = 0;
|
||||
|
||||
/* If output is currently held, simply ignore the call */ |
||||
|
||||
if (typtr->tyoheld) { |
||||
return; |
||||
} |
||||
|
||||
/* If echo and output queues empty, turn off interrupts */ |
||||
|
||||
if ( (typtr->tyehead == typtr->tyetail) && |
||||
(semcount(typtr->tyosem) >= TY_OBUFLEN) ) { |
||||
csrptr->cr1 &= ~(1 << UART_INTR_TX); |
||||
//ier = csrptr->ier;
|
||||
//csrptr->ier = ier & ~UART_IER_ETBEI;
|
||||
return; |
||||
} |
||||
|
||||
/* Initialize uspace to the available space in the Tx FIFO */ |
||||
|
||||
//uspace = UART_FIFO_SIZE - csrptr->txfifo_lvl;
|
||||
uspace = UART_FIFO_SIZE; |
||||
|
||||
|
||||
/* While onboard FIFO is not full and the echo queue is */ |
||||
/* nonempty, xmit chars from the echo queue */ |
||||
|
||||
while ( (uspace>0) && typtr->tyehead != typtr->tyetail) { |
||||
csrptr->dr = *typtr->tyehead++; |
||||
if (typtr->tyehead >= &typtr->tyebuff[TY_EBUFLEN]) { |
||||
typtr->tyehead = typtr->tyebuff; |
||||
} |
||||
uspace--; |
||||
} |
||||
|
||||
/* While onboard FIFO is not full and the output queue is */ |
||||
/* nonempty, transmit chars from the output queue */ |
||||
|
||||
ochars = 0; |
||||
avail = TY_OBUFLEN - semcount(typtr->tyosem); |
||||
while ( (uspace>0) && (avail > 0) ) { |
||||
//while(!(csrptr->sr & UART_TC));
|
||||
//while(csrptr->sr &= ~(1 << UART_TEST));
|
||||
csrptr->dr = *typtr->tyohead++; |
||||
if (typtr->tyohead >= &typtr->tyobuff[TY_OBUFLEN]) { |
||||
typtr->tyohead = typtr->tyobuff; |
||||
} |
||||
avail--; |
||||
uspace--; |
||||
ochars++; |
||||
} |
||||
if (ochars > 0) { |
||||
signaln(typtr->tyosem, ochars); |
||||
} |
||||
|
||||
if ( (typtr->tyehead == typtr->tyetail) && |
||||
(semcount(typtr->tyosem) >= TY_OBUFLEN) ) { |
||||
csrptr->cr1 &= ~(1 << UART_INTR_TX); |
||||
//ier = csrptr->ier;
|
||||
//csrptr->ier = (ier & ~UART_IER_ETBEI);
|
||||
} |
||||
return; |
||||
} |
||||
@ -0,0 +1,114 @@
|
||||
/* ttyhandler.c - ttyhandler */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ttyhandler - Handle an interrupt for a tty (serial) device |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
void ttyhandler(uint32 xnum) { |
||||
struct dentry *devptr; /* Address of device control blk*/ |
||||
struct ttycblk *typtr; /* Pointer to ttytab entry */
|
||||
struct uart_csreg *csrptr; /* Address of UART's CSR */ |
||||
// uint32 iir = 0; /* Interrupt identification */
|
||||
// uint32 lsr = 0; /* Line status */
|
||||
//
|
||||
//
|
||||
/* Get CSR address of the device (assume console for now) */ |
||||
|
||||
devptr = (struct dentry *) &devtab[CONSOLE]; |
||||
csrptr = (struct uart_csreg *) devptr->dvcsr; |
||||
|
||||
/* Obtain a pointer to the tty control block */ |
||||
|
||||
typtr = &ttytab[devptr->dvminor]; |
||||
|
||||
/* Test type of UART interrupt */ |
||||
|
||||
uint8 flags = csrptr->sr & 0xFF; |
||||
//kprintf("%x", flags);
|
||||
if (flags & UART_RXNE) { |
||||
ttyhandle_in(typtr, csrptr); |
||||
return; |
||||
} |
||||
|
||||
else if (flags & UART_TC) { |
||||
ttyhandle_out(typtr, csrptr); |
||||
return; |
||||
|
||||
} |
||||
|
||||
// switch(flags) {
|
||||
//
|
||||
// case UART_TC_TXE:
|
||||
// case UART_TC:
|
||||
// ttyhandle_out(typtr, csrptr);
|
||||
// return;
|
||||
// case UART_RXNE:
|
||||
// ttyhandle_in(typtr, csrptr);
|
||||
// return;
|
||||
//
|
||||
// default:
|
||||
// kprintf("Unknown status\n");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// /* Decode hardware interrupt request from UART device */
|
||||
//
|
||||
// /* Check interrupt identification register */
|
||||
// iir = csrptr->iir;
|
||||
// if (iir & UART_IIR_IRQ) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// /* Decode the interrupt cause based upon the value extracted */
|
||||
// /* from the UART interrupt identification register. Clear */
|
||||
// /* the interrupt source and perform the appropriate handling */
|
||||
// /* to coordinate with the upper half of the driver */
|
||||
//
|
||||
// /* Decode the interrupt cause */
|
||||
//
|
||||
// iir &= UART_IIR_IDMASK; /* Mask off the interrupt ID */
|
||||
// switch (iir) {
|
||||
//
|
||||
// /* Receiver line status interrupt (error) */
|
||||
//
|
||||
// case UART_IIR_RLSI:
|
||||
// lsr = csrptr->lsr;
|
||||
// if(lsr & UART_LSR_BI) { /* Break Interrupt */
|
||||
//
|
||||
// /* Read the RHR register to acknowledge */
|
||||
//
|
||||
// lsr = csrptr->buffer;
|
||||
// }
|
||||
// return;
|
||||
//
|
||||
// /* Receiver data available or timed out */
|
||||
//
|
||||
// case UART_IIR_RDA:
|
||||
// case UART_IIR_RTO:
|
||||
//
|
||||
// resched_cntl(DEFER_START);
|
||||
//
|
||||
// /* While chars avail. in UART buffer, call ttyhandle_in */
|
||||
//
|
||||
// while ( (csrptr->lsr & UART_LSR_DR) != 0) {
|
||||
// ttyhandle_in(typtr, csrptr);
|
||||
// }
|
||||
//
|
||||
// resched_cntl(DEFER_STOP);
|
||||
//
|
||||
// return;
|
||||
//
|
||||
// /* Transmitter output FIFO is empty (i.e., ready for more) */
|
||||
//
|
||||
// case UART_IIR_THRE:
|
||||
// ttyhandle_out(typtr, csrptr);
|
||||
// return;
|
||||
//
|
||||
// /* Modem status change (simply ignore) */
|
||||
//
|
||||
// case UART_IIR_MSC:
|
||||
// return;
|
||||
// }
|
||||
} |
||||
@ -0,0 +1,83 @@
|
||||
/* ttyinit.c - ttyinit */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
struct ttycblk ttytab[Ntty]; |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ttyinit - Initialize buffers and modes for a tty line |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall ttyinit( |
||||
struct dentry *devptr /* Entry in device switch table */ |
||||
) |
||||
{ |
||||
struct ttycblk *typtr; /* Pointer to ttytab entry */ |
||||
struct uart_csreg *uptr; /* Address of UART's CSRs */ |
||||
|
||||
typtr = &ttytab[ devptr->dvminor ]; |
||||
|
||||
/* Initialize values in the tty control block */ |
||||
|
||||
typtr->tyihead = typtr->tyitail = /* Set up input queue */ |
||||
&typtr->tyibuff[0]; /* as empty */ |
||||
typtr->tyisem = semcreate(0); /* Input semaphore */ |
||||
typtr->tyohead = typtr->tyotail = /* Set up output queue */ |
||||
&typtr->tyobuff[0]; /* as empty */ |
||||
typtr->tyosem = semcreate(TY_OBUFLEN); /* Output semaphore */ |
||||
typtr->tyehead = typtr->tyetail = /* Set up echo queue */ |
||||
&typtr->tyebuff[0]; /* as empty */ |
||||
typtr->tyimode = TY_IMCOOKED; /* Start in cooked mode */ |
||||
typtr->tyiecho = TRUE; /* Echo console input */ |
||||
typtr->tyieback = TRUE; /* Honor erasing bksp */ |
||||
typtr->tyevis = TRUE; /* Visual control chars */ |
||||
typtr->tyecrlf = TRUE; /* Echo CRLF for NEWLINE*/ |
||||
typtr->tyicrlf = TRUE; /* Map CR to NEWLINE */ |
||||
typtr->tyierase = TRUE; /* Do erasing backspace */ |
||||
typtr->tyierasec = TY_BACKSP; /* Primary erase char */ |
||||
typtr->tyierasec2= TY_BACKSP2; /* Alternate erase char */ |
||||
typtr->tyeof = TRUE; /* Honor eof on input */ |
||||
typtr->tyeofch = TY_EOFCH; /* End-of-file character*/ |
||||
typtr->tyikill = TRUE; /* Allow line kill */ |
||||
typtr->tyikillc = TY_KILLCH; /* Set line kill to ^U */ |
||||
typtr->tyicursor = 0; /* Start of input line */ |
||||
typtr->tyoflow = TRUE; /* Handle flow control */ |
||||
typtr->tyoheld = FALSE; /* Output not held */ |
||||
typtr->tyostop = TY_STOPCH; /* Stop char is ^S */ |
||||
typtr->tyostart = TY_STRTCH; /* Start char is ^Q */ |
||||
typtr->tyocrlf = TRUE; /* Send CRLF for NEWLINE*/ |
||||
typtr->tyifullc = TY_FULLCH; /* Send ^G when buffer */ |
||||
/* is full */ |
||||
|
||||
/* Initialize UART */ |
||||
struct gpio_csreg *gptr;
|
||||
struct clock_csreg *cptr; |
||||
|
||||
/* Enable 'clock' on peripherals */ |
||||
cptr = (struct clock_csreg *)CLOCK_BASE; |
||||
cptr->apb2enr |= (1 << IOPAEN) | (1 << USART1EN); |
||||
|
||||
/* Set in and output mode */ |
||||
gptr = (struct gpio_csreg *)(0x40010800); |
||||
gptr->crh = 0x44444894; |
||||
|
||||
/* Enable peripheral */ |
||||
uptr = (struct uart_csreg *)(0x40013800); |
||||
uptr->cr1 &= ~(1 << UART_EN); |
||||
|
||||
/* Set baudrate 115200 */ |
||||
uptr->brr = 0x00000045; |
||||
|
||||
uptr->cr1 |= (1 << UART_TX_EN) | (1 << UART_RX_EN); /* Enable lines */ |
||||
uptr->cr1 |= (1 << UART_INTR_RX) | (1 << UART_INTR_TX); /* Enable interrupts */
|
||||
|
||||
/* Set and enable interrupt vector */ |
||||
set_evec(devptr->dvirq, (uint32)devptr->dvintr); |
||||
*NVIC_ISER1 |= (1 << 5); |
||||
|
||||
/* Start the device */ |
||||
uptr->cr1 |= (1 << UART_EN); |
||||
|
||||
// ttykickout(uptr);
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,19 @@
|
||||
/* ttykickout.c - ttykickout */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ttykickout - "Kick" the hardware for a tty device, causing it to |
||||
* generate an output interrupt (interrupts disabled) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
void ttykickout( |
||||
struct uart_csreg *csrptr /* Address of UART's CSRs */ |
||||
) |
||||
{ |
||||
/* Force the UART hardware generate an output interrupt */ |
||||
csrptr->cr1 |= (1 << UART_INTR_TX); |
||||
*NVIC_STIR = 0x25; /* Generate general UART interrupt */ |
||||
|
||||
return; |
||||
} |
||||
@ -0,0 +1,44 @@
|
||||
/* ttyputc.c - ttyputc */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ttyputc - Write one character to a tty device (interrupts disabled) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall ttyputc( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char ch /* Character to write */ |
||||
) |
||||
{ |
||||
//struct uart_csreg * uptr;
|
||||
struct ttycblk *typtr; /* Pointer to tty control block */ |
||||
|
||||
//uptr = (struct uart_csreg *)devptr->csreg;
|
||||
typtr = &ttytab[devptr->dvminor]; |
||||
|
||||
/* Handle output CRLF by sending CR first */ |
||||
|
||||
if ( ch==TY_NEWLINE && typtr->tyocrlf ) { |
||||
ttyputc(devptr, TY_RETURN); |
||||
} |
||||
|
||||
|
||||
wait(typtr->tyosem); /* Wait for space in queue */ |
||||
*typtr->tyotail++ = ch; |
||||
|
||||
/* Wrap around to beginning of buffer, if needed */ |
||||
|
||||
if (typtr->tyotail >= &typtr->tyobuff[TY_OBUFLEN]) { |
||||
typtr->tyotail = typtr->tyobuff; |
||||
} |
||||
|
||||
/* Start output in case device is idle */ |
||||
//while () {
|
||||
//
|
||||
// uptr->dr =
|
||||
//}
|
||||
ttykickout((struct uart_csreg *)devptr->dvcsr); |
||||
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,68 @@
|
||||
/* ttyread.c - ttyread */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ttyread - Read character(s) from a tty device (interrupts disabled) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall ttyread( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *buff, /* Buffer of characters */ |
||||
int32 count /* Count of character to read */ |
||||
) |
||||
{ |
||||
struct ttycblk *typtr; /* Pointer to tty control block */ |
||||
int32 avail; /* Characters available in buff.*/ |
||||
int32 nread; /* Number of characters read */ |
||||
int32 firstch; /* First input character on line*/ |
||||
char ch; /* Next input character */ |
||||
|
||||
if (count < 0) { |
||||
return SYSERR; |
||||
} |
||||
typtr= &ttytab[devptr->dvminor]; |
||||
|
||||
if (typtr->tyimode != TY_IMCOOKED) { |
||||
|
||||
/* For count of zero, return all available characters */ |
||||
|
||||
if (count == 0) { |
||||
avail = semcount(typtr->tyisem); |
||||
if (avail == 0) { |
||||
return 0; |
||||
} else { |
||||
count = avail; |
||||
} |
||||
} |
||||
for (nread = 0; nread < count; nread++) { |
||||
*buff++ = (char) ttygetc(devptr); |
||||
} |
||||
return nread; |
||||
} |
||||
|
||||
/* Block until input arrives */ |
||||
|
||||
firstch = ttygetc(devptr); |
||||
|
||||
/* Check for End-Of-File */ |
||||
|
||||
if (firstch == EOF) { |
||||
return EOF; |
||||
} |
||||
|
||||
/* Read up to a line */ |
||||
|
||||
ch = (char) firstch; |
||||
*buff++ = ch; |
||||
nread = 1; |
||||
while ( (nread < count) && (ch != TY_NEWLINE) && |
||||
(ch != TY_RETURN) ) { |
||||
ch = ttygetc(devptr); |
||||
*buff++ = ch; |
||||
nread++; |
||||
} |
||||
return nread; |
||||
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,29 @@
|
||||
/* ttywrite.c - ttywrite */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* ttywrite - Write character(s) to a tty device (interrupts disabled) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall ttywrite( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *buff, /* Buffer of characters */ |
||||
int32 count /* Count of character to write */ |
||||
) |
||||
{ |
||||
/* Handle negative and zero counts */ |
||||
|
||||
if (count < 0) { |
||||
return SYSERR; |
||||
} else if (count == 0){ |
||||
return OK; |
||||
} |
||||
|
||||
/* Write count characters one at a time */ |
||||
|
||||
for (; count>0 ; count--) { |
||||
ttyputc(devptr, *buff++); |
||||
} |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,76 @@
|
||||
/* mount.c - mount, namlen */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* mount - Add a prefix mapping to the name space |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
syscall mount( |
||||
char *prefix, /* Prefix to add */ |
||||
char *replace, /* Replacement string */ |
||||
did32 device /* Device ID to use */ |
||||
) |
||||
{ |
||||
intmask mask; /* Saved interrupt mask */ |
||||
struct nmentry *namptr; /* Pointer to unused table entry*/ |
||||
int32 psiz, rsiz; /* Sizes of prefix & replacement*/ |
||||
int32 i; /* Counter for copy loop */ |
||||
|
||||
mask = disable(); |
||||
|
||||
psiz = namlen(prefix, NM_PRELEN); |
||||
rsiz = namlen(replace, NM_REPLLEN); |
||||
|
||||
/* If arguments are invalid or table is full, return error */ |
||||
|
||||
if ( (psiz == SYSERR) || (rsiz == SYSERR) || |
||||
(isbaddev(device)) || (nnames >= NNAMES) ) { |
||||
restore(mask); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Allocate a slot in the table */ |
||||
|
||||
namptr = &nametab[nnames]; /* Next unused entry in table */ |
||||
|
||||
/* copy prefix and replacement strings and record device ID */ |
||||
|
||||
for (i=0; i<psiz; i++) { /* Copy prefix into table entry */ |
||||
namptr->nprefix[i] = *prefix++; |
||||
} |
||||
|
||||
for (i=0; i<rsiz; i++) { /* Copy replacement into entry */ |
||||
namptr->nreplace[i] = *replace++; |
||||
} |
||||
|
||||
namptr->ndevice = device; /* Record the device ID */ |
||||
|
||||
nnames++; /* Increment number of names */ |
||||
|
||||
restore(mask); |
||||
return OK; |
||||
} |
||||
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* namlen - Compute the length of a string stopping at maxlen |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
int32 namlen( |
||||
char *name, /* Name to use */ |
||||
int32 maxlen /* Maximum length (including a */ |
||||
/* NULLCH) */ |
||||
) |
||||
{ |
||||
int32 i; /* Count of characters found */ |
||||
|
||||
/* Search until a null terminator or length reaches max */ |
||||
|
||||
for (i=0; i < maxlen; i++) { |
||||
if (*name++ == NULLCH) { |
||||
return i+1; /* Include NULLCH in length */ |
||||
} |
||||
} |
||||
return SYSERR; |
||||
} |
||||
@ -0,0 +1,93 @@
|
||||
/* naminit.c - naminit */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
#ifndef RFILESYS |
||||
#define RFILESYS SYSERR |
||||
#endif |
||||
|
||||
#ifndef FILESYS |
||||
#define FILESYS SYSERR |
||||
#endif |
||||
|
||||
#ifndef LFILESYS |
||||
#define LFILESYS SYSERR |
||||
#endif |
||||
|
||||
struct nmentry nametab[NNAMES]; /* Table of name mappings */ |
||||
int32 nnames; /* Number of entries allocated */ |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* naminit - Initialize the syntactic namespace |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
status naminit(void) |
||||
{ |
||||
did32 i; /* Index into devtab */ |
||||
struct dentry *devptr; /* Pointer to device table entry*/ |
||||
char tmpstr[NM_MAXLEN]; /* String to hold a name */ |
||||
status retval; /* Return value */ |
||||
char *tptr; /* Pointer into tempstring */ |
||||
char *nptr; /* Pointer to device name */ |
||||
char devprefix[] = "/dev/"; /* Prefix to use for devices */ |
||||
int32 len; /* Length of created name */ |
||||
char ch; /* Storage for a character */ |
||||
|
||||
/* Set prefix table to empty */ |
||||
|
||||
nnames = 0; |
||||
|
||||
for (i=0; i<NDEVS ; i++) { |
||||
tptr = tmpstr; |
||||
nptr = devprefix; |
||||
|
||||
/* Copy prefix into tmpstr */ |
||||
|
||||
len = 0; |
||||
while ((*tptr++ = *nptr++) != NULLCH) { |
||||
len++; |
||||
} |
||||
tptr--; /* Move pointer to position before NULLCH */ |
||||
devptr = &devtab[i]; |
||||
nptr = devptr->dvname; /* Move to device name */ |
||||
|
||||
/* Map device name to lower case and append */ |
||||
|
||||
while(++len < NM_MAXLEN) { |
||||
ch = *nptr++; |
||||
if ( (ch >= 'A') && (ch <= 'Z')) { |
||||
ch += 'a' - 'A'; |
||||
} |
||||
if ( (*tptr++ = ch) == NULLCH) { |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if (len > NM_MAXLEN) { |
||||
// RAFA kprintf("namespace: device name %s too long\r\n",
|
||||
kprintf(&m5[0], |
||||
devptr->dvname); |
||||
continue; |
||||
} |
||||
|
||||
retval = mount(tmpstr, NULLSTR, devptr->dvnum); |
||||
if (retval == SYSERR) { |
||||
// RAFA kprintf("namespace: cannot mount device %d\r\n",
|
||||
kprintf(&m4[0], |
||||
devptr->dvname); |
||||
continue; |
||||
} |
||||
} |
||||
|
||||
/* Add other prefixes (longest prefix first) */ |
||||
|
||||
mount("/dev/null", "", NULLDEV); |
||||
// mount("/remote/", "remote:", RFILESYS);
|
||||
// mount("/local/", NULLSTR, LFILESYS);
|
||||
mount("/dev/", NULLSTR, SYSERR); |
||||
// mount("~/", NULLSTR, LFILESYS);
|
||||
// mount("/", "root:", RFILESYS);
|
||||
// mount("", "", LFILESYS);
|
||||
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,135 @@
|
||||
/* nammap.c - nammap, namrepl, namcpy */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
status namcpy(char *, char *, int32); |
||||
did32 namrepl(char *, char[]); |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* nammap - Using namespace, map name to new name and new device |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall nammap( |
||||
char *name, /* The name to map */ |
||||
char newname[NM_MAXLEN], /* Buffer for mapped name */ |
||||
did32 namdev /* ID of the namespace device */ |
||||
) |
||||
{ |
||||
did32 newdev; /* Device descriptor to return */ |
||||
char tmpname[NM_MAXLEN]; /* Temporary buffer for name */ |
||||
int32 iter; /* Number of iterations */ |
||||
|
||||
/* Place original name in temporary buffer and null terminate */ |
||||
|
||||
if (namcpy(tmpname, name, NM_MAXLEN) == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Repeatedly substitute the name prefix until a non-namespace */ |
||||
/* device is reached or an iteration limit is exceeded */ |
||||
|
||||
for (iter=0; iter<nnames ; iter++) { |
||||
newdev = namrepl(tmpname, newname); |
||||
if (newdev != namdev) { |
||||
return newdev; /* Either valid ID or SYSERR */ |
||||
} |
||||
namcpy(tmpname, newname, NM_MAXLEN); |
||||
} |
||||
return SYSERR; |
||||
} |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* namrepl - Use the name table to perform prefix substitution |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
did32 namrepl( |
||||
char *name, /* Original name */ |
||||
char newname[NM_MAXLEN] /* Buffer for mapped name */ |
||||
) |
||||
{ |
||||
int32 i; /* Iterate through name table */ |
||||
char *pptr; /* Walks through a prefix */ |
||||
char *rptr; /* Walks through a replacement */ |
||||
char *optr; /* Walks through original name */ |
||||
char *nptr; /* Walks through new name */ |
||||
char olen; /* Length of original name */ |
||||
/* including the NULL byte */ |
||||
int32 plen; /* Length of a prefix string */ |
||||
/* *not* including NULL byte */ |
||||
int32 rlen; /* Length of replacment string */ |
||||
int32 remain; /* Bytes in name beyond prefix */ |
||||
struct nmentry *namptr; /* Pointer to a table entry */ |
||||
|
||||
/* Search name table for first prefix that matches */ |
||||
|
||||
for (i=0; i<nnames; i++) { |
||||
namptr = &nametab[i]; |
||||
optr = name; /* Start at beginning of name */ |
||||
pptr = namptr->nprefix; /* Start at beginning of prefix */ |
||||
|
||||
/* Compare prefix to string and count prefix size */ |
||||
|
||||
for (plen=0; *pptr != NULLCH ; plen++) { |
||||
if (*pptr != *optr) { |
||||
break; |
||||
} |
||||
pptr++; |
||||
optr++; |
||||
} |
||||
if (*pptr != NULLCH) { /* Prefix does not match */ |
||||
continue; |
||||
} |
||||
|
||||
/* Found a match - check that replacement string plus */ |
||||
/* bytes remaining at the end of the original name will */ |
||||
/* fit into new name buffer. Ignore null on replacement*/ |
||||
/* string, but keep null on remainder of name. */ |
||||
|
||||
olen = namlen(name ,NM_MAXLEN); |
||||
rlen = namlen(namptr->nreplace,NM_MAXLEN) - 1; |
||||
remain = olen - plen; |
||||
if ( (rlen + remain) > NM_MAXLEN) { |
||||
return (did32)SYSERR; |
||||
} |
||||
|
||||
/* Place replacement string followed by remainder of */ |
||||
/* original name (and null) into the new name buffer */ |
||||
|
||||
|
||||
nptr = newname; |
||||
rptr = namptr->nreplace; |
||||
for (; rlen>0 ; rlen--) { |
||||
*nptr++ = *rptr++; |
||||
} |
||||
for (; remain>0 ; remain--) { |
||||
*nptr++ = *optr++; |
||||
} |
||||
return namptr->ndevice; |
||||
} |
||||
return (did32)SYSERR; |
||||
} |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* namcpy - Copy a name from one buffer to another, checking length |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
status namcpy( |
||||
char *newname, /* Buffer to hold copy */ |
||||
char *oldname, /* Buffer containing name */ |
||||
int32 buflen /* Size of buffer for copy */ |
||||
) |
||||
{ |
||||
char *nptr; /* Point to new name */ |
||||
char *optr; /* Point to old name */ |
||||
int32 cnt; /* Count of characters copied */ |
||||
|
||||
nptr = newname; |
||||
optr = oldname; |
||||
|
||||
for (cnt=0; cnt<buflen; cnt++) { |
||||
if ( (*nptr++ = *optr++) == NULLCH) { |
||||
return OK; |
||||
} |
||||
} |
||||
return SYSERR; /* Buffer filled before copy completed */ |
||||
} |
||||
@ -0,0 +1,29 @@
|
||||
/* namopen.c - namopen */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* namopen - Open a file or device based on the name |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall namopen( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *name, /* Name to open */ |
||||
char *mode /* Mode argument */ |
||||
) |
||||
{ |
||||
char newname[NM_MAXLEN]; /* Name with prefix replaced */ |
||||
did32 newdev; /* Device ID after mapping */ |
||||
|
||||
/* Use namespace to map name to a new name and new descriptor */ |
||||
|
||||
newdev = nammap(name, newname, devptr->dvnum); |
||||
|
||||
if (newdev == SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Open underlying device and return status */ |
||||
|
||||
return open(newdev, newname, mode); |
||||
} |
||||
@ -0,0 +1,50 @@
|
||||
/* rdsbufalloc.c - rdsbufalloc */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rdsbufalloc - Allocate a buffer from the free list or the cache |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
struct rdbuff *rdsbufalloc ( |
||||
struct rdscblk *rdptr /* Ptr to device control block */ |
||||
) |
||||
{ |
||||
struct rdbuff *bptr; /* Pointer to a buffer */ |
||||
struct rdbuff *pptr; /* Pointer to previous buffer */ |
||||
struct rdbuff *nptr; /* Pointer to next buffer */ |
||||
|
||||
/* Wait for an available buffer */ |
||||
|
||||
wait(rdptr->rd_availsem); |
||||
|
||||
/* If free list contains a buffer, extract it */ |
||||
|
||||
bptr = rdptr->rd_free; |
||||
|
||||
if ( bptr != (struct rdbuff *)NULL ) { |
||||
rdptr->rd_free = bptr->rd_next; |
||||
return bptr; |
||||
} |
||||
|
||||
/* Extract oldest item in cache that has ref count zero (at */ |
||||
/* least one such entry must exist because the semaphore */ |
||||
/* had a nonzero count) */ |
||||
|
||||
bptr = rdptr->rd_ctprev; |
||||
while (bptr != (struct rdbuff *) &rdptr->rd_chnext) { |
||||
if (bptr->rd_refcnt <= 0) { |
||||
|
||||
/* Remove from cache and return to caller */ |
||||
|
||||
pptr = bptr->rd_prev; |
||||
nptr = bptr->rd_next; |
||||
pptr->rd_next = nptr; |
||||
nptr->rd_prev = pptr; |
||||
return bptr; |
||||
} |
||||
bptr = bptr->rd_prev; |
||||
} |
||||
panic("Remote disk cannot find an available buffer"); |
||||
return (struct rdbuff *)SYSERR; |
||||
} |
||||
@ -0,0 +1,60 @@
|
||||
/* rdsclose.c - rdsclose */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rdsclose - Close a remote disk device |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall rdsclose ( |
||||
struct dentry *devptr /* Entry in device switch table */ |
||||
) |
||||
{ |
||||
struct rdscblk *rdptr; /* Ptr to control block entry */ |
||||
struct rdbuff *bptr; /* Ptr to buffer on a list */ |
||||
struct rdbuff *nptr; /* Ptr to next buff on the list */ |
||||
int32 nmoved; /* Number of buffers moved */ |
||||
|
||||
/* Device must be open */ |
||||
|
||||
rdptr = &rdstab[devptr->dvminor]; |
||||
if (rdptr->rd_state != RD_OPEN) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Request queue must be empty */ |
||||
|
||||
if (rdptr->rd_rhnext != (struct rdbuff *)&rdptr->rd_rtnext) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Move all buffers from the cache to the free list */ |
||||
|
||||
bptr = rdptr->rd_chnext; |
||||
nmoved = 0; |
||||
while (bptr != (struct rdbuff *)&rdptr->rd_ctnext) { |
||||
nmoved++; |
||||
|
||||
/* Unlink buffer from cache */ |
||||
|
||||
nptr = bptr->rd_next; |
||||
(bptr->rd_prev)->rd_next = nptr; |
||||
nptr->rd_prev = bptr->rd_prev; |
||||
|
||||
/* Insert buffer into free list */ |
||||
|
||||
bptr->rd_next = rdptr->rd_free; |
||||
|
||||
rdptr->rd_free = bptr; |
||||
bptr->rd_status = RD_INVALID; |
||||
|
||||
/* Move to next buffer in the cache */ |
||||
|
||||
bptr = nptr; |
||||
} |
||||
|
||||
/* Set the state to indicate the device is closed */ |
||||
|
||||
rdptr->rd_state = RD_FREE; |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,124 @@
|
||||
/* rdscomm.c - rdscomm */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rdscomm - handle communication with a remote disk server (send a |
||||
* request and receive a reply, including sequencing and |
||||
* retries) |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
status rdscomm ( |
||||
struct rd_msg_hdr *msg, /* Message to send */ |
||||
int32 mlen, /* Message length */ |
||||
struct rd_msg_hdr *reply, /* Buffer for reply */ |
||||
int32 rlen, /* Size of reply buffer */ |
||||
struct rdscblk *rdptr /* Ptr to device control block */ |
||||
) |
||||
{ |
||||
intmask mask; /* Saved interrupt mask */ |
||||
int32 i; /* Counts retries */ |
||||
int32 retval; /* Return value */ |
||||
int32 seq; /* Sequence for this exchange */ |
||||
uint32 localip; /* Local IP address */ |
||||
int16 rtype; /* Reply type in host byte order*/ |
||||
bool8 xmit; /* Should we transmit again? */ |
||||
int32 slot; /* UDP slot */ |
||||
|
||||
/* Disable interrupts while testing status */ |
||||
|
||||
mask = disable(); |
||||
|
||||
/* Register the server port, if not registered */ |
||||
|
||||
if ( ! rdptr->rd_registered ) { |
||||
slot = udp_register(0, rdptr->rd_ser_port, |
||||
rdptr->rd_loc_port); |
||||
if(slot == SYSERR) { |
||||
restore(mask); |
||||
return SYSERR; |
||||
} |
||||
rdptr->rd_udpslot = slot; |
||||
rdptr->rd_registered = TRUE; |
||||
} |
||||
|
||||
/* Get the local IP address */ |
||||
|
||||
if ( NetData.ipvalid == FALSE ) { |
||||
localip = getlocalip(); |
||||
if((int32)localip == SYSERR) { |
||||
restore(mask); |
||||
return SYSERR; |
||||
} |
||||
} |
||||
restore(mask); |
||||
|
||||
/* Retrieve the saved UDP slot number */ |
||||
|
||||
slot = rdptr->rd_udpslot; |
||||
|
||||
/* Assign message next sequence number */ |
||||
|
||||
seq = rdptr->rd_seq++; |
||||
msg->rd_seq = htonl(seq); |
||||
|
||||
/* Repeat RD_RETRIES times: send message and receive reply */ |
||||
|
||||
xmit = TRUE; |
||||
for (i=0; i<RD_RETRIES; i++) { |
||||
if (xmit) { |
||||
|
||||
/* Send a copy of the message */ |
||||
|
||||
retval = udp_sendto(slot, rdptr->rd_ser_ip, rdptr->rd_ser_port, |
||||
(char *)msg, mlen); |
||||
if (retval == SYSERR) { |
||||
kprintf("Cannot send to remote disk server\n\r"); |
||||
return SYSERR; |
||||
} |
||||
} else { |
||||
xmit = TRUE; |
||||
} |
||||
|
||||
/* Receive a reply */ |
||||
|
||||
retval = udp_recv(slot, (char *)reply, rlen, |
||||
RD_TIMEOUT); |
||||
|
||||
if (retval == TIMEOUT) { |
||||
continue; |
||||
} else if (retval == SYSERR) { |
||||
kprintf("Error reading remote disk reply\n\r"); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Verify that sequence in reply matches request */ |
||||
|
||||
|
||||
if (ntohl(reply->rd_seq) < seq) { |
||||
xmit = FALSE; |
||||
} else if (ntohl(reply->rd_seq) != seq) { |
||||
continue; |
||||
} |
||||
|
||||
/* Verify the type in the reply matches the request */ |
||||
|
||||
rtype = ntohs(reply->rd_type); |
||||
if (rtype != ( ntohs(msg->rd_type) | RD_MSG_RESPONSE) ) { |
||||
continue; |
||||
} |
||||
|
||||
/* Check the status */ |
||||
|
||||
if (ntohs(reply->rd_status) != 0) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
return OK; |
||||
} |
||||
|
||||
/* Retries exhausted without success */ |
||||
|
||||
kprintf("Timeout on exchange with remote disk server\n\r"); |
||||
return TIMEOUT; |
||||
} |
||||
@ -0,0 +1,131 @@
|
||||
/* rdscontrol.c - rdscontrol */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rdscontrol - Provide control functions for the remote disk |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall rdscontrol ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
int32 func, /* The control function to use */ |
||||
int32 arg1, /* Argument #1 */ |
||||
int32 arg2 /* Argument #2 */ |
||||
) |
||||
{ |
||||
struct rdscblk *rdptr; /* Pointer to control block */ |
||||
struct rdbuff *bptr; /* Ptr to buffer that will be */ |
||||
/* placed on the req. queue */ |
||||
struct rdbuff *pptr; /* Ptr to "previous" node on */ |
||||
/* a list */ |
||||
struct rd_msg_dreq msg; /* Buffer for delete request */ |
||||
struct rd_msg_dres resp; /* Buffer for delete response */ |
||||
char *to, *from; /* Used during name copy */ |
||||
int32 retval; /* Return value */ |
||||
|
||||
/* Verify that device is currently open */ |
||||
|
||||
rdptr = &rdstab[devptr->dvminor]; |
||||
if (rdptr->rd_state != RD_OPEN) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Ensure rdsprocess is runnning */ |
||||
|
||||
if ( ! rdptr->rd_comruns ) { |
||||
rdptr->rd_comruns = TRUE; |
||||
resume(rdptr->rd_comproc); |
||||
} |
||||
|
||||
switch (func) { |
||||
|
||||
/* Synchronize writes */ |
||||
|
||||
case RDS_CTL_SYNC: |
||||
|
||||
/* Allocate a buffer to use for the request list */ |
||||
|
||||
bptr = rdsbufalloc(rdptr); |
||||
if (bptr == (struct rdbuff *)SYSERR) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Form a sync request */ |
||||
|
||||
bptr->rd_op = RD_OP_SYNC; |
||||
bptr->rd_refcnt = 1; |
||||
bptr->rd_blknum = 0; /* Unused */ |
||||
bptr->rd_status = RD_INVALID; |
||||
bptr->rd_pid = getpid(); |
||||
|
||||
/* Insert new request into list just before tail */ |
||||
|
||||
pptr = rdptr->rd_rtprev; |
||||
rdptr->rd_rtprev = bptr; |
||||
bptr->rd_next = pptr->rd_next; |
||||
bptr->rd_prev = pptr; |
||||
pptr->rd_next = bptr; |
||||
|
||||
/* Prepare to wait until item is processed */ |
||||
|
||||
recvclr(); |
||||
|
||||
/* Signal then semaphore to start communication */ |
||||
|
||||
signal(rdptr->rd_reqsem); |
||||
|
||||
/* Block to wait for a message */ |
||||
|
||||
bptr = (struct rdbuff *)receive(); |
||||
if (bptr == (struct rdbuff *)SYSERR) {
|
||||
return SYSERR; |
||||
} |
||||
break; |
||||
|
||||
/* Delete the remote disk (entirely remove it) */ |
||||
|
||||
case RDS_CTL_DEL: |
||||
|
||||
/* Handcraft a message for the server that requests */ |
||||
/* deleting the disk with the specified ID */ |
||||
|
||||
msg.rd_type = htons(RD_MSG_DREQ);/* Request deletion */ |
||||
msg.rd_status = htons(0); |
||||
msg.rd_seq = 0; /* rdscomm will insert sequence # later */ |
||||
to = msg.rd_id; |
||||
memset(to, NULLCH, RD_IDLEN); /* Initialize to zeroes */ |
||||
from = rdptr->rd_id; |
||||
while ( (*to++ = *from++) != NULLCH ) { /* copy ID */ |
||||
; |
||||
} |
||||
|
||||
/* Send message and receive response */ |
||||
|
||||
retval = rdscomm((struct rd_msg_hdr *)&msg, |
||||
sizeof(struct rd_msg_dreq), |
||||
(struct rd_msg_hdr *)&resp, |
||||
sizeof(struct rd_msg_dres), |
||||
rdptr); |
||||
|
||||
/* Check response */ |
||||
|
||||
if (retval == SYSERR) { |
||||
return SYSERR; |
||||
} else if (retval == TIMEOUT) { |
||||
kprintf("Timeout during remote file delete\n\r"); |
||||
return SYSERR; |
||||
} else if (ntohs(resp.rd_status) != 0) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Close local device */ |
||||
|
||||
return rdsclose(devptr); |
||||
|
||||
default: |
||||
kprintf("rfsControl: function %d not valid\n\r", func); |
||||
return SYSERR; |
||||
} |
||||
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,108 @@
|
||||
/* rdsinit.c - rdsinit */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
struct rdscblk rdstab[Nrds]; |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rdsinit - Initialize the remote disk system device |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall rdsinit ( |
||||
struct dentry *devptr /* Entry in device switch table */ |
||||
) |
||||
{ |
||||
struct rdscblk *rdptr; /* Ptr to device contol block */ |
||||
struct rdbuff *bptr; /* Ptr to buffer in memory */ |
||||
/* used to form linked list */ |
||||
struct rdbuff *pptr; /* Ptr to previous buff on list */ |
||||
struct rdbuff *buffend; /* Last address in buffer memory*/ |
||||
uint32 size; /* Total size of memory needed */ |
||||
/* buffers */ |
||||
|
||||
/* Obtain address of control block */ |
||||
|
||||
rdptr = &rdstab[devptr->dvminor]; |
||||
|
||||
/* Set control block to unused */ |
||||
|
||||
rdptr->rd_state = RD_FREE; |
||||
|
||||
/* Create the resprocess and leave it suspended. */ |
||||
/* Note: the process cannot be resumed because */ |
||||
/* device initialization occurs before interrupts */ |
||||
/* are enabled. */ |
||||
|
||||
rdptr->rd_comproc = create(rdsprocess, RD_STACK, RD_PRIO, |
||||
"rdsproc", 1, rdptr); |
||||
if (rdptr->rd_comproc == SYSERR) { |
||||
panic("Cannot create remote disk process"); |
||||
} |
||||
rdptr->rd_comruns = FALSE; |
||||
|
||||
rdptr->rd_id[0] = NULLCH; |
||||
|
||||
/* Set initial message sequence number */ |
||||
|
||||
rdptr->rd_seq = 1; |
||||
|
||||
/* Initialize request queue and cache to empty */ |
||||
|
||||
rdptr->rd_rhnext = (struct rdbuff *) &rdptr->rd_rtnext; |
||||
rdptr->rd_rhprev = (struct rdbuff *)NULL; |
||||
|
||||
rdptr->rd_rtnext = (struct rdbuff *)NULL; |
||||
rdptr->rd_rtprev = (struct rdbuff *) &rdptr->rd_rhnext; |
||||
|
||||
|
||||
rdptr->rd_chnext = (struct rdbuff *) &rdptr->rd_ctnext; |
||||
rdptr->rd_chprev = (struct rdbuff *)NULL; |
||||
|
||||
rdptr->rd_ctnext = (struct rdbuff *)NULL; |
||||
rdptr->rd_ctprev = (struct rdbuff *) &rdptr->rd_chnext; |
||||
|
||||
/* Allocate memory for a set of buffers (actually request */ |
||||
/* blocks and link them to form the initial free list */ |
||||
|
||||
size = sizeof(struct rdbuff) * RD_BUFFS; |
||||
|
||||
bptr = (struct rdbuff *)getmem(size); |
||||
rdptr->rd_free = bptr; |
||||
|
||||
if ((int32)bptr == SYSERR) { |
||||
panic("Cannot allocate memory for remote disk buffers"); |
||||
} |
||||
|
||||
pptr = (struct rdbuff *) NULL; /* To avoid a compiler warning */ |
||||
buffend = (struct rdbuff *) ((char *)bptr + size); |
||||
while (bptr < buffend) { /* walk through memory */ |
||||
pptr = bptr; |
||||
bptr = (struct rdbuff *) |
||||
(sizeof(struct rdbuff)+ (char *)bptr); |
||||
pptr->rd_status = RD_INVALID; /* Buffer is empty */ |
||||
pptr->rd_next = bptr; /* Point to next buffer */ |
||||
} |
||||
pptr->rd_next = (struct rdbuff *) NULL; /* Last buffer on list */ |
||||
|
||||
/* Create the request list and available buffer semaphores */ |
||||
|
||||
rdptr->rd_availsem = semcreate(RD_BUFFS); |
||||
rdptr->rd_reqsem = semcreate(0); |
||||
|
||||
/* Set the server IP address, server port, and local port */ |
||||
|
||||
if ( dot2ip(RD_SERVER_IP, &rdptr->rd_ser_ip) == SYSERR ) { |
||||
panic("invalid IP address for remote disk server"); |
||||
} |
||||
|
||||
/* Set the port numbers */ |
||||
|
||||
rdptr->rd_ser_port = RD_SERVER_PORT; |
||||
rdptr->rd_loc_port = RD_LOC_PORT + devptr->dvminor; |
||||
|
||||
/* Specify that the server port is not yet registered */ |
||||
|
||||
rdptr->rd_registered = FALSE; |
||||
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,93 @@
|
||||
/* rdsopen.c - rdsopen */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rdsopen - Open a remote disk device and specify an ID to use |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
|
||||
devcall rdsopen ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *diskid, /* Disk ID to use */ |
||||
char *mode /* Unused for a remote disk */ |
||||
) |
||||
{ |
||||
struct rdscblk *rdptr; /* Ptr to control block entry */ |
||||
struct rd_msg_oreq msg; /* Message to be sent */ |
||||
struct rd_msg_ores resp; /* Buffer to hold response */ |
||||
int32 retval; /* Return value from rdscomm */ |
||||
int32 len; /* Counts chars in diskid */ |
||||
char *idto; /* Ptr to ID string copy */ |
||||
char *idfrom; /* Pointer into ID string */ |
||||
|
||||
rdptr = &rdstab[devptr->dvminor]; |
||||
|
||||
/* Reject if device is already open */ |
||||
|
||||
if (rdptr->rd_state != RD_FREE) { |
||||
return SYSERR; |
||||
} |
||||
rdptr->rd_state = RD_PEND; |
||||
|
||||
/* Copy disk ID into free table slot */ |
||||
|
||||
idto = rdptr->rd_id; |
||||
idfrom = diskid; |
||||
len = 0; |
||||
while ( (*idto++ = *idfrom++) != NULLCH) { |
||||
len++; |
||||
if (len >= RD_IDLEN) { /* ID string is too long */ |
||||
return SYSERR; |
||||
} |
||||
} |
||||
|
||||
/* Verify that name is non-null */ |
||||
|
||||
if (len == 0) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Hand-craft an open request message to be sent to the server */ |
||||
|
||||
msg.rd_type = htons(RD_MSG_OREQ);/* Request an open */ |
||||
msg.rd_status = htons(0); |
||||
msg.rd_seq = 0; /* Rdscomm fills in an entry */ |
||||
idto = msg.rd_id; |
||||
memset(idto, NULLCH, RD_IDLEN);/* initialize ID to zero bytes */ |
||||
|
||||
idfrom = diskid; |
||||
while ( (*idto++ = *idfrom++) != NULLCH ) { /* Copy ID to req. */ |
||||
; |
||||
} |
||||
|
||||
/* Send message and receive response */ |
||||
|
||||
retval = rdscomm((struct rd_msg_hdr *)&msg, |
||||
sizeof(struct rd_msg_oreq), |
||||
(struct rd_msg_hdr *)&resp, |
||||
sizeof(struct rd_msg_ores), |
||||
rdptr ); |
||||
|
||||
/* Check response */ |
||||
|
||||
if (retval == SYSERR) { |
||||
rdptr->rd_state = RD_FREE; |
||||
return SYSERR; |
||||
} else if (retval == TIMEOUT) { |
||||
kprintf("Timeout during remote file open\n\r"); |
||||
rdptr->rd_state = RD_FREE; |
||||
return SYSERR; |
||||
} else if (ntohs(resp.rd_status) != 0) { |
||||
rdptr->rd_state = RD_FREE; |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Change state of device to indicate currently open */ |
||||
|
||||
rdptr->rd_state = RD_OPEN; |
||||
|
||||
/* Return device descriptor */ |
||||
|
||||
return devptr->dvnum; |
||||
} |
||||
@ -0,0 +1,212 @@
|
||||
/* rdsprocess.c - rdsprocess */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rdsprocess - High-priority background process that repeatedly |
||||
* extracts an item from the request queue, sends the |
||||
* request to the remote disk server, and handles the |
||||
* response, including caching responses blocks |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
void rdsprocess ( |
||||
struct rdscblk *rdptr /* Ptr to device control block */ |
||||
) |
||||
{ |
||||
struct rd_msg_wreq msg; /* Message to be sent */ |
||||
/* (includes data area) */ |
||||
struct rd_msg_rres resp; /* Buffer to hold response */ |
||||
/* (includes data area) */ |
||||
int32 retval; /* Return value from rdscomm */ |
||||
char *idto; /* Ptr to ID string copy */ |
||||
char *idfrom; /* Ptr into ID string */ |
||||
struct rdbuff *bptr; /* Ptr to buffer at the head of */ |
||||
/* the request queue */ |
||||
struct rdbuff *nptr; /* Ptr to next buffer on the */ |
||||
/* request queue */ |
||||
struct rdbuff *pptr; /* Ptr to previous buffer */ |
||||
struct rdbuff *qptr; /* Ptr that runs along the */ |
||||
/* request queue */ |
||||
int32 i; /* Loop index */ |
||||
|
||||
while (TRUE) { /* Do forever */ |
||||
|
||||
/* Wait until the request queue contains a node */ |
||||
wait(rdptr->rd_reqsem); |
||||
bptr = rdptr->rd_rhnext; |
||||
|
||||
/* Use operation in request to determine action */ |
||||
|
||||
switch (bptr->rd_op) { |
||||
|
||||
case RD_OP_READ: |
||||
|
||||
/* Build a read request message for the server */ |
||||
|
||||
msg.rd_type = htons(RD_MSG_RREQ); /* Read request */ |
||||
msg.rd_status = htons(0); |
||||
msg.rd_seq = 0; /* Rdscomm fills in an entry */ |
||||
idto = msg.rd_id; |
||||
memset(idto, NULLCH, RD_IDLEN);/* Initialize ID to zero */ |
||||
idfrom = rdptr->rd_id; |
||||
while ( (*idto++ = *idfrom++) != NULLCH ) { /* Copy ID */ |
||||
; |
||||
} |
||||
|
||||
/* Send the message and receive a response */ |
||||
|
||||
retval = rdscomm((struct rd_msg_hdr *)&msg, |
||||
sizeof(struct rd_msg_rreq), |
||||
(struct rd_msg_hdr *)&resp, |
||||
sizeof(struct rd_msg_rres), |
||||
rdptr ); |
||||
|
||||
/* Check response */ |
||||
|
||||
if ( (retval == SYSERR) || (retval == TIMEOUT) || |
||||
(ntohs(resp.rd_status) != 0) ) { |
||||
panic("Failed to contact remote disk server"); |
||||
} |
||||
|
||||
/* Copy data from the reply into the buffer */ |
||||
|
||||
for (i=0; i<RD_BLKSIZ; i++) { |
||||
bptr->rd_block[i] = resp.rd_data[i]; |
||||
} |
||||
|
||||
/* Unlink buffer from the request queue */ |
||||
|
||||
nptr = bptr->rd_next; |
||||
pptr = bptr->rd_prev; |
||||
nptr->rd_prev = bptr->rd_prev; |
||||
pptr->rd_next = bptr->rd_next; |
||||
|
||||
/* Insert buffer in the cache */ |
||||
|
||||
pptr = (struct rdbuff *) &rdptr->rd_chnext; |
||||
nptr = pptr->rd_next; |
||||
bptr->rd_next = nptr; |
||||
bptr->rd_prev = pptr; |
||||
pptr->rd_next = bptr; |
||||
nptr->rd_prev = bptr; |
||||
|
||||
/* Initialize reference count */ |
||||
|
||||
bptr->rd_refcnt = 1; |
||||
|
||||
/* Signal the available semaphore */ |
||||
|
||||
signal(rdptr->rd_availsem); |
||||
|
||||
/* Send a message to waiting process */ |
||||
|
||||
send(bptr->rd_pid, (uint32)bptr); |
||||
|
||||
/* If other processes are waiting to read the */ |
||||
/* block, notify them and remove the request */ |
||||
|
||||
qptr = rdptr->rd_rhnext; |
||||
while (qptr != (struct rdbuff *)&rdptr->rd_rtnext) { |
||||
if (qptr->rd_blknum == bptr->rd_blknum) { |
||||
bptr->rd_refcnt++; |
||||
send(qptr->rd_pid,(uint32)bptr); |
||||
|
||||
/* Unlink request from queue */ |
||||
|
||||
pptr = qptr->rd_prev; |
||||
nptr = qptr->rd_next; |
||||
pptr->rd_next = bptr->rd_next; |
||||
nptr->rd_prev = bptr->rd_prev; |
||||
|
||||
/* Move buffer to the free list */ |
||||
|
||||
qptr->rd_next = rdptr->rd_free; |
||||
rdptr->rd_free = qptr; |
||||
signal(rdptr->rd_availsem); |
||||
break; |
||||
} |
||||
qptr = qptr->rd_next; |
||||
} |
||||
break; |
||||
|
||||
case RD_OP_WRITE: |
||||
|
||||
/* Build a write request message for the server */ |
||||
|
||||
msg.rd_type = htons(RD_MSG_WREQ); /* Write request*/ |
||||
msg.rd_blk = bptr->rd_blknum; |
||||
msg.rd_status = htons(0); |
||||
msg.rd_seq = 0; /* Rdscomb fills in an entry */ |
||||
idto = msg.rd_id; |
||||
memset(idto, NULLCH, RD_IDLEN);/* Initialize ID to zero */ |
||||
idfrom = rdptr->rd_id; |
||||
while ( (*idto++ = *idfrom++) != NULLCH ) { /* Copy ID */ |
||||
; |
||||
} |
||||
for (i=0; i<RD_BLKSIZ; i++) { |
||||
msg.rd_data[i] = bptr->rd_block[i]; |
||||
} |
||||
|
||||
/* Unlink buffer from request queue */ |
||||
|
||||
nptr = bptr->rd_next; |
||||
pptr = bptr->rd_prev; |
||||
pptr->rd_next = nptr; |
||||
nptr->rd_prev = pptr; |
||||
|
||||
/* Insert buffer in the cache */ |
||||
|
||||
pptr = (struct rdbuff *) &rdptr->rd_chnext; |
||||
nptr = pptr->rd_next; |
||||
bptr->rd_next = nptr; |
||||
bptr->rd_prev = pptr; |
||||
pptr->rd_next = bptr; |
||||
nptr->rd_prev = bptr; |
||||
|
||||
/* Declare that buffer is eligible for reuse */ |
||||
|
||||
bptr->rd_refcnt = 0; |
||||
signal(rdptr->rd_availsem); |
||||
|
||||
/* Send the message and receive a response */ |
||||
|
||||
retval = rdscomm((struct rd_msg_hdr *)&msg, |
||||
sizeof(struct rd_msg_wreq), |
||||
(struct rd_msg_hdr *)&resp, |
||||
sizeof(struct rd_msg_wres), |
||||
rdptr ); |
||||
|
||||
/* Check response */ |
||||
|
||||
if ( (retval == SYSERR) || (retval == TIMEOUT) || |
||||
(ntohs(resp.rd_status) != 0) ) { |
||||
panic("failed to contact remote disk server"); |
||||
} |
||||
break; |
||||
|
||||
case RD_OP_SYNC: |
||||
|
||||
/* Send a message to the waiting process */ |
||||
|
||||
send(bptr->rd_pid, OK); |
||||
|
||||
/* Unlink buffer from the request queue */ |
||||
|
||||
nptr = bptr->rd_next; |
||||
pptr = bptr->rd_prev; |
||||
nptr->rd_prev = bptr->rd_prev; |
||||
pptr->rd_next = bptr->rd_next; |
||||
|
||||
/* Insert buffer into the free list */ |
||||
|
||||
bptr->rd_next = rdptr->rd_free; |
||||
rdptr->rd_free = bptr; |
||||
signal(rdptr->rd_availsem); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,130 @@
|
||||
/* rdsread.c - rdsread */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rdsread - Read a block from a remote disk |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall rdsread ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *buff, /* Buffer to hold disk block */ |
||||
int32 blk /* Block number of block to read*/ |
||||
) |
||||
{ |
||||
struct rdscblk *rdptr; /* Pointer to control block */ |
||||
struct rdbuff *bptr; /* Pointer to buffer possibly */ |
||||
/* in the request list */ |
||||
struct rdbuff *nptr; /* Pointer to "next" node on a */ |
||||
/* list */ |
||||
struct rdbuff *pptr; /* Pointer to "previous" node */ |
||||
/* on a list */ |
||||
struct rdbuff *cptr; /* Pointer that walks the cache */ |
||||
|
||||
/* If device not currently in use, report an error */ |
||||
|
||||
rdptr = &rdstab[devptr->dvminor]; |
||||
if (rdptr->rd_state != RD_OPEN) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Ensure rdsprocess is runnning */ |
||||
|
||||
if ( ! rdptr->rd_comruns ) { |
||||
rdptr->rd_comruns = TRUE; |
||||
resume(rdptr->rd_comproc); |
||||
} |
||||
|
||||
/* Search the cache for specified block */ |
||||
|
||||
bptr = rdptr->rd_chnext; |
||||
while (bptr != (struct rdbuff *)&rdptr->rd_ctnext) { |
||||
if (bptr->rd_blknum == blk) { |
||||
if (bptr->rd_status == RD_INVALID) { |
||||
break; |
||||
} |
||||
memcpy(buff, bptr->rd_block, RD_BLKSIZ); |
||||
return OK; |
||||
} |
||||
bptr = bptr->rd_next; |
||||
} |
||||
|
||||
/* Search the request list for most recent occurrence of block */ |
||||
|
||||
bptr = rdptr->rd_rtprev; /* Start at tail of list */ |
||||
|
||||
while (bptr != (struct rdbuff *)&rdptr->rd_rhnext) { |
||||
if (bptr->rd_blknum == blk) { |
||||
|
||||
/* If most recent request for block is write, copy data */ |
||||
|
||||
if (bptr->rd_op == RD_OP_WRITE) { |
||||
memcpy(buff, bptr->rd_block, RD_BLKSIZ); |
||||
return OK; |
||||
} |
||||
break; |
||||
} |
||||
bptr = bptr->rd_prev; |
||||
} |
||||
|
||||
/* Allocate a buffer and add read request to tail of req. queue */ |
||||
|
||||
bptr = rdsbufalloc(rdptr);
|
||||
bptr->rd_op = RD_OP_READ; |
||||
bptr->rd_refcnt = 1; |
||||
bptr->rd_blknum = blk; |
||||
bptr->rd_status = RD_INVALID; |
||||
bptr->rd_pid = getpid(); |
||||
|
||||
/* Insert new request into list just before tail */ |
||||
|
||||
pptr = rdptr->rd_rtprev; |
||||
rdptr->rd_rtprev = bptr; |
||||
bptr->rd_next = pptr->rd_next; |
||||
bptr->rd_prev = pptr; |
||||
pptr->rd_next = bptr; |
||||
|
||||
/* Prepare to receive message when read completes */ |
||||
|
||||
recvclr(); |
||||
|
||||
/* Signal the semaphore to start communication */ |
||||
|
||||
signal(rdptr->rd_reqsem); |
||||
|
||||
/* Block to wait for a message */ |
||||
|
||||
bptr = (struct rdbuff *)receive(); |
||||
if (bptr == (struct rdbuff *)SYSERR) {
|
||||
return SYSERR; |
||||
} |
||||
memcpy(buff, bptr->rd_block, RD_BLKSIZ); |
||||
bptr->rd_refcnt--; |
||||
if (bptr->rd_refcnt <= 0) { |
||||
|
||||
/* Look for previous item in cache with the same block */ |
||||
/* number to see if this item was only being kept */ |
||||
/* until pending read completed */ |
||||
|
||||
cptr = rdptr->rd_chnext; |
||||
while (cptr != bptr) { |
||||
if (cptr->rd_blknum == blk) { |
||||
|
||||
/* Unlink from cache */ |
||||
|
||||
pptr = bptr->rd_prev; |
||||
nptr = bptr->rd_next; |
||||
pptr->rd_next = nptr; |
||||
nptr->rd_prev = pptr; |
||||
|
||||
/* Add to the free list */ |
||||
|
||||
bptr->rd_next = rdptr->rd_free; |
||||
rdptr->rd_free = bptr; |
||||
break; |
||||
} |
||||
cptr = cptr->rd_next; |
||||
} |
||||
} |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,97 @@
|
||||
/* rdswrite.c - rdswrite */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rdswrite - Write a block to a remote disk |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall rdswrite ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *buff, /* Buffer that holds a disk blk */ |
||||
int32 blk /* Block number to write */ |
||||
) |
||||
{ |
||||
struct rdscblk *rdptr; /* Pointer to control block */ |
||||
struct rdbuff *bptr; /* Pointer to buffer on a list */ |
||||
struct rdbuff *pptr; /* Ptr to previous buff on list */ |
||||
struct rdbuff *nptr; /* Ptr to next buffer on list */ |
||||
bool8 found; /* Was buff found during search?*/ |
||||
|
||||
/* If device not currently in use, report an error */ |
||||
|
||||
rdptr = &rdstab[devptr->dvminor]; |
||||
if (rdptr->rd_state != RD_OPEN) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Ensure rdsprocess is runnning */ |
||||
|
||||
if ( ! rdptr->rd_comruns ) { |
||||
rdptr->rd_comruns = TRUE; |
||||
resume(rdptr->rd_comproc); |
||||
} |
||||
|
||||
/* If request queue already contains a write request */ |
||||
/* for the block, replace the contents */ |
||||
|
||||
bptr = rdptr->rd_rhnext; |
||||
while (bptr != (struct rdbuff *)&rdptr->rd_rtnext) { |
||||
if ( (bptr->rd_blknum == blk) && |
||||
(bptr->rd_op == RD_OP_WRITE) ) { |
||||
memcpy(bptr->rd_block, buff, RD_BLKSIZ); |
||||
return OK; |
||||
} |
||||
bptr = bptr->rd_next; |
||||
} |
||||
|
||||
/* Search cache for cached copy of block */ |
||||
|
||||
bptr = rdptr->rd_chnext; |
||||
found = FALSE; |
||||
while (bptr != (struct rdbuff *)&rdptr->rd_ctnext) { |
||||
if (bptr->rd_blknum == blk) { |
||||
if (bptr->rd_refcnt <= 0) { |
||||
pptr = bptr->rd_prev; |
||||
nptr = bptr->rd_next; |
||||
|
||||
/* Unlink node from cache list and reset*/ |
||||
/* the available semaphore accordingly*/ |
||||
|
||||
pptr->rd_next = bptr->rd_next; |
||||
nptr->rd_prev = bptr->rd_prev; |
||||
semreset(rdptr->rd_availsem, |
||||
semcount(rdptr->rd_availsem) - 1); |
||||
found = TRUE; |
||||
} |
||||
break; |
||||
} |
||||
bptr = bptr->rd_next; |
||||
} |
||||
|
||||
if ( !found ) { |
||||
bptr = rdsbufalloc(rdptr); |
||||
} |
||||
|
||||
/* Create a write request */ |
||||
|
||||
memcpy(bptr->rd_block, buff, RD_BLKSIZ); |
||||
bptr->rd_op = RD_OP_WRITE; |
||||
bptr->rd_refcnt = 0; |
||||
bptr->rd_blknum = blk; |
||||
bptr->rd_status = RD_VALID; |
||||
bptr->rd_pid = getpid(); |
||||
|
||||
/* Insert new request into list just before tail */ |
||||
|
||||
pptr = rdptr->rd_rtprev; |
||||
rdptr->rd_rtprev = bptr; |
||||
bptr->rd_next = pptr->rd_next; |
||||
bptr->rd_prev = pptr; |
||||
pptr->rd_next = bptr; |
||||
|
||||
/* Signal semaphore to start communication process */ |
||||
|
||||
signal(rdptr->rd_reqsem); |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,32 @@
|
||||
/* rflclose.c - rflclose */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rflclose - Close a remote file device |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall rflclose ( |
||||
struct dentry *devptr /* Entry in device switch table */ |
||||
) |
||||
{ |
||||
struct rflcblk *rfptr; /* Pointer to control block */ |
||||
|
||||
/* Wait for exclusive access */ |
||||
|
||||
wait(Rf_data.rf_mutex); |
||||
|
||||
/* Verify remote file device is open */ |
||||
|
||||
rfptr = &rfltab[devptr->dvminor]; |
||||
if (rfptr->rfstate == RF_FREE) { |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Mark device closed */ |
||||
|
||||
rfptr->rfstate = RF_FREE; |
||||
signal(Rf_data.rf_mutex); |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,23 @@
|
||||
/* rflgetc.c - rflgetc */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rflgetc - Read one character from a remote file |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall rflgetc( |
||||
struct dentry *devptr /* Entry in device switch table */ |
||||
) |
||||
{ |
||||
char ch; /* Character to read */ |
||||
int32 retval; /* Return value */ |
||||
|
||||
retval = rflread(devptr, &ch, 1); |
||||
|
||||
if (retval != 1) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
return (devcall)ch; |
||||
} |
||||
@ -0,0 +1,29 @@
|
||||
/* rflinit.c - rflinit */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
struct rflcblk rfltab[Nrfl]; /* Remote file control blocks */ |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rflinit - Initialize a remote file device |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall rflinit( |
||||
struct dentry *devptr /* Entry in device switch table */ |
||||
) |
||||
{ |
||||
struct rflcblk *rflptr; /* Ptr. to control block entry */ |
||||
int32 i; /* Walks through name arrary */ |
||||
|
||||
rflptr = &rfltab[ devptr->dvminor ]; |
||||
|
||||
/* Initialize entry to unused */ |
||||
|
||||
rflptr->rfstate = RF_FREE; |
||||
rflptr->rfdev = devptr->dvnum; |
||||
for (i=0; i<RF_NAMLEN; i++) { |
||||
rflptr->rfname[i] = NULLCH; |
||||
} |
||||
rflptr->rfpos = rflptr->rfmode = 0; |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,19 @@
|
||||
/* rflputc.c - rflputc */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rflputc - Write one character to a remote file |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall rflputc( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char ch /* Character to write */ |
||||
) |
||||
{ |
||||
if (rflwrite(devptr, &ch, 1) != 1) { |
||||
return SYSERR; |
||||
} |
||||
|
||||
return OK; |
||||
} |
||||
@ -0,0 +1,100 @@
|
||||
/* rflread.c - rflread */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rflread - Read data from a remote file |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall rflread ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *buff, /* Buffer of bytes */ |
||||
int32 count /* Count of bytes to read */ |
||||
) |
||||
{ |
||||
struct rflcblk *rfptr; /* Pointer to control block */ |
||||
int32 retval; /* Return value */ |
||||
struct rf_msg_rreq msg; /* Request message to send */ |
||||
struct rf_msg_rres resp; /* Buffer for response */ |
||||
int32 i; /* Counts bytes copied */ |
||||
char *from, *to; /* Used during name copy */ |
||||
int32 len; /* Length of name */ |
||||
|
||||
/* Wait for exclusive access */ |
||||
|
||||
wait(Rf_data.rf_mutex); |
||||
|
||||
/* Verify count is legitimate */ |
||||
|
||||
if ( (count <= 0) || (count > RF_DATALEN) ) { |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Verify pseudo-device is in use */ |
||||
|
||||
rfptr = &rfltab[devptr->dvminor]; |
||||
|
||||
/* If device not currently in use, report an error */ |
||||
|
||||
if (rfptr->rfstate == RF_FREE) { |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Verify pseudo-device allows reading */ |
||||
|
||||
if ((rfptr->rfmode & RF_MODE_R) == 0) { |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Form read request */ |
||||
|
||||
msg.rf_type = htons(RF_MSG_RREQ); |
||||
msg.rf_status = htons(0); |
||||
msg.rf_seq = 0; /* Rfscomm will set sequence */ |
||||
from = rfptr->rfname; |
||||
to = msg.rf_name; |
||||
memset(to, NULLCH, RF_NAMLEN); /* Start name as all zero bytes */ |
||||
len = 0; |
||||
while ( (*to++ = *from++) ) { /* Copy name to request */ |
||||
if (++len >= RF_NAMLEN) { |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} |
||||
} |
||||
msg.rf_pos = htonl(rfptr->rfpos);/* Set file position */ |
||||
msg.rf_len = htonl(count); /* Set count of bytes to read */ |
||||
|
||||
/* Send message and receive response */ |
||||
|
||||
retval = rfscomm((struct rf_msg_hdr *)&msg, |
||||
sizeof(struct rf_msg_rreq), |
||||
(struct rf_msg_hdr *)&resp, |
||||
sizeof(struct rf_msg_rres) ); |
||||
|
||||
/* Check response */ |
||||
|
||||
if (retval == SYSERR) { |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} else if (retval == TIMEOUT) { |
||||
kprintf("Timeout during remote file read\n"); |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} else if (ntohs(resp.rf_status) != 0) { |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Copy data to application buffer and update file position */ |
||||
|
||||
for (i=0; i<ntohl(resp.rf_len); i++) { |
||||
*buff++ = resp.rf_data[i]; |
||||
} |
||||
rfptr->rfpos += ntohl(resp.rf_len); |
||||
|
||||
signal(Rf_data.rf_mutex); |
||||
return ntohl(resp.rf_len); |
||||
} |
||||
@ -0,0 +1,33 @@
|
||||
/* rflseek.c - rflseek */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rflseek - Change the current position in an open file |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall rflseek ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
uint32 pos /* New file position */ |
||||
) |
||||
{ |
||||
struct rflcblk *rfptr; /* Pointer to control block */ |
||||
|
||||
/* Wait for exclusive access */ |
||||
|
||||
wait(Rf_data.rf_mutex); |
||||
|
||||
/* Verify remote file device is open */ |
||||
|
||||
rfptr = &rfltab[devptr->dvminor]; |
||||
if (rfptr->rfstate == RF_FREE) { |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Set the new position */ |
||||
|
||||
rfptr->rfpos = pos; |
||||
signal(Rf_data.rf_mutex); |
||||
return OK; |
||||
} |
||||
@ -0,0 +1,97 @@
|
||||
/* rflwrite.c - rflwrite */ |
||||
|
||||
#include <xinu.h> |
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* rflwrite - Write data to a remote file |
||||
*------------------------------------------------------------------------ |
||||
*/ |
||||
devcall rflwrite ( |
||||
struct dentry *devptr, /* Entry in device switch table */ |
||||
char *buff, /* Buffer of bytes */ |
||||
int32 count /* Count of bytes to write */ |
||||
) |
||||
{ |
||||
struct rflcblk *rfptr; /* Pointer to control block */ |
||||
int32 retval; /* Return value */ |
||||
struct rf_msg_wreq msg; /* Request message to send */ |
||||
struct rf_msg_wres resp; /* Buffer for response */ |
||||
char *from, *to; /* Used to copy name */ |
||||
int i; /* Counts bytes copied into req */ |
||||
int32 len; /* Length of name */ |
||||
|
||||
/* Wait for exclusive access */ |
||||
|
||||
wait(Rf_data.rf_mutex); |
||||
|
||||
/* Verify count is legitimate */ |
||||
|
||||
if ( (count <= 0) || (count > RF_DATALEN) ) { |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Verify pseudo-device is in use and mode allows writing */ |
||||
|
||||
rfptr = &rfltab[devptr->dvminor]; |
||||
if ( (rfptr->rfstate == RF_FREE) || |
||||
! (rfptr->rfmode & RF_MODE_W) ) { |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Form write request */ |
||||
|
||||
msg.rf_type = htons(RF_MSG_WREQ); |
||||
msg.rf_status = htons(0); |
||||
msg.rf_seq = 0; /* Rfscomm will set sequence */ |
||||
from = rfptr->rfname; |
||||
to = msg.rf_name; |
||||
memset(to, NULLCH, RF_NAMLEN); /* Start name as all zero bytes */ |
||||
len = 0; |
||||
while ( (*to++ = *from++) ) { /* Copy name to request */ |
||||
if (++len >= RF_NAMLEN) { |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} |
||||
} |
||||
while ( (*to++ = *from++) ) { /* Copy name into request */ |
||||
; |
||||
} |
||||
msg.rf_pos = htonl(rfptr->rfpos);/* Set file position */ |
||||
msg.rf_len = htonl(count); /* Set count of bytes to write */ |
||||
for (i=0; i<count; i++) { /* Copy data into message */ |
||||
msg.rf_data[i] = *buff++; |
||||
} |
||||
while (i < RF_DATALEN) { |
||||
msg.rf_data[i++] = NULLCH; |
||||
} |
||||
|
||||
/* Send message and receive response */ |
||||
|
||||
retval = rfscomm((struct rf_msg_hdr *)&msg, |
||||
sizeof(struct rf_msg_wreq), |
||||
(struct rf_msg_hdr *)&resp, |
||||
sizeof(struct rf_msg_wres) ); |
||||
|
||||
/* Check response */ |
||||
|
||||
if (retval == SYSERR) { |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} else if (retval == TIMEOUT) { |
||||
kprintf("Timeout during remote file read\n"); |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} else if (ntohs(resp.rf_status) != 0) { |
||||
signal(Rf_data.rf_mutex); |
||||
return SYSERR; |
||||
} |
||||
|
||||
/* Report results to caller */ |
||||
|
||||
rfptr->rfpos += ntohl(resp.rf_len); |
||||
|
||||
signal(Rf_data.rf_mutex); |
||||
return ntohl(resp.rf_len); |
||||
} |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue