diff --git a/lab7/kernel/include/device.h b/lab7/kernel/include/device.h index 9cfffa31b..687f856c5 100644 --- a/lab7/kernel/include/device.h +++ b/lab7/kernel/include/device.h @@ -7,7 +7,7 @@ #define MAX_DEVICE_IN_DIR 16 -typedef enum { DEV_ROOT, DEV_UART, DEV_NONE } DEV_TYPE; +typedef enum { DEV_ROOT, DEV_UART, DEV_NONE, DEV_FB } DEV_TYPE; struct device_fentry { char name[20]; @@ -18,6 +18,13 @@ struct device_fentry { struct device_fentry* child[MAX_DEVICE_IN_DIR]; }; +struct framebuffer_info { + unsigned int width; + unsigned int height; + unsigned int pitch; + unsigned int isrgb; +}; + struct vnode_operations* device_v_ops; struct file_operations* device_f_ops; @@ -38,14 +45,21 @@ void device_list(struct vnode* dir); void root_init(); - - -/**********************************************/ -/* uart file system */ -/**********************************************/ - struct vnode_operations* uartfs_v_ops; struct file_operations* uartfs_f_ops; void uartfs_init(); int uartfs_read(struct file* file, void* buf, size_t len); int uartfs_write(struct file* file, const void* buf, size_t len); + + +struct vnode_operations* fb_v_ops; +struct file_operations* fb_f_ops; +void fb_init(); +int fb_write(struct file* file, const void* buf, size_t len); + + +//framebuffer syscall +long lseek64(int fd, long offset, int whence); +int ioctl(int fd, unsigned long request, struct framebuffer_info* info ); +unsigned char *lfb; /* raw frame buffer address */ +unsigned int isrgb; /* dimensions and channel order */ diff --git a/lab7/kernel/src/device.c b/lab7/kernel/src/device.c index b89942bd0..d8a212ebc 100644 --- a/lab7/kernel/src/device.c +++ b/lab7/kernel/src/device.c @@ -1,4 +1,3 @@ - #include "uart.h" #include "printf.h" #include "gpio.h" @@ -6,7 +5,8 @@ #include "vfs.h" #include "alloc.h" #include "string.h" - +#include "thread.h" +#include "mbox.h" /**********************************************/ /* uart file system */ /**********************************************/ @@ -35,14 +35,27 @@ void uartfs_init() { // uartfs_f_ops->list = device_list; } +void fb_init() { + fb_v_ops = + (struct vnode_operations*)malloc(sizeof(struct vnode_operations)); + fb_v_ops->lookup = device_lookup; + fb_v_ops->create = device_create; + fb_v_ops->set_parent = device_set_parent; + fb_f_ops = (struct file_operations*)malloc(sizeof(struct file_operations)); + fb_f_ops->write = fb_write; + // fb_f_ops->read = fb_read; + // uartfs_f_ops->list = device_list; +} + void device_init() { root_init(); uartfs_init(); + fb_init(); } void device_set_fentry(struct device_fentry* fentry, const char* component_name, struct vnode* vnode, DEV_TYPE type) { - printf("[device_set_fentry]\n"); + // printf("[device_set_fentry]\n"); strcpy(fentry->name, component_name); fentry->vnode = vnode; fentry->type = type; @@ -74,6 +87,8 @@ int device_setup_mount(struct filesystem* fs, struct mount* mount) { // create device vnode _device_create(mount->root, "uart", DEV_UART); + // create frame buffer + _device_create(mount->root, "framebuffer", DEV_FB); return 1; } @@ -81,7 +96,7 @@ int device_setup_mount(struct filesystem* fs, struct mount* mount) { int device_lookup(struct vnode* dir_node, struct vnode** target, const char* component_name) { - printf("[device_lookup] %s\n", component_name); + // printf("[device_lookup] %s\n", component_name); struct device_fentry* fentry = (struct device_fentry*)dir_node->internal; if (fentry->type != DEV_ROOT) return 0; @@ -99,7 +114,7 @@ int device_lookup(struct vnode* dir_node, struct vnode** target, for (int i = 0; i < MAX_DEVICE_IN_DIR; i++) { fentry = ((struct device_fentry*)dir_node->internal)->child[i]; - printf("[device_lookup] %s\n", fentry->name); + // printf("[device_lookup] %s\n", fentry->name); if (!strcmp(fentry->name, component_name)) { *target = fentry->vnode; return 1; @@ -125,6 +140,13 @@ int _device_create(struct vnode* dir_node, device_set_fentry(fentry, component_name, vnode, type); return 1; } + else if(type == DEV_FB){ + vnode->v_ops = fb_v_ops; + vnode->f_ops = fb_f_ops; + vnode->internal = fentry; + device_set_fentry(fentry, component_name, vnode, type); + return 1; + } } } return -1; @@ -165,8 +187,6 @@ int device_read(struct file* file, void* buf, size_t len) { return -1; } - - // uart read write functions int uartfs_read(struct file* file, void* buf, size_t len) { @@ -187,3 +207,100 @@ int uartfs_write(struct file* file, const void* buf, size_t len) { } return len; } + +int fb_write(struct file* file, const void* buf, size_t len) { + // printf("[fb_write]\n"); + // write to lfb + // printf("file->f_pos = %d\n",file->f_pos); + // for(int i = 0; i < len; i++) printf("0x%x, ", ((char* )buf)[i]); + // printf("\n"); + if(isrgb){ //RGB + lfb[file->f_pos++] = ((char* )buf)[0]; + lfb[file->f_pos++] = ((char* )buf)[1]; + lfb[file->f_pos++] = ((char* )buf)[2]; + + lfb[file->f_pos++] = ((char* )buf)[3]; + } + else{ //BGR + lfb[file->f_pos++] = ((char* )buf)[2]; + lfb[file->f_pos++] = ((char* )buf)[1]; + lfb[file->f_pos++] = ((char* )buf)[0]; + + lfb[file->f_pos++] = ((char* )buf)[3]; // 0x0 + } + + return len; +} + +long lseek64(int fd, long offset, int whence){ + struct file* file = thread_get_file(fd); + file->f_pos = offset + whence; + return file->f_pos; +} + +int ioctl(int fd, unsigned long request, struct framebuffer_info * info){ + #define MBOX_REQUEST 0 + #define MBOX_CH_PROP 8 + #define MBOX_TAG_LAST 0 + unsigned int __attribute__((aligned(16))) mbox[36]; + unsigned int width, height, pitch; /* dimensions and channel order */ + + mbox[0] = 35 * 4; + mbox[1] = MBOX_REQUEST; + + mbox[2] = 0x48003; // set phy wh + mbox[3] = 8; + mbox[4] = 8; + mbox[5] = 1024; // FrameBufferInfo.width + mbox[6] = 768; // FrameBufferInfo.height + + mbox[7] = 0x48004; // set virt wh + mbox[8] = 8; + mbox[9] = 8; + mbox[10] = 1024; // FrameBufferInfo.virtual_width + mbox[11] = 768; // FrameBufferInfo.virtual_height + + mbox[12] = 0x48009; // set virt offset + mbox[13] = 8; + mbox[14] = 8; + mbox[15] = 0; // FrameBufferInfo.x_offset + mbox[16] = 0; // FrameBufferInfo.y.offset + + mbox[17] = 0x48005; // set depth + mbox[18] = 4; + mbox[19] = 4; + mbox[20] = 32; // FrameBufferInfo.depth + + mbox[21] = 0x48006; // set pixel order + mbox[22] = 4; + mbox[23] = 4; + mbox[24] = 1; // RGB, not BGR preferably + + mbox[25] = 0x40001; // get framebuffer, gets alignment on request + mbox[26] = 8; + mbox[27] = 8; + mbox[28] = 4096; // FrameBufferInfo.pointer + mbox[29] = 0; // FrameBufferInfo.size + + mbox[30] = 0x40008; // get pitch + mbox[31] = 4; + mbox[32] = 4; + mbox[33] = 0; // FrameBufferInfo.pitch + + mbox[34] = MBOX_TAG_LAST; + + // this might not return exactly what we asked for, could be + // the closest supported resolution instead + if (mbox_call(MBOX_CH_PROP, mbox) && mbox[20] == 32 && mbox[28] != 0) { + mbox[28] &= 0x3FFFFFFF; // convert GPU address to ARM address + width = mbox[5]; // get actual physical width + height = mbox[6]; // get actual physical height + pitch = mbox[33]; // get number of bytes per line + isrgb = mbox[24]; // get the actual channel order + lfb = (void *)((unsigned long)mbox[28]); + printf("width =%d, height =%d, pitch =%d, isrgb =%d\n", width, height, pitch, isrgb); + } else { + printf("Unable to set screen resolution to 1024x768x32\n"); + } + return 1; +} diff --git a/lab7/kernel/src/exception.c b/lab7/kernel/src/exception.c index 5932716f1..f56fce893 100644 --- a/lab7/kernel/src/exception.c +++ b/lab7/kernel/src/exception.c @@ -7,6 +7,7 @@ #include "printf.h" #include "mbox.h" #include "vfs.h" +#include "device.h" int count = 0; @@ -68,7 +69,7 @@ void sync_handler_lowerEL_64(uint64_t sp) { } else if (iss == 5) { // exit exit(); } else if (iss == 6) { // mbox_call - // printf("[mbox_call]\n"); + printf("\n\n\n[mbox_call]\n"); trap_frame->x[0] = mbox_call(trap_frame->x[0],(unsigned int *)trap_frame->x[1]); } else if (iss == 7) { // kill kill((int)trap_frame->x[0]); @@ -77,7 +78,7 @@ void sync_handler_lowerEL_64(uint64_t sp) { printf("[open]%s\n",(const char *)trap_frame->x[0]); struct file* file = vfs_open((const char *)trap_frame->x[0],trap_frame->x[1]); int fd = thread_register_fd(file); - printf("[open]fd :%d\n",(const char *)trap_frame->x[0]); + printf("[open]fd :%d\n",fd); trap_frame->x[0] = fd; @@ -88,10 +89,10 @@ void sync_handler_lowerEL_64(uint64_t sp) { } else if (iss == 13) { // write // remember to return read size or error code - printf("[write]\n"); - printf("[write]fd =%d\n",trap_frame->x[0]); - printf("[write]write_buf =%s\n",trap_frame->x[1]); - printf("[write]size =%d\n",trap_frame->x[2]); + // printf("[write]\n"); + // printf("[write]fd =%d\n",trap_frame->x[0]); + // printf("[write]write_buf =%s\n",trap_frame->x[1]); + // printf("[write]size =%d\n",trap_frame->x[2]); struct file* file = thread_get_file(trap_frame->x[0]); trap_frame->x[0] = vfs_write(file, (const void *)trap_frame->x[1], trap_frame->x[2]); @@ -127,6 +128,17 @@ void sync_handler_lowerEL_64(uint64_t sp) { int result = vfs_chdir(pathname); trap_frame->x[0] = result; + } else if (iss == 18) { // lseek64 + // printf("[lseek64]\n"); + // printf("[lseek64]fd = %d\n", trap_frame->x[0]); + // printf("[lseek64]offset = %ld\n", (long) trap_frame->x[1]); + // printf("[lseek64]whence = %d\n", trap_frame->x[2]); + trap_frame->x[0] = lseek64(trap_frame->x[0], trap_frame->x[1], trap_frame->x[2]); + } else if (iss == 19) { // ioctl + printf("[ioctl]\n"); + printf("[ioctl]fd = %d\n", trap_frame->x[0]); + printf("[ioctl]request = %ld\n", (long) trap_frame->x[1]); + trap_frame->x[0] = ioctl(trap_frame->x[0], trap_frame->x[1], (struct framebuffer_info*)trap_frame->x[2]); } } } diff --git a/lab7/kernel/src/thread.c b/lab7/kernel/src/thread.c index e871c7fb0..04c6a9550 100644 --- a/lab7/kernel/src/thread.c +++ b/lab7/kernel/src/thread.c @@ -74,10 +74,6 @@ void thread_init() { run_queue.head = 0; run_queue.tail = 0; thread_cnt = 0; - - stdin = vfs_open("/dev/uart", 0); - stdout = vfs_open("/dev/uart", 0); - stderr = vfs_open("/dev/uart", 0); } thread_info *thread_create(void (*func)()) { diff --git a/lab7/kernel/src/vfs.c b/lab7/kernel/src/vfs.c index d5f14c072..9c66b3164 100644 --- a/lab7/kernel/src/vfs.c +++ b/lab7/kernel/src/vfs.c @@ -54,7 +54,7 @@ void vfs_init() { } fs->setup_mount(fs, rootfs); current_dir = rootfs->root; - cpio_populate_rootfs(); + // cpio_populate_rootfs(); // init and register cpio cpiofs_init(); @@ -78,7 +78,10 @@ void vfs_init() { vfs_mkdir("/dev"); vfs_mount("", "/dev", "dev"); - + // uart + stdin = vfs_open("/dev/uart", 0); + stdout = vfs_open("/dev/uart", 0); + stderr = vfs_open("/dev/uart", 0); } int register_filesystem(struct filesystem* fs) {