Skip to content
Snippets Groups Projects
Commit 2fb3ca9f authored by Zhao Weng's avatar Zhao Weng
Browse files

mouse, soundblaster, signal

parents
No related branches found
No related tags found
No related merge requests found
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
# =========================
# Operating System Files
# =========================
.svn
# OSX
# =========================
.DS_Store
.AppleDouble
.LSOverride
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
Makefile.dep
*.o
bootimg
mp3.img
See the INSTALL file in the student-distrib/ directory.
README 0 → 100644
ECE391 MP3 - Package contents
================================
createfs
This program takes a flat source directory (i.e. no subdirectories
in the source directory) and creates a filesystem image in the
format specified for this MP. Run it with no parameters to see
usage.
elfconvert
This program takes a 32-bit ELF (Executable and Linking Format) file
- the standard executable type on Linux - and converts it to the
executable format specified for this MP. The output filename is
<exename>.converted.
fish/
This directory contains the source for the fish animation program.
It can be compiled two ways - one for your operating system, and one
for Linux using an emulation layer. The Makefile is currently set
up to build "fish" for your operating system using the elfconvert
utility described above. If you want to build a Linux version, do
"make fish_emulated". You can then run fish_emulated as superuser
at a standard Linux console, and you should see the fish animation.
fsdir/
This is the directory from which your filesystem image was created.
It contains versions of cat, fish, grep, hello, ls, and shell, as
well as the frame0.txt and frame1.txt files that fish needs to run.
If you want to change files in your OS's filesystem, modify this
directory and then run the "createfs" utility on it to create a new
filesystem image.
The only problem with this directory is that
there is no "rtc" device file. This is due to limitations with the
Samba network filesystem that your home directories are shared from.
If you wish to include the "rtc" device file in this directory (to
make the fish animation work properly), you must copy the entire
"fsdir" directory to a Linux filesystem (say, in /home/user). Then,
as root, run "mknod /home/user/fsdir/rtc c 10 61". Then you can run
the "createfs" utility on /home/user/fsdir to obtain a new
filesystem image that contains the rtc device file.
README
This file.
student-distrib/
This is the directory that contains the source code for your
operating system. Currently, a skeleton is provided that will build
and boot you into protected mode, printing out various boot
parameters. Read the INSTALL file in that directory for
instructions on how to set up the bootloader to boot this OS.
syscalls/
This directory contains a basic system call library that is used by
the utility programs such as cat, grep, ls, etc. The library
provides a C interface to the system calls, much like the C library
(libc) provides on a real Linux/Unix system. A few support
functions have also been written (things like strlen, strcpy, etc.)
that are used by the utility programs. The Makefile is set up to
build these programs for your OS.
createfs 0 → 100644
File added
File added
all: fish
# Note that you must be superuser to run the emulated version of the
# program.
fish_emulated: fish.o blink.o ece391emulate.o ece391support.o
gcc -nostdlib -lc -g -o fish_emulated fish.o blink.o ece391emulate.o ece391support.o
fish: fish.exe
../elfconvert fish.exe
mv fish.exe.converted fish
fish.exe: fish.o blink.o ece391support.o ece391syscall.o
gcc -nostdlib -g -o fish.exe fish.o blink.o ece391syscall.o ece391support.o
%.o: %.S
gcc -nostdlib -c -Wall -g -D_USERLAND -D_ASM -o $@ $<
%.o: %.c
gcc -nostdlib -Wall -c -g -o $@ $<
clean::
rm -f *.o *~
clear: clean
rm fish fish.exe fish_emulated
.data # section declaration
# Useful offset constants for accessing members of a
# struct mp1_blink_struct structure
LOCATION = 0
ON_CHAR = 2
OFF_CHAR = 3
ON_LENGTH = 4
OFF_LENGTH = 6
COUNTDOWN = 8
STATUS = 10
NEXT = 12
STRUCT_SIZE = 16
# Pointer to head of list (initialized to NULL)
mp1_list_head:
.long 0
call_table:
.long mp1_ioctl_add
.long mp1_ioctl_remove
.long mp1_ioctl_find
.long mp1_ioctl_sync
.text # section declaration
# Export the function symbol names
.global mp1_rtc_tasklet
.global mp1_ioctl
# void mp1_poke(void);
#
# Interface: Register-based arguments (not C-style)
# Inputs: %cl - The byte you wish to write
# %eax - Offset from the start of video memory that you wish
# to write to
# Outputs: Text-mode video screen is written to at location %eax with
# the byte in %cl
# Registers: Clobbers EDX
mp1_poke:
movl vmem_base_addr(,1),%edx
movb %cl,(%edx,%eax,1)
ret
mp1_rtc_tasklet:
pushl %ebp
movl %esp, %ebp
pushl %esi
pushl %edi
pushl %ebx
movl mp1_list_head, %ebx
tasklet_loop:
cmpl $0, %ebx
je tasklet_end
decw COUNTDOWN(%ebx)
cmpw $0,COUNTDOWN(%ebx)
jg next_loop
movzwl LOCATION(%ebx), %eax #blink location is now in eax
shl $1,%eax
testw $0x1,STATUS(%ebx)
jz currently_off
movb OFF_CHAR(%ebx), %cl
call mp1_poke
movw OFF_LENGTH(%ebx),%dx
jmp end_blink
currently_off:
movb ON_CHAR(%ebx), %cl
call mp1_poke
movw ON_LENGTH(%ebx),%dx
end_blink:
movw %dx, COUNTDOWN(%ebx)
xorw $0x1, STATUS(%ebx)
next_loop:
movl NEXT(%ebx), %ebx
jmp tasklet_loop
tasklet_end:
popl %ebx
popl %edi
popl %esi
popl %ebp
ret
mp1_ioctl:
movl 8(%esp), %eax
jmp *call_table(,%eax,4)
mp1_ioctl_add:
pushl %ebp
movl %esp, %ebp
# Allocate temp structure on the stack
subl $STRUCT_SIZE, %esp
# Preserve registers
pushl %esi
pushl %edi
pushl %ebx
# Get pointer to temp structure
leal -STRUCT_SIZE(%ebp), %ebx
# Copy user data onto the stack
pushl $STRUCT_SIZE
pushl 8(%ebp)
pushl %ebx
call ece391_memcpy
addl $12,%esp
# Check that the copy succeeded
cmpl $0,%eax
jne add_fail_return
# Check that the location is valid
cmpw $80*25,LOCATION(%ebx)
jae add_fail_return
# Mark this structure as valid
movw $0x1,STATUS(%ebx) # Mark it as on
movw ON_LENGTH(%ebx),%dx
movw %dx,COUNTDOWN(%ebx)
# Allocate some memory, pointer returned in EAX
pushl $STRUCT_SIZE
call mp1_malloc
add $4, %esp
cmpl $0, %eax
je add_fail_return
# Save EAX
pushl %eax
pushl $STRUCT_SIZE
pushl %ebx
pushl %eax
call ece391_memcpy
addl $12, %esp
# Restore the value from EAX into EDX
popl %edx
# Insert this new item at the front of the list
movl mp1_list_head, %eax
movl %eax, NEXT(%edx)
movl %edx, mp1_list_head
display:
# Display the character
movzwl LOCATION(%edx),%eax
shll $1,%eax
movb ON_CHAR(%edx),%cl
call mp1_poke
jmp add_success_return
add_fail_return:
movl $-1,%eax
jmp add_leave
add_success_return:
movl $0, %eax
add_leave:
popl %ebx
popl %edi
popl %esi
leave
ret
mp1_ioctl_remove:
pushl %ebp
movl %esp, %ebp
pushl %esi
pushl %edi
pushl %ebx
pushl 8(%ebp)
call mp1_find_helper
addl $4, %esp
cmpl $0, %eax
je remove_fail_return
# Found the right element. Now find the
# previous pointer in the list, and remove it
# We should not fail here, because mp1_find_helper
# returned a valid list element
leal mp1_list_head, %edx
remove_find_prev:
cmp %eax, (%edx)
je found_prev
movl (%edx), %edx
leal NEXT(%edx), %edx
jmp remove_find_prev
found_prev:
# Perform the removal
movl NEXT(%eax), %ecx
movl %ecx, (%edx)
free_mem:
pushl %eax
call mp1_free
addl $4, %esp
jmp remove_success_return
remove_fail_return:
movl $-1,%eax
jmp remove_leave
remove_success_return:
movl $0, %eax
remove_leave:
popl %ebx
popl %edi
popl %esi
leave
ret
mp1_ioctl_sync:
pushl %ebp
movl %esp, %ebp
pushl %esi
pushl %edi
pushl %ebx
sync_find_first:
movl 8(%ebp), %eax
shr $16, %eax
pushl %eax
call mp1_find_helper
addl $4, %esp
cmpl $0, %eax
je sync_fail_return
movl %eax, %esi
movl 8(%ebp), %eax
andl $0xFFFF, %eax
pushl %eax
call mp1_find_helper
addl $4, %esp
cmpl $0, %eax
je sync_fail_return
movl %eax, %edi
sync_copy_loop:
movw ON_LENGTH(%esi), %ax
movw %ax, ON_LENGTH(%edi)
movw OFF_LENGTH(%esi), %ax
movw %ax, OFF_LENGTH(%edi)
movw COUNTDOWN(%esi), %ax
movw %ax, COUNTDOWN(%edi)
movw STATUS(%esi), %ax
movw %ax, STATUS(%edi)
movzwl LOCATION(%edi), %eax
shll $1,%eax
movzbl OFF_CHAR(%edi),%ecx
movzbl ON_CHAR(%edi),%ebx
testb $0x1,STATUS(%edi)
cmovl %ebx, %ecx
sync_display:
call mp1_poke
jmp sync_success_return
sync_fail_return:
movl $-1,%eax
jmp sync_leave
sync_success_return:
movl $0, %eax
sync_leave:
popl %ebx
popl %edi
popl %esi
leave
ret
mp1_ioctl_find:
pushl %ebp
movl %esp, %ebp
subl $2,%esp
pushl %esi
pushl %edi
pushl %ebx
pushl $2
pushl 8(%ebp)
leal -2(%ebp),%edi
pushl %edi
call ece391_memcpy
addl $12,%esp
cmp $0,%eax
jne find_fail_return
movzwl -2(%ebp),%eax
pushl %eax
call mp1_find_helper
addl $4, %esp
cmpl $0, %eax
je find_fail_return
pushl $STRUCT_SIZE
pushl %eax
pushl 8(%ebp)
call ece391_memcpy
addl $12,%esp
cmp $0,%eax
je find_success_return
find_fail_return:
movl $-1,%eax
jmp find_leave
find_success_return:
movl $0, %eax
find_leave:
popl %ebx
popl %edi
popl %esi
leave
ret
mp1_find_helper:
pushl %ebp
movl %esp, %ebp
pushl %ebx
movw 8(%ebp), %ax
movl mp1_list_head, %ebx
loop:
cmpl $0, %ebx
je helper_fail_return
cmpw %ax, LOCATION(%ebx)
je helper_success_return
movl NEXT(%ebx), %ebx
jmp loop
helper_fail_return:
xorl %eax, %eax
jmp helper_leave
helper_success_return:
movl %ebx, %eax
helper_leave:
popl %ebx
leave
ret
.end
#define RTC_ADD 0
#define RTC_REMOVE 1
#define RTC_FIND 2
#define RTC_SYNC 3
struct mp1_blink_struct {
unsigned short location;
char on_char;
char off_char;
unsigned short on_length;
unsigned short off_length;
unsigned short countdown;
unsigned short status;
struct mp1_blink_struct* next;
} __attribute((packed));
#include <stdint.h>
#include "ece391support.h"
#include "ece391syscall.h"
uint32_t
ece391_strlen (const uint8_t* s)
{
uint32_t len;
for (len = 0; '\0' != *s; s++, len++);
return len;
}
void
ece391_strcpy (uint8_t* dst, const uint8_t* src)
{
while ('\0' != (*dst++ = *src++));
}
void
ece391_fdputs (int32_t fd, const uint8_t* s)
{
(void)ece391_write (fd, s, ece391_strlen (s));
}
int32_t
ece391_strcmp (const uint8_t* s1, const uint8_t* s2)
{
while (*s1 == *s2) {
if (*s1 == '\0')
return 0;
s1++;
s2++;
}
return ((int32_t)*s1) - ((int32_t)*s2);
}
int32_t
ece391_strncmp (const uint8_t* s1, const uint8_t* s2, uint32_t n)
{
if (0 == n)
return 0;
while (*s1 == *s2) {
if (*s1 == '\0' || --n == 0)
return 0;
s1++;
s2++;
}
return ((int32_t)*s1) - ((int32_t)*s2);
}
#if !defined(ECE391SUPPORT_H)
#define ECE391SUPPORT_H
extern uint32_t ece391_strlen (const uint8_t* s);
extern void ece391_strcpy (uint8_t* dst, const uint8_t* src);
extern void ece391_fdputs (int32_t fd, const uint8_t* s);
extern int32_t ece391_strcmp (const uint8_t* s1, const uint8_t* s2);
extern int32_t ece391_strncmp (const uint8_t* s1, const uint8_t* s2,
uint32_t n);
#endif /* ECE391SUPPORT_H */
#include "ece391sysnum.h"
/*
* Rather than create a case for each number of arguments, we simplify
* and use one macro for up to three arguments; the system calls should
* ignore the other registers, and they're caller-saved anyway.
*/
#define DO_CALL(name,number) \
.GLOBL name ;\
name: PUSHL %EBX ;\
MOVL $number,%EAX ;\
MOVL 8(%ESP),%EBX ;\
MOVL 12(%ESP),%ECX ;\
MOVL 16(%ESP),%EDX ;\
INT $0x80 ;\
POPL %EBX ;\
RET
/* the system call library wrappers */
DO_CALL(ece391_halt,SYS_HALT)
DO_CALL(ece391_execute,SYS_EXECUTE)
DO_CALL(ece391_read,SYS_READ)
DO_CALL(ece391_write,SYS_WRITE)
DO_CALL(ece391_open,SYS_OPEN)
DO_CALL(ece391_close,SYS_CLOSE)
DO_CALL(ece391_getargs,SYS_GETARGS)
DO_CALL(ece391_vidmap,SYS_VIDMAP)
DO_CALL(ece391_set_handler,SYS_SET_HANDLER)
DO_CALL(ece391_sigreturn,SYS_SIGRETURN)
/* Call the main() function, then halt with its return value. */
.GLOBAL _start
_start:
CALL main
PUSHL $0
PUSHL $0
PUSHL %EAX
CALL ece391_halt
#if !defined(ECE391SYSCALL_H)
#define ECE391SYSCALL_H
#include <stdint.h>
/* All calls return >= 0 on success or -1 on failure. */
/*
* Note that the system call for halt will have to make sure that only
* the low byte of EBX (the status argument) is returned to the calling
* task. Negative returns from execute indicate that the desired program
* could not be found.
*/
extern int32_t ece391_halt (uint8_t status);
extern int32_t ece391_execute (const uint8_t* command);
extern int32_t ece391_read (int32_t fd, void* buf, int32_t nbytes);
extern int32_t ece391_write (int32_t fd, const void* buf, int32_t nbytes);
extern int32_t ece391_open (const uint8_t* filename);
extern int32_t ece391_close (int32_t fd);
extern int32_t ece391_getargs (uint8_t* buf, int32_t nbytes);
extern int32_t ece391_vidmap (uint8_t** screen_start);
#endif /* ECE391SYSCALL_H */
#if !defined(ECE391SYSNUM_H)
#define ECE391SYSNUM_H
#define SYS_HALT 1
#define SYS_EXECUTE 2
#define SYS_READ 3
#define SYS_WRITE 4
#define SYS_OPEN 5
#define SYS_CLOSE 6
#define SYS_GETARGS 7
#define SYS_VIDMAP 8
#define SYS_SET_HANDLER 9
#define SYS_SIGRETURN 10
#endif /* ECE391SYSNUM_H */
fish/fish 0 → 100644
File added
#include <stdint.h>
#include "ece391support.h"
#include "ece391syscall.h"
#include "blink.h"
#define NULL 0
#define WAIT 200
uint8_t *vmem_base_addr;
uint8_t *mp1_set_video_mode (void);
void add_frames(uint8_t *, uint8_t *, int32_t);
void ece391_memset(void* memory, char c, int n);
int32_t ece391_memcpy(void* dest, const void* src, int32_t n);
uint8_t file0[] = "frame0.txt";
uint8_t file1[] = "frame1.txt";
/* Extern the externally-visible MP1 functions */
extern int mp1_ioctl(unsigned long arg, unsigned long cmd);
extern void mp1_rtc_tasklet(unsigned long trash);
static struct mp1_blink_struct blink_array[80*25];
int main(void)
{
int rtc_fd, ret_val, i, garbage;
struct mp1_blink_struct blink_struct;
ece391_memset(blink_array, 0, sizeof(struct mp1_blink_struct)*80*25);
if(mp1_set_video_mode() == NULL) {
return -1;
}
rtc_fd = ece391_open((uint8_t*)"rtc");
add_frames(file0, file1, rtc_fd);
ret_val = 32;
ret_val = ece391_write(rtc_fd, &ret_val, 4);
for(i=0; i<WAIT; i++) {
ece391_read(rtc_fd, &garbage, 4);
mp1_rtc_tasklet(garbage);
}
blink_struct.on_char = 'I';
blink_struct.off_char = 'M';
blink_struct.on_length = 7;
blink_struct.off_length = 6;
blink_struct.location = 6*80+60;
mp1_ioctl((unsigned long)&blink_struct, RTC_ADD);
for(i=0; i<WAIT; i++) {
ece391_read(rtc_fd, &garbage, 4);
mp1_rtc_tasklet(garbage);
}
mp1_ioctl((40 << 16 | (6*80+60)), RTC_SYNC);
for(i=0; i<WAIT; i++) {
ece391_read(rtc_fd, &garbage, 4);
mp1_rtc_tasklet(garbage);
}
blink_struct.location = 60;
mp1_ioctl(i, RTC_REMOVE);
for(i=0; i<80*25; i++) {
ece391_read(rtc_fd, &garbage, 4);
mp1_rtc_tasklet(garbage);
}
ece391_close(rtc_fd);
return 0;
}
void
add_frames(uint8_t *f0, uint8_t *f1, int32_t rtc_fd)
{
int32_t row, col, offset = 40, eof0 = 0, eof1 = 0, num_bytes;
int32_t fd0, fd1;
struct mp1_blink_struct blink_struct;
uint8_t c0 = '0', c1 = '0';
blink_struct.on_length = 15;
blink_struct.off_length = 15;
row = 0;
if( (fd0 = ece391_open(f0)) < 0 ) {
ece391_halt(-1);
}
if( (fd1 = ece391_open(f1)) < 0 ) {
ece391_halt(-1);
}
while(eof0 == 0 || eof1 == 0) {
col = 0;
while(1) {
if(c0 != '\n') {
num_bytes = ece391_read(fd0, &c0, 1);
if(num_bytes == 0) {
c0 = '\n';
eof0 = 1;
}
}
if(c1 != '\n') {
num_bytes = ece391_read(fd1, &c1, 1);
if(num_bytes == 0) {
c1 = '\n';
eof1 = 1;
}
}
if(c0 == '\n' && c1 == '\n') {
break;
} else {
if((c0 != ' ' && c0 != '\n') || (c1 != ' ' && c1 != '\n')) {
blink_struct.on_char = ( (c0 == '\n') ? ' ' : c0);
blink_struct.off_char = ( (c1 == '\n') ? ' ' : c1);
blink_struct.location = row*80 + col + offset;
mp1_ioctl((unsigned long)&blink_struct, RTC_ADD);
}
}
col++;
}
if(eof0) {
c0 = '\n';
ece391_close(fd0);
} else {
c0 = '0';
}
if(eof1) {
c1 = '\n';
ece391_close(fd1);
} else {
c1 = '0';
}
row++;
}
}
uint8_t*
mp1_set_video_mode (void)
{
if(ece391_vidmap(&vmem_base_addr) == -1) {
return NULL;
} else {
return vmem_base_addr;
}
}
void* mp1_malloc(int32_t size)
{
int32_t i;
for(i=0; i< 80*25; i++) {
if(blink_array[i].location == 0) {
return &blink_array[i];
}
}
return NULL;
}
void mp1_free(void* memory)
{
ece391_memset(memory, 0, sizeof(struct mp1_blink_struct));
}
void ece391_memset(void* memory, char c, int n)
{
char* mem = (char*)memory;
int i;
for(i=0; i<n; i++) {
mem[i] = c;
}
}
int32_t ece391_memcpy(void* dest, const void* src, int32_t n)
{
int32_t i;
char* d = (char*)dest;
char* s = (char*)src;
for(i=0; i<n; i++) {
d[i] = s[i];
}
return 0;
}
File added
/\/\/\/\/\/\/\/\/\/\/\/\
o
o o
o
o
o O
_ \
|\/.\ | \/ / /
|= _> \| \ /
|/\_/ |/ |/
----------M----M--------
\/\/\/\/\/\/\/\/\/\/\/\/
o o
o
o
o o
_ /
|\/.\ \ \/ \ /
|= _> \ \ \|
|/\_> |/ |/
----------M----M--------
fsdir/cat 0 → 100644
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment