#include "types.h" #include "defs.h" #include "param.h" #include "spinlock.h" #include "sleeplock.h" #include "fs.h" #include "file.h" #include "x86.h" #include "errno.h" extern int consoleread(struct inode*, uint64, char*, int); extern int consolewrite(struct inode*, uint64, char*, int); extern int mouseread(struct inode*, uint64, char*, int); static uint64 rseed = 0x2A99554433221100ULL; int nullwrite(struct inode *ip, uint64 off, char *dst, int n) { return n; } int nullread(struct inode *ip, uint64 off, char *dst, int n) { return 0; } int zeroread(struct inode *ip, uint64 off, char *dst, int n) { memset(dst, 0, n); return n; } int randomread(struct inode *ip, uint64 off, char *dst, int n) { for(int i = 0; i < n; i++){ rseed = rseed * 6364136223846793005ULL + 1442695040888963407ULL; dst[i] = (rseed >> 32) & 0xFF; } return n; } // /dev/full — reads as an endless run of zero bytes, every write fails with // ENOSPC. Programs use it to exercise their out-of-disk-space paths. int fullwrite(struct inode *ip, uint64 off, char *dst, int n) { return -ENOSPC; } int mousewrite(struct inode *ip, uint64 off, char *dst, int n) { return n; } int memread(struct inode *ip, uint64 off, char *dst, int n) { switch(ip->minor) { case 1: return consoleread(ip, off, dst, n); case 2: return nullread(ip, off, dst, n); case 3: return consoleread(ip, off, dst, n); /* 10 = /dev/tty, 11..16 = /dev/tty1..tty6. consoleread resolves the minor to a terminal; see vt_for_minor(). */ case 10: case 11: case 12: case 13: case 14: case 15: case 16: return consoleread(ip, off, dst, n); case 5: return zeroread(ip, off, dst, n); case 7: return zeroread(ip, off, dst, n); // /dev/full reads as zeros case 8: case 9: return randomread(ip, off, dst, n); default: return -1; } } int memwrite(struct inode *ip, uint64 off, char *dst, int n) { switch(ip->minor) { case 1: return consolewrite(ip, off, dst, n); case 10: case 11: case 12: case 13: case 14: case 15: case 16: return consolewrite(ip, off, dst, n); case 7: return fullwrite(ip, off, dst, n); // /dev/full: always ENOSPC case 2: case 5: case 8: case 9: return nullwrite(ip, off, dst, n); default: return -1; } } struct devsw devsw[] = { [0] = { 0, 0 }, [1] = { memread, memwrite }, // /dev/fb0 (major 2) — the framebuffer, kernel/dev/fb.c. This used to be // { nullread, nullwrite }, so writing pixels to it succeeded and did // nothing. // The close hook gives the text console its screen back when whatever was // drawing on the framebuffer exits — see fbclose(). [2] = { fbread, fbwrite, 0, fbclose }, [3] = { mouseread, mousewrite }, [4] = { 0, 0 }, // /dev/tty (major 5) — alias for the console [5] = { memread, memwrite }, // /proc status files (major 6) — see kernel/dev/procfs.c [6] = { procread, procwrite }, // /dev/input/eventN (major 7) — raw evdev events, kernel/dev/input.c. The // minor is the device index, so event0 is the keyboard and event1 the mouse. [7] = { inputread, inputwrite, inputready, inputclose, inputopen }, // /dev/hdN (major 8) — raw disks, kernel/dev/disk.c. The minor is the IDE // device number. No `ready` hook: a disk is always ready, which is what // fileread assumes when one is absent. [8] = { diskread, diskwrite }, // /dev/pci (major 9) -- PCI devices reachable from userspace, for drivers // that do not live in the kernel. Registers arrive through mmap and // everything else through ioctl; see include/pciuser.h. [9] = { pciuser_read, pciuser_write }, };