File: Page: 639 include/ansi.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/ansi.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00000 /* The header attempts to decide whether the compiler has enough 00001 * conformance to Standard C for Minix to take advantage of. If so, the 00002 * symbol _ANSI is defined (as 31459). Otherwise _ANSI is not defined 00003 * here, but it may be defined by applications that want to bend the rules. 00004 * The magic number in the definition is to inhibit unnecessary bending 00005 * of the rules. (For consistency with the new '#ifdef _ANSI" tests in 00006 * the headers, _ANSI should really be defined as nothing, but that would 00007 * break many library routines that use "#if _ANSI".) 00008 00009 * If _ANSI ends up being defined, a macro 00010 * 00011 * _PROTOTYPE(function, params) 00012 * 00013 * is defined. This macro expands in different ways, generating either 00014 * ANSI Standard C prototypes or old-style K&R (Kernighan & Ritchie) 00015 * prototypes, as needed. Finally, some programs use _CONST, _VOIDSTAR etc 00016 * in such a way that they are portable over both ANSI and K&R compilers. 00017 * The appropriate macros are defined here. 00018 */ 00019 00020 #ifndef _ANSI_H 00021 #define _ANSI_H 00022 00023 #if __STDC__ == 1 00024 #define _ANSI 31459 /* compiler claims full ANSI conformance */ 00025 #endif 00026 00027 #ifdef __GNUC__ 00028 #define _ANSI 31459 /* gcc conforms enough even in non-ANSI mode */ 00029 #endif 00030 00031 #ifdef _ANSI 00032 00033 /* Keep everything for ANSI prototypes. */ 00034 #define _PROTOTYPE(function, params) function params 00035 #define _ARGS(params) params 00036 00037 #define _VOIDSTAR void * 00038 #define _VOID void 00039 #define _CONST const 00040 #define _VOLATILE volatile 00041 #define _SIZET size_t 00042 00043 #else 00044 00045 /* Throw away the parameters for K&R prototypes. */ 00046 #define _PROTOTYPE(function, params) function() 00047 #define _ARGS(params) () 00048 00049 #define _VOIDSTAR void * 00050 #define _VOID void 00051 #define _CONST 00052 #define _VOLATILE 00053 #define _SIZET int 00054 File: Page: 640 include/ansi.h 00055 #endif /* _ANSI */ 00056 00057 /* This should be defined as restrict when a C99 compiler is used. */ 00058 #define _RESTRICT 00059 00060 /* Setting any of _MINIX, _POSIX_C_SOURCE or _POSIX2_SOURCE implies 00061 * _POSIX_SOURCE. (Seems wrong to put this here in ANSI space.) 00062 */ 00063 #if defined(_MINIX) || _POSIX_C_SOURCE > 0 || defined(_POSIX2_SOURCE) 00064 #undef _POSIX_SOURCE 00065 #define _POSIX_SOURCE 1 00066 #endif 00067 00068 #endif /* ANSI_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/limits.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00100 /* The header defines some basic sizes, both of the language types 00101 * (e.g., the number of bits in an integer), and of the operating system (e.g. 00102 * the number of characters in a file name. 00103 */ 00104 00105 #ifndef _LIMITS_H 00106 #define _LIMITS_H 00107 00108 /* Definitions about chars (8 bits in MINIX, and signed). */ 00109 #define CHAR_BIT 8 /* # bits in a char */ 00110 #define CHAR_MIN -128 /* minimum value of a char */ 00111 #define CHAR_MAX 127 /* maximum value of a char */ 00112 #define SCHAR_MIN -128 /* minimum value of a signed char */ 00113 #define SCHAR_MAX 127 /* maximum value of a signed char */ 00114 #define UCHAR_MAX 255 /* maximum value of an unsigned char */ 00115 #define MB_LEN_MAX 1 /* maximum length of a multibyte char */ 00116 00117 /* Definitions about shorts (16 bits in MINIX). */ 00118 #define SHRT_MIN (-32767-1) /* minimum value of a short */ 00119 #define SHRT_MAX 32767 /* maximum value of a short */ 00120 #define USHRT_MAX 0xFFFF /* maximum value of unsigned short */ 00121 00122 /* _EM_WSIZE is a compiler-generated symbol giving the word size in bytes. */ 00123 #define INT_MIN (-2147483647-1) /* minimum value of a 32-bit int */ 00124 #define INT_MAX 2147483647 /* maximum value of a 32-bit int */ 00125 #define UINT_MAX 0xFFFFFFFF /* maximum value of an unsigned 32-bit int */ 00126 00127 /*Definitions about longs (32 bits in MINIX). */ 00128 #define LONG_MIN (-2147483647L-1)/* minimum value of a long */ 00129 #define LONG_MAX 2147483647L /* maximum value of a long */ 00130 #define ULONG_MAX 0xFFFFFFFFL /* maximum value of an unsigned long */ 00131 00132 #include 00133 00134 /* Minimum sizes required by the POSIX P1003.1 standard (Table 2-3). */ 00135 #ifdef _POSIX_SOURCE /* these are only visible for POSIX */ 00136 #define _POSIX_ARG_MAX 4096 /* exec() may have 4K worth of args */ 00137 #define _POSIX_CHILD_MAX 6 /* a process may have 6 children */ 00138 #define _POSIX_LINK_MAX 8 /* a file may have 8 links */ 00139 #define _POSIX_MAX_CANON 255 /* size of the canonical input queue */ File: Page: 641 include/limits.h 00140 #define _POSIX_MAX_INPUT 255 /* you can type 255 chars ahead */ 00141 #define _POSIX_NAME_MAX DIRSIZ /* a file name may have 14 chars */ 00142 #define _POSIX_NGROUPS_MAX 0 /* supplementary group IDs are optional */ 00143 #define _POSIX_OPEN_MAX 16 /* a process may have 16 files open */ 00144 #define _POSIX_PATH_MAX 255 /* a pathname may contain 255 chars */ 00145 #define _POSIX_PIPE_BUF 512 /* pipes writes of 512 bytes must be atomic */ 00146 #define _POSIX_STREAM_MAX 8 /* at least 8 FILEs can be open at once */ 00147 #define _POSIX_TZNAME_MAX 3 /* time zone names can be at least 3 chars */ 00148 #define _POSIX_SSIZE_MAX 32767 /* read() must support 32767 byte reads */ 00149 00150 /* Values actually implemented by MINIX (Tables 2-4, 2-5, 2-6, and 2-7). */ 00151 /* Some of these old names had better be defined when not POSIX. */ 00152 #define _NO_LIMIT 100 /* arbitrary number; limit not enforced */ 00153 00154 #define NGROUPS_MAX 0 /* supplemental group IDs not available */ 00155 #define ARG_MAX 16384 /* # bytes of args + environ for exec() */ 00156 #define CHILD_MAX _NO_LIMIT /* MINIX does not limit children */ 00157 #define OPEN_MAX 20 /* # open files a process may have */ 00158 #define LINK_MAX SHRT_MAX /* # links a file may have */ 00159 #define MAX_CANON 255 /* size of the canonical input queue */ 00160 #define MAX_INPUT 255 /* size of the type-ahead buffer */ 00161 #define NAME_MAX DIRSIZ /* # chars in a file name */ 00162 #define PATH_MAX 255 /* # chars in a path name */ 00163 #define PIPE_BUF 7168 /* # bytes in atomic write to a pipe */ 00164 #define STREAM_MAX 20 /* must be the same as FOPEN_MAX in stdio.h */ 00165 #define TZNAME_MAX 3 /* maximum bytes in a time zone name is 3 */ 00166 #define SSIZE_MAX 32767 /* max defined byte count for read() */ 00167 00168 #endif /* _POSIX_SOURCE */ 00169 00170 #endif /* _LIMITS_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/errno.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00200 /* The header defines the numbers of the various errors that can 00201 * occur during program execution. They are visible to user programs and 00202 * should be small positive integers. However, they are also used within 00203 * MINIX, where they must be negative. For example, the READ system call is 00204 * executed internally by calling do_read(). This function returns either a 00205 * (negative) error number or a (positive) number of bytes actually read. 00206 * 00207 * To solve the problem of having the error numbers be negative inside the 00208 * the system and positive outside, the following mechanism is used. All the 00209 * definitions are are the form: 00210 * 00211 * #define EPERM (_SIGN 1) 00212 * 00213 * If the macro _SYSTEM is defined, then _SIGN is set to "-", otherwise it is 00214 * set to "". Thus when compiling the operating system, the macro _SYSTEM 00215 * will be defined, setting EPERM to (- 1), whereas when when this 00216 * file is included in an ordinary user program, EPERM has the value ( 1). 00217 */ 00218 00219 #ifndef _ERRNO_H /* check if is already included */ File: Page: 642 include/errno.h 00220 #define _ERRNO_H /* it is not included; note that fact */ 00221 00222 /* Now define _SIGN as "" or "-" depending on _SYSTEM. */ 00223 #ifdef _SYSTEM 00224 # define _SIGN - 00225 # define OK 0 00226 #else 00227 # define _SIGN 00228 #endif 00229 00230 extern int errno; /* place where the error numbers go */ 00231 00232 /* Here are the numerical values of the error numbers. */ 00233 #define _NERROR 70 /* number of errors */ 00234 00235 #define EGENERIC (_SIGN 99) /* generic error */ 00236 #define EPERM (_SIGN 1) /* operation not permitted */ 00237 #define ENOENT (_SIGN 2) /* no such file or directory */ 00238 #define ESRCH (_SIGN 3) /* no such process */ 00239 #define EINTR (_SIGN 4) /* interrupted function call */ 00240 #define EIO (_SIGN 5) /* input/output error */ 00241 #define ENXIO (_SIGN 6) /* no such device or address */ 00242 #define E2BIG (_SIGN 7) /* arg list too long */ 00243 #define ENOEXEC (_SIGN 8) /* exec format error */ 00244 #define EBADF (_SIGN 9) /* bad file descriptor */ 00245 #define ECHILD (_SIGN 10) /* no child process */ 00246 #define EAGAIN (_SIGN 11) /* resource temporarily unavailable */ 00247 #define ENOMEM (_SIGN 12) /* not enough space */ 00248 #define EACCES (_SIGN 13) /* permission denied */ 00249 #define EFAULT (_SIGN 14) /* bad address */ 00250 #define ENOTBLK (_SIGN 15) /* Extension: not a block special file */ 00251 #define EBUSY (_SIGN 16) /* resource busy */ 00252 #define EEXIST (_SIGN 17) /* file exists */ 00253 #define EXDEV (_SIGN 18) /* improper link */ 00254 #define ENODEV (_SIGN 19) /* no such device */ 00255 #define ENOTDIR (_SIGN 20) /* not a directory */ 00256 #define EISDIR (_SIGN 21) /* is a directory */ 00257 #define EINVAL (_SIGN 22) /* invalid argument */ 00258 #define ENFILE (_SIGN 23) /* too many open files in system */ 00259 #define EMFILE (_SIGN 24) /* too many open files */ 00260 #define ENOTTY (_SIGN 25) /* inappropriate I/O control operation */ 00261 #define ETXTBSY (_SIGN 26) /* no longer used */ 00262 #define EFBIG (_SIGN 27) /* file too large */ 00263 #define ENOSPC (_SIGN 28) /* no space left on device */ 00264 #define ESPIPE (_SIGN 29) /* invalid seek */ 00265 #define EROFS (_SIGN 30) /* read-only file system */ 00266 #define EMLINK (_SIGN 31) /* too many links */ 00267 #define EPIPE (_SIGN 32) /* broken pipe */ 00268 #define EDOM (_SIGN 33) /* domain error (from ANSI C std) */ 00269 #define ERANGE (_SIGN 34) /* result too large (from ANSI C std) */ 00270 #define EDEADLK (_SIGN 35) /* resource deadlock avoided */ 00271 #define ENAMETOOLONG (_SIGN 36) /* file name too long */ 00272 #define ENOLCK (_SIGN 37) /* no locks available */ 00273 #define ENOSYS (_SIGN 38) /* function not implemented */ 00274 #define ENOTEMPTY (_SIGN 39) /* directory not empty */ 00275 00276 /* The following errors relate to networking. */ 00277 #define EPACKSIZE (_SIGN 50) /* invalid packet size for some protocol */ 00278 #define EOUTOFBUFS (_SIGN 51) /* not enough buffers left */ 00279 #define EBADIOCTL (_SIGN 52) /* illegal ioctl for device */ File: Page: 643 include/errno.h 00280 #define EBADMODE (_SIGN 53) /* badmode in ioctl */ 00281 #define EWOULDBLOCK (_SIGN 54) 00282 #define EBADDEST (_SIGN 55) /* not a valid destination address */ 00283 #define EDSTNOTRCH (_SIGN 56) /* destination not reachable */ 00284 #define EISCONN (_SIGN 57) /* all ready connected */ 00285 #define EADDRINUSE (_SIGN 58) /* address in use */ 00286 #define ECONNREFUSED (_SIGN 59) /* connection refused */ 00287 #define ECONNRESET (_SIGN 60) /* connection reset */ 00288 #define ETIMEDOUT (_SIGN 61) /* connection timed out */ 00289 #define EURG (_SIGN 62) /* urgent data present */ 00290 #define ENOURG (_SIGN 63) /* no urgent data present */ 00291 #define ENOTCONN (_SIGN 64) /* no connection (yet or anymore) */ 00292 #define ESHUTDOWN (_SIGN 65) /* a write call to a shutdown connection */ 00293 #define ENOCONN (_SIGN 66) /* no such connection */ 00294 #define EAFNOSUPPORT (_SIGN 67) /* address family not supported */ 00295 #define EPROTONOSUPPORT (_SIGN 68) /* protocol not supported by AF */ 00296 #define EPROTOTYPE (_SIGN 69) /* Protocol wrong type for socket */ 00297 #define EINPROGRESS (_SIGN 70) /* Operation now in progress */ 00298 #define EADDRNOTAVAIL (_SIGN 71) /* Can't assign requested address */ 00299 #define EALREADY (_SIGN 72) /* Connection already in progress */ 00300 #define EMSGSIZE (_SIGN 73) /* Message too long */ 00301 00302 /* The following are not POSIX errors, but they can still happen. 00303 * All of these are generated by the kernel and relate to message passing. 00304 */ 00305 #define ELOCKED (_SIGN 101) /* can't send message due to deadlock */ 00306 #define EBADCALL (_SIGN 102) /* illegal system call number */ 00307 #define EBADSRCDST (_SIGN 103) /* bad source or destination process */ 00308 #define ECALLDENIED (_SIGN 104) /* no permission for system call */ 00309 #define EDEADDST (_SIGN 105) /* send destination is not alive */ 00310 #define ENOTREADY (_SIGN 106) /* source or destination is not ready */ 00311 #define EBADREQUEST (_SIGN 107) /* destination cannot handle request */ 00312 #define EDONTREPLY (_SIGN 201) /* pseudo-code: don't send a reply */ 00313 00314 #endif /* _ERRNO_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/unistd.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00400 /* The header contains a few miscellaneous manifest constants. */ 00401 00402 #ifndef _UNISTD_H 00403 #define _UNISTD_H 00404 00405 #ifndef _TYPES_H 00406 #include 00407 #endif 00408 00409 /* Values used by access(). POSIX Table 2-8. */ 00410 #define F_OK 0 /* test if file exists */ 00411 #define X_OK 1 /* test if file is executable */ 00412 #define W_OK 2 /* test if file is writable */ 00413 #define R_OK 4 /* test if file is readable */ 00414 00415 /* Values used for whence in lseek(fd, offset, whence). POSIX Table 2-9. */ 00416 #define SEEK_SET 0 /* offset is absolute */ 00417 #define SEEK_CUR 1 /* offset is relative to current position */ 00418 #define SEEK_END 2 /* offset is relative to end of file */ 00419 File: Page: 644 include/unistd.h 00420 /* This value is required by POSIX Table 2-10. */ 00421 #define _POSIX_VERSION 199009L /* which standard is being conformed to */ 00422 00423 /* These three definitions are required by POSIX Sec. 8.2.1.2. */ 00424 #define STDIN_FILENO 0 /* file descriptor for stdin */ 00425 #define STDOUT_FILENO 1 /* file descriptor for stdout */ 00426 #define STDERR_FILENO 2 /* file descriptor for stderr */ 00427 00428 #ifdef _MINIX 00429 /* How to exit the system or stop a server process. */ 00430 #define RBT_HALT 0 00431 #define RBT_REBOOT 1 00432 #define RBT_PANIC 2 /* a server panics */ 00433 #define RBT_MONITOR 3 /* let the monitor do this */ 00434 #define RBT_RESET 4 /* hard reset the system */ 00435 #endif 00436 00437 /* What system info to retrieve with sysgetinfo(). */ 00438 #define SI_KINFO 0 /* get kernel info via PM */ 00439 #define SI_PROC_ADDR 1 /* address of process table */ 00440 #define SI_PROC_TAB 2 /* copy of entire process table */ 00441 #define SI_DMAP_TAB 3 /* get device <-> driver mappings */ 00442 00443 /* NULL must be defined in according to POSIX Sec. 2.7.1. */ 00444 #define NULL ((void *)0) 00445 00446 /* The following relate to configurable system variables. POSIX Table 4-2. */ 00447 #define _SC_ARG_MAX 1 00448 #define _SC_CHILD_MAX 2 00449 #define _SC_CLOCKS_PER_SEC 3 00450 #define _SC_CLK_TCK 3 00451 #define _SC_NGROUPS_MAX 4 00452 #define _SC_OPEN_MAX 5 00453 #define _SC_JOB_CONTROL 6 00454 #define _SC_SAVED_IDS 7 00455 #define _SC_VERSION 8 00456 #define _SC_STREAM_MAX 9 00457 #define _SC_TZNAME_MAX 10 00458 00459 /* The following relate to configurable pathname variables. POSIX Table 5-2. */ 00460 #define _PC_LINK_MAX 1 /* link count */ 00461 #define _PC_MAX_CANON 2 /* size of the canonical input queue */ 00462 #define _PC_MAX_INPUT 3 /* type-ahead buffer size */ 00463 #define _PC_NAME_MAX 4 /* file name size */ 00464 #define _PC_PATH_MAX 5 /* pathname size */ 00465 #define _PC_PIPE_BUF 6 /* pipe size */ 00466 #define _PC_NO_TRUNC 7 /* treatment of long name components */ 00467 #define _PC_VDISABLE 8 /* tty disable */ 00468 #define _PC_CHOWN_RESTRICTED 9 /* chown restricted or not */ 00469 00470 /* POSIX defines several options that may be implemented or not, at the 00471 * implementer's whim. This implementer has made the following choices: 00472 * 00473 * _POSIX_JOB_CONTROL not defined: no job control 00474 * _POSIX_SAVED_IDS not defined: no saved uid/gid 00475 * _POSIX_NO_TRUNC defined as -1: long path names are truncated 00476 * _POSIX_CHOWN_RESTRICTED defined: you can't give away files 00477 * _POSIX_VDISABLE defined: tty functions can be disabled 00478 */ 00479 #define _POSIX_NO_TRUNC (-1) File: Page: 645 include/unistd.h 00480 #define _POSIX_CHOWN_RESTRICTED 1 00481 00482 /* Function Prototypes. */ 00483 _PROTOTYPE( void _exit, (int _status) ); 00484 _PROTOTYPE( int access, (const char *_path, int _amode) ); 00485 _PROTOTYPE( unsigned int alarm, (unsigned int _seconds) ); 00486 _PROTOTYPE( int chdir, (const char *_path) ); 00487 _PROTOTYPE( int fchdir, (int fd) ); 00488 _PROTOTYPE( int chown, (const char *_path, _mnx_Uid_t _owner, _mnx_Gid_t _group) ); 00489 _PROTOTYPE( int close, (int _fd) ); 00490 _PROTOTYPE( char *ctermid, (char *_s) ); 00491 _PROTOTYPE( char *cuserid, (char *_s) ); 00492 _PROTOTYPE( int dup, (int _fd) ); 00493 _PROTOTYPE( int dup2, (int _fd, int _fd2) ); 00494 _PROTOTYPE( int execl, (const char *_path, const char *_arg, ...) ); 00495 _PROTOTYPE( int execle, (const char *_path, const char *_arg, ...) ); 00496 _PROTOTYPE( int execlp, (const char *_file, const char *arg, ...) ); 00497 _PROTOTYPE( int execv, (const char *_path, char *const _argv[]) ); 00498 _PROTOTYPE( int execve, (const char *_path, char *const _argv[], 00499 char *const _envp[]) ); 00500 _PROTOTYPE( int execvp, (const char *_file, char *const _argv[]) ); 00501 _PROTOTYPE( pid_t fork, (void) ); 00502 _PROTOTYPE( long fpathconf, (int _fd, int _name) ); 00503 _PROTOTYPE( char *getcwd, (char *_buf, size_t _size) ); 00504 _PROTOTYPE( gid_t getegid, (void) ); 00505 _PROTOTYPE( uid_t geteuid, (void) ); 00506 _PROTOTYPE( gid_t getgid, (void) ); 00507 _PROTOTYPE( int getgroups, (int _gidsetsize, gid_t _grouplist[]) ); 00508 _PROTOTYPE( char *getlogin, (void) ); 00509 _PROTOTYPE( pid_t getpgrp, (void) ); 00510 _PROTOTYPE( pid_t getpid, (void) ); 00511 _PROTOTYPE( pid_t getppid, (void) ); 00512 _PROTOTYPE( uid_t getuid, (void) ); 00513 _PROTOTYPE( int isatty, (int _fd) ); 00514 _PROTOTYPE( int link, (const char *_existing, const char *_new) ); 00515 _PROTOTYPE( off_t lseek, (int _fd, off_t _offset, int _whence) ); 00516 _PROTOTYPE( long pathconf, (const char *_path, int _name) ); 00517 _PROTOTYPE( int pause, (void) ); 00518 _PROTOTYPE( int pipe, (int _fildes[2]) ); 00519 _PROTOTYPE( ssize_t read, (int _fd, void *_buf, size_t _n) ); 00520 _PROTOTYPE( int rmdir, (const char *_path) ); 00521 _PROTOTYPE( int setgid, (_mnx_Gid_t _gid) ); 00522 _PROTOTYPE( int setpgid, (pid_t _pid, pid_t _pgid) ); 00523 _PROTOTYPE( pid_t setsid, (void) ); 00524 _PROTOTYPE( int setuid, (_mnx_Uid_t _uid) ); 00525 _PROTOTYPE( unsigned int sleep, (unsigned int _seconds) ); 00526 _PROTOTYPE( long sysconf, (int _name) ); 00527 _PROTOTYPE( pid_t tcgetpgrp, (int _fd) ); 00528 _PROTOTYPE( int tcsetpgrp, (int _fd, pid_t _pgrp_id) ); 00529 _PROTOTYPE( char *ttyname, (int _fd) ); 00530 _PROTOTYPE( int unlink, (const char *_path) ); 00531 _PROTOTYPE( ssize_t write, (int _fd, const void *_buf, size_t _n) ); 00532 00533 /* Open Group Base Specifications Issue 6 (not complete) */ 00534 _PROTOTYPE( int symlink, (const char *path1, const char *path2) ); 00535 _PROTOTYPE( int getopt, (int _argc, char **_argv, char *_opts) ); 00536 extern char *optarg; 00537 extern int optind, opterr, optopt; 00538 _PROTOTYPE( int usleep, (useconds_t _useconds) ); 00539 File: Page: 646 include/unistd.h 00540 #ifdef _MINIX 00541 #ifndef _TYPE_H 00542 #include 00543 #endif 00544 _PROTOTYPE( int brk, (char *_addr) ); 00545 _PROTOTYPE( int chroot, (const char *_name) ); 00546 _PROTOTYPE( int mknod, (const char *_name, _mnx_Mode_t _mode, Dev_t _addr) ); 00547 _PROTOTYPE( int mknod4, (const char *_name, _mnx_Mode_t _mode, Dev_t _addr, 00548 long _size) ); 00549 _PROTOTYPE( char *mktemp, (char *_template) ); 00550 _PROTOTYPE( int mount, (char *_spec, char *_name, int _flag) ); 00551 _PROTOTYPE( long ptrace, (int _req, pid_t _pid, long _addr, long _data) ); 00552 _PROTOTYPE( char *sbrk, (int _incr) ); 00553 _PROTOTYPE( int sync, (void) ); 00554 _PROTOTYPE( int fsync, (int fd) ); 00555 _PROTOTYPE( int umount, (const char *_name) ); 00556 _PROTOTYPE( int reboot, (int _how, ...) ); 00557 _PROTOTYPE( int gethostname, (char *_hostname, size_t _len) ); 00558 _PROTOTYPE( int getdomainname, (char *_domain, size_t _len) ); 00559 _PROTOTYPE( int ttyslot, (void) ); 00560 _PROTOTYPE( int fttyslot, (int _fd) ); 00561 _PROTOTYPE( char *crypt, (const char *_key, const char *_salt) ); 00562 _PROTOTYPE( int getsysinfo, (int who, int what, void *where) ); 00563 _PROTOTYPE( int getprocnr, (void) ); 00564 _PROTOTYPE( int findproc, (char *proc_name, int *proc_nr) ); 00565 _PROTOTYPE( int allocmem, (phys_bytes size, phys_bytes *base) ); 00566 _PROTOTYPE( int freemem, (phys_bytes size, phys_bytes base) ); 00567 #define DEV_MAP 1 00568 #define DEV_UNMAP 2 00569 #define mapdriver(driver, device, style) devctl(DEV_MAP, driver, device, style) 00570 #define unmapdriver(device) devctl(DEV_UNMAP, 0, device, 0) 00571 _PROTOTYPE( int devctl, (int ctl_req, int driver, int device, int style)); 00572 00573 /* For compatibility with other Unix systems */ 00574 _PROTOTYPE( int getpagesize, (void) ); 00575 _PROTOTYPE( int setgroups, (int ngroups, const gid_t *gidset) ); 00576 00577 #endif 00578 00579 _PROTOTYPE( int readlink, (const char *, char *, int)); 00580 _PROTOTYPE( int getopt, (int, char **, char *)); 00581 extern int optind, opterr, optopt; 00582 00583 #endif /* _UNISTD_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/string.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00600 /* The header contains prototypes for the string handling 00601 * functions. 00602 */ 00603 00604 #ifndef _STRING_H 00605 #define _STRING_H 00606 00607 #define NULL ((void *)0) 00608 00609 #ifndef _SIZE_T File: Page: 647 include/string.h 00610 #define _SIZE_T 00611 typedef unsigned int size_t; /* type returned by sizeof */ 00612 #endif /*_SIZE_T */ 00613 00614 /* Function Prototypes. */ 00615 #ifndef _ANSI_H 00616 #include 00617 #endif 00618 00619 _PROTOTYPE( void *memchr, (const void *_s, int _c, size_t _n) ); 00620 _PROTOTYPE( int memcmp, (const void *_s1, const void *_s2, size_t _n) ); 00621 _PROTOTYPE( void *memcpy, (void *_s1, const void *_s2, size_t _n) ); 00622 _PROTOTYPE( void *memmove, (void *_s1, const void *_s2, size_t _n) ); 00623 _PROTOTYPE( void *memset, (void *_s, int _c, size_t _n) ); 00624 _PROTOTYPE( char *strcat, (char *_s1, const char *_s2) ); 00625 _PROTOTYPE( char *strchr, (const char *_s, int _c) ); 00626 _PROTOTYPE( int strncmp, (const char *_s1, const char *_s2, size_t _n) ); 00627 _PROTOTYPE( int strcmp, (const char *_s1, const char *_s2) ); 00628 _PROTOTYPE( int strcoll, (const char *_s1, const char *_s2) ); 00629 _PROTOTYPE( char *strcpy, (char *_s1, const char *_s2) ); 00630 _PROTOTYPE( size_t strcspn, (const char *_s1, const char *_s2) ); 00631 _PROTOTYPE( char *strerror, (int _errnum) ); 00632 _PROTOTYPE( size_t strlen, (const char *_s) ); 00633 _PROTOTYPE( char *strncat, (char *_s1, const char *_s2, size_t _n) ); 00634 _PROTOTYPE( char *strncpy, (char *_s1, const char *_s2, size_t _n) ); 00635 _PROTOTYPE( char *strpbrk, (const char *_s1, const char *_s2) ); 00636 _PROTOTYPE( char *strrchr, (const char *_s, int _c) ); 00637 _PROTOTYPE( size_t strspn, (const char *_s1, const char *_s2) ); 00638 _PROTOTYPE( char *strstr, (const char *_s1, const char *_s2) ); 00639 _PROTOTYPE( char *strtok, (char *_s1, const char *_s2) ); 00640 _PROTOTYPE( size_t strxfrm, (char *_s1, const char *_s2, size_t _n) ); 00641 00642 #ifdef _POSIX_SOURCE 00643 /* Open Group Base Specifications Issue 6 (not complete) */ 00644 char *strdup(const char *_s1); 00645 #endif 00646 00647 #ifdef _MINIX 00648 /* For backward compatibility. */ 00649 _PROTOTYPE( char *index, (const char *_s, int _charwanted) ); 00650 _PROTOTYPE( char *rindex, (const char *_s, int _charwanted) ); 00651 _PROTOTYPE( void bcopy, (const void *_src, void *_dst, size_t _length) ); 00652 _PROTOTYPE( int bcmp, (const void *_s1, const void *_s2, size_t _length)); 00653 _PROTOTYPE( void bzero, (void *_dst, size_t _length) ); 00654 _PROTOTYPE( void *memccpy, (char *_dst, const char *_src, int _ucharstop, 00655 size_t _size) ); 00656 00657 /* Misc. extra functions */ 00658 _PROTOTYPE( int strcasecmp, (const char *_s1, const char *_s2) ); 00659 _PROTOTYPE( int strncasecmp, (const char *_s1, const char *_s2, 00660 size_t _len) ); 00661 _PROTOTYPE( size_t strnlen, (const char *_s, size_t _n) ); 00662 #endif 00663 00664 #endif /* _STRING_H */ File: Page: 648 include/signal.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/signal.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00700 /* The header defines all the ANSI and POSIX signals. 00701 * MINIX supports all the signals required by POSIX. They are defined below. 00702 * Some additional signals are also supported. 00703 */ 00704 00705 #ifndef _SIGNAL_H 00706 #define _SIGNAL_H 00707 00708 #ifndef _ANSI_H 00709 #include 00710 #endif 00711 #ifdef _POSIX_SOURCE 00712 #ifndef _TYPES_H 00713 #include 00714 #endif 00715 #endif 00716 00717 /* Here are types that are closely associated with signal handling. */ 00718 typedef int sig_atomic_t; 00719 00720 #ifdef _POSIX_SOURCE 00721 #ifndef _SIGSET_T 00722 #define _SIGSET_T 00723 typedef unsigned long sigset_t; 00724 #endif 00725 #endif 00726 00727 #define _NSIG 20 /* number of signals used */ 00728 00729 #define SIGHUP 1 /* hangup */ 00730 #define SIGINT 2 /* interrupt (DEL) */ 00731 #define SIGQUIT 3 /* quit (ASCII FS) */ 00732 #define SIGILL 4 /* illegal instruction */ 00733 #define SIGTRAP 5 /* trace trap (not reset when caught) */ 00734 #define SIGABRT 6 /* IOT instruction */ 00735 #define SIGIOT 6 /* SIGABRT for people who speak PDP-11 */ 00736 #define SIGUNUSED 7 /* spare code */ 00737 #define SIGFPE 8 /* floating point exception */ 00738 #define SIGKILL 9 /* kill (cannot be caught or ignored) */ 00739 #define SIGUSR1 10 /* user defined signal # 1 */ 00740 #define SIGSEGV 11 /* segmentation violation */ 00741 #define SIGUSR2 12 /* user defined signal # 2 */ 00742 #define SIGPIPE 13 /* write on a pipe with no one to read it */ 00743 #define SIGALRM 14 /* alarm clock */ 00744 #define SIGTERM 15 /* software termination signal from kill */ 00745 #define SIGCHLD 17 /* child process terminated or stopped */ 00746 00747 #define SIGEMT 7 /* obsolete */ 00748 #define SIGBUS 10 /* obsolete */ 00749 00750 /* MINIX specific signals. These signals are not used by user proceses, 00751 * but meant to inform system processes, like the PM, about system events. 00752 */ 00753 #define SIGKMESS 18 /* new kernel message */ 00754 #define SIGKSIG 19 /* kernel signal pending */ File: Page: 649 include/signal.h 00755 #define SIGKSTOP 20 /* kernel shutting down */ 00756 00757 /* POSIX requires the following signals to be defined, even if they are 00758 * not supported. Here are the definitions, but they are not supported. 00759 */ 00760 #define SIGCONT 18 /* continue if stopped */ 00761 #define SIGSTOP 19 /* stop signal */ 00762 #define SIGTSTP 20 /* interactive stop signal */ 00763 #define SIGTTIN 21 /* background process wants to read */ 00764 #define SIGTTOU 22 /* background process wants to write */ 00765 00766 /* The sighandler_t type is not allowed unless _POSIX_SOURCE is defined. */ 00767 typedef void _PROTOTYPE( (*__sighandler_t), (int) ); 00768 00769 /* Macros used as function pointers. */ 00770 #define SIG_ERR ((__sighandler_t) -1) /* error return */ 00771 #define SIG_DFL ((__sighandler_t) 0) /* default signal handling */ 00772 #define SIG_IGN ((__sighandler_t) 1) /* ignore signal */ 00773 #define SIG_HOLD ((__sighandler_t) 2) /* block signal */ 00774 #define SIG_CATCH ((__sighandler_t) 3) /* catch signal */ 00775 #define SIG_MESS ((__sighandler_t) 4) /* pass as message (MINIX) */ 00776 00777 #ifdef _POSIX_SOURCE 00778 struct sigaction { 00779 __sighandler_t sa_handler; /* SIG_DFL, SIG_IGN, or pointer to function */ 00780 sigset_t sa_mask; /* signals to be blocked during handler */ 00781 int sa_flags; /* special flags */ 00782 }; 00783 00784 /* Fields for sa_flags. */ 00785 #define SA_ONSTACK 0x0001 /* deliver signal on alternate stack */ 00786 #define SA_RESETHAND 0x0002 /* reset signal handler when signal caught */ 00787 #define SA_NODEFER 0x0004 /* don't block signal while catching it */ 00788 #define SA_RESTART 0x0008 /* automatic system call restart */ 00789 #define SA_SIGINFO 0x0010 /* extended signal handling */ 00790 #define SA_NOCLDWAIT 0x0020 /* don't create zombies */ 00791 #define SA_NOCLDSTOP 0x0040 /* don't receive SIGCHLD when child stops */ 00792 00793 /* POSIX requires these values for use with sigprocmask(2). */ 00794 #define SIG_BLOCK 0 /* for blocking signals */ 00795 #define SIG_UNBLOCK 1 /* for unblocking signals */ 00796 #define SIG_SETMASK 2 /* for setting the signal mask */ 00797 #define SIG_INQUIRE 4 /* for internal use only */ 00798 #endif /* _POSIX_SOURCE */ 00799 00800 /* POSIX and ANSI function prototypes. */ 00801 _PROTOTYPE( int raise, (int _sig) ); 00802 _PROTOTYPE( __sighandler_t signal, (int _sig, __sighandler_t _func) ); 00803 00804 #ifdef _POSIX_SOURCE 00805 _PROTOTYPE( int kill, (pid_t _pid, int _sig) ); 00806 _PROTOTYPE( int sigaction, 00807 (int _sig, const struct sigaction *_act, struct sigaction *_oact) ); 00808 _PROTOTYPE( int sigaddset, (sigset_t *_set, int _sig) ); 00809 _PROTOTYPE( int sigdelset, (sigset_t *_set, int _sig) ); 00810 _PROTOTYPE( int sigemptyset, (sigset_t *_set) ); 00811 _PROTOTYPE( int sigfillset, (sigset_t *_set) ); 00812 _PROTOTYPE( int sigismember, (const sigset_t *_set, int _sig) ); 00813 _PROTOTYPE( int sigpending, (sigset_t *_set) ); 00814 _PROTOTYPE( int sigprocmask, File: Page: 650 include/signal.h 00815 (int _how, const sigset_t *_set, sigset_t *_oset) ); 00816 _PROTOTYPE( int sigsuspend, (const sigset_t *_sigmask) ); 00817 #endif 00818 00819 #endif /* _SIGNAL_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/fcntl.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00900 /* The header is needed by the open() and fcntl() system calls, 00901 * which have a variety of parameters and flags. They are described here. 00902 * The formats of the calls to each of these are: 00903 * 00904 * open(path, oflag [,mode]) open a file 00905 * fcntl(fd, cmd [,arg]) get or set file attributes 00906 * 00907 */ 00908 00909 #ifndef _FCNTL_H 00910 #define _FCNTL_H 00911 00912 #ifndef _TYPES_H 00913 #include 00914 #endif 00915 00916 /* These values are used for cmd in fcntl(). POSIX Table 6-1. */ 00917 #define F_DUPFD 0 /* duplicate file descriptor */ 00918 #define F_GETFD 1 /* get file descriptor flags */ 00919 #define F_SETFD 2 /* set file descriptor flags */ 00920 #define F_GETFL 3 /* get file status flags */ 00921 #define F_SETFL 4 /* set file status flags */ 00922 #define F_GETLK 5 /* get record locking information */ 00923 #define F_SETLK 6 /* set record locking information */ 00924 #define F_SETLKW 7 /* set record locking info; wait if blocked */ 00925 00926 /* File descriptor flags used for fcntl(). POSIX Table 6-2. */ 00927 #define FD_CLOEXEC 1 /* close on exec flag for third arg of fcntl */ 00928 00929 /* L_type values for record locking with fcntl(). POSIX Table 6-3. */ 00930 #define F_RDLCK 1 /* shared or read lock */ 00931 #define F_WRLCK 2 /* exclusive or write lock */ 00932 #define F_UNLCK 3 /* unlock */ 00933 00934 /* Oflag values for open(). POSIX Table 6-4. */ 00935 #define O_CREAT 00100 /* creat file if it doesn't exist */ 00936 #define O_EXCL 00200 /* exclusive use flag */ 00937 #define O_NOCTTY 00400 /* do not assign a controlling terminal */ 00938 #define O_TRUNC 01000 /* truncate flag */ 00939 00940 /* File status flags for open() and fcntl(). POSIX Table 6-5. */ 00941 #define O_APPEND 02000 /* set append mode */ 00942 #define O_NONBLOCK 04000 /* no delay */ 00943 00944 /* File access modes for open() and fcntl(). POSIX Table 6-6. */ 00945 #define O_RDONLY 0 /* open(name, O_RDONLY) opens read only */ 00946 #define O_WRONLY 1 /* open(name, O_WRONLY) opens write only */ 00947 #define O_RDWR 2 /* open(name, O_RDWR) opens read/write */ 00948 00949 /* Mask for use with file access modes. POSIX Table 6-7. */ File: Page: 651 include/fcntl.h 00950 #define O_ACCMODE 03 /* mask for file access modes */ 00951 00952 /* Struct used for locking. POSIX Table 6-8. */ 00953 struct flock { 00954 short l_type; /* type: F_RDLCK, F_WRLCK, or F_UNLCK */ 00955 short l_whence; /* flag for starting offset */ 00956 off_t l_start; /* relative offset in bytes */ 00957 off_t l_len; /* size; if 0, then until EOF */ 00958 pid_t l_pid; /* process id of the locks' owner */ 00959 }; 00960 00961 /* Function Prototypes. */ 00962 _PROTOTYPE( int creat, (const char *_path, _mnx_Mode_t _mode) ); 00963 _PROTOTYPE( int fcntl, (int _filedes, int _cmd, ...) ); 00964 _PROTOTYPE( int open, (const char *_path, int _oflag, ...) ); 00965 00966 #endif /* _FCNTL_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/termios.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 01000 /* The header is used for controlling tty modes. */ 01001 01002 #ifndef _TERMIOS_H 01003 #define _TERMIOS_H 01004 01005 typedef unsigned short tcflag_t; 01006 typedef unsigned char cc_t; 01007 typedef unsigned int speed_t; 01008 01009 #define NCCS 20 /* size of cc_c array, some extra space 01010 * for extensions. */ 01011 01012 /* Primary terminal control structure. POSIX Table 7-1. */ 01013 struct termios { 01014 tcflag_t c_iflag; /* input modes */ 01015 tcflag_t c_oflag; /* output modes */ 01016 tcflag_t c_cflag; /* control modes */ 01017 tcflag_t c_lflag; /* local modes */ 01018 speed_t c_ispeed; /* input speed */ 01019 speed_t c_ospeed; /* output speed */ 01020 cc_t c_cc[NCCS]; /* control characters */ 01021 }; 01022 01023 /* Values for termios c_iflag bit map. POSIX Table 7-2. */ 01024 #define BRKINT 0x0001 /* signal interrupt on break */ 01025 #define ICRNL 0x0002 /* map CR to NL on input */ 01026 #define IGNBRK 0x0004 /* ignore break */ 01027 #define IGNCR 0x0008 /* ignore CR */ 01028 #define IGNPAR 0x0010 /* ignore characters with parity errors */ 01029 #define INLCR 0x0020 /* map NL to CR on input */ 01030 #define INPCK 0x0040 /* enable input parity check */ 01031 #define ISTRIP 0x0080 /* mask off 8th bit */ 01032 #define IXOFF 0x0100 /* enable start/stop input control */ 01033 #define IXON 0x0200 /* enable start/stop output control */ 01034 #define PARMRK 0x0400 /* mark parity errors in the input queue */ File: Page: 652 include/termios.h 01035 01036 /* Values for termios c_oflag bit map. POSIX Sec. 7.1.2.3. */ 01037 #define OPOST 0x0001 /* perform output processing */ 01038 01039 /* Values for termios c_cflag bit map. POSIX Table 7-3. */ 01040 #define CLOCAL 0x0001 /* ignore modem status lines */ 01041 #define CREAD 0x0002 /* enable receiver */ 01042 #define CSIZE 0x000C /* number of bits per character */ 01043 #define CS5 0x0000 /* if CSIZE is CS5, characters are 5 bits */ 01044 #define CS6 0x0004 /* if CSIZE is CS6, characters are 6 bits */ 01045 #define CS7 0x0008 /* if CSIZE is CS7, characters are 7 bits */ 01046 #define CS8 0x000C /* if CSIZE is CS8, characters are 8 bits */ 01047 #define CSTOPB 0x0010 /* send 2 stop bits if set, else 1 */ 01048 #define HUPCL 0x0020 /* hang up on last close */ 01049 #define PARENB 0x0040 /* enable parity on output */ 01050 #define PARODD 0x0080 /* use odd parity if set, else even */ 01051 01052 /* Values for termios c_lflag bit map. POSIX Table 7-4. */ 01053 #define ECHO 0x0001 /* enable echoing of input characters */ 01054 #define ECHOE 0x0002 /* echo ERASE as backspace */ 01055 #define ECHOK 0x0004 /* echo KILL */ 01056 #define ECHONL 0x0008 /* echo NL */ 01057 #define ICANON 0x0010 /* canonical input (erase and kill enabled) */ 01058 #define IEXTEN 0x0020 /* enable extended functions */ 01059 #define ISIG 0x0040 /* enable signals */ 01060 #define NOFLSH 0x0080 /* disable flush after interrupt or quit */ 01061 #define TOSTOP 0x0100 /* send SIGTTOU (job control, not implemented*/ 01062 01063 /* Indices into c_cc array. Default values in parentheses. POSIX Table 7-5. */ 01064 #define VEOF 0 /* cc_c[VEOF] = EOF char (^D) */ 01065 #define VEOL 1 /* cc_c[VEOL] = EOL char (undef) */ 01066 #define VERASE 2 /* cc_c[VERASE] = ERASE char (^H) */ 01067 #define VINTR 3 /* cc_c[VINTR] = INTR char (DEL) */ 01068 #define VKILL 4 /* cc_c[VKILL] = KILL char (^U) */ 01069 #define VMIN 5 /* cc_c[VMIN] = MIN value for timer */ 01070 #define VQUIT 6 /* cc_c[VQUIT] = QUIT char (^\) */ 01071 #define VTIME 7 /* cc_c[VTIME] = TIME value for timer */ 01072 #define VSUSP 8 /* cc_c[VSUSP] = SUSP (^Z, ignored) */ 01073 #define VSTART 9 /* cc_c[VSTART] = START char (^S) */ 01074 #define VSTOP 10 /* cc_c[VSTOP] = STOP char (^Q) */ 01075 01076 #define _POSIX_VDISABLE (cc_t)0xFF /* You can't even generate this 01077 * character with 'normal' keyboards. 01078 * But some language specific keyboards 01079 * can generate 0xFF. It seems that all 01080 * 256 are used, so cc_t should be a 01081 * short... 01082 */ 01083 01084 /* Values for the baud rate settings. POSIX Table 7-6. */ 01085 #define B0 0x0000 /* hang up the line */ 01086 #define B50 0x1000 /* 50 baud */ 01087 #define B75 0x2000 /* 75 baud */ 01088 #define B110 0x3000 /* 110 baud */ 01089 #define B134 0x4000 /* 134.5 baud */ 01090 #define B150 0x5000 /* 150 baud */ 01091 #define B200 0x6000 /* 200 baud */ 01092 #define B300 0x7000 /* 300 baud */ 01093 #define B600 0x8000 /* 600 baud */ 01094 #define B1200 0x9000 /* 1200 baud */ File: Page: 653 include/termios.h 01095 #define B1800 0xA000 /* 1800 baud */ 01096 #define B2400 0xB000 /* 2400 baud */ 01097 #define B4800 0xC000 /* 4800 baud */ 01098 #define B9600 0xD000 /* 9600 baud */ 01099 #define B19200 0xE000 /* 19200 baud */ 01100 #define B38400 0xF000 /* 38400 baud */ 01101 01102 /* Optional actions for tcsetattr(). POSIX Sec. 7.2.1.2. */ 01103 #define TCSANOW 1 /* changes take effect immediately */ 01104 #define TCSADRAIN 2 /* changes take effect after output is done */ 01105 #define TCSAFLUSH 3 /* wait for output to finish and flush input */ 01106 01107 /* Queue_selector values for tcflush(). POSIX Sec. 7.2.2.2. */ 01108 #define TCIFLUSH 1 /* flush accumulated input data */ 01109 #define TCOFLUSH 2 /* flush accumulated output data */ 01110 #define TCIOFLUSH 3 /* flush accumulated input and output data */ 01111 01112 /* Action values for tcflow(). POSIX Sec. 7.2.2.2. */ 01113 #define TCOOFF 1 /* suspend output */ 01114 #define TCOON 2 /* restart suspended output */ 01115 #define TCIOFF 3 /* transmit a STOP character on the line */ 01116 #define TCION 4 /* transmit a START character on the line */ 01117 01118 /* Function Prototypes. */ 01119 #ifndef _ANSI_H 01120 #include 01121 #endif 01122 01123 _PROTOTYPE( int tcsendbreak, (int _fildes, int _duration) ); 01124 _PROTOTYPE( int tcdrain, (int _filedes) ); 01125 _PROTOTYPE( int tcflush, (int _filedes, int _queue_selector) ); 01126 _PROTOTYPE( int tcflow, (int _filedes, int _action) ); 01127 _PROTOTYPE( speed_t cfgetispeed, (const struct termios *_termios_p) ); 01128 _PROTOTYPE( speed_t cfgetospeed, (const struct termios *_termios_p) ); 01129 _PROTOTYPE( int cfsetispeed, (struct termios *_termios_p, speed_t _speed) ); 01130 _PROTOTYPE( int cfsetospeed, (struct termios *_termios_p, speed_t _speed) ); 01131 _PROTOTYPE( int tcgetattr, (int _filedes, struct termios *_termios_p) ); 01132 _PROTOTYPE( int tcsetattr, \ 01133 (int _filedes, int _opt_actions, const struct termios *_termios_p) ); 01134 01135 #define cfgetispeed(termios_p) ((termios_p)->c_ispeed) 01136 #define cfgetospeed(termios_p) ((termios_p)->c_ospeed) 01137 #define cfsetispeed(termios_p, speed) ((termios_p)->c_ispeed = (speed), 0) 01138 #define cfsetospeed(termios_p, speed) ((termios_p)->c_ospeed = (speed), 0) 01139 01140 #ifdef _MINIX 01141 /* Here are the local extensions to the POSIX standard for Minix. Posix 01142 * conforming programs are not able to access these, and therefore they are 01143 * only defined when a Minix program is compiled. 01144 */ 01145 01146 /* Extensions to the termios c_iflag bit map. */ 01147 #define IXANY 0x0800 /* allow any key to continue ouptut */ 01148 01149 /* Extensions to the termios c_oflag bit map. They are only active iff 01150 * OPOST is enabled. */ 01151 #define ONLCR 0x0002 /* Map NL to CR-NL on output */ 01152 #define XTABS 0x0004 /* Expand tabs to spaces */ 01153 #define ONOEOT 0x0008 /* discard EOT's (^D) on output) */ 01154 File: Page: 654 include/termios.h 01155 /* Extensions to the termios c_lflag bit map. */ 01156 #define LFLUSHO 0x0200 /* Flush output. */ 01157 01158 /* Extensions to the c_cc array. */ 01159 #define VREPRINT 11 /* cc_c[VREPRINT] (^R) */ 01160 #define VLNEXT 12 /* cc_c[VLNEXT] (^V) */ 01161 #define VDISCARD 13 /* cc_c[VDISCARD] (^O) */ 01162 01163 /* Extensions to baud rate settings. */ 01164 #define B57600 0x0100 /* 57600 baud */ 01165 #define B115200 0x0200 /* 115200 baud */ 01166 01167 /* These are the default settings used by the kernel and by 'stty sane' */ 01168 01169 #define TCTRL_DEF (CREAD | CS8 | HUPCL) 01170 #define TINPUT_DEF (BRKINT | ICRNL | IXON | IXANY) 01171 #define TOUTPUT_DEF (OPOST | ONLCR) 01172 #define TLOCAL_DEF (ISIG | IEXTEN | ICANON | ECHO | ECHOE) 01173 #define TSPEED_DEF B9600 01174 01175 #define TEOF_DEF '\4' /* ^D */ 01176 #define TEOL_DEF _POSIX_VDISABLE 01177 #define TERASE_DEF '\10' /* ^H */ 01178 #define TINTR_DEF '\3' /* ^C */ 01179 #define TKILL_DEF '\25' /* ^U */ 01180 #define TMIN_DEF 1 01181 #define TQUIT_DEF '\34' /* ^\ */ 01182 #define TSTART_DEF '\21' /* ^Q */ 01183 #define TSTOP_DEF '\23' /* ^S */ 01184 #define TSUSP_DEF '\32' /* ^Z */ 01185 #define TTIME_DEF 0 01186 #define TREPRINT_DEF '\22' /* ^R */ 01187 #define TLNEXT_DEF '\26' /* ^V */ 01188 #define TDISCARD_DEF '\17' /* ^O */ 01189 01190 /* Window size. This information is stored in the TTY driver but not used. 01191 * This can be used for screen based applications in a window environment. 01192 * The ioctls TIOCGWINSZ and TIOCSWINSZ can be used to get and set this 01193 * information. 01194 */ 01195 01196 struct winsize 01197 { 01198 unsigned short ws_row; /* rows, in characters */ 01199 unsigned short ws_col; /* columns, in characters */ 01200 unsigned short ws_xpixel; /* horizontal size, pixels */ 01201 unsigned short ws_ypixel; /* vertical size, pixels */ 01202 }; 01203 #endif /* _MINIX */ 01204 01205 #endif /* _TERMIOS_H */ File: Page: 655 include/timers.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/timers.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 01300 /* This library provides generic watchdog timer management functionality. 01301 * The functions operate on a timer queue provided by the caller. Note that 01302 * the timers must use absolute time to allow sorting. The library provides: 01303 * 01304 * tmrs_settimer: (re)set a new watchdog timer in the timers queue 01305 * tmrs_clrtimer: remove a timer from both the timers queue 01306 * tmrs_exptimers: check for expired timers and run watchdog functions 01307 * 01308 * Author: 01309 * Jorrit N. Herder 01310 * Adapted from tmr_settimer and tmr_clrtimer in src/kernel/clock.c. 01311 * Last modified: September 30, 2004. 01312 */ 01313 01314 #ifndef _TIMERS_H 01315 #define _TIMERS_H 01316 01317 #include 01318 #include 01319 01320 struct timer; 01321 typedef void (*tmr_func_t)(struct timer *tp); 01322 typedef union { int ta_int; long ta_long; void *ta_ptr; } tmr_arg_t; 01323 01324 /* A timer_t variable must be declare for each distinct timer to be used. 01325 * The timers watchdog function and expiration time are automatically set 01326 * by the library function tmrs_settimer, but its argument is not. 01327 */ 01328 typedef struct timer 01329 { 01330 struct timer *tmr_next; /* next in a timer chain */ 01331 clock_t tmr_exp_time; /* expiration time */ 01332 tmr_func_t tmr_func; /* function to call when expired */ 01333 tmr_arg_t tmr_arg; /* random argument */ 01334 } timer_t; 01335 01336 /* Used when the timer is not active. */ 01337 #define TMR_NEVER ((clock_t) -1 < 0) ? ((clock_t) LONG_MAX) : ((clock_t) -1) 01338 #undef TMR_NEVER 01339 #define TMR_NEVER ((clock_t) LONG_MAX) 01340 01341 /* These definitions can be used to set or get data from a timer variable. */ 01342 #define tmr_arg(tp) (&(tp)->tmr_arg) 01343 #define tmr_exp_time(tp) (&(tp)->tmr_exp_time) 01344 01345 /* Timers should be initialized once before they are being used. Be careful 01346 * not to reinitialize a timer that is in a list of timers, or the chain 01347 * will be broken. 01348 */ 01349 #define tmr_inittimer(tp) (void)((tp)->tmr_exp_time = TMR_NEVER, \ 01350 (tp)->tmr_next = NULL) 01351 01352 /* The following generic timer management functions are available. They 01353 * can be used to operate on the lists of timers. Adding a timer to a list 01354 * automatically takes care of removing it. File: Page: 656 include/timers.h 01355 */ 01356 _PROTOTYPE( clock_t tmrs_clrtimer, (timer_t **tmrs, timer_t *tp, clock_t *new_head) ); 01357 _PROTOTYPE( void tmrs_exptimers, (timer_t **tmrs, clock_t now, clock_t *new_head) ); 01358 _PROTOTYPE( clock_t tmrs_settimer, (timer_t **tmrs, timer_t *tp, 01359 clock_t exp_time, tmr_func_t watchdog, clock_t *new_head) ); 01360 01361 #endif /* _TIMERS_H */ 01362 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/sys/types.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 01400 /* The header contains important data type definitions. 01401 * It is considered good programming practice to use these definitions, 01402 * instead of the underlying base type. By convention, all type names end 01403 * with _t. 01404 */ 01405 01406 #ifndef _TYPES_H 01407 #define _TYPES_H 01408 01409 #ifndef _ANSI_H 01410 #include 01411 #endif 01412 01413 /* The type size_t holds all results of the sizeof operator. At first glance, 01414 * it seems obvious that it should be an unsigned int, but this is not always 01415 * the case. For example, MINIX-ST (68000) has 32-bit pointers and 16-bit 01416 * integers. When one asks for the size of a 70K struct or array, the result 01417 * requires 17 bits to express, so size_t must be a long type. The type 01418 * ssize_t is the signed version of size_t. 01419 */ 01420 #ifndef _SIZE_T 01421 #define _SIZE_T 01422 typedef unsigned int size_t; 01423 #endif 01424 01425 #ifndef _SSIZE_T 01426 #define _SSIZE_T 01427 typedef int ssize_t; 01428 #endif 01429 01430 #ifndef _TIME_T 01431 #define _TIME_T 01432 typedef long time_t; /* time in sec since 1 Jan 1970 0000 GMT */ 01433 #endif 01434 01435 #ifndef _CLOCK_T 01436 #define _CLOCK_T 01437 typedef long clock_t; /* unit for system accounting */ 01438 #endif 01439 01440 #ifndef _SIGSET_T 01441 #define _SIGSET_T 01442 typedef unsigned long sigset_t; 01443 #endif 01444 File: Page: 657 include/sys/types.h 01445 /* Open Group Base Specifications Issue 6 (not complete) */ 01446 typedef long useconds_t; /* Time in microseconds */ 01447 01448 /* Types used in disk, inode, etc. data structures. */ 01449 typedef short dev_t; /* holds (major|minor) device pair */ 01450 typedef char gid_t; /* group id */ 01451 typedef unsigned long ino_t; /* i-node number (V3 filesystem) */ 01452 typedef unsigned short mode_t; /* file type and permissions bits */ 01453 typedef short nlink_t; /* number of links to a file */ 01454 typedef unsigned long off_t; /* offset within a file */ 01455 typedef int pid_t; /* process id (must be signed) */ 01456 typedef short uid_t; /* user id */ 01457 typedef unsigned long zone_t; /* zone number */ 01458 typedef unsigned long block_t; /* block number */ 01459 typedef unsigned long bit_t; /* bit number in a bit map */ 01460 typedef unsigned short zone1_t; /* zone number for V1 file systems */ 01461 typedef unsigned short bitchunk_t; /* collection of bits in a bitmap */ 01462 01463 typedef unsigned char u8_t; /* 8 bit type */ 01464 typedef unsigned short u16_t; /* 16 bit type */ 01465 typedef unsigned long u32_t; /* 32 bit type */ 01466 01467 typedef char i8_t; /* 8 bit signed type */ 01468 typedef short i16_t; /* 16 bit signed type */ 01469 typedef long i32_t; /* 32 bit signed type */ 01470 01471 typedef struct { u32_t _[2]; } u64_t; 01472 01473 /* The following types are needed because MINIX uses K&R style function 01474 * definitions (for maximum portability). When a short, such as dev_t, is 01475 * passed to a function with a K&R definition, the compiler automatically 01476 * promotes it to an int. The prototype must contain an int as the parameter, 01477 * not a short, because an int is what an old-style function definition 01478 * expects. Thus using dev_t in a prototype would be incorrect. It would be 01479 * sufficient to just use int instead of dev_t in the prototypes, but Dev_t 01480 * is clearer. 01481 */ 01482 typedef int Dev_t; 01483 typedef int _mnx_Gid_t; 01484 typedef int Nlink_t; 01485 typedef int _mnx_Uid_t; 01486 typedef int U8_t; 01487 typedef unsigned long U32_t; 01488 typedef int I8_t; 01489 typedef int I16_t; 01490 typedef long I32_t; 01491 01492 /* ANSI C makes writing down the promotion of unsigned types very messy. When 01493 * sizeof(short) == sizeof(int), there is no promotion, so the type stays 01494 * unsigned. When the compiler is not ANSI, there is usually no loss of 01495 * unsignedness, and there are usually no prototypes so the promoted type 01496 * doesn't matter. The use of types like Ino_t is an attempt to use ints 01497 * (which are not promoted) while providing information to the reader. 01498 */ 01499 01500 typedef unsigned long Ino_t; 01501 01502 #if _EM_WSIZE == 2 01503 /*typedef unsigned int Ino_t; Ino_t is now 32 bits */ 01504 typedef unsigned int Zone1_t; File: Page: 658 include/sys/types.h 01505 typedef unsigned int Bitchunk_t; 01506 typedef unsigned int U16_t; 01507 typedef unsigned int _mnx_Mode_t; 01508 01509 #else /* _EM_WSIZE == 4, or _EM_WSIZE undefined */ 01510 /*typedef int Ino_t; Ino_t is now 32 bits */ 01511 typedef int Zone1_t; 01512 typedef int Bitchunk_t; 01513 typedef int U16_t; 01514 typedef int _mnx_Mode_t; 01515 01516 #endif /* _EM_WSIZE == 2, etc */ 01517 01518 /* Signal handler type, e.g. SIG_IGN */ 01519 typedef void _PROTOTYPE( (*sighandler_t), (int) ); 01520 01521 /* Compatibility with other systems */ 01522 typedef unsigned char u_char; 01523 typedef unsigned short u_short; 01524 typedef unsigned int u_int; 01525 typedef unsigned long u_long; 01526 typedef char *caddr_t; 01527 01528 #endif /* _TYPES_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/sys/sigcontext.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 01600 #ifndef _SIGCONTEXT_H 01601 #define _SIGCONTEXT_H 01602 01603 /* The sigcontext structure is used by the sigreturn(2) system call. 01604 * sigreturn() is seldom called by user programs, but it is used internally 01605 * by the signal catching mechanism. 01606 */ 01607 01608 #ifndef _ANSI_H 01609 #include 01610 #endif 01611 01612 #ifndef _MINIX_SYS_CONFIG_H 01613 #include 01614 #endif 01615 01616 #if !defined(_MINIX_CHIP) 01617 #include "error, configuration is not known" 01618 #endif 01619 01620 /* The following structure should match the stackframe_s structure used 01621 * by the kernel's context switching code. Floating point registers should 01622 * be added in a different struct. 01623 */ 01624 struct sigregs { 01625 short sr_gs; 01626 short sr_fs; 01627 short sr_es; 01628 short sr_ds; 01629 int sr_di; File: Page: 659 include/sys/sigcontext.h 01630 int sr_si; 01631 int sr_bp; 01632 int sr_st; /* stack top -- used in kernel */ 01633 int sr_bx; 01634 int sr_dx; 01635 int sr_cx; 01636 int sr_retreg; 01637 int sr_retadr; /* return address to caller of save -- used 01638 * in kernel */ 01639 int sr_pc; 01640 int sr_cs; 01641 int sr_psw; 01642 int sr_sp; 01643 int sr_ss; 01644 }; 01645 01646 struct sigframe { /* stack frame created for signalled process */ 01647 _PROTOTYPE( void (*sf_retadr), (void) ); 01648 int sf_signo; 01649 int sf_code; 01650 struct sigcontext *sf_scp; 01651 int sf_fp; 01652 _PROTOTYPE( void (*sf_retadr2), (void) ); 01653 struct sigcontext *sf_scpcopy; 01654 }; 01655 01656 struct sigcontext { 01657 int sc_flags; /* sigstack state to restore */ 01658 long sc_mask; /* signal mask to restore */ 01659 struct sigregs sc_regs; /* register set to restore */ 01660 }; 01661 01662 #define sc_gs sc_regs.sr_gs 01663 #define sc_fs sc_regs.sr_fs 01664 #define sc_es sc_regs.sr_es 01665 #define sc_ds sc_regs.sr_ds 01666 #define sc_di sc_regs.sr_di 01667 #define sc_si sc_regs.sr_si 01668 #define sc_fp sc_regs.sr_bp 01669 #define sc_st sc_regs.sr_st /* stack top -- used in kernel */ 01670 #define sc_bx sc_regs.sr_bx 01671 #define sc_dx sc_regs.sr_dx 01672 #define sc_cx sc_regs.sr_cx 01673 #define sc_retreg sc_regs.sr_retreg 01674 #define sc_retadr sc_regs.sr_retadr /* return address to caller of 01675 save -- used in kernel */ 01676 #define sc_pc sc_regs.sr_pc 01677 #define sc_cs sc_regs.sr_cs 01678 #define sc_psw sc_regs.sr_psw 01679 #define sc_sp sc_regs.sr_sp 01680 #define sc_ss sc_regs.sr_ss 01681 01682 /* Values for sc_flags. Must agree with . */ 01683 #define SC_SIGCONTEXT 2 /* nonzero when signal context is included */ 01684 #define SC_NOREGLOCALS 4 /* nonzero when registers are not to be 01685 saved and restored */ 01686 01687 _PROTOTYPE( int sigreturn, (struct sigcontext *_scp) ); 01688 01689 #endif /* _SIGCONTEXT_H */ File: Page: 660 include/sys/stat.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/sys/stat.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 01700 /* The header defines a struct that is used in the stat() and 01701 * fstat functions. The information in this struct comes from the i-node of 01702 * some file. These calls are the only approved way to inspect i-nodes. 01703 */ 01704 01705 #ifndef _STAT_H 01706 #define _STAT_H 01707 01708 #ifndef _TYPES_H 01709 #include 01710 #endif 01711 01712 struct stat { 01713 dev_t st_dev; /* major/minor device number */ 01714 ino_t st_ino; /* i-node number */ 01715 mode_t st_mode; /* file mode, protection bits, etc. */ 01716 short int st_nlink; /* # links; TEMPORARY HACK: should be nlink_t*/ 01717 uid_t st_uid; /* uid of the file's owner */ 01718 short int st_gid; /* gid; TEMPORARY HACK: should be gid_t */ 01719 dev_t st_rdev; 01720 off_t st_size; /* file size */ 01721 time_t st_atime; /* time of last access */ 01722 time_t st_mtime; /* time of last data modification */ 01723 time_t st_ctime; /* time of last file status change */ 01724 }; 01725 01726 /* Traditional mask definitions for st_mode. */ 01727 /* The ugly casts on only some of the definitions are to avoid suprising sign 01728 * extensions such as S_IFREG != (mode_t) S_IFREG when ints are 32 bits. 01729 */ 01730 #define S_IFMT ((mode_t) 0170000) /* type of file */ 01731 #define S_IFLNK ((mode_t) 0120000) /* symbolic link, not implemented */ 01732 #define S_IFREG ((mode_t) 0100000) /* regular */ 01733 #define S_IFBLK 0060000 /* block special */ 01734 #define S_IFDIR 0040000 /* directory */ 01735 #define S_IFCHR 0020000 /* character special */ 01736 #define S_IFIFO 0010000 /* this is a FIFO */ 01737 #define S_ISUID 0004000 /* set user id on execution */ 01738 #define S_ISGID 0002000 /* set group id on execution */ 01739 /* next is reserved for future use */ 01740 #define S_ISVTX 01000 /* save swapped text even after use */ 01741 01742 /* POSIX masks for st_mode. */ 01743 #define S_IRWXU 00700 /* owner: rwx------ */ 01744 #define S_IRUSR 00400 /* owner: r-------- */ 01745 #define S_IWUSR 00200 /* owner: -w------- */ 01746 #define S_IXUSR 00100 /* owner: --x------ */ 01747 01748 #define S_IRWXG 00070 /* group: ---rwx--- */ 01749 #define S_IRGRP 00040 /* group: ---r----- */ 01750 #define S_IWGRP 00020 /* group: ----w---- */ 01751 #define S_IXGRP 00010 /* group: -----x--- */ 01752 01753 #define S_IRWXO 00007 /* others: ------rwx */ 01754 #define S_IROTH 00004 /* others: ------r-- */ File: Page: 661 include/sys/stat.h 01755 #define S_IWOTH 00002 /* others: -------w- */ 01756 #define S_IXOTH 00001 /* others: --------x */ 01757 01758 /* The following macros test st_mode (from POSIX Sec. 5.6.1.1). */ 01759 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) /* is a reg file */ 01760 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) /* is a directory */ 01761 #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) /* is a char spec */ 01762 #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) /* is a block spec */ 01763 #define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) /* is a pipe/FIFO */ 01764 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) /* is a sym link */ 01765 01766 /* Function Prototypes. */ 01767 _PROTOTYPE( int chmod, (const char *_path, _mnx_Mode_t _mode) ); 01768 _PROTOTYPE( int fstat, (int _fildes, struct stat *_buf) ); 01769 _PROTOTYPE( int mkdir, (const char *_path, _mnx_Mode_t _mode) ); 01770 _PROTOTYPE( int mkfifo, (const char *_path, _mnx_Mode_t _mode) ); 01771 _PROTOTYPE( int stat, (const char *_path, struct stat *_buf) ); 01772 _PROTOTYPE( mode_t umask, (_mnx_Mode_t _cmask) ); 01773 01774 /* Open Group Base Specifications Issue 6 (not complete) */ 01775 _PROTOTYPE( int lstat, (const char *_path, struct stat *_buf) ); 01776 01777 #endif /* _STAT_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/sys/dir.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 01800 /* The header gives the layout of a directory. */ 01801 01802 #ifndef _DIR_H 01803 #define _DIR_H 01804 01805 #include 01806 01807 #define DIRBLKSIZ 512 /* size of directory block */ 01808 01809 #ifndef DIRSIZ 01810 #define DIRSIZ 60 01811 #endif 01812 01813 struct direct { 01814 ino_t d_ino; 01815 char d_name[DIRSIZ]; 01816 }; 01817 01818 #endif /* _DIR_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/sys/wait.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 01900 /* The header contains macros related to wait(). The value 01901 * returned by wait() and waitpid() depends on whether the process 01902 * terminated by an exit() call, was killed by a signal, or was stopped 01903 * due to job control, as follows: 01904 * File: Page: 662 include/sys/wait.h 01905 * High byte Low byte 01906 * +---------------------+ 01907 * exit(status) | status | 0 | 01908 * +---------------------+ 01909 * killed by signal | 0 | signal | 01910 * +---------------------+ 01911 * stopped (job control) | signal | 0177 | 01912 * +---------------------+ 01913 */ 01914 01915 #ifndef _WAIT_H 01916 #define _WAIT_H 01917 01918 #ifndef _TYPES_H 01919 #include 01920 #endif 01921 01922 #define _LOW(v) ( (v) & 0377) 01923 #define _HIGH(v) ( ((v) >> 8) & 0377) 01924 01925 #define WNOHANG 1 /* do not wait for child to exit */ 01926 #define WUNTRACED 2 /* for job control; not implemented */ 01927 01928 #define WIFEXITED(s) (_LOW(s) == 0) /* normal exit */ 01929 #define WEXITSTATUS(s) (_HIGH(s)) /* exit status */ 01930 #define WTERMSIG(s) (_LOW(s) & 0177) /* sig value */ 01931 #define WIFSIGNALED(s) (((unsigned int)(s)-1 & 0xFFFF) < 0xFF) /* signaled */ 01932 #define WIFSTOPPED(s) (_LOW(s) == 0177) /* stopped */ 01933 #define WSTOPSIG(s) (_HIGH(s) & 0377) /* stop signal */ 01934 01935 /* Function Prototypes. */ 01936 _PROTOTYPE( pid_t wait, (int *_stat_loc) ); 01937 _PROTOTYPE( pid_t waitpid, (pid_t _pid, int *_stat_loc, int _options) ); 01938 01939 #endif /* _WAIT_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/sys/ioctl.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 02000 /* sys/ioctl.h - All ioctl() command codes. Author: Kees J. Bot 02001 * 23 Nov 2002 02002 * 02003 * This header file includes all other ioctl command code headers. 02004 */ 02005 02006 #ifndef _S_IOCTL_H 02007 #define _S_IOCTL_H 02008 02009 /* A driver that uses ioctls claims a character for its series of commands. 02010 * For instance: #define TCGETS _IOR('T', 8, struct termios) 02011 * This is a terminal ioctl that uses the character 'T'. The character(s) 02012 * used in each header file are shown in the comment following. 02013 */ 02014 02015 #include /* 'T' 't' 'k' */ 02016 #include /* 'd' */ 02017 #include /* 'm' */ 02018 #include /* 'c' */ 02019 File: Page: 663 include/sys/ioctl.h 02020 #endif /* _S_IOCTL_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/sys/ioc_disk.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 02100 /* sys/ioc_disk.h - Disk ioctl() command codes. Author: Kees J. Bot 02101 * 23 Nov 2002 02102 * 02103 */ 02104 02105 #ifndef _S_I_DISK_H 02106 #define _S_I_DISK_H 02107 02108 #include 02109 02110 #define DIOCSETP _IOW('d', 3, struct partition) 02111 #define DIOCGETP _IOR('d', 4, struct partition) 02112 #define DIOCEJECT _IO ('d', 5) 02113 #define DIOCTIMEOUT _IOW('d', 6, int) 02114 #define DIOCOPENCT _IOR('d', 7, int) 02115 02116 #endif /* _S_I_DISK_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/minix/ioctl.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 02200 /* minix/ioctl.h - Ioctl helper definitions. Author: Kees J. Bot 02201 * 23 Nov 2002 02202 * 02203 * This file is included by every header file that defines ioctl codes. 02204 */ 02205 02206 #ifndef _M_IOCTL_H 02207 #define _M_IOCTL_H 02208 02209 #ifndef _TYPES_H 02210 #include 02211 #endif 02212 02213 #if _EM_WSIZE >= 4 02214 /* Ioctls have the command encoded in the low-order word, and the size 02215 * of the parameter in the high-order word. The 3 high bits of the high- 02216 * order word are used to encode the in/out/void status of the parameter. 02217 */ 02218 #define _IOCPARM_MASK 0x1FFF 02219 #define _IOC_VOID 0x20000000 02220 #define _IOCTYPE_MASK 0xFFFF 02221 #define _IOC_IN 0x40000000 02222 #define _IOC_OUT 0x80000000 02223 #define _IOC_INOUT (_IOC_IN | _IOC_OUT) 02224 File: Page: 664 include/minix/ioctl.h 02225 #define _IO(x,y) ((x << 8) | y | _IOC_VOID) 02226 #define _IOR(x,y,t) ((x << 8) | y | ((sizeof(t) & _IOCPARM_MASK) << 16) |\ 02227 _IOC_OUT) 02228 #define _IOW(x,y,t) ((x << 8) | y | ((sizeof(t) & _IOCPARM_MASK) << 16) |\ 02229 _IOC_IN) 02230 #define _IORW(x,y,t) ((x << 8) | y | ((sizeof(t) & _IOCPARM_MASK) << 16) |\ 02231 _IOC_INOUT) 02232 #else 02233 /* No fancy encoding on a 16-bit machine. */ 02234 02235 #define _IO(x,y) ((x << 8) | y) 02236 #define _IOR(x,y,t) _IO(x,y) 02237 #define _IOW(x,y,t) _IO(x,y) 02238 #define _IORW(x,y,t) _IO(x,y) 02239 #endif 02240 02241 int ioctl(int _fd, int _request, void *_data); 02242 02243 #endif /* _M_IOCTL_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/minix/config.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 02300 #ifndef _CONFIG_H 02301 #define _CONFIG_H 02302 02303 /* Minix release and version numbers. */ 02304 #define OS_RELEASE "3" 02305 #define OS_VERSION "1.0" 02306 02307 /* This file sets configuration parameters for the MINIX kernel, FS, and PM. 02308 * It is divided up into two main sections. The first section contains 02309 * user-settable parameters. In the second section, various internal system 02310 * parameters are set based on the user-settable parameters. 02311 * 02312 * Parts of config.h have been moved to sys_config.h, which can be included 02313 * by other include files that wish to get at the configuration data, but 02314 * don't want to pollute the users namespace. Some editable values have 02315 * gone there. 02316 * 02317 * This is a modified version of config.h for compiling a small Minix system 02318 * with only the options described in the text, Operating Systems Design and 02319 * Implementation, 3rd edition. See the version of config.h in the full 02320 * source code directory for information on alternatives omitted here. 02321 */ 02322 02323 /* The MACHINE (called _MINIX_MACHINE) setting can be done 02324 * in . 02325 */ 02326 #include 02327 02328 #define MACHINE _MINIX_MACHINE 02329 02330 #define IBM_PC _MACHINE_IBM_PC 02331 #define SUN_4 _MACHINE_SUN_4 02332 #define SUN_4_60 _MACHINE_SUN_4_60 02333 #define ATARI _MACHINE_ATARI 02334 #define MACINTOSH _MACHINE_MACINTOSH File: Page: 665 include/minix/config.h 02335 02336 /* Number of slots in the process table for non-kernel processes. The number 02337 * of system processes defines how many processes with special privileges 02338 * there can be. User processes share the same properties and count for one. 02339 * 02340 * These can be changed in sys_config.h. 02341 */ 02342 #define NR_PROCS _NR_PROCS 02343 #define NR_SYS_PROCS _NR_SYS_PROCS 02344 02345 #define NR_BUFS 128 02346 #define NR_BUF_HASH 128 02347 02348 /* Number of controller tasks (/dev/cN device classes). */ 02349 #define NR_CTRLRS 2 02350 02351 /* Enable or disable the second level file system cache on the RAM disk. */ 02352 #define ENABLE_CACHE2 0 02353 02354 /* Enable or disable swapping processes to disk. */ 02355 #define ENABLE_SWAP 0 02356 02357 /* Include or exclude an image of /dev/boot in the boot image. 02358 * Please update the makefile in /usr/src/tools/ as well. 02359 */ 02360 #define ENABLE_BOOTDEV 0 /* load image of /dev/boot at boot time */ 02361 02362 /* DMA_SECTORS may be increased to speed up DMA based drivers. */ 02363 #define DMA_SECTORS 1 /* DMA buffer size (must be >= 1) */ 02364 02365 /* Include or exclude backwards compatibility code. */ 02366 #define ENABLE_BINCOMPAT 0 /* for binaries using obsolete calls */ 02367 #define ENABLE_SRCCOMPAT 0 /* for sources using obsolete calls */ 02368 02369 /* Which process should receive diagnostics from the kernel and system? 02370 * Directly sending it to TTY only displays the output. Sending it to the 02371 * log driver will cause the diagnostics to be buffered and displayed. 02372 */ 02373 #define OUTPUT_PROC_NR LOG_PROC_NR /* TTY_PROC_NR or LOG_PROC_NR */ 02374 02375 /* NR_CONS, NR_RS_LINES, and NR_PTYS determine the number of terminals the 02376 * system can handle. 02377 */ 02378 #define NR_CONS 4 /* # system consoles (1 to 8) */ 02379 #define NR_RS_LINES 0 /* # rs232 terminals (0 to 4) */ 02380 #define NR_PTYS 0 /* # pseudo terminals (0 to 64) */ 02381 02382 /*===========================================================================* 02383 * There are no user-settable parameters after this line * 02384 *===========================================================================*/ 02385 /* Set the CHIP type based on the machine selected. The symbol CHIP is actually 02386 * indicative of more than just the CPU. For example, machines for which 02387 * CHIP == INTEL are expected to have 8259A interrrupt controllers and the 02388 * other properties of IBM PC/XT/AT/386 types machines in general. */ 02389 #define INTEL _CHIP_INTEL /* CHIP type for PC, XT, AT, 386 and clones */ 02390 #define M68000 _CHIP_M68000 /* CHIP type for Atari, Amiga, Macintosh */ 02391 #define SPARC _CHIP_SPARC /* CHIP type for SUN-4 (e.g. SPARCstation) */ 02392 02393 /* Set the FP_FORMAT type based on the machine selected, either hw or sw */ 02394 #define FP_NONE _FP_NONE /* no floating point support */ File: Page: 666 include/minix/config.h 02395 #define FP_IEEE _FP_IEEE /* conform IEEE floating point standard */ 02396 02397 /* _MINIX_CHIP is defined in sys_config.h. */ 02398 #define CHIP _MINIX_CHIP 02399 02400 /* _MINIX_FP_FORMAT is defined in sys_config.h. */ 02401 #define FP_FORMAT _MINIX_FP_FORMAT 02402 02403 /* _ASKDEV and _FASTLOAD are defined in sys_config.h. */ 02404 #define ASKDEV _ASKDEV 02405 #define FASTLOAD _FASTLOAD 02406 02407 #endif /* _CONFIG_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/minix/sys_config.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 02500 #ifndef _MINIX_SYS_CONFIG_H 02501 #define _MINIX_SYS_CONFIG_H 1 02502 02503 /* This is a modified sys_config.h for compiling a small Minix system 02504 * with only the options described in the text, Operating Systems Design and 02505 * Implementation, 3rd edition. See the sys_config.h in the full 02506 * source code directory for information on alternatives omitted here. 02507 */ 02508 02509 /*===========================================================================* 02510 * This section contains user-settable parameters * 02511 *===========================================================================*/ 02512 #define _MINIX_MACHINE _MACHINE_IBM_PC 02513 02514 #define _MACHINE_IBM_PC 1 /* any 8088 or 80x86-based system */ 02515 02516 /* Word size in bytes (a constant equal to sizeof(int)). */ 02517 #if __ACK__ || __GNUC__ 02518 #define _WORD_SIZE _EM_WSIZE 02519 #define _PTR_SIZE _EM_WSIZE 02520 #endif 02521 02522 #define _NR_PROCS 64 02523 #define _NR_SYS_PROCS 32 02524 02525 /* Set the CHIP type based on the machine selected. The symbol CHIP is actually 02526 * indicative of more than just the CPU. For example, machines for which 02527 * CHIP == INTEL are expected to have 8259A interrrupt controllers and the 02528 * other properties of IBM PC/XT/AT/386 types machines in general. */ 02529 #define _CHIP_INTEL 1 /* CHIP type for PC, XT, AT, 386 and clones */ 02530 02531 /* Set the FP_FORMAT type based on the machine selected, either hw or sw */ 02532 #define _FP_NONE 0 /* no floating point support */ 02533 #define _FP_IEEE 1 /* conform IEEE floating point standard */ 02534 02535 #define _MINIX_CHIP _CHIP_INTEL 02536 02537 #define _MINIX_FP_FORMAT _FP_NONE 02538 02539 #ifndef _MINIX_MACHINE File: Page: 667 include/minix/sys_config.h 02540 error "In please define _MINIX_MACHINE" 02541 #endif 02542 02543 #ifndef _MINIX_CHIP 02544 error "In please define _MINIX_MACHINE to have a legal value" 02545 #endif 02546 02547 #if (_MINIX_MACHINE == 0) 02548 error "_MINIX_MACHINE has incorrect value (0)" 02549 #endif 02550 02551 #endif /* _MINIX_SYS_CONFIG_H */ 02552 02553 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/minix/const.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 02600 /* Copyright (C) 2001 by Prentice-Hall, Inc. See the copyright notice in 02601 * the file /usr/src/LICENSE. 02602 */ 02603 02604 #ifndef CHIP 02605 #error CHIP is not defined 02606 #endif 02607 02608 #define EXTERN extern /* used in *.h files */ 02609 #define PRIVATE static /* PRIVATE x limits the scope of x */ 02610 #define PUBLIC /* PUBLIC is the opposite of PRIVATE */ 02611 #define FORWARD static /* some compilers require this to be 'static'*/ 02612 02613 #define TRUE 1 /* used for turning integers into Booleans */ 02614 #define FALSE 0 /* used for turning integers into Booleans */ 02615 02616 #define HZ 60 /* clock freq (software settable on IBM-PC) */ 02617 02618 #define SUPER_USER (uid_t) 0 /* uid_t of superuser */ 02619 02620 /* Devices. */ 02621 #define MAJOR 8 /* major device = (dev>>MAJOR) & 0377 */ 02622 #define MINOR 0 /* minor device = (dev>>MINOR) & 0377 */ 02623 02624 #define NULL ((void *)0) /* null pointer */ 02625 #define CPVEC_NR 16 /* max # of entries in a SYS_VCOPY request */ 02626 #define CPVVEC_NR 64 /* max # of entries in a SYS_VCOPY request */ 02627 #define NR_IOREQS MIN(NR_BUFS, 64) 02628 /* maximum number of entries in an iorequest */ 02629 02630 /* Message passing constants. */ 02631 #define MESS_SIZE (sizeof(message)) /* might need usizeof from FS here */ 02632 #define NIL_MESS ((message *) 0) /* null pointer */ 02633 02634 /* Memory related constants. */ 02635 #define SEGMENT_TYPE 0xFF00 /* bit mask to get segment type */ 02636 #define SEGMENT_INDEX 0x00FF /* bit mask to get segment index */ 02637 02638 #define LOCAL_SEG 0x0000 /* flags indicating local memory segment */ 02639 #define NR_LOCAL_SEGS 3 /* # local segments per process (fixed) */ File: Page: 668 include/minix/const.h 02640 #define T 0 /* proc[i].mem_map[T] is for text */ 02641 #define D 1 /* proc[i].mem_map[D] is for data */ 02642 #define S 2 /* proc[i].mem_map[S] is for stack */ 02643 02644 #define REMOTE_SEG 0x0100 /* flags indicating remote memory segment */ 02645 #define NR_REMOTE_SEGS 3 /* # remote memory regions (variable) */ 02646 02647 #define BIOS_SEG 0x0200 /* flags indicating BIOS memory segment */ 02648 #define NR_BIOS_SEGS 3 /* # BIOS memory regions (variable) */ 02649 02650 #define PHYS_SEG 0x0400 /* flag indicating entire physical memory */ 02651 02652 /* Labels used to disable code sections for different reasons. */ 02653 #define DEAD_CODE 0 /* unused code in normal configuration */ 02654 #define FUTURE_CODE 0 /* new code to be activated + tested later */ 02655 #define TEMP_CODE 1 /* active code to be removed later */ 02656 02657 /* Process name length in the PM process table, including '\0'. */ 02658 #define PROC_NAME_LEN 16 02659 02660 /* Miscellaneous */ 02661 #define BYTE 0377 /* mask for 8 bits */ 02662 #define READING 0 /* copy data to user */ 02663 #define WRITING 1 /* copy data from user */ 02664 #define NO_NUM 0x8000 /* used as numerical argument to panic() */ 02665 #define NIL_PTR (char *) 0 /* generally useful expression */ 02666 #define HAVE_SCATTERED_IO 1 /* scattered I/O is now standard */ 02667 02668 /* Macros. */ 02669 #define MAX(a, b) ((a) > (b) ? (a) : (b)) 02670 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 02671 02672 /* Memory is allocated in clicks. */ 02673 #if (CHIP == INTEL) 02674 #define CLICK_SIZE 1024 /* unit in which memory is allocated */ 02675 #define CLICK_SHIFT 10 /* log2 of CLICK_SIZE */ 02676 #endif 02677 02678 #if (CHIP == SPARC) || (CHIP == M68000) 02679 #define CLICK_SIZE 4096 /* unit in which memory is allocated */ 02680 #define CLICK_SHIFT 12 /* log2 of CLICK_SIZE */ 02681 #endif 02682 02683 /* Click to byte conversions (and vice versa). */ 02684 #define HCLICK_SHIFT 4 /* log2 of HCLICK_SIZE */ 02685 #define HCLICK_SIZE 16 /* hardware segment conversion magic */ 02686 #if CLICK_SIZE >= HCLICK_SIZE 02687 #define click_to_hclick(n) ((n) << (CLICK_SHIFT - HCLICK_SHIFT)) 02688 #else 02689 #define click_to_hclick(n) ((n) >> (HCLICK_SHIFT - CLICK_SHIFT)) 02690 #endif 02691 #define hclick_to_physb(n) ((phys_bytes) (n) << HCLICK_SHIFT) 02692 #define physb_to_hclick(n) ((n) >> HCLICK_SHIFT) 02693 02694 #define ABS -999 /* this process means absolute memory */ 02695 02696 /* Flag bits for i_mode in the inode. */ 02697 #define I_TYPE 0170000 /* this field gives inode type */ 02698 #define I_REGULAR 0100000 /* regular file, not dir or special */ 02699 #define I_BLOCK_SPECIAL 0060000 /* block special file */ File: Page: 669 include/minix/const.h 02700 #define I_DIRECTORY 0040000 /* file is a directory */ 02701 #define I_CHAR_SPECIAL 0020000 /* character special file */ 02702 #define I_NAMED_PIPE 0010000 /* named pipe (FIFO) */ 02703 #define I_SET_UID_BIT 0004000 /* set effective uid_t on exec */ 02704 #define I_SET_GID_BIT 0002000 /* set effective gid_t on exec */ 02705 #define ALL_MODES 0006777 /* all bits for user, group and others */ 02706 #define RWX_MODES 0000777 /* mode bits for RWX only */ 02707 #define R_BIT 0000004 /* Rwx protection bit */ 02708 #define W_BIT 0000002 /* rWx protection bit */ 02709 #define X_BIT 0000001 /* rwX protection bit */ 02710 #define I_NOT_ALLOC 0000000 /* this inode is free */ 02711 02712 /* Flag used only in flags argument of dev_open. */ 02713 #define RO_BIT 0200000 /* Open device readonly; fail if writable. */ 02714 02715 /* Some limits. */ 02716 #define MAX_BLOCK_NR ((block_t) 077777777) /* largest block number */ 02717 #define HIGHEST_ZONE ((zone_t) 077777777) /* largest zone number */ 02718 #define MAX_INODE_NR ((ino_t) 037777777777) /* largest inode number */ 02719 #define MAX_FILE_POS ((off_t) 037777777777) /* largest legal file offset */ 02720 02721 #define NO_BLOCK ((block_t) 0) /* absence of a block number */ 02722 #define NO_ENTRY ((ino_t) 0) /* absence of a dir entry */ 02723 #define NO_ZONE ((zone_t) 0) /* absence of a zone number */ 02724 #define NO_DEV ((dev_t) 0) /* absence of a device numb */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/minix/type.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 02800 #ifndef _TYPE_H 02801 #define _TYPE_H 02802 02803 #ifndef _MINIX_SYS_CONFIG_H 02804 #include 02805 #endif 02806 02807 #ifndef _TYPES_H 02808 #include 02809 #endif 02810 02811 /* Type definitions. */ 02812 typedef unsigned int vir_clicks; /* virtual addr/length in clicks */ 02813 typedef unsigned long phys_bytes; /* physical addr/length in bytes */ 02814 typedef unsigned int phys_clicks; /* physical addr/length in clicks */ 02815 02816 #if (_MINIX_CHIP == _CHIP_INTEL) 02817 typedef unsigned int vir_bytes; /* virtual addresses and lengths in bytes */ 02818 #endif 02819 02820 #if (_MINIX_CHIP == _CHIP_M68000) 02821 typedef unsigned long vir_bytes;/* virtual addresses and lengths in bytes */ 02822 #endif 02823 02824 #if (_MINIX_CHIP == _CHIP_SPARC) 02825 typedef unsigned long vir_bytes;/* virtual addresses and lengths in bytes */ 02826 #endif 02827 02828 /* Memory map for local text, stack, data segments. */ 02829 struct mem_map { File: Page: 670 include/minix/type.h 02830 vir_clicks mem_vir; /* virtual address */ 02831 phys_clicks mem_phys; /* physical address */ 02832 vir_clicks mem_len; /* length */ 02833 }; 02834 02835 /* Memory map for remote memory areas, e.g., for the RAM disk. */ 02836 struct far_mem { 02837 int in_use; /* entry in use, unless zero */ 02838 phys_clicks mem_phys; /* physical address */ 02839 vir_clicks mem_len; /* length */ 02840 }; 02841 02842 /* Structure for virtual copying by means of a vector with requests. */ 02843 struct vir_addr { 02844 int proc_nr; 02845 int segment; 02846 vir_bytes offset; 02847 }; 02848 02849 #define phys_cp_req vir_cp_req 02850 struct vir_cp_req { 02851 struct vir_addr src; 02852 struct vir_addr dst; 02853 phys_bytes count; 02854 }; 02855 02856 typedef struct { 02857 vir_bytes iov_addr; /* address of an I/O buffer */ 02858 vir_bytes iov_size; /* sizeof an I/O buffer */ 02859 } iovec_t; 02860 02861 /* PM passes the address of a structure of this type to KERNEL when 02862 * sys_sendsig() is invoked as part of the signal catching mechanism. 02863 * The structure contain all the information that KERNEL needs to build 02864 * the signal stack. 02865 */ 02866 struct sigmsg { 02867 int sm_signo; /* signal number being caught */ 02868 unsigned long sm_mask; /* mask to restore when handler returns */ 02869 vir_bytes sm_sighandler; /* address of handler */ 02870 vir_bytes sm_sigreturn; /* address of _sigreturn in C library */ 02871 vir_bytes sm_stkptr; /* user stack pointer */ 02872 }; 02873 02874 /* This is used to obtain system information through SYS_GETINFO. */ 02875 struct kinfo { 02876 phys_bytes code_base; /* base of kernel code */ 02877 phys_bytes code_size; 02878 phys_bytes data_base; /* base of kernel data */ 02879 phys_bytes data_size; 02880 vir_bytes proc_addr; /* virtual address of process table */ 02881 phys_bytes kmem_base; /* kernel memory layout (/dev/kmem) */ 02882 phys_bytes kmem_size; 02883 phys_bytes bootdev_base; /* boot device from boot image (/dev/boot) */ 02884 phys_bytes bootdev_size; 02885 phys_bytes bootdev_mem; 02886 phys_bytes params_base; /* parameters passed by boot monitor */ 02887 phys_bytes params_size; 02888 int nr_procs; /* number of user processes */ 02889 int nr_tasks; /* number of kernel tasks */ File: Page: 671 include/minix/type.h 02890 char release[6]; /* kernel release number */ 02891 char version[6]; /* kernel version number */ 02892 int relocking; /* relocking check (for debugging) */ 02893 }; 02894 02895 struct machine { 02896 int pc_at; 02897 int ps_mca; 02898 int processor; 02899 int protected; 02900 int vdu_ega; 02901 int vdu_vga; 02902 }; 02903 02904 #endif /* _TYPE_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/minix/ipc.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 03000 #ifndef _IPC_H 03001 #define _IPC_H 03002 03003 /*==========================================================================* 03004 * Types relating to messages. * 03005 *==========================================================================*/ 03006 03007 #define M1 1 03008 #define M3 3 03009 #define M4 4 03010 #define M3_STRING 14 03011 03012 typedef struct {int m1i1, m1i2, m1i3; char *m1p1, *m1p2, *m1p3;} mess_1; 03013 typedef struct {int m2i1, m2i2, m2i3; long m2l1, m2l2; char *m2p1;} mess_2; 03014 typedef struct {int m3i1, m3i2; char *m3p1; char m3ca1[M3_STRING];} mess_3; 03015 typedef struct {long m4l1, m4l2, m4l3, m4l4, m4l5;} mess_4; 03016 typedef struct {short m5c1, m5c2; int m5i1, m5i2; long m5l1, m5l2, m5l3;}mess_5; 03017 typedef struct {int m7i1, m7i2, m7i3, m7i4; char *m7p1, *m7p2;} mess_7; 03018 typedef struct {int m8i1, m8i2; char *m8p1, *m8p2, *m8p3, *m8p4;} mess_8; 03019 03020 typedef struct { 03021 int m_source; /* who sent the message */ 03022 int m_type; /* what kind of message is it */ 03023 union { 03024 mess_1 m_m1; 03025 mess_2 m_m2; 03026 mess_3 m_m3; 03027 mess_4 m_m4; 03028 mess_5 m_m5; 03029 mess_7 m_m7; 03030 mess_8 m_m8; 03031 } m_u; 03032 } message; 03033 03034 /* The following defines provide names for useful members. */ 03035 #define m1_i1 m_u.m_m1.m1i1 03036 #define m1_i2 m_u.m_m1.m1i2 03037 #define m1_i3 m_u.m_m1.m1i3 03038 #define m1_p1 m_u.m_m1.m1p1 03039 #define m1_p2 m_u.m_m1.m1p2 File: Page: 672 include/minix/ipc.h 03040 #define m1_p3 m_u.m_m1.m1p3 03041 03042 #define m2_i1 m_u.m_m2.m2i1 03043 #define m2_i2 m_u.m_m2.m2i2 03044 #define m2_i3 m_u.m_m2.m2i3 03045 #define m2_l1 m_u.m_m2.m2l1 03046 #define m2_l2 m_u.m_m2.m2l2 03047 #define m2_p1 m_u.m_m2.m2p1 03048 03049 #define m3_i1 m_u.m_m3.m3i1 03050 #define m3_i2 m_u.m_m3.m3i2 03051 #define m3_p1 m_u.m_m3.m3p1 03052 #define m3_ca1 m_u.m_m3.m3ca1 03053 03054 #define m4_l1 m_u.m_m4.m4l1 03055 #define m4_l2 m_u.m_m4.m4l2 03056 #define m4_l3 m_u.m_m4.m4l3 03057 #define m4_l4 m_u.m_m4.m4l4 03058 #define m4_l5 m_u.m_m4.m4l5 03059 03060 #define m5_c1 m_u.m_m5.m5c1 03061 #define m5_c2 m_u.m_m5.m5c2 03062 #define m5_i1 m_u.m_m5.m5i1 03063 #define m5_i2 m_u.m_m5.m5i2 03064 #define m5_l1 m_u.m_m5.m5l1 03065 #define m5_l2 m_u.m_m5.m5l2 03066 #define m5_l3 m_u.m_m5.m5l3 03067 03068 #define m7_i1 m_u.m_m7.m7i1 03069 #define m7_i2 m_u.m_m7.m7i2 03070 #define m7_i3 m_u.m_m7.m7i3 03071 #define m7_i4 m_u.m_m7.m7i4 03072 #define m7_p1 m_u.m_m7.m7p1 03073 #define m7_p2 m_u.m_m7.m7p2 03074 03075 #define m8_i1 m_u.m_m8.m8i1 03076 #define m8_i2 m_u.m_m8.m8i2 03077 #define m8_p1 m_u.m_m8.m8p1 03078 #define m8_p2 m_u.m_m8.m8p2 03079 #define m8_p3 m_u.m_m8.m8p3 03080 #define m8_p4 m_u.m_m8.m8p4 03081 03082 /*==========================================================================* 03083 * Minix run-time system (IPC). * 03084 *==========================================================================*/ 03085 03086 /* Hide names to avoid name space pollution. */ 03087 #define echo _echo 03088 #define notify _notify 03089 #define sendrec _sendrec 03090 #define receive _receive 03091 #define send _send 03092 #define nb_receive _nb_receive 03093 #define nb_send _nb_send 03094 03095 _PROTOTYPE( int echo, (message *m_ptr) ); 03096 _PROTOTYPE( int notify, (int dest) ); 03097 _PROTOTYPE( int sendrec, (int src_dest, message *m_ptr) ); 03098 _PROTOTYPE( int receive, (int src, message *m_ptr) ); 03099 _PROTOTYPE( int send, (int dest, message *m_ptr) ); File: Page: 673 include/minix/ipc.h 03100 _PROTOTYPE( int nb_receive, (int src, message *m_ptr) ); 03101 _PROTOTYPE( int nb_send, (int dest, message *m_ptr) ); 03102 03103 #endif /* _IPC_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/minix/syslib.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 03200 /* Prototypes for system library functions. */ 03201 03202 #ifndef _SYSLIB_H 03203 #define _SYSLIB_H 03204 03205 #ifndef _TYPES_H 03206 #include 03207 #endif 03208 03209 #ifndef _IPC_H 03210 #include 03211 #endif 03212 03213 #ifndef _DEVIO_H 03214 #include 03215 #endif 03216 03217 /* Forward declaration */ 03218 struct reg86u; 03219 03220 #define SYSTASK SYSTEM 03221 03222 /*==========================================================================* 03223 * Minix system library. * 03224 *==========================================================================*/ 03225 _PROTOTYPE( int _taskcall, (int who, int syscallnr, message *msgptr)); 03226 03227 _PROTOTYPE( int sys_abort, (int how, ...)); 03228 _PROTOTYPE( int sys_exec, (int proc, char *ptr, 03229 char *aout, vir_bytes initpc)); 03230 _PROTOTYPE( int sys_fork, (int parent, int child)); 03231 _PROTOTYPE( int sys_newmap, (int proc, struct mem_map *ptr)); 03232 _PROTOTYPE( int sys_exit, (int proc)); 03233 _PROTOTYPE( int sys_trace, (int req, int proc, long addr, long *data_p)); 03234 03235 _PROTOTYPE( int sys_svrctl, (int proc, int req, int priv,vir_bytes argp)); 03236 _PROTOTYPE( int sys_nice, (int proc, int priority)); 03237 03238 _PROTOTYPE( int sys_int86, (struct reg86u *reg86p)); 03239 03240 /* Shorthands for sys_sdevio() system call. */ 03241 #define sys_insb(port, proc_nr, buffer, count) \ 03242 sys_sdevio(DIO_INPUT, port, DIO_BYTE, proc_nr, buffer, count) 03243 #define sys_insw(port, proc_nr, buffer, count) \ 03244 sys_sdevio(DIO_INPUT, port, DIO_WORD, proc_nr, buffer, count) 03245 #define sys_outsb(port, proc_nr, buffer, count) \ 03246 sys_sdevio(DIO_OUTPUT, port, DIO_BYTE, proc_nr, buffer, count) 03247 #define sys_outsw(port, proc_nr, buffer, count) \ 03248 sys_sdevio(DIO_OUTPUT, port, DIO_WORD, proc_nr, buffer, count) 03249 _PROTOTYPE( int sys_sdevio, (int req, long port, int type, int proc_nr, File: Page: 674 include/minix/syslib.h 03250 void *buffer, int count)); 03251 03252 /* Clock functionality: get system times or (un)schedule an alarm call. */ 03253 _PROTOTYPE( int sys_times, (int proc_nr, clock_t *ptr)); 03254 _PROTOTYPE(int sys_setalarm, (clock_t exp_time, int abs_time)); 03255 03256 /* Shorthands for sys_irqctl() system call. */ 03257 #define sys_irqdisable(hook_id) \ 03258 sys_irqctl(IRQ_DISABLE, 0, 0, hook_id) 03259 #define sys_irqenable(hook_id) \ 03260 sys_irqctl(IRQ_ENABLE, 0, 0, hook_id) 03261 #define sys_irqsetpolicy(irq_vec, policy, hook_id) \ 03262 sys_irqctl(IRQ_SETPOLICY, irq_vec, policy, hook_id) 03263 #define sys_irqrmpolicy(irq_vec, hook_id) \ 03264 sys_irqctl(IRQ_RMPOLICY, irq_vec, 0, hook_id) 03265 _PROTOTYPE ( int sys_irqctl, (int request, int irq_vec, int policy, 03266 int *irq_hook_id) ); 03267 03268 /* Shorthands for sys_vircopy() and sys_physcopy() system calls. */ 03269 #define sys_biosin(bios_vir, dst_vir, bytes) \ 03270 sys_vircopy(SELF, BIOS_SEG, bios_vir, SELF, D, dst_vir, bytes) 03271 #define sys_biosout(src_vir, bios_vir, bytes) \ 03272 sys_vircopy(SELF, D, src_vir, SELF, BIOS_SEG, bios_vir, bytes) 03273 #define sys_datacopy(src_proc, src_vir, dst_proc, dst_vir, bytes) \ 03274 sys_vircopy(src_proc, D, src_vir, dst_proc, D, dst_vir, bytes) 03275 #define sys_textcopy(src_proc, src_vir, dst_proc, dst_vir, bytes) \ 03276 sys_vircopy(src_proc, T, src_vir, dst_proc, T, dst_vir, bytes) 03277 #define sys_stackcopy(src_proc, src_vir, dst_proc, dst_vir, bytes) \ 03278 sys_vircopy(src_proc, S, src_vir, dst_proc, S, dst_vir, bytes) 03279 _PROTOTYPE(int sys_vircopy, (int src_proc, int src_seg, vir_bytes src_vir, 03280 int dst_proc, int dst_seg, vir_bytes dst_vir, phys_bytes bytes)); 03281 03282 #define sys_abscopy(src_phys, dst_phys, bytes) \ 03283 sys_physcopy(NONE, PHYS_SEG, src_phys, NONE, PHYS_SEG, dst_phys, bytes) 03284 _PROTOTYPE(int sys_physcopy, (int src_proc, int src_seg, vir_bytes src_vir, 03285 int dst_proc, int dst_seg, vir_bytes dst_vir, phys_bytes bytes)); 03286 _PROTOTYPE(int sys_memset, (unsigned long pattern, 03287 phys_bytes base, phys_bytes bytes)); 03288 03289 /* Vectored virtual / physical copy calls. */ 03290 #if DEAD_CODE /* library part not yet implemented */ 03291 _PROTOTYPE(int sys_virvcopy, (phys_cp_req *vec_ptr,int vec_size,int *nr_ok)); 03292 _PROTOTYPE(int sys_physvcopy, (phys_cp_req *vec_ptr,int vec_size,int *nr_ok)); 03293 #endif 03294 03295 _PROTOTYPE(int sys_umap, (int proc_nr, int seg, vir_bytes vir_addr, 03296 vir_bytes bytes, phys_bytes *phys_addr)); 03297 _PROTOTYPE(int sys_segctl, (int *index, u16_t *seg, vir_bytes *off, 03298 phys_bytes phys, vir_bytes size)); 03299 03300 /* Shorthands for sys_getinfo() system call. */ 03301 #define sys_getkmessages(dst) sys_getinfo(GET_KMESSAGES, dst, 0,0,0) 03302 #define sys_getkinfo(dst) sys_getinfo(GET_KINFO, dst, 0,0,0) 03303 #define sys_getmachine(dst) sys_getinfo(GET_MACHINE, dst, 0,0,0) 03304 #define sys_getproctab(dst) sys_getinfo(GET_PROCTAB, dst, 0,0,0) 03305 #define sys_getprivtab(dst) sys_getinfo(GET_PRIVTAB, dst, 0,0,0) 03306 #define sys_getproc(dst,nr) sys_getinfo(GET_PROC, dst, 0,0, nr) 03307 #define sys_getrandomness(dst) sys_getinfo(GET_RANDOMNESS, dst, 0,0,0) 03308 #define sys_getimage(dst) sys_getinfo(GET_IMAGE, dst, 0,0,0) 03309 #define sys_getirqhooks(dst) sys_getinfo(GET_IRQHOOKS, dst, 0,0,0) File: Page: 675 include/minix/syslib.h 03310 #define sys_getmonparams(v,vl) sys_getinfo(GET_MONPARAMS, v,vl, 0,0) 03311 #define sys_getschedinfo(v1,v2) sys_getinfo(GET_SCHEDINFO, v1,0, v2,0) 03312 #define sys_getlocktimings(dst) sys_getinfo(GET_LOCKTIMING, dst, 0,0,0) 03313 #define sys_getbiosbuffer(virp, sizep) sys_getinfo(GET_BIOSBUFFER, virp, \ 03314 sizeof(*virp), sizep, sizeof(*sizep)) 03315 _PROTOTYPE(int sys_getinfo, (int request, void *val_ptr, int val_len, 03316 void *val_ptr2, int val_len2) ); 03317 03318 /* Signal control. */ 03319 _PROTOTYPE(int sys_kill, (int proc, int sig) ); 03320 _PROTOTYPE(int sys_sigsend, (int proc_nr, struct sigmsg *sig_ctxt) ); 03321 _PROTOTYPE(int sys_sigreturn, (int proc_nr, struct sigmsg *sig_ctxt) ); 03322 _PROTOTYPE(int sys_getksig, (int *k_proc_nr, sigset_t *k_sig_map) ); 03323 _PROTOTYPE(int sys_endksig, (int proc_nr) ); 03324 03325 /* NOTE: two different approaches were used to distinguish the device I/O 03326 * types 'byte', 'word', 'long': the latter uses #define and results in a 03327 * smaller implementation, but looses the static type checking. 03328 */ 03329 _PROTOTYPE(int sys_voutb, (pvb_pair_t *pvb_pairs, int nr_ports) ); 03330 _PROTOTYPE(int sys_voutw, (pvw_pair_t *pvw_pairs, int nr_ports) ); 03331 _PROTOTYPE(int sys_voutl, (pvl_pair_t *pvl_pairs, int nr_ports) ); 03332 _PROTOTYPE(int sys_vinb, (pvb_pair_t *pvb_pairs, int nr_ports) ); 03333 _PROTOTYPE(int sys_vinw, (pvw_pair_t *pvw_pairs, int nr_ports) ); 03334 _PROTOTYPE(int sys_vinl, (pvl_pair_t *pvl_pairs, int nr_ports) ); 03335 03336 /* Shorthands for sys_out() system call. */ 03337 #define sys_outb(p,v) sys_out((p), (unsigned long) (v), DIO_BYTE) 03338 #define sys_outw(p,v) sys_out((p), (unsigned long) (v), DIO_WORD) 03339 #define sys_outl(p,v) sys_out((p), (unsigned long) (v), DIO_LONG) 03340 _PROTOTYPE(int sys_out, (int port, unsigned long value, int type) ); 03341 03342 /* Shorthands for sys_in() system call. */ 03343 #define sys_inb(p,v) sys_in((p), (unsigned long*) (v), DIO_BYTE) 03344 #define sys_inw(p,v) sys_in((p), (unsigned long*) (v), DIO_WORD) 03345 #define sys_inl(p,v) sys_in((p), (unsigned long*) (v), DIO_LONG) 03346 _PROTOTYPE(int sys_in, (int port, unsigned long *value, int type) ); 03347 03348 #endif /* _SYSLIB_H */ 03349 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/minix/sysutil.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 03400 #ifndef _EXTRALIB_H 03401 #define _EXTRALIB_H 03402 03403 /* Extra system library definitions to support device drivers and servers. 03404 * 03405 * Created: 03406 * Mar 15, 2004 by Jorrit N. Herder 03407 * 03408 * Changes: 03409 * May 31, 2005: added printf, kputc (relocated from syslib) 03410 * May 31, 2005: added getuptime 03411 * Mar 18, 2005: added tickdelay 03412 * Oct 01, 2004: added env_parse, env_prefix, env_panic 03413 * Jul 13, 2004: added fkey_ctl 03414 * Apr 28, 2004: added report, panic File: Page: 676 include/minix/sysutil.h 03415 * Mar 31, 2004: setup like other libraries, such as syslib 03416 */ 03417 03418 /*==========================================================================* 03419 * Miscellaneous helper functions. 03420 *==========================================================================*/ 03421 03422 /* Environment parsing return values. */ 03423 #define EP_BUF_SIZE 128 /* local buffer for env value */ 03424 #define EP_UNSET 0 /* variable not set */ 03425 #define EP_OFF 1 /* var = off */ 03426 #define EP_ON 2 /* var = on (or field left blank) */ 03427 #define EP_SET 3 /* var = 1: 2: 3 (nonblank field) */ 03428 #define EP_EGETKENV 4 /* sys_getkenv() failed ... */ 03429 03430 _PROTOTYPE( void env_setargs, (int argc, char *argv[]) ); 03431 _PROTOTYPE( int env_get_param, (char *key, char *value, int max_size) ); 03432 _PROTOTYPE( int env_prefix, (char *env, char *prefix) ); 03433 _PROTOTYPE( void env_panic, (char *key) ); 03434 _PROTOTYPE( int env_parse, (char *env, char *fmt, int field, long *param, 03435 long min, long max) ); 03436 03437 #define fkey_map(fkeys, sfkeys) fkey_ctl(FKEY_MAP, (fkeys), (sfkeys)) 03438 #define fkey_unmap(fkeys, sfkeys) fkey_ctl(FKEY_UNMAP, (fkeys), (sfkeys)) 03439 #define fkey_events(fkeys, sfkeys) fkey_ctl(FKEY_EVENTS, (fkeys), (sfkeys)) 03440 _PROTOTYPE( int fkey_ctl, (int req, int *fkeys, int *sfkeys) ); 03441 03442 _PROTOTYPE( int printf, (const char *fmt, ...)); 03443 _PROTOTYPE( void kputc, (int c)); 03444 _PROTOTYPE( void report, (char *who, char *mess, int num)); 03445 _PROTOTYPE( void panic, (char *who, char *mess, int num)); 03446 _PROTOTYPE( int getuptime, (clock_t *ticks)); 03447 _PROTOTYPE( int tickdelay, (clock_t ticks)); 03448 03449 #endif /* _EXTRALIB_H */ 03450 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/minix/callnr.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 03500 #define NCALLS 91 /* number of system calls allowed */ 03501 03502 #define EXIT 1 03503 #define FORK 2 03504 #define READ 3 03505 #define WRITE 4 03506 #define OPEN 5 03507 #define CLOSE 6 03508 #define WAIT 7 03509 #define CREAT 8 03510 #define LINK 9 03511 #define UNLINK 10 03512 #define WAITPID 11 03513 #define CHDIR 12 03514 #define TIME 13 File: Page: 677 include/minix/callnr.h 03515 #define MKNOD 14 03516 #define CHMOD 15 03517 #define CHOWN 16 03518 #define BRK 17 03519 #define STAT 18 03520 #define LSEEK 19 03521 #define GETPID 20 03522 #define MOUNT 21 03523 #define UMOUNT 22 03524 #define SETUID 23 03525 #define GETUID 24 03526 #define STIME 25 03527 #define PTRACE 26 03528 #define ALARM 27 03529 #define FSTAT 28 03530 #define PAUSE 29 03531 #define UTIME 30 03532 #define ACCESS 33 03533 #define SYNC 36 03534 #define KILL 37 03535 #define RENAME 38 03536 #define MKDIR 39 03537 #define RMDIR 40 03538 #define DUP 41 03539 #define PIPE 42 03540 #define TIMES 43 03541 #define SETGID 46 03542 #define GETGID 47 03543 #define SIGNAL 48 03544 #define IOCTL 54 03545 #define FCNTL 55 03546 #define EXEC 59 03547 #define UMASK 60 03548 #define CHROOT 61 03549 #define SETSID 62 03550 #define GETPGRP 63 03551 03552 /* The following are not system calls, but are processed like them. */ 03553 #define UNPAUSE 65 /* to MM or FS: check for EINTR */ 03554 #define REVIVE 67 /* to FS: revive a sleeping process */ 03555 #define TASK_REPLY 68 /* to FS: reply code from tty task */ 03556 03557 /* Posix signal handling. */ 03558 #define SIGACTION 71 03559 #define SIGSUSPEND 72 03560 #define SIGPENDING 73 03561 #define SIGPROCMASK 74 03562 #define SIGRETURN 75 03563 03564 #define REBOOT 76 /* to PM */ 03565 03566 /* MINIX specific calls, e.g., to support system services. */ 03567 #define SVRCTL 77 03568 /* unused */ 03569 #define GETSYSINFO 79 /* to PM or FS */ 03570 #define GETPROCNR 80 /* to PM */ 03571 #define DEVCTL 81 /* to FS */ 03572 #define FSTATFS 82 /* to FS */ 03573 #define ALLOCMEM 83 /* to PM */ 03574 #define FREEMEM 84 /* to PM */ File: Page: 678 include/minix/callnr.h 03575 #define SELECT 85 /* to FS */ 03576 #define FCHDIR 86 /* to FS */ 03577 #define FSYNC 87 /* to FS */ 03578 #define GETPRIORITY 88 /* to PM */ 03579 #define SETPRIORITY 89 /* to PM */ 03580 #define GETTIMEOFDAY 90 /* to PM */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/minix/com.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 03600 #ifndef _MINIX_COM_H 03601 #define _MINIX_COM_H 03602 03603 /*===========================================================================* 03604 * Magic process numbers * 03605 *===========================================================================*/ 03606 03607 #define ANY 0x7ace /* used to indicate 'any process' */ 03608 #define NONE 0x6ace /* used to indicate 'no process at all' */ 03609 #define SELF 0x8ace /* used to indicate 'own process' */ 03610 03611 /*===========================================================================* 03612 * Process numbers of processes in the system image * 03613 *===========================================================================*/ 03614 03615 /* The values of several task numbers depend on whether they or other tasks 03616 * are enabled. They are defined as (PREVIOUS_TASK - ENABLE_TASK) in general. 03617 * ENABLE_TASK is either 0 or 1, so a task either gets a new number, or gets 03618 * the same number as the previous task and is further unused. Note that the 03619 * order should correspond to the order in the task table defined in table.c. 03620 */ 03621 03622 /* Kernel tasks. These all run in the same address space. */ 03623 #define IDLE -4 /* runs when no one else can run */ 03624 #define CLOCK -3 /* alarms and other clock functions */ 03625 #define SYSTEM -2 /* request system functionality */ 03626 #define KERNEL -1 /* pseudo-process for IPC and scheduling */ 03627 #define HARDWARE KERNEL /* for hardware interrupt handlers */ 03628 03629 /* Number of tasks. Note that NR_PROCS is defined in . */ 03630 #define NR_TASKS 4 03631 03632 /* User-space processes, that is, device drivers, servers, and INIT. */ 03633 #define PM_PROC_NR 0 /* process manager */ 03634 #define FS_PROC_NR 1 /* file system */ 03635 #define RS_PROC_NR 2 /* reincarnation server */ 03636 #define MEM_PROC_NR 3 /* memory driver (RAM disk, null, etc.) */ 03637 #define LOG_PROC_NR 4 /* log device driver */ 03638 #define TTY_PROC_NR 5 /* terminal (TTY) driver */ 03639 #define DRVR_PROC_NR 6 /* device driver for boot medium */ 03640 #define INIT_PROC_NR 7 /* init -- goes multiuser */ 03641 03642 /* Number of processes contained in the system image. */ 03643 #define NR_BOOT_PROCS (NR_TASKS + INIT_PROC_NR + 1) 03644 File: Page: 679 include/minix/com.h 03645 /*===========================================================================* 03646 * Kernel notification types * 03647 *===========================================================================*/ 03648 03649 /* Kernel notification types. In principle, these can be sent to any process, 03650 * so make sure that these types do not interfere with other message types. 03651 * Notifications are prioritized because of the way they are unhold() and 03652 * blocking notifications are delivered. The lowest numbers go first. The 03653 * offset are used for the per-process notification bit maps. 03654 */ 03655 #define NOTIFY_MESSAGE 0x1000 03656 #define NOTIFY_FROM(p_nr) (NOTIFY_MESSAGE | ((p_nr) + NR_TASKS)) 03657 # define SYN_ALARM NOTIFY_FROM(CLOCK) /* synchronous alarm */ 03658 # define SYS_SIG NOTIFY_FROM(SYSTEM) /* system signal */ 03659 # define HARD_INT NOTIFY_FROM(HARDWARE) /* hardware interrupt */ 03660 # define NEW_KSIG NOTIFY_FROM(HARDWARE) /* new kernel signal */ 03661 # define FKEY_PRESSED NOTIFY_FROM(TTY_PROC_NR)/* function key press */ 03662 03663 /* Shorthands for message parameters passed with notifications. */ 03664 #define NOTIFY_SOURCE m_source 03665 #define NOTIFY_TYPE m_type 03666 #define NOTIFY_ARG m2_l1 03667 #define NOTIFY_TIMESTAMP m2_l2 03668 #define NOTIFY_FLAGS m2_i1 03669 03670 /*===========================================================================* 03671 * Messages for BLOCK and CHARACTER device drivers * 03672 *===========================================================================*/ 03673 03674 /* Message types for device drivers. */ 03675 #define DEV_RQ_BASE 0x400 /* base for device request types */ 03676 #define DEV_RS_BASE 0x500 /* base for device response types */ 03677 03678 #define CANCEL (DEV_RQ_BASE + 0) /* general req to force a task to cancel */ 03679 #define DEV_READ (DEV_RQ_BASE + 3) /* read from minor device */ 03680 #define DEV_WRITE (DEV_RQ_BASE + 4) /* write to minor device */ 03681 #define DEV_IOCTL (DEV_RQ_BASE + 5) /* I/O control code */ 03682 #define DEV_OPEN (DEV_RQ_BASE + 6) /* open a minor device */ 03683 #define DEV_CLOSE (DEV_RQ_BASE + 7) /* close a minor device */ 03684 #define DEV_SCATTER (DEV_RQ_BASE + 8) /* write from a vector */ 03685 #define DEV_GATHER (DEV_RQ_BASE + 9) /* read into a vector */ 03686 #define TTY_SETPGRP (DEV_RQ_BASE + 10) /* set process group */ 03687 #define TTY_EXIT (DEV_RQ_BASE + 11) /* process group leader exited */ 03688 #define DEV_SELECT (DEV_RQ_BASE + 12) /* request select() attention */ 03689 #define DEV_STATUS (DEV_RQ_BASE + 13) /* request driver status */ 03690 03691 #define DEV_REPLY (DEV_RS_BASE + 0) /* general task reply */ 03692 #define DEV_CLONED (DEV_RS_BASE + 1) /* return cloned minor */ 03693 #define DEV_REVIVE (DEV_RS_BASE + 2) /* driver revives process */ 03694 #define DEV_IO_READY (DEV_RS_BASE + 3) /* selected device ready */ 03695 #define DEV_NO_STATUS (DEV_RS_BASE + 4) /* empty status reply */ 03696 03697 /* Field names for messages to block and character device drivers. */ 03698 #define DEVICE m2_i1 /* major-minor device */ 03699 #define PROC_NR m2_i2 /* which (proc) wants I/O? */ 03700 #define COUNT m2_i3 /* how many bytes to transfer */ 03701 #define REQUEST m2_i3 /* ioctl request code */ 03702 #define POSITION m2_l1 /* file offset */ 03703 #define ADDRESS m2_p1 /* core buffer address */ 03704 File: Page: 680 include/minix/com.h 03705 /* Field names for DEV_SELECT messages to device drivers. */ 03706 #define DEV_MINOR m2_i1 /* minor device */ 03707 #define DEV_SEL_OPS m2_i2 /* which select operations are requested */ 03708 #define DEV_SEL_WATCH m2_i3 /* request notify if no operations are ready */ 03709 03710 /* Field names used in reply messages from tasks. */ 03711 #define REP_PROC_NR m2_i1 /* # of proc on whose behalf I/O was done */ 03712 #define REP_STATUS m2_i2 /* bytes transferred or error number */ 03713 # define SUSPEND -998 /* status to suspend caller, reply later */ 03714 03715 /* Field names for messages to TTY driver. */ 03716 #define TTY_LINE DEVICE /* message parameter: terminal line */ 03717 #define TTY_REQUEST COUNT /* message parameter: ioctl request code */ 03718 #define TTY_SPEK POSITION/* message parameter: ioctl speed, erasing */ 03719 #define TTY_FLAGS m2_l2 /* message parameter: ioctl tty mode */ 03720 #define TTY_PGRP m2_i3 /* message parameter: process group */ 03721 03722 /* Field names for the QIC 02 status reply from tape driver */ 03723 #define TAPE_STAT0 m2_l1 03724 #define TAPE_STAT1 m2_l2 03725 03726 /*===========================================================================* 03727 * Messages for networking layer * 03728 *===========================================================================*/ 03729 03730 /* Message types for network layer requests. This layer acts like a driver. */ 03731 #define NW_OPEN DEV_OPEN 03732 #define NW_CLOSE DEV_CLOSE 03733 #define NW_READ DEV_READ 03734 #define NW_WRITE DEV_WRITE 03735 #define NW_IOCTL DEV_IOCTL 03736 #define NW_CANCEL CANCEL 03737 03738 /* Base type for data link layer requests and responses. */ 03739 #define DL_RQ_BASE 0x800 03740 #define DL_RS_BASE 0x900 03741 03742 /* Message types for data link layer requests. */ 03743 #define DL_WRITE (DL_RQ_BASE + 3) 03744 #define DL_WRITEV (DL_RQ_BASE + 4) 03745 #define DL_READ (DL_RQ_BASE + 5) 03746 #define DL_READV (DL_RQ_BASE + 6) 03747 #define DL_INIT (DL_RQ_BASE + 7) 03748 #define DL_STOP (DL_RQ_BASE + 8) 03749 #define DL_GETSTAT (DL_RQ_BASE + 9) 03750 03751 /* Message type for data link layer replies. */ 03752 #define DL_INIT_REPLY (DL_RS_BASE + 20) 03753 #define DL_TASK_REPLY (DL_RS_BASE + 21) 03754 03755 /* Field names for data link layer messages. */ 03756 #define DL_PORT m2_i1 03757 #define DL_PROC m2_i2 03758 #define DL_COUNT m2_i3 03759 #define DL_MODE m2_l1 03760 #define DL_CLCK m2_l2 03761 #define DL_ADDR m2_p1 03762 #define DL_STAT m2_l1 03763 03764 /* Bits in 'DL_STAT' field of DL replies. */ File: Page: 681 include/minix/com.h 03765 # define DL_PACK_SEND 0x01 03766 # define DL_PACK_RECV 0x02 03767 # define DL_READ_IP 0x04 03768 03769 /* Bits in 'DL_MODE' field of DL requests. */ 03770 # define DL_NOMODE 0x0 03771 # define DL_PROMISC_REQ 0x2 03772 # define DL_MULTI_REQ 0x4 03773 # define DL_BROAD_REQ 0x8 03774 03775 /*===========================================================================* 03776 * SYSTASK request types and field names * 03777 *===========================================================================*/ 03778 03779 /* System library calls are dispatched via a call vector, so be careful when 03780 * modifying the system call numbers. The numbers here determine which call 03781 * is made from the call vector. 03782 */ 03783 #define KERNEL_CALL 0x600 /* base for kernel calls to SYSTEM */ 03784 03785 # define SYS_FORK (KERNEL_CALL + 0) /* sys_fork() */ 03786 # define SYS_EXEC (KERNEL_CALL + 1) /* sys_exec() */ 03787 # define SYS_EXIT (KERNEL_CALL + 2) /* sys_exit() */ 03788 # define SYS_NICE (KERNEL_CALL + 3) /* sys_nice() */ 03789 # define SYS_PRIVCTL (KERNEL_CALL + 4) /* sys_privctl() */ 03790 # define SYS_TRACE (KERNEL_CALL + 5) /* sys_trace() */ 03791 # define SYS_KILL (KERNEL_CALL + 6) /* sys_kill() */ 03792 03793 # define SYS_GETKSIG (KERNEL_CALL + 7) /* sys_getsig() */ 03794 # define SYS_ENDKSIG (KERNEL_CALL + 8) /* sys_endsig() */ 03795 # define SYS_SIGSEND (KERNEL_CALL + 9) /* sys_sigsend() */ 03796 # define SYS_SIGRETURN (KERNEL_CALL + 10) /* sys_sigreturn() */ 03797 03798 # define SYS_NEWMAP (KERNEL_CALL + 11) /* sys_newmap() */ 03799 # define SYS_SEGCTL (KERNEL_CALL + 12) /* sys_segctl() */ 03800 # define SYS_MEMSET (KERNEL_CALL + 13) /* sys_memset() */ 03801 03802 # define SYS_UMAP (KERNEL_CALL + 14) /* sys_umap() */ 03803 # define SYS_VIRCOPY (KERNEL_CALL + 15) /* sys_vircopy() */ 03804 # define SYS_PHYSCOPY (KERNEL_CALL + 16) /* sys_physcopy() */ 03805 # define SYS_VIRVCOPY (KERNEL_CALL + 17) /* sys_virvcopy() */ 03806 # define SYS_PHYSVCOPY (KERNEL_CALL + 18) /* sys_physvcopy() */ 03807 03808 # define SYS_IRQCTL (KERNEL_CALL + 19) /* sys_irqctl() */ 03809 # define SYS_INT86 (KERNEL_CALL + 20) /* sys_int86() */ 03810 # define SYS_DEVIO (KERNEL_CALL + 21) /* sys_devio() */ 03811 # define SYS_SDEVIO (KERNEL_CALL + 22) /* sys_sdevio() */ 03812 # define SYS_VDEVIO (KERNEL_CALL + 23) /* sys_vdevio() */ 03813 03814 # define SYS_SETALARM (KERNEL_CALL + 24) /* sys_setalarm() */ 03815 # define SYS_TIMES (KERNEL_CALL + 25) /* sys_times() */ 03816 # define SYS_GETINFO (KERNEL_CALL + 26) /* sys_getinfo() */ 03817 # define SYS_ABORT (KERNEL_CALL + 27) /* sys_abort() */ 03818 03819 #define NR_SYS_CALLS 28 /* number of system calls */ 03820 03821 /* Field names for SYS_MEMSET, SYS_SEGCTL. */ 03822 #define MEM_PTR m2_p1 /* base */ 03823 #define MEM_COUNT m2_l1 /* count */ 03824 #define MEM_PATTERN m2_l2 /* pattern to write */ File: Page: 682 include/minix/com.h 03825 #define MEM_CHUNK_BASE m4_l1 /* physical base address */ 03826 #define MEM_CHUNK_SIZE m4_l2 /* size of mem chunk */ 03827 #define MEM_TOT_SIZE m4_l3 /* total memory size */ 03828 #define MEM_CHUNK_TAG m4_l4 /* tag to identify chunk of mem */ 03829 03830 /* Field names for SYS_DEVIO, SYS_VDEVIO, SYS_SDEVIO. */ 03831 #define DIO_REQUEST m2_i3 /* device in or output */ 03832 # define DIO_INPUT 0 /* input */ 03833 # define DIO_OUTPUT 1 /* output */ 03834 #define DIO_TYPE m2_i1 /* flag indicating byte, word, or long */ 03835 # define DIO_BYTE 'b' /* byte type values */ 03836 # define DIO_WORD 'w' /* word type values */ 03837 # define DIO_LONG 'l' /* long type values */ 03838 #define DIO_PORT m2_l1 /* single port address */ 03839 #define DIO_VALUE m2_l2 /* single I/O value */ 03840 #define DIO_VEC_ADDR m2_p1 /* address of buffer or (p,v)-pairs */ 03841 #define DIO_VEC_SIZE m2_l2 /* number of elements in vector */ 03842 #define DIO_VEC_PROC m2_i2 /* number of process where vector is */ 03843 03844 /* Field names for SYS_SIGNARLM, SYS_FLAGARLM, SYS_SYNCALRM. */ 03845 #define ALRM_EXP_TIME m2_l1 /* expire time for the alarm call */ 03846 #define ALRM_ABS_TIME m2_i2 /* set to 1 to use absolute alarm time */ 03847 #define ALRM_TIME_LEFT m2_l1 /* how many ticks were remaining */ 03848 #define ALRM_PROC_NR m2_i1 /* which process wants the alarm? */ 03849 #define ALRM_FLAG_PTR m2_p1 /* virtual address of timeout flag */ 03850 03851 /* Field names for SYS_IRQCTL. */ 03852 #define IRQ_REQUEST m5_c1 /* what to do? */ 03853 # define IRQ_SETPOLICY 1 /* manage a slot of the IRQ table */ 03854 # define IRQ_RMPOLICY 2 /* remove a slot of the IRQ table */ 03855 # define IRQ_ENABLE 3 /* enable interrupts */ 03856 # define IRQ_DISABLE 4 /* disable interrupts */ 03857 #define IRQ_VECTOR m5_c2 /* irq vector */ 03858 #define IRQ_POLICY m5_i1 /* options for IRQCTL request */ 03859 # define IRQ_REENABLE 0x001 /* reenable IRQ line after interrupt */ 03860 # define IRQ_BYTE 0x100 /* byte values */ 03861 # define IRQ_WORD 0x200 /* word values */ 03862 # define IRQ_LONG 0x400 /* long values */ 03863 #define IRQ_PROC_NR m5_i2 /* process number, SELF, NONE */ 03864 #define IRQ_HOOK_ID m5_l3 /* id of irq hook at kernel */ 03865 03866 /* Field names for SYS_SEGCTL. */ 03867 #define SEG_SELECT m4_l1 /* segment selector returned */ 03868 #define SEG_OFFSET m4_l2 /* offset in segment returned */ 03869 #define SEG_PHYS m4_l3 /* physical address of segment */ 03870 #define SEG_SIZE m4_l4 /* segment size */ 03871 #define SEG_INDEX m4_l5 /* segment index in remote map */ 03872 03873 /* Field names for SYS_VIDCOPY. */ 03874 #define VID_REQUEST m4_l1 /* what to do? */ 03875 # define VID_VID_COPY 1 /* request vid_vid_copy() */ 03876 # define MEM_VID_COPY 2 /* request mem_vid_copy() */ 03877 #define VID_SRC_ADDR m4_l2 /* virtual address in memory */ 03878 #define VID_SRC_OFFSET m4_l3 /* offset in video memory */ 03879 #define VID_DST_OFFSET m4_l4 /* offset in video memory */ 03880 #define VID_CP_COUNT m4_l5 /* number of words to be copied */ 03881 03882 /* Field names for SYS_ABORT. */ 03883 #define ABRT_HOW m1_i1 /* RBT_REBOOT, RBT_HALT, etc. */ 03884 #define ABRT_MON_PROC m1_i2 /* process where monitor params are */ File: Page: 683 include/minix/com.h 03885 #define ABRT_MON_LEN m1_i3 /* length of monitor params */ 03886 #define ABRT_MON_ADDR m1_p1 /* virtual address of monitor params */ 03887 03888 /* Field names for _UMAP, _VIRCOPY, _PHYSCOPY. */ 03889 #define CP_SRC_SPACE m5_c1 /* T or D space (stack is also D) */ 03890 #define CP_SRC_PROC_NR m5_i1 /* process to copy from */ 03891 #define CP_SRC_ADDR m5_l1 /* address where data come from */ 03892 #define CP_DST_SPACE m5_c2 /* T or D space (stack is also D) */ 03893 #define CP_DST_PROC_NR m5_i2 /* process to copy to */ 03894 #define CP_DST_ADDR m5_l2 /* address where data go to */ 03895 #define CP_NR_BYTES m5_l3 /* number of bytes to copy */ 03896 03897 /* Field names for SYS_VCOPY and SYS_VVIRCOPY. */ 03898 #define VCP_NR_OK m1_i2 /* number of successfull copies */ 03899 #define VCP_VEC_SIZE m1_i3 /* size of copy vector */ 03900 #define VCP_VEC_ADDR m1_p1 /* pointer to copy vector */ 03901 03902 /* Field names for SYS_GETINFO. */ 03903 #define I_REQUEST m7_i3 /* what info to get */ 03904 # define GET_KINFO 0 /* get kernel information structure */ 03905 # define GET_IMAGE 1 /* get system image table */ 03906 # define GET_PROCTAB 2 /* get kernel process table */ 03907 # define GET_RANDOMNESS 3 /* get randomness buffer */ 03908 # define GET_MONPARAMS 4 /* get monitor parameters */ 03909 # define GET_KENV 5 /* get kernel environment string */ 03910 # define GET_IRQHOOKS 6 /* get the IRQ table */ 03911 # define GET_KMESSAGES 7 /* get kernel messages */ 03912 # define GET_PRIVTAB 8 /* get kernel privileges table */ 03913 # define GET_KADDRESSES 9 /* get various kernel addresses */ 03914 # define GET_SCHEDINFO 10 /* get scheduling queues */ 03915 # define GET_PROC 11 /* get process slot if given process */ 03916 # define GET_MACHINE 12 /* get machine information */ 03917 # define GET_LOCKTIMING 13 /* get lock()/unlock() latency timing */ 03918 # define GET_BIOSBUFFER 14 /* get a buffer for BIOS calls */ 03919 #define I_PROC_NR m7_i4 /* calling process */ 03920 #define I_VAL_PTR m7_p1 /* virtual address at caller */ 03921 #define I_VAL_LEN m7_i1 /* max length of value */ 03922 #define I_VAL_PTR2 m7_p2 /* second virtual address */ 03923 #define I_VAL_LEN2 m7_i2 /* second length, or proc nr */ 03924 03925 /* Field names for SYS_TIMES. */ 03926 #define T_PROC_NR m4_l1 /* process to request time info for */ 03927 #define T_USER_TIME m4_l1 /* user time consumed by process */ 03928 #define T_SYSTEM_TIME m4_l2 /* system time consumed by process */ 03929 #define T_CHILD_UTIME m4_l3 /* user time consumed by process' children */ 03930 #define T_CHILD_STIME m4_l4 /* sys time consumed by process' children */ 03931 #define T_BOOT_TICKS m4_l5 /* number of clock ticks since boot time */ 03932 03933 /* Field names for SYS_TRACE, SYS_SVRCTL. */ 03934 #define CTL_PROC_NR m2_i1 /* process number of the caller */ 03935 #define CTL_REQUEST m2_i2 /* server control request */ 03936 #define CTL_MM_PRIV m2_i3 /* privilege as seen by PM */ 03937 #define CTL_ARG_PTR m2_p1 /* pointer to argument */ 03938 #define CTL_ADDRESS m2_l1 /* address at traced process' space */ 03939 #define CTL_DATA m2_l2 /* data field for tracing */ 03940 03941 /* Field names for SYS_KILL, SYS_SIGCTL */ 03942 #define SIG_REQUEST m2_l2 /* PM signal control request */ 03943 #define S_GETSIG 0 /* get pending kernel signal */ 03944 #define S_ENDSIG 1 /* finish a kernel signal */ File: Page: 684 include/minix/com.h 03945 #define S_SENDSIG 2 /* POSIX style signal handling */ 03946 #define S_SIGRETURN 3 /* return from POSIX handling */ 03947 #define S_KILL 4 /* servers kills process with signal */ 03948 #define SIG_PROC m2_i1 /* process number for inform */ 03949 #define SIG_NUMBER m2_i2 /* signal number to send */ 03950 #define SIG_FLAGS m2_i3 /* signal flags field */ 03951 #define SIG_MAP m2_l1 /* used by kernel to pass signal bit map */ 03952 #define SIG_CTXT_PTR m2_p1 /* pointer to info to restore signal context */ 03953 03954 /* Field names for SYS_FORK, _EXEC, _EXIT, _NEWMAP. */ 03955 #define PR_PROC_NR m1_i1 /* indicates a (child) process */ 03956 #define PR_PRIORITY m1_i2 /* process priority */ 03957 #define PR_PPROC_NR m1_i2 /* indicates a (parent) process */ 03958 #define PR_PID m1_i3 /* process id at process manager */ 03959 #define PR_STACK_PTR m1_p1 /* used for stack ptr in sys_exec, sys_getsp */ 03960 #define PR_TRACING m1_i3 /* flag to indicate tracing is on/ off */ 03961 #define PR_NAME_PTR m1_p2 /* tells where program name is for dmp */ 03962 #define PR_IP_PTR m1_p3 /* initial value for ip after exec */ 03963 #define PR_MEM_PTR m1_p1 /* tells where memory map is for sys_newmap */ 03964 03965 /* Field names for SYS_INT86 */ 03966 #define INT86_REG86 m1_p1 /* pointer to registers */ 03967 03968 /* Field names for SELECT (FS). */ 03969 #define SEL_NFDS m8_i1 03970 #define SEL_READFDS m8_p1 03971 #define SEL_WRITEFDS m8_p2 03972 #define SEL_ERRORFDS m8_p3 03973 #define SEL_TIMEOUT m8_p4 03974 03975 /*===========================================================================* 03976 * Messages for system management server * 03977 *===========================================================================*/ 03978 03979 #define SRV_RQ_BASE 0x700 03980 03981 #define SRV_UP (SRV_RQ_BASE + 0) /* start system service */ 03982 #define SRV_DOWN (SRV_RQ_BASE + 1) /* stop system service */ 03983 #define SRV_STATUS (SRV_RQ_BASE + 2) /* get service status */ 03984 03985 # define SRV_PATH_ADDR m1_p1 /* path of binary */ 03986 # define SRV_PATH_LEN m1_i1 /* length of binary */ 03987 # define SRV_ARGS_ADDR m1_p2 /* arguments to be passed */ 03988 # define SRV_ARGS_LEN m1_i2 /* length of arguments */ 03989 # define SRV_DEV_MAJOR m1_i3 /* major device number */ 03990 # define SRV_PRIV_ADDR m1_p3 /* privileges string */ 03991 # define SRV_PRIV_LEN m1_i3 /* length of privileges */ 03992 03993 /*===========================================================================* 03994 * Miscellaneous messages used by TTY * 03995 *===========================================================================*/ 03996 03997 /* Miscellaneous request types and field names, e.g. used by IS server. */ 03998 #define PANIC_DUMPS 97 /* debug dumps at the TTY on RBT_PANIC */ 03999 #define FKEY_CONTROL 98 /* control a function key at the TTY */ 04000 # define FKEY_REQUEST m2_i1 /* request to perform at TTY */ 04001 # define FKEY_MAP 10 /* observe function key */ 04002 # define FKEY_UNMAP 11 /* stop observing function key */ 04003 # define FKEY_EVENTS 12 /* request open key presses */ 04004 # define FKEY_FKEYS m2_l1 /* F1-F12 keys pressed */ File: Page: 685 include/minix/com.h 04005 # define FKEY_SFKEYS m2_l2 /* Shift-F1-F12 keys pressed */ 04006 #define DIAGNOSTICS 100 /* output a string without FS in between */ 04007 # define DIAG_PRINT_BUF m1_p1 04008 # define DIAG_BUF_COUNT m1_i1 04009 # define DIAG_PROC_NR m1_i2 04010 04011 #endif /* _MINIX_COM_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/minix/devio.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 04100 /* This file provides basic types and some constants for the 04101 * SYS_DEVIO and SYS_VDEVIO system calls, which allow user-level 04102 * processes to perform device I/O. 04103 * 04104 * Created: 04105 * Apr 08, 2004 by Jorrit N. Herder 04106 */ 04107 04108 #ifndef _DEVIO_H 04109 #define _DEVIO_H 04110 04111 #include /* needed to include */ 04112 #include /* u8_t, u16_t, u32_t needed */ 04113 04114 typedef u16_t port_t; 04115 typedef U16_t Port_t; 04116 04117 /* We have different granularities of port I/O: 8, 16, 32 bits. 04118 * Also see , which has functions for bytes, words, 04119 * and longs. Hence, we need different (port,value)-pair types. 04120 */ 04121 typedef struct { u16_t port; u8_t value; } pvb_pair_t; 04122 typedef struct { u16_t port; u16_t value; } pvw_pair_t; 04123 typedef struct { u16_t port; u32_t value; } pvl_pair_t; 04124 04125 /* Macro shorthand to set (port,value)-pair. */ 04126 #define pv_set(pv, p, v) ((pv).port = (p), (pv).value = (v)) 04127 #define pv_ptr_set(pv_ptr, p, v) ((pv_ptr)->port = (p), (pv_ptr)->value = (v)) 04128 04129 #endif /* _DEVIO_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/minix/dmap.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 04200 #ifndef _DMAP_H 04201 #define _DMAP_H 04202 04203 #include 04204 #include 04205 File: Page: 686 include/minix/dmap.h 04206 /*===========================================================================* 04207 * Device <-> Driver Table * 04208 *===========================================================================*/ 04209 04210 /* Device table. This table is indexed by major device number. It provides 04211 * the link between major device numbers and the routines that process them. 04212 * The table can be update dynamically. The field 'dmap_flags' describe an 04213 * entry's current status and determines what control options are possible. 04214 */ 04215 #define DMAP_MUTABLE 0x01 /* mapping can be overtaken */ 04216 #define DMAP_BUSY 0x02 /* driver busy with request */ 04217 04218 enum dev_style { STYLE_DEV, STYLE_NDEV, STYLE_TTY, STYLE_CLONE }; 04219 04220 extern struct dmap { 04221 int _PROTOTYPE ((*dmap_opcl), (int, Dev_t, int, int) ); 04222 void _PROTOTYPE ((*dmap_io), (int, message *) ); 04223 int dmap_driver; 04224 int dmap_flags; 04225 } dmap[]; 04226 04227 /*===========================================================================* 04228 * Major and minor device numbers * 04229 *===========================================================================*/ 04230 04231 /* Total number of different devices. */ 04232 #define NR_DEVICES 32 /* number of (major) devices */ 04233 04234 /* Major and minor device numbers for MEMORY driver. */ 04235 #define MEMORY_MAJOR 1 /* major device for memory devices */ 04236 # define RAM_DEV 0 /* minor device for /dev/ram */ 04237 # define MEM_DEV 1 /* minor device for /dev/mem */ 04238 # define KMEM_DEV 2 /* minor device for /dev/kmem */ 04239 # define NULL_DEV 3 /* minor device for /dev/null */ 04240 # define BOOT_DEV 4 /* minor device for /dev/boot */ 04241 # define ZERO_DEV 5 /* minor device for /dev/zero */ 04242 04243 #define CTRLR(n) ((n)==0 ? 3 : (8 + 2*((n)-1))) /* magic formula */ 04244 04245 /* Full device numbers that are special to the boot monitor and FS. */ 04246 # define DEV_RAM 0x0100 /* device number of /dev/ram */ 04247 # define DEV_BOOT 0x0104 /* device number of /dev/boot */ 04248 04249 #define FLOPPY_MAJOR 2 /* major device for floppy disks */ 04250 #define TTY_MAJOR 4 /* major device for ttys */ 04251 #define CTTY_MAJOR 5 /* major device for /dev/tty */ 04252 04253 #define INET_MAJOR 7 /* major device for inet */ 04254 04255 #define LOG_MAJOR 15 /* major device for log driver */ 04256 # define IS_KLOG_DEV 0 /* minor device for /dev/klog */ 04257 04258 #endif /* _DMAP_H */ File: Page: 687 include/ibm/portio.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/ibm/portio.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 04300 /* 04301 ibm/portio.h 04302 04303 Created: Jan 15, 1992 by Philip Homburg 04304 */ 04305 04306 #ifndef _PORTIO_H_ 04307 #define _PORTIO_H_ 04308 04309 #ifndef _TYPES_H 04310 #include 04311 #endif 04312 04313 unsigned inb(U16_t _port); 04314 unsigned inw(U16_t _port); 04315 unsigned inl(U32_t _port); 04316 void outb(U16_t _port, U8_t _value); 04317 void outw(U16_t _port, U16_t _value); 04318 void outl(U16_t _port, U32_t _value); 04319 void insb(U16_t _port, void *_buf, size_t _count); 04320 void insw(U16_t _port, void *_buf, size_t _count); 04321 void insl(U16_t _port, void *_buf, size_t _count); 04322 void outsb(U16_t _port, void *_buf, size_t _count); 04323 void outsw(U16_t _port, void *_buf, size_t _count); 04324 void outsl(U16_t _port, void *_buf, size_t _count); 04325 void intr_disable(void); 04326 void intr_enable(void); 04327 04328 #endif /* _PORTIO_H_ */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/ibm/interrupt.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 04400 /* Interrupt numbers and hardware vectors. */ 04401 04402 #ifndef _INTERRUPT_H 04403 #define _INTERRUPT_H 04404 04405 #if (CHIP == INTEL) 04406 04407 /* 8259A interrupt controller ports. */ 04408 #define INT_CTL 0x20 /* I/O port for interrupt controller */ 04409 #define INT_CTLMASK 0x21 /* setting bits in this port disables ints */ 04410 #define INT2_CTL 0xA0 /* I/O port for second interrupt controller */ 04411 #define INT2_CTLMASK 0xA1 /* setting bits in this port disables ints */ 04412 04413 /* Magic numbers for interrupt controller. */ 04414 #define END_OF_INT 0x20 /* code used to re-enable after an interrupt */ 04415 04416 /* Interrupt vectors defined/reserved by processor. */ 04417 #define DIVIDE_VECTOR 0 /* divide error */ 04418 #define DEBUG_VECTOR 1 /* single step (trace) */ 04419 #define NMI_VECTOR 2 /* non-maskable interrupt */ File: Page: 688 include/ibm/interrupt.h 04420 #define BREAKPOINT_VECTOR 3 /* software breakpoint */ 04421 #define OVERFLOW_VECTOR 4 /* from INTO */ 04422 04423 /* Fixed system call vector. */ 04424 #define SYS_VECTOR 32 /* system calls are made with int SYSVEC */ 04425 #define SYS386_VECTOR 33 /* except 386 system calls use this */ 04426 #define LEVEL0_VECTOR 34 /* for execution of a function at level 0 */ 04427 04428 /* Suitable irq bases for hardware interrupts. Reprogram the 8259(s) from 04429 * the PC BIOS defaults since the BIOS doesn't respect all the processor's 04430 * reserved vectors (0 to 31). 04431 */ 04432 #define BIOS_IRQ0_VEC 0x08 /* base of IRQ0-7 vectors used by BIOS */ 04433 #define BIOS_IRQ8_VEC 0x70 /* base of IRQ8-15 vectors used by BIOS */ 04434 #define IRQ0_VECTOR 0x50 /* nice vectors to relocate IRQ0-7 to */ 04435 #define IRQ8_VECTOR 0x70 /* no need to move IRQ8-15 */ 04436 04437 /* Hardware interrupt numbers. */ 04438 #define NR_IRQ_VECTORS 16 04439 #define CLOCK_IRQ 0 04440 #define KEYBOARD_IRQ 1 04441 #define CASCADE_IRQ 2 /* cascade enable for 2nd AT controller */ 04442 #define ETHER_IRQ 3 /* default ethernet interrupt vector */ 04443 #define SECONDARY_IRQ 3 /* RS232 interrupt vector for port 2 */ 04444 #define RS232_IRQ 4 /* RS232 interrupt vector for port 1 */ 04445 #define XT_WINI_IRQ 5 /* xt winchester */ 04446 #define FLOPPY_IRQ 6 /* floppy disk */ 04447 #define PRINTER_IRQ 7 04448 #define AT_WINI_0_IRQ 14 /* at winchester controller 0 */ 04449 #define AT_WINI_1_IRQ 15 /* at winchester controller 1 */ 04450 04451 /* Interrupt number to hardware vector. */ 04452 #define BIOS_VECTOR(irq) \ 04453 (((irq) < 8 ? BIOS_IRQ0_VEC : BIOS_IRQ8_VEC) + ((irq) & 0x07)) 04454 #define VECTOR(irq) \ 04455 (((irq) < 8 ? IRQ0_VECTOR : IRQ8_VECTOR) + ((irq) & 0x07)) 04456 04457 #endif /* (CHIP == INTEL) */ 04458 04459 #endif /* _INTERRUPT_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/ibm/ports.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 04500 /* Addresses and magic numbers for miscellaneous ports. */ 04501 04502 #ifndef _PORTS_H 04503 #define _PORTS_H 04504 04505 #if (CHIP == INTEL) 04506 04507 /* Miscellaneous ports. */ 04508 #define PCR 0x65 /* Planar Control Register */ 04509 #define PORT_B 0x61 /* I/O port for 8255 port B (kbd, beeper...) */ 04510 #define TIMER0 0x40 /* I/O port for timer channel 0 */ 04511 #define TIMER2 0x42 /* I/O port for timer channel 2 */ 04512 #define TIMER_MODE 0x43 /* I/O port for timer mode control */ 04513 04514 #endif /* (CHIP == INTEL) */ File: Page: 689 include/ibm/ports.h 04515 04516 #endif /* _PORTS_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/kernel.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 04600 #ifndef KERNEL_H 04601 #define KERNEL_H 04602 04603 /* This is the master header for the kernel. It includes some other files 04604 * and defines the principal constants. 04605 */ 04606 #define _POSIX_SOURCE 1 /* tell headers to include POSIX stuff */ 04607 #define _MINIX 1 /* tell headers to include MINIX stuff */ 04608 #define _SYSTEM 1 /* tell headers that this is the kernel */ 04609 04610 /* The following are so basic, all the *.c files get them automatically. */ 04611 #include /* global configuration, MUST be first */ 04612 #include /* C style: ANSI or K&R, MUST be second */ 04613 #include /* general system types */ 04614 #include /* MINIX specific constants */ 04615 #include /* MINIX specific types, e.g. message */ 04616 #include /* MINIX run-time system */ 04617 #include /* watchdog timer management */ 04618 #include /* return codes and error numbers */ 04619 #include /* device I/O and toggle interrupts */ 04620 04621 /* Important kernel header files. */ 04622 #include "config.h" /* configuration, MUST be first */ 04623 #include "const.h" /* constants, MUST be second */ 04624 #include "type.h" /* type definitions, MUST be third */ 04625 #include "proto.h" /* function prototypes */ 04626 #include "glo.h" /* global variables */ 04627 #include "ipc.h" /* IPC constants */ 04628 /* #include "debug.h" */ /* debugging, MUST be last kernel header */ 04629 04630 #endif /* KERNEL_H */ 04631 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/config.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 04700 #ifndef CONFIG_H 04701 #define CONFIG_H 04702 04703 /* This file defines the kernel configuration. It allows to set sizes of some 04704 * kernel buffers and to enable or disable debugging code, timing features, 04705 * and individual kernel calls. 04706 * 04707 * Changes: 04708 * Jul 11, 2005 Created. (Jorrit N. Herder) 04709 */ File: Page: 690 kernel/config.h 04710 04711 /* In embedded and sensor applications, not all the kernel calls may be 04712 * needed. In this section you can specify which kernel calls are needed 04713 * and which are not. The code for unneeded kernel calls is not included in 04714 * the system binary, making it smaller. If you are not sure, it is best 04715 * to keep all kernel calls enabled. 04716 */ 04717 #define USE_FORK 1 /* fork a new process */ 04718 #define USE_NEWMAP 1 /* set a new memory map */ 04719 #define USE_EXEC 1 /* update process after execute */ 04720 #define USE_EXIT 1 /* clean up after process exit */ 04721 #define USE_TRACE 1 /* process information and tracing */ 04722 #define USE_GETKSIG 1 /* retrieve pending kernel signals */ 04723 #define USE_ENDKSIG 1 /* finish pending kernel signals */ 04724 #define USE_KILL 1 /* send a signal to a process */ 04725 #define USE_SIGSEND 1 /* send POSIX-style signal */ 04726 #define USE_SIGRETURN 1 /* sys_sigreturn(proc_nr, ctxt_ptr, flags) */ 04727 #define USE_ABORT 1 /* shut down MINIX */ 04728 #define USE_GETINFO 1 /* retrieve a copy of kernel data */ 04729 #define USE_TIMES 1 /* get process and system time info */ 04730 #define USE_SETALARM 1 /* schedule a synchronous alarm */ 04731 #define USE_DEVIO 1 /* read or write a single I/O port */ 04732 #define USE_VDEVIO 1 /* process vector with I/O requests */ 04733 #define USE_SDEVIO 1 /* perform I/O request on a buffer */ 04734 #define USE_IRQCTL 1 /* set an interrupt policy */ 04735 #define USE_SEGCTL 1 /* set up a remote segment */ 04736 #define USE_PRIVCTL 1 /* system privileges control */ 04737 #define USE_NICE 1 /* change scheduling priority */ 04738 #define USE_UMAP 1 /* map virtual to physical address */ 04739 #define USE_VIRCOPY 1 /* copy using virtual addressing */ 04740 #define USE_VIRVCOPY 1 /* vector with virtual copy requests */ 04741 #define USE_PHYSCOPY 1 /* copy using physical addressing */ 04742 #define USE_PHYSVCOPY 1 /* vector with physical copy requests */ 04743 #define USE_MEMSET 1 /* write char to a given memory area */ 04744 04745 /* Length of program names stored in the process table. This is only used 04746 * for the debugging dumps that can be generated with the IS server. The PM 04747 * server keeps its own copy of the program name. 04748 */ 04749 #define P_NAME_LEN 8 04750 04751 /* Kernel diagnostics are written to a circular buffer. After each message, 04752 * a system server is notified and a copy of the buffer can be retrieved to 04753 * display the message. The buffers size can safely be reduced. 04754 */ 04755 #define KMESS_BUF_SIZE 256 04756 04757 /* Buffer to gather randomness. This is used to generate a random stream by 04758 * the MEMORY driver when reading from /dev/random. 04759 */ 04760 #define RANDOM_ELEMENTS 32 04761 04762 /* This section contains defines for valuable system resources that are used 04763 * by device drivers. The number of elements of the vectors is determined by 04764 * the maximum needed by any given driver. The number of interrupt hooks may 04765 * be incremented on systems with many device drivers. 04766 */ 04767 #define NR_IRQ_HOOKS 16 /* number of interrupt hooks */ 04768 #define VDEVIO_BUF_SIZE 64 /* max elements per VDEVIO request */ 04769 #define VCOPY_VEC_SIZE 16 /* max elements per VCOPY request */ File: Page: 691 kernel/config.h 04770 04771 /* How many bytes for the kernel stack. Space allocated in mpx.s. */ 04772 #define K_STACK_BYTES 1024 04773 04774 /* This section allows to enable kernel debugging and timing functionality. 04775 * For normal operation all options should be disabled. 04776 */ 04777 #define DEBUG_SCHED_CHECK 0 /* sanity check of scheduling queues */ 04778 #define DEBUG_LOCK_CHECK 0 /* kernel lock() sanity check */ 04779 #define DEBUG_TIME_LOCKS 0 /* measure time spent in locks */ 04780 04781 #endif /* CONFIG_H */ 04782 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/const.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 04800 /* General macros and constants used by the kernel. */ 04801 #ifndef CONST_H 04802 #define CONST_H 04803 04804 #include /* interrupt numbers and hardware vectors */ 04805 #include /* port addresses and magic numbers */ 04806 #include /* BIOS addresses, sizes and magic numbers */ 04807 #include /* BIOS addresses, sizes and magic numbers */ 04808 #include 04809 #include "config.h" 04810 04811 /* To translate an address in kernel space to a physical address. This is 04812 * the same as umap_local(proc_ptr, D, vir, sizeof(*vir)), but less costly. 04813 */ 04814 #define vir2phys(vir) (kinfo.data_base + (vir_bytes) (vir)) 04815 04816 /* Map a process number to a privilege structure id. */ 04817 #define s_nr_to_id(n) (NR_TASKS + (n) + 1) 04818 04819 /* Translate a pointer to a field in a structure to a pointer to the structure 04820 * itself. So it translates '&struct_ptr->field' back to 'struct_ptr'. 04821 */ 04822 #define structof(type, field, ptr) \ 04823 ((type *) (((char *) (ptr)) - offsetof(type, field))) 04824 04825 /* Constants used in virtual_copy(). Values must be 0 and 1, respectively. */ 04826 #define _SRC_ 0 04827 #define _DST_ 1 04828 04829 /* Number of random sources */ 04830 #define RANDOM_SOURCES 16 04831 04832 /* Constants and macros for bit map manipulation. */ 04833 #define BITCHUNK_BITS (sizeof(bitchunk_t) * CHAR_BIT) 04834 #define BITMAP_CHUNKS(nr_bits) (((nr_bits)+BITCHUNK_BITS-1)/BITCHUNK_BITS) 04835 #define MAP_CHUNK(map,bit) (map)[((bit)/BITCHUNK_BITS)] 04836 #define CHUNK_OFFSET(bit) ((bit)%BITCHUNK_BITS)) 04837 #define GET_BIT(map,bit) ( MAP_CHUNK(map,bit) & (1 << CHUNK_OFFSET(bit) ) 04838 #define SET_BIT(map,bit) ( MAP_CHUNK(map,bit) |= (1 << CHUNK_OFFSET(bit) ) 04839 #define UNSET_BIT(map,bit) ( MAP_CHUNK(map,bit) &= ~(1 << CHUNK_OFFSET(bit) ) File: Page: 692 kernel/const.h 04840 04841 #define get_sys_bit(map,bit) \ 04842 ( MAP_CHUNK(map.chunk,bit) & (1 << CHUNK_OFFSET(bit) ) 04843 #define set_sys_bit(map,bit) \ 04844 ( MAP_CHUNK(map.chunk,bit) |= (1 << CHUNK_OFFSET(bit) ) 04845 #define unset_sys_bit(map,bit) \ 04846 ( MAP_CHUNK(map.chunk,bit) &= ~(1 << CHUNK_OFFSET(bit) ) 04847 #define NR_SYS_CHUNKS BITMAP_CHUNKS(NR_SYS_PROCS) 04848 04849 /* Program stack words and masks. */ 04850 #define INIT_PSW 0x0200 /* initial psw */ 04851 #define INIT_TASK_PSW 0x1200 /* initial psw for tasks (with IOPL 1) */ 04852 #define TRACEBIT 0x0100 /* OR this with psw in proc[] for tracing */ 04853 #define SETPSW(rp, new) /* permits only certain bits to be set */ \ 04854 ((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xCD5 | (new) & 0xCD5) 04855 #define IF_MASK 0x00000200 04856 #define IOPL_MASK 0x003000 04857 04858 /* Disable/ enable hardware interrupts. The parameters of lock() and unlock() 04859 * are used when debugging is enabled. See debug.h for more information. 04860 */ 04861 #define lock(c, v) intr_disable(); 04862 #define unlock(c) intr_enable(); 04863 04864 /* Sizes of memory tables. The boot monitor distinguishes three memory areas, 04865 * namely low mem below 1M, 1M-16M, and mem after 16M. More chunks are needed 04866 * for DOS MINIX. 04867 */ 04868 #define NR_MEMS 8 04869 04870 #endif /* CONST_H */ 04871 04872 04873 04874 04875 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/type.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 04900 #ifndef TYPE_H 04901 #define TYPE_H 04902 04903 typedef _PROTOTYPE( void task_t, (void) ); 04904 04905 /* Process table and system property related types. */ 04906 typedef int proc_nr_t; /* process table entry number */ 04907 typedef short sys_id_t; /* system process index */ 04908 typedef struct { /* bitmap for system indexes */ 04909 bitchunk_t chunk[BITMAP_CHUNKS(NR_SYS_PROCS)]; 04910 } sys_map_t; 04911 04912 struct boot_image { 04913 proc_nr_t proc_nr; /* process number to use */ 04914 task_t *initial_pc; /* start function for tasks */ File: Page: 693 kernel/type.h 04915 int flags; /* process flags */ 04916 unsigned char quantum; /* quantum (tick count) */ 04917 int priority; /* scheduling priority */ 04918 int stksize; /* stack size for tasks */ 04919 short trap_mask; /* allowed system call traps */ 04920 bitchunk_t ipc_to; /* send mask protection */ 04921 long call_mask; /* system call protection */ 04922 char proc_name[P_NAME_LEN]; /* name in process table */ 04923 }; 04924 04925 struct memory { 04926 phys_clicks base; /* start address of chunk */ 04927 phys_clicks size; /* size of memory chunk */ 04928 }; 04929 04930 /* The kernel outputs diagnostic messages in a circular buffer. */ 04931 struct kmessages { 04932 int km_next; /* next index to write */ 04933 int km_size; /* current size in buffer */ 04934 char km_buf[KMESS_BUF_SIZE]; /* buffer for messages */ 04935 }; 04936 04937 struct randomness { 04938 struct { 04939 int r_next; /* next index to write */ 04940 int r_size; /* number of random elements */ 04941 unsigned short r_buf[RANDOM_ELEMENTS]; /* buffer for random info */ 04942 } bin[RANDOM_SOURCES]; 04943 }; 04944 04945 #if (CHIP == INTEL) 04946 typedef unsigned reg_t; /* machine register */ 04947 04948 /* The stack frame layout is determined by the software, but for efficiency 04949 * it is laid out so the assembly code to use it is as simple as possible. 04950 * 80286 protected mode and all real modes use the same frame, built with 04951 * 16-bit registers. Real mode lacks an automatic stack switch, so little 04952 * is lost by using the 286 frame for it. The 386 frame differs only in 04953 * having 32-bit registers and more segment registers. The same names are 04954 * used for the larger registers to avoid differences in the code. 04955 */ 04956 struct stackframe_s { /* proc_ptr points here */ 04957 #if _WORD_SIZE == 4 04958 u16_t gs; /* last item pushed by save */ 04959 u16_t fs; /* ^ */ 04960 #endif 04961 u16_t es; /* | */ 04962 u16_t ds; /* | */ 04963 reg_t di; /* di through cx are not accessed in C */ 04964 reg_t si; /* order is to match pusha/popa */ 04965 reg_t fp; /* bp */ 04966 reg_t st; /* hole for another copy of sp */ 04967 reg_t bx; /* | */ 04968 reg_t dx; /* | */ 04969 reg_t cx; /* | */ 04970 reg_t retreg; /* ax and above are all pushed by save */ 04971 reg_t retadr; /* return address for assembly code save() */ 04972 reg_t pc; /* ^ last item pushed by interrupt */ 04973 reg_t cs; /* | */ 04974 reg_t psw; /* | */ File: Page: 694 kernel/type.h 04975 reg_t sp; /* | */ 04976 reg_t ss; /* these are pushed by CPU during interrupt */ 04977 }; 04978 04979 struct segdesc_s { /* segment descriptor for protected mode */ 04980 u16_t limit_low; 04981 u16_t base_low; 04982 u8_t base_middle; 04983 u8_t access; /* |P|DL|1|X|E|R|A| */ 04984 u8_t granularity; /* |G|X|0|A|LIMT| */ 04985 u8_t base_high; 04986 }; 04987 04988 typedef unsigned long irq_policy_t; 04989 typedef unsigned long irq_id_t; 04990 04991 typedef struct irq_hook { 04992 struct irq_hook *next; /* next hook in chain */ 04993 int (*handler)(struct irq_hook *); /* interrupt handler */ 04994 int irq; /* IRQ vector number */ 04995 int id; /* id of this hook */ 04996 int proc_nr; /* NONE if not in use */ 04997 irq_id_t notify_id; /* id to return on interrupt */ 04998 irq_policy_t policy; /* bit mask for policy */ 04999 } irq_hook_t; 05000 05001 typedef int (*irq_handler_t)(struct irq_hook *); 05002 05003 #endif /* (CHIP == INTEL) */ 05004 05005 #if (CHIP == M68000) 05006 /* M68000 specific types go here. */ 05007 #endif /* (CHIP == M68000) */ 05008 05009 #endif /* TYPE_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/proto.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 05100 /* Function prototypes. */ 05101 05102 #ifndef PROTO_H 05103 #define PROTO_H 05104 05105 /* Struct declarations. */ 05106 struct proc; 05107 struct timer; 05108 05109 /* clock.c */ 05110 _PROTOTYPE( void clock_task, (void) ); 05111 _PROTOTYPE( void clock_stop, (void) ); 05112 _PROTOTYPE( clock_t get_uptime, (void) ); 05113 _PROTOTYPE( unsigned long read_clock, (void) ); 05114 _PROTOTYPE( void set_timer, (struct timer *tp, clock_t t, tmr_func_t f) ); 05115 _PROTOTYPE( void reset_timer, (struct timer *tp) ); 05116 05117 /* main.c */ 05118 _PROTOTYPE( void main, (void) ); 05119 _PROTOTYPE( void prepare_shutdown, (int how) ); File: Page: 695 kernel/proto.h 05120 05121 /* utility.c */ 05122 _PROTOTYPE( void kprintf, (const char *fmt, ...) ); 05123 _PROTOTYPE( void panic, (_CONST char *s, int n) ); 05124 05125 /* proc.c */ 05126 _PROTOTYPE( int sys_call, (int function, int src_dest, message *m_ptr) ); 05127 _PROTOTYPE( int lock_notify, (int src, int dst) ); 05128 _PROTOTYPE( int lock_send, (int dst, message *m_ptr) ); 05129 _PROTOTYPE( void lock_enqueue, (struct proc *rp) ); 05130 _PROTOTYPE( void lock_dequeue, (struct proc *rp) ); 05131 05132 /* start.c */ 05133 _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mds, 05134 U16_t parmoff, U16_t parmsize) ); 05135 05136 /* system.c */ 05137 _PROTOTYPE( int get_priv, (register struct proc *rc, int proc_type) ); 05138 _PROTOTYPE( void send_sig, (int proc_nr, int sig_nr) ); 05139 _PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr) ); 05140 _PROTOTYPE( void sys_task, (void) ); 05141 _PROTOTYPE( void get_randomness, (int source) ); 05142 _PROTOTYPE( int virtual_copy, (struct vir_addr *src, struct vir_addr *dst, 05143 vir_bytes bytes) ); 05144 #define numap_local(proc_nr, vir_addr, bytes) \ 05145 umap_local(proc_addr(proc_nr), D, (vir_addr), (bytes)) 05146 _PROTOTYPE( phys_bytes umap_local, (struct proc *rp, int seg, 05147 vir_bytes vir_addr, vir_bytes bytes) ); 05148 _PROTOTYPE( phys_bytes umap_remote, (struct proc *rp, int seg, 05149 vir_bytes vir_addr, vir_bytes bytes) ); 05150 _PROTOTYPE( phys_bytes umap_bios, (struct proc *rp, vir_bytes vir_addr, 05151 vir_bytes bytes) ); 05152 05153 /* exception.c */ 05154 _PROTOTYPE( void exception, (unsigned vec_nr) ); 05155 05156 /* i8259.c */ 05157 _PROTOTYPE( void intr_init, (int mine) ); 05158 _PROTOTYPE( void intr_handle, (irq_hook_t *hook) ); 05159 _PROTOTYPE( void put_irq_handler, (irq_hook_t *hook, int irq, 05160 irq_handler_t handler) ); 05161 _PROTOTYPE( void rm_irq_handler, (irq_hook_t *hook) ); 05162 05163 /* klib*.s */ 05164 _PROTOTYPE( void int86, (void) ); 05165 _PROTOTYPE( void cp_mess, (int src,phys_clicks src_clicks,vir_bytes src_offset, 05166 phys_clicks dst_clicks, vir_bytes dst_offset) ); 05167 _PROTOTYPE( void enable_irq, (irq_hook_t *hook) ); 05168 _PROTOTYPE( int disable_irq, (irq_hook_t *hook) ); 05169 _PROTOTYPE( u16_t mem_rdw, (U16_t segm, vir_bytes offset) ); 05170 _PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest, 05171 phys_bytes count) ); 05172 _PROTOTYPE( void phys_memset, (phys_bytes source, unsigned long pattern, 05173 phys_bytes count) ); 05174 _PROTOTYPE( void phys_insb, (U16_t port, phys_bytes buf, size_t count) ); 05175 _PROTOTYPE( void phys_insw, (U16_t port, phys_bytes buf, size_t count) ); 05176 _PROTOTYPE( void phys_outsb, (U16_t port, phys_bytes buf, size_t count) ); 05177 _PROTOTYPE( void phys_outsw, (U16_t port, phys_bytes buf, size_t count) ); 05178 _PROTOTYPE( void reset, (void) ); 05179 _PROTOTYPE( void level0, (void (*func)(void)) ); File: Page: 696 kernel/proto.h 05180 _PROTOTYPE( void monitor, (void) ); 05181 _PROTOTYPE( void read_tsc, (unsigned long *high, unsigned long *low) ); 05182 _PROTOTYPE( unsigned long read_cpu_flags, (void) ); 05183 05184 /* mpx*.s */ 05185 _PROTOTYPE( void idle_task, (void) ); 05186 _PROTOTYPE( void restart, (void) ); 05187 05188 /* The following are never called from C (pure asm procs). */ 05189 05190 /* Exception handlers (real or protected mode), in numerical order. */ 05191 void _PROTOTYPE( int00, (void) ), _PROTOTYPE( divide_error, (void) ); 05192 void _PROTOTYPE( int01, (void) ), _PROTOTYPE( single_step_exception, (void) ); 05193 void _PROTOTYPE( int02, (void) ), _PROTOTYPE( nmi, (void) ); 05194 void _PROTOTYPE( int03, (void) ), _PROTOTYPE( breakpoint_exception, (void) ); 05195 void _PROTOTYPE( int04, (void) ), _PROTOTYPE( overflow, (void) ); 05196 void _PROTOTYPE( int05, (void) ), _PROTOTYPE( bounds_check, (void) ); 05197 void _PROTOTYPE( int06, (void) ), _PROTOTYPE( inval_opcode, (void) ); 05198 void _PROTOTYPE( int07, (void) ), _PROTOTYPE( copr_not_available, (void) ); 05199 void _PROTOTYPE( double_fault, (void) ); 05200 void _PROTOTYPE( copr_seg_overrun, (void) ); 05201 void _PROTOTYPE( inval_tss, (void) ); 05202 void _PROTOTYPE( segment_not_present, (void) ); 05203 void _PROTOTYPE( stack_exception, (void) ); 05204 void _PROTOTYPE( general_protection, (void) ); 05205 void _PROTOTYPE( page_fault, (void) ); 05206 void _PROTOTYPE( copr_error, (void) ); 05207 05208 /* Hardware interrupt handlers. */ 05209 _PROTOTYPE( void hwint00, (void) ); 05210 _PROTOTYPE( void hwint01, (void) ); 05211 _PROTOTYPE( void hwint02, (void) ); 05212 _PROTOTYPE( void hwint03, (void) ); 05213 _PROTOTYPE( void hwint04, (void) ); 05214 _PROTOTYPE( void hwint05, (void) ); 05215 _PROTOTYPE( void hwint06, (void) ); 05216 _PROTOTYPE( void hwint07, (void) ); 05217 _PROTOTYPE( void hwint08, (void) ); 05218 _PROTOTYPE( void hwint09, (void) ); 05219 _PROTOTYPE( void hwint10, (void) ); 05220 _PROTOTYPE( void hwint11, (void) ); 05221 _PROTOTYPE( void hwint12, (void) ); 05222 _PROTOTYPE( void hwint13, (void) ); 05223 _PROTOTYPE( void hwint14, (void) ); 05224 _PROTOTYPE( void hwint15, (void) ); 05225 05226 /* Software interrupt handlers, in numerical order. */ 05227 _PROTOTYPE( void trp, (void) ); 05228 _PROTOTYPE( void s_call, (void) ), _PROTOTYPE( p_s_call, (void) ); 05229 _PROTOTYPE( void level0_call, (void) ); 05230 05231 /* protect.c */ 05232 _PROTOTYPE( void prot_init, (void) ); 05233 _PROTOTYPE( void init_codeseg, (struct segdesc_s *segdp, phys_bytes base, 05234 vir_bytes size, int privilege) ); 05235 _PROTOTYPE( void init_dataseg, (struct segdesc_s *segdp, phys_bytes base, 05236 vir_bytes size, int privilege) ); 05237 _PROTOTYPE( phys_bytes seg2phys, (U16_t seg) ); 05238 _PROTOTYPE( void phys2seg, (u16_t *seg, vir_bytes *off, phys_bytes phys)); 05239 _PROTOTYPE( void enable_iop, (struct proc *pp) ); File: Page: 697 kernel/proto.h 05240 _PROTOTYPE( void alloc_segments, (struct proc *rp) ); 05241 05242 #endif /* PROTO_H */ 05243 05244 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/glo.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 05300 #ifndef GLO_H 05301 #define GLO_H 05302 05303 /* Global variables used in the kernel. This file contains the declarations; 05304 * storage space for the variables is allocated in table.c, because EXTERN is 05305 * defined as extern unless the _TABLE definition is seen. We rely on the 05306 * compiler's default initialization (0) for several global variables. 05307 */ 05308 #ifdef _TABLE 05309 #undef EXTERN 05310 #define EXTERN 05311 #endif 05312 05313 #include 05314 #include "config.h" 05315 05316 /* Variables relating to shutting down MINIX. */ 05317 EXTERN char kernel_exception; /* TRUE after system exceptions */ 05318 EXTERN char shutdown_started; /* TRUE after shutdowns / reboots */ 05319 05320 /* Kernel information structures. This groups vital kernel information. */ 05321 EXTERN phys_bytes aout; /* address of a.out headers */ 05322 EXTERN struct kinfo kinfo; /* kernel information for users */ 05323 EXTERN struct machine machine; /* machine information for users */ 05324 EXTERN struct kmessages kmess; /* diagnostic messages in kernel */ 05325 EXTERN struct randomness krandom; /* gather kernel random information */ 05326 05327 /* Process scheduling information and the kernel reentry count. */ 05328 EXTERN struct proc *prev_ptr; /* previously running process */ 05329 EXTERN struct proc *proc_ptr; /* pointer to currently running process */ 05330 EXTERN struct proc *next_ptr; /* next process to run after restart() */ 05331 EXTERN struct proc *bill_ptr; /* process to bill for clock ticks */ 05332 EXTERN char k_reenter; /* kernel reentry count (entry count less 1) */ 05333 EXTERN unsigned lost_ticks; /* clock ticks counted outside clock task */ 05334 05335 /* Interrupt related variables. */ 05336 EXTERN irq_hook_t irq_hooks[NR_IRQ_HOOKS]; /* hooks for general use */ 05337 EXTERN irq_hook_t *irq_handlers[NR_IRQ_VECTORS];/* list of IRQ handlers */ 05338 EXTERN int irq_actids[NR_IRQ_VECTORS]; /* IRQ ID bits active */ 05339 EXTERN int irq_use; /* map of all in-use irq's */ 05340 05341 /* Miscellaneous. */ 05342 EXTERN reg_t mon_ss, mon_sp; /* boot monitor stack */ 05343 EXTERN int mon_return; /* true if we can return to monitor */ 05344 05345 /* Variables that are initialized elsewhere are just extern here. */ 05346 extern struct boot_image image[]; /* system image processes */ 05347 extern char *t_stack[]; /* task stack space */ 05348 extern struct segdesc_s gdt[]; /* global descriptor table */ 05349 File: Page: 698 kernel/glo.h 05350 EXTERN _PROTOTYPE( void (*level0_func), (void) ); 05351 05352 #endif /* GLO_H */ 05353 05354 05355 05356 05357 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/ipc.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 05400 #ifndef IPC_H 05401 #define IPC_H 05402 05403 /* This header file defines constants for MINIX inter-process communication. 05404 * These definitions are used in the file proc.c. 05405 */ 05406 #include 05407 05408 /* Masks and flags for system calls. */ 05409 #define SYSCALL_FUNC 0x0F /* mask for system call function */ 05410 #define SYSCALL_FLAGS 0xF0 /* mask for system call flags */ 05411 #define NON_BLOCKING 0x10 /* prevent blocking, return error */ 05412 05413 /* System call numbers that are passed when trapping to the kernel. The 05414 * numbers are carefully defined so that it can easily be seen (based on 05415 * the bits that are on) which checks should be done in sys_call(). 05416 */ 05417 #define SEND 1 /* 0 0 0 1 : blocking send */ 05418 #define RECEIVE 2 /* 0 0 1 0 : blocking receive */ 05419 #define SENDREC 3 /* 0 0 1 1 : SEND + RECEIVE */ 05420 #define NOTIFY 4 /* 0 1 0 0 : nonblocking notify */ 05421 #define ECHO 8 /* 1 0 0 0 : echo a message */ 05422 05423 /* The following bit masks determine what checks that should be done. */ 05424 #define CHECK_PTR 0x0B /* 1 0 1 1 : validate message buffer */ 05425 #define CHECK_DST 0x05 /* 0 1 0 1 : validate message destination */ 05426 #define CHECK_SRC 0x02 /* 0 0 1 0 : validate message source */ 05427 05428 #endif /* IPC_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/proc.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 05500 #ifndef PROC_H 05501 #define PROC_H 05502 05503 /* Here is the declaration of the process table. It contains all process 05504 * data, including registers, flags, scheduling priority, memory map, 05505 * accounting, message passing (IPC) information, and so on. 05506 * 05507 * Many assembly code routines reference fields in it. The offsets to these 05508 * fields are defined in the assembler include file sconst.h. When changing 05509 * struct proc, be sure to change sconst.h to match. File: Page: 699 kernel/proc.h 05510 */ 05511 #include 05512 #include "protect.h" 05513 #include "const.h" 05514 #include "priv.h" 05515 05516 struct proc { 05517 struct stackframe_s p_reg; /* process' registers saved in stack frame */ 05518 reg_t p_ldt_sel; /* selector in gdt with ldt base and limit */ 05519 struct segdesc_s p_ldt[2+NR_REMOTE_SEGS]; /* CS, DS and remote segments */ 05520 05521 proc_nr_t p_nr; /* number of this process (for fast access) */ 05522 struct priv *p_priv; /* system privileges structure */ 05523 char p_rts_flags; /* SENDING, RECEIVING, etc. */ 05524 05525 char p_priority; /* current scheduling priority */ 05526 char p_max_priority; /* maximum scheduling priority */ 05527 char p_ticks_left; /* number of scheduling ticks left */ 05528 char p_quantum_size; /* quantum size in ticks */ 05529 05530 struct mem_map p_memmap[NR_LOCAL_SEGS]; /* memory map (T, D, S) */ 05531 05532 clock_t p_user_time; /* user time in ticks */ 05533 clock_t p_sys_time; /* sys time in ticks */ 05534 05535 struct proc *p_nextready; /* pointer to next ready process */ 05536 struct proc *p_caller_q; /* head of list of procs wishing to send */ 05537 struct proc *p_q_link; /* link to next proc wishing to send */ 05538 message *p_messbuf; /* pointer to passed message buffer */ 05539 proc_nr_t p_getfrom; /* from whom does process want to receive? */ 05540 proc_nr_t p_sendto; /* to whom does process want to send? */ 05541 05542 sigset_t p_pending; /* bit map for pending kernel signals */ 05543 05544 char p_name[P_NAME_LEN]; /* name of the process, including \0 */ 05545 }; 05546 05547 /* Bits for the runtime flags. A process is runnable iff p_rts_flags == 0. */ 05548 #define SLOT_FREE 0x01 /* process slot is free */ 05549 #define NO_MAP 0x02 /* keeps unmapped forked child from running */ 05550 #define SENDING 0x04 /* process blocked trying to SEND */ 05551 #define RECEIVING 0x08 /* process blocked trying to RECEIVE */ 05552 #define SIGNALED 0x10 /* set when new kernel signal arrives */ 05553 #define SIG_PENDING 0x20 /* unready while signal being processed */ 05554 #define P_STOP 0x40 /* set when process is being traced */ 05555 #define NO_PRIV 0x80 /* keep forked system process from running */ 05556 05557 /* Scheduling priorities for p_priority. Values must start at zero (highest 05558 * priority) and increment. Priorities of the processes in the boot image 05559 * can be set in table.c. IDLE must have a queue for itself, to prevent low 05560 * priority user processes to run round-robin with IDLE. 05561 */ 05562 #define NR_SCHED_QUEUES 16 /* MUST equal minimum priority + 1 */ 05563 #define TASK_Q 0 /* highest, used for kernel tasks */ 05564 #define MAX_USER_Q 0 /* highest priority for user processes */ 05565 #define USER_Q 7 /* default (should correspond to nice 0) */ 05566 #define MIN_USER_Q 14 /* minimum priority for user processes */ 05567 #define IDLE_Q 15 /* lowest, only IDLE process goes here */ 05568 05569 /* Magic process table addresses. */ File: Page: 700 kernel/proc.h 05570 #define BEG_PROC_ADDR (&proc[0]) 05571 #define BEG_USER_ADDR (&proc[NR_TASKS]) 05572 #define END_PROC_ADDR (&proc[NR_TASKS + NR_PROCS]) 05573 05574 #define NIL_PROC ((struct proc *) 0) 05575 #define NIL_SYS_PROC ((struct proc *) 1) 05576 #define cproc_addr(n) (&(proc + NR_TASKS)[(n)]) 05577 #define proc_addr(n) (pproc_addr + NR_TASKS)[(n)] 05578 #define proc_nr(p) ((p)->p_nr) 05579 05580 #define isokprocn(n) ((unsigned) ((n) + NR_TASKS) < NR_PROCS + NR_TASKS) 05581 #define isemptyn(n) isemptyp(proc_addr(n)) 05582 #define isemptyp(p) ((p)->p_rts_flags == SLOT_FREE) 05583 #define iskernelp(p) iskerneln((p)->p_nr) 05584 #define iskerneln(n) ((n) < 0) 05585 #define isuserp(p) isusern((p)->p_nr) 05586 #define isusern(n) ((n) >= 0) 05587 05588 /* The process table and pointers to process table slots. The pointers allow 05589 * faster access because now a process entry can be found by indexing the 05590 * pproc_addr array, while accessing an element i requires a multiplication 05591 * with sizeof(struct proc) to determine the address. 05592 */ 05593 EXTERN struct proc proc[NR_TASKS + NR_PROCS]; /* process table */ 05594 EXTERN struct proc *pproc_addr[NR_TASKS + NR_PROCS]; 05595 EXTERN struct proc *rdy_head[NR_SCHED_QUEUES]; /* ptrs to ready list headers */ 05596 EXTERN struct proc *rdy_tail[NR_SCHED_QUEUES]; /* ptrs to ready list tails */ 05597 05598 #endif /* PROC_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/sconst.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 05600 ! Miscellaneous constants used in assembler code. 05601 W = _WORD_SIZE ! Machine word size. 05602 05603 ! Offsets in struct proc. They MUST match proc.h. 05604 P_STACKBASE = 0 05605 GSREG = P_STACKBASE 05606 FSREG = GSREG + 2 ! 386 introduces FS and GS segments 05607 ESREG = FSREG + 2 05608 DSREG = ESREG + 2 05609 DIREG = DSREG + 2 05610 SIREG = DIREG + W 05611 BPREG = SIREG + W 05612 STREG = BPREG + W ! hole for another SP 05613 BXREG = STREG + W 05614 DXREG = BXREG + W 05615 CXREG = DXREG + W 05616 AXREG = CXREG + W 05617 RETADR = AXREG + W ! return address for save() call 05618 PCREG = RETADR + W 05619 CSREG = PCREG + W 05620 PSWREG = CSREG + W 05621 SPREG = PSWREG + W 05622 SSREG = SPREG + W 05623 P_STACKTOP = SSREG + W 05624 P_LDT_SEL = P_STACKTOP File: Page: 701 kernel/sconst.h 05625 P_LDT = P_LDT_SEL + W 05626 05627 Msize = 9 ! size of a message in 32-bit words ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/priv.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 05700 #ifndef PRIV_H 05701 #define PRIV_H 05702 05703 /* Declaration of the system privileges structure. It defines flags, system 05704 * call masks, an synchronous alarm timer, I/O privileges, pending hardware 05705 * interrupts and notifications, and so on. 05706 * System processes each get their own structure with properties, whereas all 05707 * user processes share one structure. This setup provides a clear separation 05708 * between common and privileged process fields and is very space efficient. 05709 * 05710 * Changes: 05711 * Jul 01, 2005 Created. (Jorrit N. Herder) 05712 */ 05713 #include 05714 #include "protect.h" 05715 #include "const.h" 05716 #include "type.h" 05717 05718 struct priv { 05719 proc_nr_t s_proc_nr; /* number of associated process */ 05720 sys_id_t s_id; /* index of this system structure */ 05721 short s_flags; /* PREEMTIBLE, BILLABLE, etc. */ 05722 05723 short s_trap_mask; /* allowed system call traps */ 05724 sys_map_t s_ipc_from; /* allowed callers to receive from */ 05725 sys_map_t s_ipc_to; /* allowed destination processes */ 05726 long s_call_mask; /* allowed kernel calls */ 05727 05728 sys_map_t s_notify_pending; /* bit map with pending notifications */ 05729 irq_id_t s_int_pending; /* pending hardware interrupts */ 05730 sigset_t s_sig_pending; /* pending signals */ 05731 05732 timer_t s_alarm_timer; /* synchronous alarm timer */ 05733 struct far_mem s_farmem[NR_REMOTE_SEGS]; /* remote memory map */ 05734 reg_t *s_stack_guard; /* stack guard word for kernel tasks */ 05735 }; 05736 05737 /* Guard word for task stacks. */ 05738 #define STACK_GUARD ((reg_t) (sizeof(reg_t) == 2 ? 0xBEEF : 0xDEADBEEF)) 05739 05740 /* Bits for the system property flags. */ 05741 #define PREEMPTIBLE 0x01 /* kernel tasks are not preemptible */ 05742 #define BILLABLE 0x04 /* some processes are not billable */ 05743 #define SYS_PROC 0x10 /* system processes are privileged */ 05744 #define SENDREC_BUSY 0x20 /* sendrec() in progress */ 05745 05746 /* Magic system structure table addresses. */ 05747 #define BEG_PRIV_ADDR (&priv[0]) 05748 #define END_PRIV_ADDR (&priv[NR_SYS_PROCS]) 05749 File: Page: 702 kernel/priv.h 05750 #define priv_addr(i) (ppriv_addr)[(i)] 05751 #define priv_id(rp) ((rp)->p_priv->s_id) 05752 #define priv(rp) ((rp)->p_priv) 05753 05754 #define id_to_nr(id) priv_addr(id)->s_proc_nr 05755 #define nr_to_id(nr) priv(proc_addr(nr))->s_id 05756 05757 /* The system structures table and pointers to individual table slots. The 05758 * pointers allow faster access because now a process entry can be found by 05759 * indexing the psys_addr array, while accessing an element i requires a 05760 * multiplication with sizeof(struct sys) to determine the address. 05761 */ 05762 EXTERN struct priv priv[NR_SYS_PROCS]; /* system properties table */ 05763 EXTERN struct priv *ppriv_addr[NR_SYS_PROCS]; /* direct slot pointers */ 05764 05765 /* Unprivileged user processes all share the same privilege structure. 05766 * This id must be fixed because it is used to check send mask entries. 05767 */ 05768 #define USER_PRIV_ID 0 05769 05770 /* Make sure the system can boot. The following sanity check verifies that 05771 * the system privileges table is large enough for the number of processes 05772 * in the boot image. 05773 */ 05774 #if (NR_BOOT_PROCS > NR_SYS_PROCS) 05775 #error NR_SYS_PROCS must be larger than NR_BOOT_PROCS 05776 #endif 05777 05778 #endif /* PRIV_H */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/protect.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 05800 /* Constants for protected mode. */ 05801 05802 /* Table sizes. */ 05803 #define GDT_SIZE (FIRST_LDT_INDEX + NR_TASKS + NR_PROCS) 05804 /* spec. and LDT's */ 05805 #define IDT_SIZE (IRQ8_VECTOR + 8) /* only up to the highest vector */ 05806 #define LDT_SIZE (2 + NR_REMOTE_SEGS) /* CS, DS and remote segments */ 05807 05808 /* Fixed global descriptors. 1 to 7 are prescribed by the BIOS. */ 05809 #define GDT_INDEX 1 /* GDT descriptor */ 05810 #define IDT_INDEX 2 /* IDT descriptor */ 05811 #define DS_INDEX 3 /* kernel DS */ 05812 #define ES_INDEX 4 /* kernel ES (386: flag 4 Gb at startup) */ 05813 #define SS_INDEX 5 /* kernel SS (386: monitor SS at startup) */ 05814 #define CS_INDEX 6 /* kernel CS */ 05815 #define MON_CS_INDEX 7 /* temp for BIOS (386: monitor CS at startup) */ 05816 #define TSS_INDEX 8 /* kernel TSS */ 05817 #define DS_286_INDEX 9 /* scratch 16-bit source segment */ 05818 #define ES_286_INDEX 10 /* scratch 16-bit destination segment */ 05819 #define A_INDEX 11 /* 64K memory segment at A0000 */ 05820 #define B_INDEX 12 /* 64K memory segment at B0000 */ 05821 #define C_INDEX 13 /* 64K memory segment at C0000 */ 05822 #define D_INDEX 14 /* 64K memory segment at D0000 */ 05823 #define FIRST_LDT_INDEX 15 /* rest of descriptors are LDT's */ 05824 File: Page: 703 kernel/protect.h 05825 #define GDT_SELECTOR 0x08 /* (GDT_INDEX * DESC_SIZE) bad for asld */ 05826 #define IDT_SELECTOR 0x10 /* (IDT_INDEX * DESC_SIZE) */ 05827 #define DS_SELECTOR 0x18 /* (DS_INDEX * DESC_SIZE) */ 05828 #define ES_SELECTOR 0x20 /* (ES_INDEX * DESC_SIZE) */ 05829 #define FLAT_DS_SELECTOR 0x21 /* less privileged ES */ 05830 #define SS_SELECTOR 0x28 /* (SS_INDEX * DESC_SIZE) */ 05831 #define CS_SELECTOR 0x30 /* (CS_INDEX * DESC_SIZE) */ 05832 #define MON_CS_SELECTOR 0x38 /* (MON_CS_INDEX * DESC_SIZE) */ 05833 #define TSS_SELECTOR 0x40 /* (TSS_INDEX * DESC_SIZE) */ 05834 #define DS_286_SELECTOR 0x49 /* (DS_286_INDEX*DESC_SIZE+TASK_PRIVILEGE) */ 05835 #define ES_286_SELECTOR 0x51 /* (ES_286_INDEX*DESC_SIZE+TASK_PRIVILEGE) */ 05836 05837 /* Fixed local descriptors. */ 05838 #define CS_LDT_INDEX 0 /* process CS */ 05839 #define DS_LDT_INDEX 1 /* process DS=ES=FS=GS=SS */ 05840 #define EXTRA_LDT_INDEX 2 /* first of the extra LDT entries */ 05841 05842 /* Privileges. */ 05843 #define INTR_PRIVILEGE 0 /* kernel and interrupt handlers */ 05844 #define TASK_PRIVILEGE 1 /* kernel tasks */ 05845 #define USER_PRIVILEGE 3 /* servers and user processes */ 05846 05847 /* 286 hardware constants. */ 05848 05849 /* Exception vector numbers. */ 05850 #define BOUNDS_VECTOR 5 /* bounds check failed */ 05851 #define INVAL_OP_VECTOR 6 /* invalid opcode */ 05852 #define COPROC_NOT_VECTOR 7 /* coprocessor not available */ 05853 #define DOUBLE_FAULT_VECTOR 8 05854 #define COPROC_SEG_VECTOR 9 /* coprocessor segment overrun */ 05855 #define INVAL_TSS_VECTOR 10 /* invalid TSS */ 05856 #define SEG_NOT_VECTOR 11 /* segment not present */ 05857 #define STACK_FAULT_VECTOR 12 /* stack exception */ 05858 #define PROTECTION_VECTOR 13 /* general protection */ 05859 05860 /* Selector bits. */ 05861 #define TI 0x04 /* table indicator */ 05862 #define RPL 0x03 /* requester privilege level */ 05863 05864 /* Descriptor structure offsets. */ 05865 #define DESC_BASE 2 /* to base_low */ 05866 #define DESC_BASE_MIDDLE 4 /* to base_middle */ 05867 #define DESC_ACCESS 5 /* to access byte */ 05868 #define DESC_SIZE 8 /* sizeof (struct segdesc_s) */ 05869 05870 /* Base and limit sizes and shifts. */ 05871 #define BASE_MIDDLE_SHIFT 16 /* shift for base --> base_middle */ 05872 05873 /* Access-byte and type-byte bits. */ 05874 #define PRESENT 0x80 /* set for descriptor present */ 05875 #define DPL 0x60 /* descriptor privilege level mask */ 05876 #define DPL_SHIFT 5 05877 #define SEGMENT 0x10 /* set for segment-type descriptors */ 05878 05879 /* Access-byte bits. */ 05880 #define EXECUTABLE 0x08 /* set for executable segment */ 05881 #define CONFORMING 0x04 /* set for conforming segment if executable */ 05882 #define EXPAND_DOWN 0x04 /* set for expand-down segment if !executable*/ 05883 #define READABLE 0x02 /* set for readable segment if executable */ 05884 #define WRITEABLE 0x02 /* set for writeable segment if !executable */ File: Page: 704 kernel/protect.h 05885 #define TSS_BUSY 0x02 /* set if TSS descriptor is busy */ 05886 #define ACCESSED 0x01 /* set if segment accessed */ 05887 05888 /* Special descriptor types. */ 05889 #define AVL_286_TSS 1 /* available 286 TSS */ 05890 #define LDT 2 /* local descriptor table */ 05891 #define BUSY_286_TSS 3 /* set transparently to the software */ 05892 #define CALL_286_GATE 4 /* not used */ 05893 #define TASK_GATE 5 /* only used by debugger */ 05894 #define INT_286_GATE 6 /* interrupt gate, used for all vectors */ 05895 #define TRAP_286_GATE 7 /* not used */ 05896 05897 /* Extra 386 hardware constants. */ 05898 05899 /* Exception vector numbers. */ 05900 #define PAGE_FAULT_VECTOR 14 05901 #define COPROC_ERR_VECTOR 16 /* coprocessor error */ 05902 05903 /* Descriptor structure offsets. */ 05904 #define DESC_GRANULARITY 6 /* to granularity byte */ 05905 #define DESC_BASE_HIGH 7 /* to base_high */ 05906 05907 /* Base and limit sizes and shifts. */ 05908 #define BASE_HIGH_SHIFT 24 /* shift for base --> base_high */ 05909 #define BYTE_GRAN_MAX 0xFFFFFL /* maximum size for byte granular segment */ 05910 #define GRANULARITY_SHIFT 16 /* shift for limit --> granularity */ 05911 #define OFFSET_HIGH_SHIFT 16 /* shift for (gate) offset --> offset_high */ 05912 #define PAGE_GRAN_SHIFT 12 /* extra shift for page granular limits */ 05913 05914 /* Type-byte bits. */ 05915 #define DESC_386_BIT 0x08 /* 386 types are obtained by ORing with this */ 05916 /* LDT's and TASK_GATE's don't need it */ 05917 05918 /* Granularity byte. */ 05919 #define GRANULAR 0x80 /* set for 4K granularilty */ 05920 #define DEFAULT 0x40 /* set for 32-bit defaults (executable seg) */ 05921 #define BIG 0x40 /* set for "BIG" (expand-down seg) */ 05922 #define AVL 0x10 /* 0 for available */ 05923 #define LIMIT_HIGH 0x0F /* mask for high bits of limit */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/table.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 06000 /* The object file of "table.c" contains most kernel data. Variables that 06001 * are declared in the *.h files appear with EXTERN in front of them, as in 06002 * 06003 * EXTERN int x; 06004 * 06005 * Normally EXTERN is defined as extern, so when they are included in another 06006 * file, no storage is allocated. If EXTERN were not present, but just say, 06007 * 06008 * int x; 06009 * 06010 * then including this file in several source files would cause 'x' to be 06011 * declared several times. While some linkers accept this, others do not, 06012 * so they are declared extern when included normally. However, it must be 06013 * declared for real somewhere. That is done here, by redefining EXTERN as 06014 * the null string, so that inclusion of all *.h files in table.c actually File: Page: 705 kernel/table.c 06015 * generates storage for them. 06016 * 06017 * Various variables could not be declared EXTERN, but are declared PUBLIC 06018 * or PRIVATE. The reason for this is that extern variables cannot have a 06019 * default initialization. If such variables are shared, they must also be 06020 * declared in one of the *.h files without the initialization. Examples 06021 * include 'boot_image' (this file) and 'idt' and 'gdt' (protect.c). 06022 * 06023 * Changes: 06024 * Aug 02, 2005 set privileges and minimal boot image (Jorrit N. Herder) 06025 * Oct 17, 2004 updated above and tasktab comments (Jorrit N. Herder) 06026 * May 01, 2004 changed struct for system image (Jorrit N. Herder) 06027 */ 06028 #define _TABLE 06029 06030 #include "kernel.h" 06031 #include "proc.h" 06032 #include "ipc.h" 06033 #include 06034 #include 06035 06036 /* Define stack sizes for the kernel tasks included in the system image. */ 06037 #define NO_STACK 0 06038 #define SMALL_STACK (128 * sizeof(char *)) 06039 #define IDL_S SMALL_STACK /* 3 intr, 3 temps, 4 db for Intel */ 06040 #define HRD_S NO_STACK /* dummy task, uses kernel stack */ 06041 #define TSK_S SMALL_STACK /* system and clock task */ 06042 06043 /* Stack space for all the task stacks. Declared as (char *) to align it. */ 06044 #define TOT_STACK_SPACE (IDL_S + HRD_S + (2 * TSK_S)) 06045 PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)]; 06046 06047 /* Define flags for the various process types. */ 06048 #define IDL_F (SYS_PROC | PREEMPTIBLE | BILLABLE) /* idle task */ 06049 #define TSK_F (SYS_PROC) /* kernel tasks */ 06050 #define SRV_F (SYS_PROC | PREEMPTIBLE) /* system services */ 06051 #define USR_F (BILLABLE | PREEMPTIBLE) /* user processes */ 06052 06053 /* Define system call traps for the various process types. These call masks 06054 * determine what system call traps a process is allowed to make. 06055 */ 06056 #define TSK_T (1 << RECEIVE) /* clock and system */ 06057 #define SRV_T (~0) /* system services */ 06058 #define USR_T ((1 << SENDREC) | (1 << ECHO)) /* user processes */ 06059 06060 /* Send masks determine to whom processes can send messages or notifications. 06061 * The values here are used for the processes in the boot image. We rely on 06062 * the initialization code in main() to match the s_nr_to_id() mapping for the 06063 * processes in the boot image, so that the send mask that is defined here 06064 * can be directly copied onto map[0] of the actual send mask. Privilege 06065 * structure 0 is shared by user processes. 06066 */ 06067 #define s(n) (1 << s_nr_to_id(n)) 06068 #define SRV_M (~0) 06069 #define SYS_M (~0) 06070 #define USR_M (s(PM_PROC_NR) | s(FS_PROC_NR) | s(RS_PROC_NR)) 06071 #define DRV_M (USR_M | s(SYSTEM) | s(CLOCK) | s(LOG_PROC_NR) | s(TTY_PROC_NR)) 06072 06073 /* Define kernel calls that processes are allowed to make. This is not looking 06074 * very nice, but we need to define the access rights on a per call basis. File: Page: 706 kernel/table.c 06075 * Note that the reincarnation server has all bits on, because it should 06076 * be allowed to distribute rights to services that it starts. 06077 */ 06078 #define c(n) (1 << ((n)-KERNEL_CALL)) 06079 #define RS_C ~0 06080 #define PM_C ~(c(SYS_DEVIO) | c(SYS_SDEVIO) | c(SYS_VDEVIO) \ 06081 | c(SYS_IRQCTL) | c(SYS_INT86)) 06082 #define FS_C (c(SYS_KILL) | c(SYS_VIRCOPY) | c(SYS_VIRVCOPY) | c(SYS_UMAP) \ 06083 | c(SYS_GETINFO) | c(SYS_EXIT) | c(SYS_TIMES) | c(SYS_SETALARM)) 06084 #define DRV_C (FS_C | c(SYS_SEGCTL) | c(SYS_IRQCTL) | c(SYS_INT86) \ 06085 | c(SYS_DEVIO) | c(SYS_VDEVIO) | c(SYS_SDEVIO)) 06086 #define MEM_C (DRV_C | c(SYS_PHYSCOPY) | c(SYS_PHYSVCOPY)) 06087 06088 /* The system image table lists all programs that are part of the boot image. 06089 * The order of the entries here MUST agree with the order of the programs 06090 * in the boot image and all kernel tasks must come first. 06091 * Each entry provides the process number, flags, quantum size (qs), scheduling 06092 * queue, allowed traps, ipc mask, and a name for the process table. The 06093 * initial program counter and stack size is also provided for kernel tasks. 06094 */ 06095 PUBLIC struct boot_image image[] = { 06096 /* process nr, pc, flags, qs, queue, stack, traps, ipcto, call, name */ 06097 { IDLE, idle_task, IDL_F, 8, IDLE_Q, IDL_S, 0, 0, 0, "IDLE" }, 06098 { CLOCK,clock_task, TSK_F, 64, TASK_Q, TSK_S, TSK_T, 0, 0, "CLOCK" }, 06099 { SYSTEM, sys_task, TSK_F, 64, TASK_Q, TSK_S, TSK_T, 0, 0, "SYSTEM"}, 06100 { HARDWARE, 0, TSK_F, 64, TASK_Q, HRD_S, 0, 0, 0, "KERNEL"}, 06101 { PM_PROC_NR, 0, SRV_F, 32, 3, 0, SRV_T, SRV_M, PM_C, "pm" }, 06102 { FS_PROC_NR, 0, SRV_F, 32, 4, 0, SRV_T, SRV_M, FS_C, "fs" }, 06103 { RS_PROC_NR, 0, SRV_F, 4, 3, 0, SRV_T, SYS_M, RS_C, "rs" }, 06104 { TTY_PROC_NR, 0, SRV_F, 4, 1, 0, SRV_T, SYS_M, DRV_C, "tty" }, 06105 { MEM_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, DRV_M, MEM_C, "memory"}, 06106 { LOG_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "log" }, 06107 { DRVR_PROC_NR, 0, SRV_F, 4, 2, 0, SRV_T, SYS_M, DRV_C, "driver"}, 06108 { INIT_PROC_NR, 0, USR_F, 8, USER_Q, 0, USR_T, USR_M, 0, "init" }, 06109 }; 06110 06111 /* Verify the size of the system image table at compile time. Also verify that 06112 * the first chunk of the ipc mask has enough bits to accommodate the processes 06113 * in the image. 06114 * If a problem is detected, the size of the 'dummy' array will be negative, 06115 * causing a compile time error. Note that no space is actually allocated 06116 * because 'dummy' is declared extern. 06117 */ 06118 extern int dummy[(NR_BOOT_PROCS==sizeof(image)/ 06119 sizeof(struct boot_image))?1: -1]; 06120 extern int dummy[(BITCHUNK_BITS > NR_BOOT_PROCS - 1) ? 1 : -1]; 06121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/mpx.s ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 06200 # 06201 ! Chooses between the 8086 and 386 versions of the Minix startup code. 06202 06203 #include 06204 #if _WORD_SIZE == 2 File: Page: 707 kernel/mpx.s 06205 #include "mpx88.s" 06206 #else 06207 #include "mpx386.s" 06208 #endif ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/mpx386.s ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 06300 # 06301 ! This file, mpx386.s, is included by mpx.s when Minix is compiled for 06302 ! 32-bit Intel CPUs. The alternative mpx88.s is compiled for 16-bit CPUs. 06303 06304 ! This file is part of the lowest layer of the MINIX kernel. (The other part 06305 ! is "proc.c".) The lowest layer does process switching and message handling. 06306 ! Furthermore it contains the assembler startup code for Minix and the 32-bit 06307 ! interrupt handlers. It cooperates with the code in "start.c" to set up a 06308 ! good environment for main(). 06309 06310 ! Every transition to the kernel goes through this file. Transitions to the 06311 ! kernel may be nested. The initial entry may be with a system call (i.e., 06312 ! send or receive a message), an exception or a hardware interrupt; kernel 06313 ! reentries may only be made by hardware interrupts. The count of reentries 06314 ! is kept in "k_reenter". It is important for deciding whether to switch to 06315 ! the kernel stack and for protecting the message passing code in "proc.c". 06316 06317 ! For the message passing trap, most of the machine state is saved in the 06318 ! proc table. (Some of the registers need not be saved.) Then the stack is 06319 ! switched to "k_stack", and interrupts are reenabled. Finally, the system 06320 ! call handler (in C) is called. When it returns, interrupts are disabled 06321 ! again and the code falls into the restart routine, to finish off held-up 06322 ! interrupts and run the process or task whose pointer is in "proc_ptr". 06323 06324 ! Hardware interrupt handlers do the same, except (1) The entire state must 06325 ! be saved. (2) There are too many handlers to do this inline, so the save 06326 ! routine is called. A few cycles are saved by pushing the address of the 06327 ! appropiate restart routine for a return later. (3) A stack switch is 06328 ! avoided when the stack is already switched. (4) The (master) 8259 interrupt 06329 ! controller is reenabled centrally in save(). (5) Each interrupt handler 06330 ! masks its interrupt line using the 8259 before enabling (other unmasked) 06331 ! interrupts, and unmasks it after servicing the interrupt. This limits the 06332 ! nest level to the number of lines and protects the handler from itself. 06333 06334 ! For communication with the boot monitor at startup time some constant 06335 ! data are compiled into the beginning of the text segment. This facilitates 06336 ! reading the data at the start of the boot process, since only the first 06337 ! sector of the file needs to be read. 06338 06339 ! Some data storage is also allocated at the end of this file. This data 06340 ! will be at the start of the data segment of the kernel and will be read 06341 ! and modified by the boot monitor before the kernel starts. 06342 06343 ! sections 06344 06345 .sect .text 06346 begtext: 06347 .sect .rom 06348 begrom: 06349 .sect .data File: Page: 708 kernel/mpx386.s 06350 begdata: 06351 .sect .bss 06352 begbss: 06353 06354 #include 06355 #include 06356 #include 06357 #include 06358 #include "const.h" 06359 #include "protect.h" 06360 #include "sconst.h" 06361 06362 /* Selected 386 tss offsets. */ 06363 #define TSS3_S_SP0 4 06364 06365 ! Exported functions 06366 ! Note: in assembly language the .define statement applied to a function name 06367 ! is loosely equivalent to a prototype in C code -- it makes it possible to 06368 ! link to an entity declared in the assembly code but does not create 06369 ! the entity. 06370 06371 .define _restart 06372 .define save 06373 06374 .define _divide_error 06375 .define _single_step_exception 06376 .define _nmi 06377 .define _breakpoint_exception 06378 .define _overflow 06379 .define _bounds_check 06380 .define _inval_opcode 06381 .define _copr_not_available 06382 .define _double_fault 06383 .define _copr_seg_overrun 06384 .define _inval_tss 06385 .define _segment_not_present 06386 .define _stack_exception 06387 .define _general_protection 06388 .define _page_fault 06389 .define _copr_error 06390 06391 .define _hwint00 ! handlers for hardware interrupts 06392 .define _hwint01 06393 .define _hwint02 06394 .define _hwint03 06395 .define _hwint04 06396 .define _hwint05 06397 .define _hwint06 06398 .define _hwint07 06399 .define _hwint08 06400 .define _hwint09 06401 .define _hwint10 06402 .define _hwint11 06403 .define _hwint12 06404 .define _hwint13 06405 .define _hwint14 06406 .define _hwint15 06407 06408 .define _s_call 06409 .define _p_s_call File: Page: 709 kernel/mpx386.s 06410 .define _level0_call 06411 06412 ! Exported variables. 06413 .define begbss 06414 .define begdata 06415 06416 .sect .text 06417 !*===========================================================================* 06418 !* MINIX * 06419 !*===========================================================================* 06420 MINIX: ! this is the entry point for the MINIX kernel 06421 jmp over_flags ! skip over the next few bytes 06422 .data2 CLICK_SHIFT ! for the monitor: memory granularity 06423 flags: 06424 .data2 0x01FD ! boot monitor flags: 06425 ! call in 386 mode, make bss, make stack, 06426 ! load high, don't patch, will return, 06427 ! uses generic INT, memory vector, 06428 ! new boot code return 06429 nop ! extra byte to sync up disassembler 06430 over_flags: 06431 06432 ! Set up a C stack frame on the monitor stack. (The monitor sets cs and ds 06433 ! right. The ss descriptor still references the monitor data segment.) 06434 movzx esp, sp ! monitor stack is a 16 bit stack 06435 push ebp 06436 mov ebp, esp 06437 push esi 06438 push edi 06439 cmp 4(ebp), 0 ! monitor return vector is 06440 jz noret ! nonzero if return possible 06441 inc (_mon_return) 06442 noret: mov (_mon_sp), esp ! save stack pointer for later return 06443 06444 ! Copy the monitor global descriptor table to the address space of kernel and 06445 ! switch over to it. Prot_init() can then update it with immediate effect. 06446 06447 sgdt (_gdt+GDT_SELECTOR) ! get the monitor gdtr 06448 mov esi, (_gdt+GDT_SELECTOR+2) ! absolute address of GDT 06449 mov ebx, _gdt ! address of kernel GDT 06450 mov ecx, 8*8 ! copying eight descriptors 06451 copygdt: 06452 eseg movb al, (esi) 06453 movb (ebx), al 06454 inc esi 06455 inc ebx 06456 loop copygdt 06457 mov eax, (_gdt+DS_SELECTOR+2) ! base of kernel data 06458 and eax, 0x00FFFFFF ! only 24 bits 06459 add eax, _gdt ! eax = vir2phys(gdt) 06460 mov (_gdt+GDT_SELECTOR+2), eax ! set base of GDT 06461 lgdt (_gdt+GDT_SELECTOR) ! switch over to kernel GDT 06462 06463 ! Locate boot parameters, set up kernel segment registers and stack. 06464 mov ebx, 8(ebp) ! boot parameters offset 06465 mov edx, 12(ebp) ! boot parameters length 06466 mov eax, 16(ebp) ! address of a.out headers 06467 mov (_aout), eax 06468 mov ax, ds ! kernel data 06469 mov es, ax File: Page: 710 kernel/mpx386.s 06470 mov fs, ax 06471 mov gs, ax 06472 mov ss, ax 06473 mov esp, k_stktop ! set sp to point to the top of kernel stack 06474 06475 ! Call C startup code to set up a proper environment to run main(). 06476 push edx 06477 push ebx 06478 push SS_SELECTOR 06479 push DS_SELECTOR 06480 push CS_SELECTOR 06481 call _cstart ! cstart(cs, ds, mds, parmoff, parmlen) 06482 add esp, 5*4 06483 06484 ! Reload gdtr, idtr and the segment registers to global descriptor table set 06485 ! up by prot_init(). 06486 06487 lgdt (_gdt+GDT_SELECTOR) 06488 lidt (_gdt+IDT_SELECTOR) 06489 06490 jmpf CS_SELECTOR: csinit 06491 csinit: 06492 o16 mov ax, DS_SELECTOR 06493 mov ds, ax 06494 mov es, ax 06495 mov fs, ax 06496 mov gs, ax 06497 mov ss, ax 06498 o16 mov ax, TSS_SELECTOR ! no other TSS is used 06499 ltr ax 06500 push 0 ! set flags to known good state 06501 popf ! esp, clear nested task and int enable 06502 06503 jmp _main ! main() 06504 06505 06506 !*===========================================================================* 06507 !* interrupt handlers * 06508 !* interrupt handlers for 386 32-bit protected mode * 06509 !*===========================================================================* 06510 06511 !*===========================================================================* 06512 !* hwint00 - 07 * 06513 !*===========================================================================* 06514 ! Note this is a macro, it just looks like a subroutine. 06515 #define hwint_master(irq) \ 06516 call save /* save interrupted process state */;\ 06517 push (_irq_handlers+4*irq) /* irq_handlers[irq] */;\ 06518 call _intr_handle /* intr_handle(irq_handlers[irq]) */;\ 06519 pop ecx ;\ 06520 cmp (_irq_actids+4*irq), 0 /* interrupt still active? */;\ 06521 jz 0f ;\ 06522 inb INT_CTLMASK /* get current mask */ ;\ 06523 orb al, [1< 06914 #include 06915 06916 FORWARD _PROTOTYPE( char *get_value, (_CONST char *params, _CONST char *key)); 06917 /*===========================================================================* 06918 * cstart * 06919 *===========================================================================*/ 06920 PUBLIC void cstart(cs, ds, mds, parmoff, parmsize) 06921 U16_t cs, ds; /* kernel code and data segment */ 06922 U16_t mds; /* monitor data segment */ 06923 U16_t parmoff, parmsize; /* boot parameters offset and length */ 06924 { 06925 /* Perform system initializations prior to calling main(). Most settings are 06926 * determined with help of the environment strings passed by MINIX' loader. 06927 */ 06928 char params[128*sizeof(char *)]; /* boot monitor parameters */ 06929 register char *value; /* value in key=value pair */ 06930 extern int etext, end; 06931 06932 /* Decide if mode is protected; 386 or higher implies protected mode. 06933 * This must be done first, because it is needed for, e.g., seg2phys(). 06934 * For 286 machines we cannot decide on protected mode, yet. This is 06935 * done below. 06936 */ 06937 #if _WORD_SIZE != 2 06938 machine.protected = 1; 06939 #endif 06940 06941 /* Record where the kernel and the monitor are. */ 06942 kinfo.code_base = seg2phys(cs); 06943 kinfo.code_size = (phys_bytes) &etext; /* size of code segment */ 06944 kinfo.data_base = seg2phys(ds); 06945 kinfo.data_size = (phys_bytes) &end; /* size of data segment */ 06946 06947 /* Initialize protected mode descriptors. */ 06948 prot_init(); 06949 File: Page: 717 kernel/start.c 06950 /* Copy the boot parameters to the local buffer. */ 06951 kinfo.params_base = seg2phys(mds) + parmoff; 06952 kinfo.params_size = MIN(parmsize,sizeof(params)-2); 06953 phys_copy(kinfo.params_base, vir2phys(params), kinfo.params_size); 06954 06955 /* Record miscellaneous information for user-space servers. */ 06956 kinfo.nr_procs = NR_PROCS; 06957 kinfo.nr_tasks = NR_TASKS; 06958 strncpy(kinfo.release, OS_RELEASE, sizeof(kinfo.release)); 06959 kinfo.release[sizeof(kinfo.release)-1] = '\0'; 06960 strncpy(kinfo.version, OS_VERSION, sizeof(kinfo.version)); 06961 kinfo.version[sizeof(kinfo.version)-1] = '\0'; 06962 kinfo.proc_addr = (vir_bytes) proc; 06963 kinfo.kmem_base = vir2phys(0); 06964 kinfo.kmem_size = (phys_bytes) &end; 06965 06966 /* Processor? 86, 186, 286, 386, ... 06967 * Decide if mode is protected for older machines. 06968 */ 06969 machine.processor=atoi(get_value(params, "processor")); 06970 #if _WORD_SIZE == 2 06971 machine.protected = machine.processor >= 286; 06972 #endif 06973 if (! machine.protected) mon_return = 0; 06974 06975 /* XT, AT or MCA bus? */ 06976 value = get_value(params, "bus"); 06977 if (value == NIL_PTR || strcmp(value, "at") == 0) { 06978 machine.pc_at = TRUE; /* PC-AT compatible hardware */ 06979 } else if (strcmp(value, "mca") == 0) { 06980 machine.pc_at = machine.ps_mca = TRUE; /* PS/2 with micro channel */ 06981 } 06982 06983 /* Type of VDU: */ 06984 value = get_value(params, "video"); /* EGA or VGA video unit */ 06985 if (strcmp(value, "ega") == 0) machine.vdu_ega = TRUE; 06986 if (strcmp(value, "vga") == 0) machine.vdu_vga = machine.vdu_ega = TRUE; 06987 06988 /* Return to assembler code to switch to protected mode (if 286), 06989 * reload selectors and call main(). 06990 */ 06991 } 06993 /*===========================================================================* 06994 * get_value * 06995 *===========================================================================*/ 06996 06997 PRIVATE char *get_value(params, name) 06998 _CONST char *params; /* boot monitor parameters */ 06999 _CONST char *name; /* key to look up */ 07000 { 07001 /* Get environment value - kernel version of getenv to avoid setting up the 07002 * usual environment array. 07003 */ 07004 register _CONST char *namep; 07005 register char *envp; 07006 07007 for (envp = (char *) params; *envp != 0;) { 07008 for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++) 07009 ; File: Page: 718 kernel/start.c 07010 if (*namep == '\0' && *envp == '=') return(envp + 1); 07011 while (*envp++ != 0) 07012 ; 07013 } 07014 return(NIL_PTR); 07015 } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/main.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 07100 /* This file contains the main program of MINIX as well as its shutdown code. 07101 * The routine main() initializes the system and starts the ball rolling by 07102 * setting up the process table, interrupt vectors, and scheduling each task 07103 * to run to initialize itself. 07104 * The routine shutdown() does the opposite and brings down MINIX. 07105 * 07106 * The entries into this file are: 07107 * main: MINIX main program 07108 * prepare_shutdown: prepare to take MINIX down 07109 * 07110 * Changes: 07111 * Nov 24, 2004 simplified main() with system image (Jorrit N. Herder) 07112 * Aug 20, 2004 new prepare_shutdown() and shutdown() (Jorrit N. Herder) 07113 */ 07114 #include "kernel.h" 07115 #include 07116 #include 07117 #include 07118 #include 07119 #include 07120 #include 07121 #include "proc.h" 07122 07123 /* Prototype declarations for PRIVATE functions. */ 07124 FORWARD _PROTOTYPE( void announce, (void)); 07125 FORWARD _PROTOTYPE( void shutdown, (timer_t *tp)); 07126 07127 /*===========================================================================* 07128 * main * 07129 *===========================================================================*/ 07130 PUBLIC void main() 07131 { 07132 /* Start the ball rolling. */ 07133 struct boot_image *ip; /* boot image pointer */ 07134 register struct proc *rp; /* process pointer */ 07135 register struct priv *sp; /* privilege structure pointer */ 07136 register int i, s; 07137 int hdrindex; /* index to array of a.out headers */ 07138 phys_clicks text_base; 07139 vir_clicks text_clicks, data_clicks; 07140 reg_t ktsb; /* kernel task stack base */ 07141 struct exec e_hdr; /* for a copy of an a.out header */ 07142 07143 /* Initialize the interrupt controller. */ 07144 intr_init(1); File: Page: 719 kernel/main.c 07145 07146 /* Clear the process table. Anounce each slot as empty and set up mappings 07147 * for proc_addr() and proc_nr() macros. Do the same for the table with 07148 * privilege structures for the system processes. 07149 */ 07150 for (rp = BEG_PROC_ADDR, i = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++i) { 07151 rp->p_rts_flags = SLOT_FREE; /* initialize free slot */ 07152 rp->p_nr = i; /* proc number from ptr */ 07153 (pproc_addr + NR_TASKS)[i] = rp; /* proc ptr from number */ 07154 } 07155 for (sp = BEG_PRIV_ADDR, i = 0; sp < END_PRIV_ADDR; ++sp, ++i) { 07156 sp->s_proc_nr = NONE; /* initialize as free */ 07157 sp->s_id = i; /* priv structure index */ 07158 ppriv_addr[i] = sp; /* priv ptr from number */ 07159 } 07160 07161 /* Set up proc table entries for tasks and servers. The stacks of the 07162 * kernel tasks are initialized to an array in data space. The stacks 07163 * of the servers have been added to the data segment by the monitor, so 07164 * the stack pointer is set to the end of the data segment. All the 07165 * processes are in low memory on the 8086. On the 386 only the kernel 07166 * is in low memory, the rest is loaded in extended memory. 07167 */ 07168 07169 /* Task stacks. */ 07170 ktsb = (reg_t) t_stack; 07171 07172 for (i=0; i < NR_BOOT_PROCS; ++i) { 07173 ip = &image[i]; /* process' attributes */ 07174 rp = proc_addr(ip->proc_nr); /* get process pointer */ 07175 rp->p_max_priority = ip->priority; /* max scheduling priority */ 07176 rp->p_priority = ip->priority; /* current priority */ 07177 rp->p_quantum_size = ip->quantum; /* quantum size in ticks */ 07178 rp->p_ticks_left = ip->quantum; /* current credit */ 07179 strncpy(rp->p_name, ip->proc_name, P_NAME_LEN); /* set process name */ 07180 (void) get_priv(rp, (ip->flags & SYS_PROC)); /* assign structure */ 07181 priv(rp)->s_flags = ip->flags; /* process flags */ 07182 priv(rp)->s_trap_mask = ip->trap_mask; /* allowed traps */ 07183 priv(rp)->s_call_mask = ip->call_mask; /* kernel call mask */ 07184 priv(rp)->s_ipc_to.chunk[0] = ip->ipc_to; /* restrict targets */ 07185 if (iskerneln(proc_nr(rp))) { /* part of the kernel? */ 07186 if (ip->stksize > 0) { /* HARDWARE stack size is 0 */ 07187 rp->p_priv->s_stack_guard = (reg_t *) ktsb; 07188 *rp->p_priv->s_stack_guard = STACK_GUARD; 07189 } 07190 ktsb += ip->stksize; /* point to high end of stack */ 07191 rp->p_reg.sp = ktsb; /* this task's initial stack ptr */ 07192 text_base = kinfo.code_base >> CLICK_SHIFT; 07193 /* processes that are in the kernel */ 07194 hdrindex = 0; /* all use the first a.out header */ 07195 } else { 07196 hdrindex = 1 + i-NR_TASKS; /* servers, drivers, INIT */ 07197 } 07198 07199 /* The bootstrap loader created an array of the a.out headers at 07200 * absolute address 'aout'. Get one element to e_hdr. 07201 */ 07202 phys_copy(aout + hdrindex * A_MINHDR, vir2phys(&e_hdr), 07203 (phys_bytes) A_MINHDR); 07204 /* Convert addresses to clicks and build process memory map */ File: Page: 720 kernel/main.c 07205 text_base = e_hdr.a_syms >> CLICK_SHIFT; 07206 text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT; 07207 if (!(e_hdr.a_flags & A_SEP)) text_clicks = 0; /* common I&D */ 07208 data_clicks = (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT; 07209 rp->p_memmap[T].mem_phys = text_base; 07210 rp->p_memmap[T].mem_len = text_clicks; 07211 rp->p_memmap[D].mem_phys = text_base + text_clicks; 07212 rp->p_memmap[D].mem_len = data_clicks; 07213 rp->p_memmap[S].mem_phys = text_base + text_clicks + data_clicks; 07214 rp->p_memmap[S].mem_vir = data_clicks; /* empty - stack is in data */ 07215 07216 /* Set initial register values. The processor status word for tasks 07217 * is different from that of other processes because tasks can 07218 * access I/O; this is not allowed to less-privileged processes 07219 */ 07220 rp->p_reg.pc = (reg_t) ip->initial_pc; 07221 rp->p_reg.psw = (iskernelp(rp)) ? INIT_TASK_PSW : INIT_PSW; 07222 07223 /* Initialize the server stack pointer. Take it down one word 07224 * to give crtso.s something to use as "argc". 07225 */ 07226 if (isusern(proc_nr(rp))) { /* user-space process? */ 07227 rp->p_reg.sp = (rp->p_memmap[S].mem_vir + 07228 rp->p_memmap[S].mem_len) << CLICK_SHIFT; 07229 rp->p_reg.sp -= sizeof(reg_t); 07230 } 07231 07232 /* Set ready. The HARDWARE task is never ready. */ 07233 if (rp->p_nr != HARDWARE) { 07234 rp->p_rts_flags = 0; /* runnable if no flags */ 07235 lock_enqueue(rp); /* add to scheduling queues */ 07236 } else { 07237 rp->p_rts_flags = NO_MAP; /* prevent from running */ 07238 } 07239 07240 /* Code and data segments must be allocated in protected mode. */ 07241 alloc_segments(rp); 07242 } 07243 07244 /* We're definitely not shutting down. */ 07245 shutdown_started = 0; 07246 07247 /* MINIX is now ready. All boot image processes are on the ready queue. 07248 * Return to the assembly code to start running the current process. 07249 */ 07250 bill_ptr = proc_addr(IDLE); /* it has to point somewhere */ 07251 announce(); /* print MINIX startup banner */ 07252 restart(); 07253 } 07255 /*===========================================================================* 07256 * announce * 07257 *===========================================================================*/ 07258 PRIVATE void announce(void) 07259 { 07260 /* Display the MINIX startup banner. */ 07261 kprintf("MINIX %s.%s." 07262 "Copyright 2006, Vrije Universiteit, Amsterdam, The Netherlands\n", 07263 OS_RELEASE, OS_VERSION); 07264 File: Page: 721 kernel/main.c 07265 /* Real mode, or 16/32-bit protected mode? */ 07266 kprintf("Executing in %s mode.\n\n", 07267 machine.protected ? "32-bit protected" : "real"); 07268 } 07270 /*===========================================================================* 07271 * prepare_shutdown * 07272 *===========================================================================*/ 07273 PUBLIC void prepare_shutdown(how) 07274 int how; 07275 { 07276 /* This function prepares to shutdown MINIX. */ 07277 static timer_t shutdown_timer; 07278 register struct proc *rp; 07279 message m; 07280 07281 /* Show debugging dumps on panics. Make sure that the TTY task is still 07282 * available to handle them. This is done with help of a non-blocking send. 07283 * We rely on TTY to call sys_abort() when it is done with the dumps. 07284 */ 07285 if (how == RBT_PANIC) { 07286 m.m_type = PANIC_DUMPS; 07287 if (nb_send(TTY_PROC_NR,&m)==OK) /* don't block if TTY isn't ready */ 07288 return; /* await sys_abort() from TTY */ 07289 } 07290 07291 /* Send a signal to all system processes that are still alive to inform 07292 * them that the MINIX kernel is shutting down. A proper shutdown sequence 07293 * should be implemented by a user-space server. This mechanism is useful 07294 * as a backup in case of system panics, so that system processes can still 07295 * run their shutdown code, e.g, to synchronize the FS or to let the TTY 07296 * switch to the first console. 07297 */ 07298 kprintf("Sending SIGKSTOP to system processes ...\n"); 07299 for (rp=BEG_PROC_ADDR; rps_flags & SYS_PROC) && !iskernelp(rp)) 07301 send_sig(proc_nr(rp), SIGKSTOP); 07302 } 07303 07304 /* We're shutting down. Diagnostics may behave differently now. */ 07305 shutdown_started = 1; 07306 07307 /* Notify system processes of the upcoming shutdown and allow them to be 07308 * scheduled by setting a watchog timer that calls shutdown(). The timer 07309 * argument passes the shutdown status. 07310 */ 07311 kprintf("MINIX will now be shut down ...\n"); 07312 tmr_arg(&shutdown_timer)->ta_int = how; 07313 07314 /* Continue after 1 second, to give processes a chance to get 07315 * scheduled to do shutdown work. 07316 */ 07317 set_timer(&shutdown_timer, get_uptime() + HZ, shutdown); 07318 } 07320 /*===========================================================================* 07321 * shutdown * 07322 *===========================================================================*/ 07323 PRIVATE void shutdown(tp) 07324 timer_t *tp; File: Page: 722 kernel/main.c 07325 { 07326 /* This function is called from prepare_shutdown or stop_sequence to bring 07327 * down MINIX. How to shutdown is in the argument: RBT_HALT (return to the 07328 * monitor), RBT_MONITOR (execute given code), RBT_RESET (hard reset). 07329 */ 07330 int how = tmr_arg(tp)->ta_int; 07331 u16_t magic; 07332 07333 /* Now mask all interrupts, including the clock, and stop the clock. */ 07334 outb(INT_CTLMASK, ~0); 07335 clock_stop(); 07336 07337 if (mon_return && how != RBT_RESET) { 07338 /* Reinitialize the interrupt controllers to the BIOS defaults. */ 07339 intr_init(0); 07340 outb(INT_CTLMASK, 0); 07341 outb(INT2_CTLMASK, 0); 07342 07343 /* Return to the boot monitor. Set the program if not already done. */ 07344 if (how != RBT_MONITOR) phys_copy(vir2phys(""), kinfo.params_base, 1); 07345 level0(monitor); 07346 } 07347 07348 /* Reset the system by jumping to the reset address (real mode), or by 07349 * forcing a processor shutdown (protected mode). First stop the BIOS 07350 * memory test by setting a soft reset flag. 07351 */ 07352 magic = STOP_MEM_CHECK; 07353 phys_copy(vir2phys(&magic), SOFT_RESET_FLAG_ADDR, SOFT_RESET_FLAG_SIZE); 07354 level0(reset); 07355 } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/proc.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 07400 /* This file contains essentially all of the process and message handling. 07401 * Together with "mpx.s" it forms the lowest layer of the MINIX kernel. 07402 * There is one entry point from the outside: 07403 * 07404 * sys_call: a system call, i.e., the kernel is trapped with an INT 07405 * 07406 * As well as several entry points used from the interrupt and task level: 07407 * 07408 * lock_notify: notify a process of a system event 07409 * lock_send: send a message to a process 07410 * lock_enqueue: put a process on one of the scheduling queues 07411 * lock_dequeue: remove a process from the scheduling queues 07412 * 07413 * Changes: 07414 * Aug 19, 2005 rewrote scheduling code (Jorrit N. Herder) 07415 * Jul 25, 2005 rewrote system call handling (Jorrit N. Herder) 07416 * May 26, 2005 rewrote message passing functions (Jorrit N. Herder) 07417 * May 24, 2005 new notification system call (Jorrit N. Herder) 07418 * Oct 28, 2004 nonblocking send and receive calls (Jorrit N. Herder) 07419 * File: Page: 723 kernel/proc.c 07420 * The code here is critical to make everything work and is important for the 07421 * overall performance of the system. A large fraction of the code deals with 07422 * list manipulation. To make this both easy to understand and fast to execute 07423 * pointer pointers are used throughout the code. Pointer pointers prevent 07424 * exceptions for the head or tail of a linked list. 07425 * 07426 * node_t *queue, *new_node; // assume these as global variables 07427 * node_t **xpp = &queue; // get pointer pointer to head of queue 07428 * while (*xpp != NULL) // find last pointer of the linked list 07429 * xpp = &(*xpp)->next; // get pointer to next pointer 07430 * *xpp = new_node; // now replace the end (the NULL pointer) 07431 * new_node->next = NULL; // and mark the new end of the list 07432 * 07433 * For example, when adding a new node to the end of the list, one normally 07434 * makes an exception for an empty list and looks up the end of the list for 07435 * nonempty lists. As shown above, this is not required with pointer pointers. 07436 */ 07437 07438 #include 07439 #include 07440 #include "kernel.h" 07441 #include "proc.h" 07442 07443 /* Scheduling and message passing functions. The functions are available to 07444 * other parts of the kernel through lock_...(). The lock temporarily disables 07445 * interrupts to prevent race conditions. 07446 */ 07447 FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dst, 07448 message *m_ptr, unsigned flags) ); 07449 FORWARD _PROTOTYPE( int mini_receive, (struct proc *caller_ptr, int src, 07450 message *m_ptr, unsigned flags) ); 07451 FORWARD _PROTOTYPE( int mini_notify, (struct proc *caller_ptr, int dst) ); 07452 07453 FORWARD _PROTOTYPE( void enqueue, (struct proc *rp) ); 07454 FORWARD _PROTOTYPE( void dequeue, (struct proc *rp) ); 07455 FORWARD _PROTOTYPE( void sched, (struct proc *rp, int *queue, int *front) ); 07456 FORWARD _PROTOTYPE( void pick_proc, (void) ); 07457 07458 #define BuildMess(m_ptr, src, dst_ptr) \ 07459 (m_ptr)->m_source = (src); \ 07460 (m_ptr)->m_type = NOTIFY_FROM(src); \ 07461 (m_ptr)->NOTIFY_TIMESTAMP = get_uptime(); \ 07462 switch (src) { \ 07463 case HARDWARE: \ 07464 (m_ptr)->NOTIFY_ARG = priv(dst_ptr)->s_int_pending; \ 07465 priv(dst_ptr)->s_int_pending = 0; \ 07466 break; \ 07467 case SYSTEM: \ 07468 (m_ptr)->NOTIFY_ARG = priv(dst_ptr)->s_sig_pending; \ 07469 priv(dst_ptr)->s_sig_pending = 0; \ 07470 break; \ 07471 } 07472 07473 #define CopyMess(s,sp,sm,dp,dm) \ 07474 cp_mess(s, (sp)->p_memmap[D].mem_phys, \ 07475 (vir_bytes)sm, (dp)->p_memmap[D].mem_phys, (vir_bytes)dm) 07476 File: Page: 724 kernel/proc.c 07477 /*===========================================================================* 07478 * sys_call * 07479 *===========================================================================*/ 07480 PUBLIC int sys_call(call_nr, src_dst, m_ptr) 07481 int call_nr; /* system call number and flags */ 07482 int src_dst; /* src to receive from or dst to send to */ 07483 message *m_ptr; /* pointer to message in the caller's space */ 07484 { 07485 /* System calls are done by trapping to the kernel with an INT instruction. 07486 * The trap is caught and sys_call() is called to send or receive a message 07487 * (or both). The caller is always given by 'proc_ptr'. 07488 */ 07489 register struct proc *caller_ptr = proc_ptr; /* get pointer to caller */ 07490 int function = call_nr & SYSCALL_FUNC; /* get system call function */ 07491 unsigned flags = call_nr & SYSCALL_FLAGS; /* get flags */ 07492 int mask_entry; /* bit to check in send mask */ 07493 int result; /* the system call's result */ 07494 vir_clicks vlo, vhi; /* virtual clicks containing message to send */ 07495 07496 /* Check if the process has privileges for the requested call. Calls to the 07497 * kernel may only be SENDREC, because tasks always reply and may not block 07498 * if the caller doesn't do receive(). 07499 */ 07500 if (! (priv(caller_ptr)->s_trap_mask & (1 << function)) || 07501 (iskerneln(src_dst) && function != SENDREC 07502 && function != RECEIVE)) { 07503 kprintf("sys_call: trap %d not allowed, caller %d, src_dst %d\n", 07504 function, proc_nr(caller_ptr), src_dst); 07505 return(ECALLDENIED); /* trap denied by mask or kernel */ 07506 } 07507 07508 /* Require a valid source and/ or destination process, unless echoing. */ 07509 if (! (isokprocn(src_dst) || src_dst == ANY || function == ECHO)) { 07510 kprintf("sys_call: invalid src_dst, src_dst %d, caller %d\n", 07511 src_dst, proc_nr(caller_ptr)); 07512 return(EBADSRCDST); /* invalid process number */ 07513 } 07514 07515 /* If the call involves a message buffer, i.e., for SEND, RECEIVE, SENDREC, 07516 * or ECHO, check the message pointer. This check allows a message to be 07517 * anywhere in data or stack or gap. It will have to be made more elaborate 07518 * for machines which don't have the gap mapped. 07519 */ 07520 if (function & CHECK_PTR) { 07521 vlo = (vir_bytes) m_ptr >> CLICK_SHIFT; 07522 vhi = ((vir_bytes) m_ptr + MESS_SIZE - 1) >> CLICK_SHIFT; 07523 if (vlo < caller_ptr->p_memmap[D].mem_vir || vlo > vhi || 07524 vhi >= caller_ptr->p_memmap[S].mem_vir + 07525 caller_ptr->p_memmap[S].mem_len) { 07526 kprintf("sys_call: invalid message pointer, trap %d, caller %d\n", 07527 function, proc_nr(caller_ptr)); 07528 return(EFAULT); /* invalid message pointer */ 07529 } 07530 } 07531 07532 /* If the call is to send to a process, i.e., for SEND, SENDREC or NOTIFY, 07533 * verify that the caller is allowed to send to the given destination and 07534 * that the destination is still alive. 07535 */ 07536 if (function & CHECK_DST) { File: Page: 725 kernel/proc.c 07537 if (! get_sys_bit(priv(caller_ptr)->s_ipc_to, nr_to_id(src_dst))) { 07538 kprintf("sys_call: ipc mask denied %d sending to %d\n", 07539 proc_nr(caller_ptr), src_dst); 07540 return(ECALLDENIED); /* call denied by ipc mask */ 07541 } 07542 07543 if (isemptyn(src_dst) && !shutdown_started) { 07544 kprintf("sys_call: dead dest; %d, %d, %d\n", 07545 function, proc_nr(caller_ptr), src_dst); 07546 return(EDEADDST); /* cannot send to the dead */ 07547 } 07548 } 07549 07550 /* Now check if the call is known and try to perform the request. The only 07551 * system calls that exist in MINIX are sending and receiving messages. 07552 * - SENDREC: combines SEND and RECEIVE in a single system call 07553 * - SEND: sender blocks until its message has been delivered 07554 * - RECEIVE: receiver blocks until an acceptable message has arrived 07555 * - NOTIFY: nonblocking call; deliver notification or mark pending 07556 * - ECHO: nonblocking call; directly echo back the message 07557 */ 07558 switch(function) { 07559 case SENDREC: 07560 /* A flag is set so that notifications cannot interrupt SENDREC. */ 07561 priv(caller_ptr)->s_flags |= SENDREC_BUSY; 07562 /* fall through */ 07563 case SEND: 07564 result = mini_send(caller_ptr, src_dst, m_ptr, flags); 07565 if (function == SEND || result != OK) { 07566 break; /* done, or SEND failed */ 07567 } /* fall through for SENDREC */ 07568 case RECEIVE: 07569 if (function == RECEIVE) 07570 priv(caller_ptr)->s_flags &= ~SENDREC_BUSY; 07571 result = mini_receive(caller_ptr, src_dst, m_ptr, flags); 07572 break; 07573 case NOTIFY: 07574 result = mini_notify(caller_ptr, src_dst); 07575 break; 07576 case ECHO: 07577 CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, caller_ptr, m_ptr); 07578 result = OK; 07579 break; 07580 default: 07581 result = EBADCALL; /* illegal system call */ 07582 } 07583 07584 /* Now, return the result of the system call to the caller. */ 07585 return(result); 07586 } 07588 /*===========================================================================* 07589 * mini_send * 07590 *===========================================================================*/ 07591 PRIVATE int mini_send(caller_ptr, dst, m_ptr, flags) 07592 register struct proc *caller_ptr; /* who is trying to send a message? */ 07593 int dst; /* to whom is message being sent? */ 07594 message *m_ptr; /* pointer to message buffer */ 07595 unsigned flags; /* system call flags */ 07596 { File: Page: 726 kernel/proc.c 07597 /* Send a message from 'caller_ptr' to 'dst'. If 'dst' is blocked waiting 07598 * for this message, copy the message to it and unblock 'dst'. If 'dst' is 07599 * not waiting at all, or is waiting for another source, queue 'caller_ptr'. 07600 */ 07601 register struct proc *dst_ptr = proc_addr(dst); 07602 register struct proc **xpp; 07603 register struct proc *xp; 07604 07605 /* Check for deadlock by 'caller_ptr' and 'dst' sending to each other. */ 07606 xp = dst_ptr; 07607 while (xp->p_rts_flags & SENDING) { /* check while sending */ 07608 xp = proc_addr(xp->p_sendto); /* get xp's destination */ 07609 if (xp == caller_ptr) return(ELOCKED); /* deadlock if cyclic */ 07610 } 07611 07612 /* Check if 'dst' is blocked waiting for this message. The destination's 07613 * SENDING flag may be set when its SENDREC call blocked while sending. 07614 */ 07615 if ( (dst_ptr->p_rts_flags & (RECEIVING | SENDING)) == RECEIVING && 07616 (dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) { 07617 /* Destination is indeed waiting for this message. */ 07618 CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, dst_ptr, 07619 dst_ptr->p_messbuf); 07620 if ((dst_ptr->p_rts_flags &= ~RECEIVING) == 0) enqueue(dst_ptr); 07621 } else if ( ! (flags & NON_BLOCKING)) { 07622 /* Destination is not waiting. Block and dequeue caller. */ 07623 caller_ptr->p_messbuf = m_ptr; 07624 if (caller_ptr->p_rts_flags == 0) dequeue(caller_ptr); 07625 caller_ptr->p_rts_flags |= SENDING; 07626 caller_ptr->p_sendto = dst; 07627 07628 /* Process is now blocked. Put in on the destination's queue. */ 07629 xpp = &dst_ptr->p_caller_q; /* find end of list */ 07630 while (*xpp != NIL_PROC) xpp = &(*xpp)->p_q_link; 07631 *xpp = caller_ptr; /* add caller to end */ 07632 caller_ptr->p_q_link = NIL_PROC; /* mark new end of list */ 07633 } else { 07634 return(ENOTREADY); 07635 } 07636 return(OK); 07637 } 07639 /*===========================================================================* 07640 * mini_receive * 07641 *===========================================================================*/ 07642 PRIVATE int mini_receive(caller_ptr, src, m_ptr, flags) 07643 register struct proc *caller_ptr; /* process trying to get message */ 07644 int src; /* which message source is wanted */ 07645 message *m_ptr; /* pointer to message buffer */ 07646 unsigned flags; /* system call flags */ 07647 { 07648 /* A process or task wants to get a message. If a message is already queued, 07649 * acquire it and deblock the sender. If no message from the desired source 07650 * is available block the caller, unless the flags don't allow blocking. 07651 */ 07652 register struct proc **xpp; 07653 register struct notification **ntf_q_pp; 07654 message m; 07655 int bit_nr; 07656 sys_map_t *map; File: Page: 727 kernel/proc.c 07657 bitchunk_t *chunk; 07658 int i, src_id, src_proc_nr; 07659 07660 /* Check to see if a message from desired source is already available. 07661 * The caller's SENDING flag may be set if SENDREC couldn't send. If it is 07662 * set, the process should be blocked. 07663 */ 07664 if (!(caller_ptr->p_rts_flags & SENDING)) { 07665 07666 /* Check if there are pending notifications, except for SENDREC. */ 07667 if (! (priv(caller_ptr)->s_flags & SENDREC_BUSY)) { 07668 07669 map = &priv(caller_ptr)->s_notify_pending; 07670 for (chunk=&map->chunk[0]; chunk<&map->chunk[NR_SYS_CHUNKS]; chunk++) { 07671 07672 /* Find a pending notification from the requested source. */ 07673 if (! *chunk) continue; /* no bits in chunk */ 07674 for (i=0; ! (*chunk & (1<chunk[0]) * BITCHUNK_BITS + i; 07676 if (src_id >= NR_SYS_PROCS) break; /* out of range */ 07677 src_proc_nr = id_to_nr(src_id); /* get source proc */ 07678 if (src!=ANY && src!=src_proc_nr) continue; /* source not ok */ 07679 *chunk &= ~(1 << i); /* no longer pending */ 07680 07681 /* Found a suitable source, deliver the notification message. */ 07682 BuildMess(&m, src_proc_nr, caller_ptr); /* assemble message */ 07683 CopyMess(src_proc_nr, proc_addr(HARDWARE), &m, caller_ptr, m_ptr); 07684 return(OK); /* report success */ 07685 } 07686 } 07687 07688 /* Check caller queue. Use pointer pointers to keep code simple. */ 07689 xpp = &caller_ptr->p_caller_q; 07690 while (*xpp != NIL_PROC) { 07691 if (src == ANY || src == proc_nr(*xpp)) { 07692 /* Found acceptable message. Copy it and update status. */ 07693 CopyMess((*xpp)->p_nr, *xpp, (*xpp)->p_messbuf, caller_ptr, m_ptr); 07694 if (((*xpp)->p_rts_flags &= ~SENDING) == 0) enqueue(*xpp); 07695 *xpp = (*xpp)->p_q_link; /* remove from queue */ 07696 return(OK); /* report success */ 07697 } 07698 xpp = &(*xpp)->p_q_link; /* proceed to next */ 07699 } 07700 } 07701 07702 /* No suitable message is available or the caller couldn't send in SENDREC. 07703 * Block the process trying to receive, unless the flags tell otherwise. 07704 */ 07705 if ( ! (flags & NON_BLOCKING)) { 07706 caller_ptr->p_getfrom = src; 07707 caller_ptr->p_messbuf = m_ptr; 07708 if (caller_ptr->p_rts_flags == 0) dequeue(caller_ptr); 07709 caller_ptr->p_rts_flags |= RECEIVING; 07710 return(OK); 07711 } else { 07712 return(ENOTREADY); 07713 } 07714 } File: Page: 728 kernel/proc.c 07716 /*===========================================================================* 07717 * mini_notify * 07718 *===========================================================================*/ 07719 PRIVATE int mini_notify(caller_ptr, dst) 07720 register struct proc *caller_ptr; /* sender of the notification */ 07721 int dst; /* which process to notify */ 07722 { 07723 register struct proc *dst_ptr = proc_addr(dst); 07724 int src_id; /* source id for late delivery */ 07725 message m; /* the notification message */ 07726 07727 /* Check to see if target is blocked waiting for this message. A process 07728 * can be both sending and receiving during a SENDREC system call. 07729 */ 07730 if ((dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING && 07731 ! (priv(dst_ptr)->s_flags & SENDREC_BUSY) && 07732 (dst_ptr->p_getfrom == ANY || dst_ptr->p_getfrom == caller_ptr->p_nr)) { 07733 07734 /* Destination is indeed waiting for a message. Assemble a notification 07735 * message and deliver it. Copy from pseudo-source HARDWARE, since the 07736 * message is in the kernel's address space. 07737 */ 07738 BuildMess(&m, proc_nr(caller_ptr), dst_ptr); 07739 CopyMess(proc_nr(caller_ptr), proc_addr(HARDWARE), &m, 07740 dst_ptr, dst_ptr->p_messbuf); 07741 dst_ptr->p_rts_flags &= ~RECEIVING; /* deblock destination */ 07742 if (dst_ptr->p_rts_flags == 0) enqueue(dst_ptr); 07743 return(OK); 07744 } 07745 07746 /* Destination is not ready to receive the notification. Add it to the 07747 * bit map with pending notifications. Note the indirectness: the system id 07748 * instead of the process number is used in the pending bit map. 07749 */ 07750 src_id = priv(caller_ptr)->s_id; 07751 set_sys_bit(priv(dst_ptr)->s_notify_pending, src_id); 07752 return(OK); 07753 } 07755 /*===========================================================================* 07756 * lock_notify * 07757 *===========================================================================*/ 07758 PUBLIC int lock_notify(src, dst) 07759 int src; /* sender of the notification */ 07760 int dst; /* who is to be notified */ 07761 { 07762 /* Safe gateway to mini_notify() for tasks and interrupt handlers. The sender 07763 * is explicitly given to prevent confusion where the call comes from. MINIX 07764 * kernel is not reentrant, which means to interrupts are disabled after 07765 * the first kernel entry (hardware interrupt, trap, or exception). Locking 07766 * is done by temporarily disabling interrupts. 07767 */ 07768 int result; 07769 07770 /* Exception or interrupt occurred, thus already locked. */ 07771 if (k_reenter >= 0) { 07772 result = mini_notify(proc_addr(src), dst); 07773 } 07774 07775 /* Call from task level, locking is required. */ File: Page: 729 kernel/proc.c 07776 else { 07777 lock(0, "notify"); 07778 result = mini_notify(proc_addr(src), dst); 07779 unlock(0); 07780 } 07781 return(result); 07782 } 07784 /*===========================================================================* 07785 * enqueue * 07786 *===========================================================================*/ 07787 PRIVATE void enqueue(rp) 07788 register struct proc *rp; /* this process is now runnable */ 07789 { 07790 /* Add 'rp' to one of the queues of runnable processes. This function is 07791 * responsible for inserting a process into one of the scheduling queues. 07792 * The mechanism is implemented here. The actual scheduling policy is 07793 * defined in sched() and pick_proc(). 07794 */ 07795 int q; /* scheduling queue to use */ 07796 int front; /* add to front or back */ 07797 07798 /* Determine where to insert to process. */ 07799 sched(rp, &q, &front); 07800 07801 /* Now add the process to the queue. */ 07802 if (rdy_head[q] == NIL_PROC) { /* add to empty queue */ 07803 rdy_head[q] = rdy_tail[q] = rp; /* create a new queue */ 07804 rp->p_nextready = NIL_PROC; /* mark new end */ 07805 } 07806 else if (front) { /* add to head of queue */ 07807 rp->p_nextready = rdy_head[q]; /* chain head of queue */ 07808 rdy_head[q] = rp; /* set new queue head */ 07809 } 07810 else { /* add to tail of queue */ 07811 rdy_tail[q]->p_nextready = rp; /* chain tail of queue */ 07812 rdy_tail[q] = rp; /* set new queue tail */ 07813 rp->p_nextready = NIL_PROC; /* mark new end */ 07814 } 07815 07816 /* Now select the next process to run. */ 07817 pick_proc(); 07818 } 07820 /*===========================================================================* 07821 * dequeue * 07822 *===========================================================================*/ 07823 PRIVATE void dequeue(rp) 07824 register struct proc *rp; /* this process is no longer runnable */ 07825 { 07826 /* A process must be removed from the scheduling queues, for example, because 07827 * it has blocked. If the currently active process is removed, a new process 07828 * is picked to run by calling pick_proc(). 07829 */ 07830 register int q = rp->p_priority; /* queue to use */ 07831 register struct proc **xpp; /* iterate over queue */ 07832 register struct proc *prev_xp; 07833 07834 /* Side-effect for kernel: check if the task's stack still is ok? */ 07835 if (iskernelp(rp)) { File: Page: 730 kernel/proc.c 07836 if (*priv(rp)->s_stack_guard != STACK_GUARD) 07837 panic("stack overrun by task", proc_nr(rp)); 07838 } 07839 07840 /* Now make sure that the process is not in its ready queue. Remove the 07841 * process if it is found. A process can be made unready even if it is not 07842 * running by being sent a signal that kills it. 07843 */ 07844 prev_xp = NIL_PROC; 07845 for (xpp = &rdy_head[q]; *xpp != NIL_PROC; xpp = &(*xpp)->p_nextready) { 07846 07847 if (*xpp == rp) { /* found process to remove */ 07848 *xpp = (*xpp)->p_nextready; /* replace with next chain */ 07849 if (rp == rdy_tail[q]) /* queue tail removed */ 07850 rdy_tail[q] = prev_xp; /* set new tail */ 07851 if (rp == proc_ptr || rp == next_ptr) /* active process removed */ 07852 pick_proc(); /* pick new process to run */ 07853 break; 07854 } 07855 prev_xp = *xpp; /* save previous in chain */ 07856 } 07857 } 07859 /*===========================================================================* 07860 * sched * 07861 *===========================================================================*/ 07862 PRIVATE void sched(rp, queue, front) 07863 register struct proc *rp; /* process to be scheduled */ 07864 int *queue; /* return: queue to use */ 07865 int *front; /* return: front or back */ 07866 { 07867 /* This function determines the scheduling policy. It is called whenever a 07868 * process must be added to one of the scheduling queues to decide where to 07869 * insert it. As a side-effect the process' priority may be updated. 07870 */ 07871 static struct proc *prev_ptr = NIL_PROC; /* previous without time */ 07872 int time_left = (rp->p_ticks_left > 0); /* quantum fully consumed */ 07873 int penalty = 0; /* change in priority */ 07874 07875 /* Check whether the process has time left. Otherwise give a new quantum 07876 * and possibly raise the priority. Processes using multiple quantums 07877 * in a row get a lower priority to catch infinite loops in high priority 07878 * processes (system servers and drivers). 07879 */ 07880 if ( ! time_left) { /* quantum consumed ? */ 07881 rp->p_ticks_left = rp->p_quantum_size; /* give new quantum */ 07882 if (prev_ptr == rp) penalty ++; /* catch infinite loops */ 07883 else penalty --; /* give slow way back */ 07884 prev_ptr = rp; /* store ptr for next */ 07885 } 07886 07887 /* Determine the new priority of this process. The bounds are determined 07888 * by IDLE's queue and the maximum priority of this process. Kernel tasks 07889 * and the idle process are never changed in priority. 07890 */ 07891 if (penalty != 0 && ! iskernelp(rp)) { 07892 rp->p_priority += penalty; /* update with penalty */ 07893 if (rp->p_priority < rp->p_max_priority) /* check upper bound */ 07894 rp->p_priority=rp->p_max_priority; 07895 else if (rp->p_priority > IDLE_Q-1) /* check lower bound */ File: Page: 731 kernel/proc.c 07896 rp->p_priority = IDLE_Q-1; 07897 } 07898 07899 /* If there is time left, the process is added to the front of its queue, 07900 * so that it can immediately run. The queue to use simply is always the 07901 * process' current priority. 07902 */ 07903 *queue = rp->p_priority; 07904 *front = time_left; 07905 } 07907 /*===========================================================================* 07908 * pick_proc * 07909 *===========================================================================*/ 07910 PRIVATE void pick_proc() 07911 { 07912 /* Decide who to run now. A new process is selected by setting 'next_ptr'. 07913 * When a billable process is selected, record it in 'bill_ptr', so that the 07914 * clock task can tell who to bill for system time. 07915 */ 07916 register struct proc *rp; /* process to run */ 07917 int q; /* iterate over queues */ 07918 07919 /* Check each of the scheduling queues for ready processes. The number of 07920 * queues is defined in proc.h, and priorities are set in the image table. 07921 * The lowest queue contains IDLE, which is always ready. 07922 */ 07923 for (q=0; q < NR_SCHED_QUEUES; q++) { 07924 if ( (rp = rdy_head[q]) != NIL_PROC) { 07925 next_ptr = rp; /* run process 'rp' next */ 07926 if (priv(rp)->s_flags & BILLABLE) 07927 bill_ptr = rp; /* bill for system time */ 07928 return; 07929 } 07930 } 07931 } 07933 /*===========================================================================* 07934 * lock_send * 07935 *===========================================================================*/ 07936 PUBLIC int lock_send(dst, m_ptr) 07937 int dst; /* to whom is message being sent? */ 07938 message *m_ptr; /* pointer to message buffer */ 07939 { 07940 /* Safe gateway to mini_send() for tasks. */ 07941 int result; 07942 lock(2, "send"); 07943 result = mini_send(proc_ptr, dst, m_ptr, NON_BLOCKING); 07944 unlock(2); 07945 return(result); 07946 } 07948 /*===========================================================================* 07949 * lock_enqueue * 07950 *===========================================================================*/ 07951 PUBLIC void lock_enqueue(rp) 07952 struct proc *rp; /* this process is now runnable */ 07953 { 07954 /* Safe gateway to enqueue() for tasks. */ 07955 lock(3, "enqueue"); File: Page: 732 kernel/proc.c 07956 enqueue(rp); 07957 unlock(3); 07958 } 07960 /*===========================================================================* 07961 * lock_dequeue * 07962 *===========================================================================*/ 07963 PUBLIC void lock_dequeue(rp) 07964 struct proc *rp; /* this process is no longer runnable */ 07965 { 07966 /* Safe gateway to dequeue() for tasks. */ 07967 lock(4, "dequeue"); 07968 dequeue(rp); 07969 unlock(4); 07970 } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/exception.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 08000 /* This file contains a simple exception handler. Exceptions in user 08001 * processes are converted to signals. Exceptions in a kernel task cause 08002 * a panic. 08003 */ 08004 08005 #include "kernel.h" 08006 #include 08007 #include "proc.h" 08008 08009 /*===========================================================================* 08010 * exception * 08011 *===========================================================================*/ 08012 PUBLIC void exception(vec_nr) 08013 unsigned vec_nr; 08014 { 08015 /* An exception or unexpected interrupt has occurred. */ 08016 08017 struct ex_s { 08018 char *msg; 08019 int signum; 08020 int minprocessor; 08021 }; 08022 static struct ex_s ex_data[] = { 08023 { "Divide error", SIGFPE, 86 }, 08024 { "Debug exception", SIGTRAP, 86 }, 08025 { "Nonmaskable interrupt", SIGBUS, 86 }, 08026 { "Breakpoint", SIGEMT, 86 }, 08027 { "Overflow", SIGFPE, 86 }, 08028 { "Bounds check", SIGFPE, 186 }, 08029 { "Invalid opcode", SIGILL, 186 }, 08030 { "Coprocessor not available", SIGFPE, 186 }, 08031 { "Double fault", SIGBUS, 286 }, 08032 { "Copressor segment overrun", SIGSEGV, 286 }, 08033 { "Invalid TSS", SIGSEGV, 286 }, 08034 { "Segment not present", SIGSEGV, 286 }, File: Page: 733 kernel/exception.c 08035 { "Stack exception", SIGSEGV, 286 }, /* STACK_FAULT already used */ 08036 { "General protection", SIGSEGV, 286 }, 08037 { "Page fault", SIGSEGV, 386 }, /* not close */ 08038 { NIL_PTR, SIGILL, 0 }, /* probably software trap */ 08039 { "Coprocessor error", SIGFPE, 386 }, 08040 }; 08041 register struct ex_s *ep; 08042 struct proc *saved_proc; 08043 08044 /* Save proc_ptr, because it may be changed by debug statements. */ 08045 saved_proc = proc_ptr; 08046 08047 ep = &ex_data[vec_nr]; 08048 08049 if (vec_nr == 2) { /* spurious NMI on some machines */ 08050 kprintf("got spurious NMI\n"); 08051 return; 08052 } 08053 08054 /* If an exception occurs while running a process, the k_reenter variable 08055 * will be zero. Exceptions in interrupt handlers or system traps will make 08056 * k_reenter larger than zero. 08057 */ 08058 if (k_reenter == 0 && ! iskernelp(saved_proc)) { 08059 cause_sig(proc_nr(saved_proc), ep->signum); 08060 return; 08061 } 08062 08063 /* Exception in system code. This is not supposed to happen. */ 08064 if (ep->msg == NIL_PTR || machine.processor < ep->minprocessor) 08065 kprintf("\nIntel-reserved exception %d\n", vec_nr); 08066 else 08067 kprintf("\n%s\n", ep->msg); 08068 kprintf("k_reenter = %d ", k_reenter); 08069 kprintf("process %d (%s), ", proc_nr(saved_proc), saved_proc->p_name); 08070 kprintf("pc = %u: 0x%x", (unsigned) saved_proc->p_reg.cs, 08071 (unsigned) saved_proc->p_reg.pc); 08072 08073 panic("exception in a kernel task", NO_NUM); 08074 } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/i8259.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 08100 /* This file contains routines for initializing the 8259 interrupt controller: 08101 * put_irq_handler: register an interrupt handler 08102 * rm_irq_handler: deregister an interrupt handler 08103 * intr_handle: handle a hardware interrupt 08104 * intr_init: initialize the interrupt controller(s) 08105 */ 08106 08107 #include "kernel.h" 08108 #include "proc.h" 08109 #include File: Page: 734 kernel/i8259.c 08110 08111 #define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */ 08112 #define ICW1_PC 0x13 /* edge triggered, no cascade, need ICW4 */ 08113 #define ICW1_PS 0x19 /* level triggered, cascade, need ICW4 */ 08114 #define ICW4_AT_SLAVE 0x01 /* not SFNM, not buffered, normal EOI, 8086 */ 08115 #define ICW4_AT_MASTER 0x05 /* not SFNM, not buffered, normal EOI, 8086 */ 08116 #define ICW4_PC_SLAVE 0x09 /* not SFNM, buffered, normal EOI, 8086 */ 08117 #define ICW4_PC_MASTER 0x0D /* not SFNM, buffered, normal EOI, 8086 */ 08118 08119 #define set_vec(nr, addr) ((void)0) 08120 08121 /*===========================================================================* 08122 * intr_init * 08123 *===========================================================================*/ 08124 PUBLIC void intr_init(mine) 08125 int mine; 08126 { 08127 /* Initialize the 8259s, finishing with all interrupts disabled. This is 08128 * only done in protected mode, in real mode we don't touch the 8259s, but 08129 * use the BIOS locations instead. The flag "mine" is set if the 8259s are 08130 * to be programmed for MINIX, or to be reset to what the BIOS expects. 08131 */ 08132 int i; 08133 08134 intr_disable(); 08135 08136 /* The AT and newer PS/2 have two interrupt controllers, one master, 08137 * one slaved at IRQ 2. (We don't have to deal with the PC that 08138 * has just one controller, because it must run in real mode.) 08139 */ 08140 outb(INT_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT); 08141 outb(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC); 08142 /* ICW2 for master */ 08143 outb(INT_CTLMASK, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */ 08144 outb(INT_CTLMASK, ICW4_AT_MASTER); 08145 outb(INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */ 08146 outb(INT2_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT); 08147 outb(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC); 08148 /* ICW2 for slave */ 08149 outb(INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */ 08150 outb(INT2_CTLMASK, ICW4_AT_SLAVE); 08151 outb(INT2_CTLMASK, ~0); /* IRQ 8-15 mask */ 08152 08153 /* Copy the BIOS vectors from the BIOS to the Minix location, so we 08154 * can still make BIOS calls without reprogramming the i8259s. 08155 */ 08156 phys_copy(BIOS_VECTOR(0) * 4L, VECTOR(0) * 4L, 8 * 4L); 08157 } 08159 /*===========================================================================* 08160 * put_irq_handler * 08161 *===========================================================================*/ 08162 PUBLIC void put_irq_handler(hook, irq, handler) 08163 irq_hook_t *hook; 08164 int irq; 08165 irq_handler_t handler; 08166 { 08167 /* Register an interrupt handler. */ 08168 int id; 08169 irq_hook_t **line; File: Page: 735 kernel/i8259.c 08170 08171 if (irq < 0 || irq >= NR_IRQ_VECTORS) 08172 panic("invalid call to put_irq_handler", irq); 08173 08174 line = &irq_handlers[irq]; 08175 id = 1; 08176 while (*line != NULL) { 08177 if (hook == *line) return; /* extra initialization */ 08178 line = &(*line)->next; 08179 id <<= 1; 08180 } 08181 if (id == 0) panic("Too many handlers for irq", irq); 08182 08183 hook->next = NULL; 08184 hook->handler = handler; 08185 hook->irq = irq; 08186 hook->id = id; 08187 *line = hook; 08188 08189 irq_use |= 1 << irq; 08190 } 08192 /*===========================================================================* 08193 * rm_irq_handler * 08194 *===========================================================================*/ 08195 PUBLIC void rm_irq_handler(hook) 08196 irq_hook_t *hook; 08197 { 08198 /* Unregister an interrupt handler. */ 08199 int irq = hook->irq; 08200 int id = hook->id; 08201 irq_hook_t **line; 08202 08203 if (irq < 0 || irq >= NR_IRQ_VECTORS) 08204 panic("invalid call to rm_irq_handler", irq); 08205 08206 line = &irq_handlers[irq]; 08207 while (*line != NULL) { 08208 if ((*line)->id == id) { 08209 (*line) = (*line)->next; 08210 if (! irq_handlers[irq]) irq_use &= ~(1 << irq); 08211 return; 08212 } 08213 line = &(*line)->next; 08214 } 08215 /* When the handler is not found, normally return here. */ 08216 } 08218 /*===========================================================================* 08219 * intr_handle * 08220 *===========================================================================*/ 08221 PUBLIC void intr_handle(hook) 08222 irq_hook_t *hook; 08223 { 08224 /* Call the interrupt handlers for an interrupt with the given hook list. 08225 * The assembly part of the handler has already masked the IRQ, reenabled the 08226 * controller(s) and enabled interrupts. 08227 */ 08228 08229 /* Call list of handlers for an IRQ. */ File: Page: 736 kernel/i8259.c 08230 while (hook != NULL) { 08231 /* For each handler in the list, mark it active by setting its ID bit, 08232 * call the function, and unmark it if the function returns true. 08233 */ 08234 irq_actids[hook->irq] |= hook->id; 08235 if ((*hook->handler)(hook)) irq_actids[hook->irq] &= ~hook->id; 08236 hook = hook->next; 08237 } 08238 08239 /* The assembly code will now disable interrupts, unmask the IRQ if and only 08240 * if all active ID bits are cleared, and restart a process. 08241 */ 08242 } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/protect.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 08300 /* This file contains code for initialization of protected mode, to initialize 08301 * code and data segment descriptors, and to initialize global descriptors 08302 * for local descriptors in the process table. 08303 */ 08304 08305 #include "kernel.h" 08306 #include "proc.h" 08307 #include "protect.h" 08308 08309 #define INT_GATE_TYPE (INT_286_GATE | DESC_386_BIT) 08310 #define TSS_TYPE (AVL_286_TSS | DESC_386_BIT) 08311 08312 struct desctableptr_s { 08313 char limit[sizeof(u16_t)]; 08314 char base[sizeof(u32_t)]; /* really u24_t + pad for 286 */ 08315 }; 08316 08317 struct gatedesc_s { 08318 u16_t offset_low; 08319 u16_t selector; 08320 u8_t pad; /* |000|XXXXX| ig & trpg, |XXXXXXXX| task g */ 08321 u8_t p_dpl_type; /* |P|DL|0|TYPE| */ 08322 u16_t offset_high; 08323 }; 08324 08325 struct tss_s { 08326 reg_t backlink; 08327 reg_t sp0; /* stack pointer to use during interrupt */ 08328 reg_t ss0; /* " segment " " " " */ 08329 reg_t sp1; 08330 reg_t ss1; 08331 reg_t sp2; 08332 reg_t ss2; 08333 reg_t cr3; 08334 reg_t ip; 08335 reg_t flags; 08336 reg_t ax; 08337 reg_t cx; 08338 reg_t dx; 08339 reg_t bx; File: Page: 737 kernel/protect.c 08340 reg_t sp; 08341 reg_t bp; 08342 reg_t si; 08343 reg_t di; 08344 reg_t es; 08345 reg_t cs; 08346 reg_t ss; 08347 reg_t ds; 08348 reg_t fs; 08349 reg_t gs; 08350 reg_t ldt; 08351 u16_t trap; 08352 u16_t iobase; 08353 /* u8_t iomap[0]; */ 08354 }; 08355 08356 PUBLIC struct segdesc_s gdt[GDT_SIZE]; /* used in klib.s and mpx.s */ 08357 PRIVATE struct gatedesc_s idt[IDT_SIZE]; /* zero-init so none present */ 08358 PUBLIC struct tss_s tss; /* zero init */ 08359 08360 FORWARD _PROTOTYPE( void int_gate, (unsigned vec_nr, vir_bytes offset, 08361 unsigned dpl_type) ); 08362 FORWARD _PROTOTYPE( void sdesc, (struct segdesc_s *segdp, phys_bytes base, 08363 vir_bytes size) ); 08364 08365 /*===========================================================================* 08366 * prot_init * 08367 *===========================================================================*/ 08368 PUBLIC void prot_init() 08369 { 08370 /* Set up tables for protected mode. 08371 * All GDT slots are allocated at compile time. 08372 */ 08373 struct gate_table_s *gtp; 08374 struct desctableptr_s *dtp; 08375 unsigned ldt_index; 08376 register struct proc *rp; 08377 08378 static struct gate_table_s { 08379 _PROTOTYPE( void (*gate), (void) ); 08380 unsigned char vec_nr; 08381 unsigned char privilege; 08382 } 08383 gate_table[] = { 08384 { divide_error, DIVIDE_VECTOR, INTR_PRIVILEGE }, 08385 { single_step_exception, DEBUG_VECTOR, INTR_PRIVILEGE }, 08386 { nmi, NMI_VECTOR, INTR_PRIVILEGE }, 08387 { breakpoint_exception, BREAKPOINT_VECTOR, USER_PRIVILEGE }, 08388 { overflow, OVERFLOW_VECTOR, USER_PRIVILEGE }, 08389 { bounds_check, BOUNDS_VECTOR, INTR_PRIVILEGE }, 08390 { inval_opcode, INVAL_OP_VECTOR, INTR_PRIVILEGE }, 08391 { copr_not_available, COPROC_NOT_VECTOR, INTR_PRIVILEGE }, 08392 { double_fault, DOUBLE_FAULT_VECTOR, INTR_PRIVILEGE }, 08393 { copr_seg_overrun, COPROC_SEG_VECTOR, INTR_PRIVILEGE }, 08394 { inval_tss, INVAL_TSS_VECTOR, INTR_PRIVILEGE }, 08395 { segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE }, 08396 { stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE }, 08397 { general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE }, 08398 { page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE }, 08399 { copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE }, File: Page: 738 kernel/protect.c 08400 { hwint00, VECTOR( 0), INTR_PRIVILEGE }, 08401 { hwint01, VECTOR( 1), INTR_PRIVILEGE }, 08402 { hwint02, VECTOR( 2), INTR_PRIVILEGE }, 08403 { hwint03, VECTOR( 3), INTR_PRIVILEGE }, 08404 { hwint04, VECTOR( 4), INTR_PRIVILEGE }, 08405 { hwint05, VECTOR( 5), INTR_PRIVILEGE }, 08406 { hwint06, VECTOR( 6), INTR_PRIVILEGE }, 08407 { hwint07, VECTOR( 7), INTR_PRIVILEGE }, 08408 { hwint08, VECTOR( 8), INTR_PRIVILEGE }, 08409 { hwint09, VECTOR( 9), INTR_PRIVILEGE }, 08410 { hwint10, VECTOR(10), INTR_PRIVILEGE }, 08411 { hwint11, VECTOR(11), INTR_PRIVILEGE }, 08412 { hwint12, VECTOR(12), INTR_PRIVILEGE }, 08413 { hwint13, VECTOR(13), INTR_PRIVILEGE }, 08414 { hwint14, VECTOR(14), INTR_PRIVILEGE }, 08415 { hwint15, VECTOR(15), INTR_PRIVILEGE }, 08416 { s_call, SYS386_VECTOR, USER_PRIVILEGE }, /* 386 system call */ 08417 { level0_call, LEVEL0_VECTOR, TASK_PRIVILEGE }, 08418 }; 08419 08420 /* Build gdt and idt pointers in GDT where the BIOS expects them. */ 08421 dtp= (struct desctableptr_s *) &gdt[GDT_INDEX]; 08422 * (u16_t *) dtp->limit = (sizeof gdt) - 1; 08423 * (u32_t *) dtp->base = vir2phys(gdt); 08424 08425 dtp= (struct desctableptr_s *) &gdt[IDT_INDEX]; 08426 * (u16_t *) dtp->limit = (sizeof idt) - 1; 08427 * (u32_t *) dtp->base = vir2phys(idt); 08428 08429 /* Build segment descriptors for tasks and interrupt handlers. */ 08430 init_codeseg(&gdt[CS_INDEX], 08431 kinfo.code_base, kinfo.code_size, INTR_PRIVILEGE); 08432 init_dataseg(&gdt[DS_INDEX], 08433 kinfo.data_base, kinfo.data_size, INTR_PRIVILEGE); 08434 init_dataseg(&gdt[ES_INDEX], 0L, 0, TASK_PRIVILEGE); 08435 08436 /* Build scratch descriptors for functions in klib88. */ 08437 init_dataseg(&gdt[DS_286_INDEX], 0L, 0, TASK_PRIVILEGE); 08438 init_dataseg(&gdt[ES_286_INDEX], 0L, 0, TASK_PRIVILEGE); 08439 08440 /* Build local descriptors in GDT for LDT's in process table. 08441 * The LDT's are allocated at compile time in the process table, and 08442 * initialized whenever a process' map is initialized or changed. 08443 */ 08444 for (rp = BEG_PROC_ADDR, ldt_index = FIRST_LDT_INDEX; 08445 rp < END_PROC_ADDR; ++rp, ldt_index++) { 08446 init_dataseg(&gdt[ldt_index], vir2phys(rp->p_ldt), 08447 sizeof(rp->p_ldt), INTR_PRIVILEGE); 08448 gdt[ldt_index].access = PRESENT | LDT; 08449 rp->p_ldt_sel = ldt_index * DESC_SIZE; 08450 } 08451 08452 /* Build main TSS. 08453 * This is used only to record the stack pointer to be used after an 08454 * interrupt. 08455 * The pointer is set up so that an interrupt automatically saves the 08456 * current process's registers ip: cs: f: sp: ss in the correct slots in the 08457 * process table. 08458 */ 08459 tss.ss0 = DS_SELECTOR; File: Page: 739 kernel/protect.c 08460 init_dataseg(&gdt[TSS_INDEX], vir2phys(&tss), sizeof(tss), INTR_PRIVILEGE); 08461 gdt[TSS_INDEX].access = PRESENT | (INTR_PRIVILEGE << DPL_SHIFT) | TSS_TYPE; 08462 08463 /* Build descriptors for interrupt gates in IDT. */ 08464 for (gtp = &gate_table[0]; 08465 gtp < &gate_table[sizeof gate_table / sizeof gate_table[0]]; ++gtp) { 08466 int_gate(gtp->vec_nr, (vir_bytes) gtp->gate, 08467 PRESENT | INT_GATE_TYPE | (gtp->privilege << DPL_SHIFT)); 08468 } 08469 08470 /* Complete building of main TSS. */ 08471 tss.iobase = sizeof tss; /* empty i/o permissions map */ 08472 } 08474 /*===========================================================================* 08475 * init_codeseg * 08476 *===========================================================================*/ 08477 PUBLIC void init_codeseg(segdp, base, size, privilege) 08478 register struct segdesc_s *segdp; 08479 phys_bytes base; 08480 vir_bytes size; 08481 int privilege; 08482 { 08483 /* Build descriptor for a code segment. */ 08484 sdesc(segdp, base, size); 08485 segdp->access = (privilege << DPL_SHIFT) 08486 | (PRESENT | SEGMENT | EXECUTABLE | READABLE); 08487 /* CONFORMING = 0, ACCESSED = 0 */ 08488 } 08490 /*===========================================================================* 08491 * init_dataseg * 08492 *===========================================================================*/ 08493 PUBLIC void init_dataseg(segdp, base, size, privilege) 08494 register struct segdesc_s *segdp; 08495 phys_bytes base; 08496 vir_bytes size; 08497 int privilege; 08498 { 08499 /* Build descriptor for a data segment. */ 08500 sdesc(segdp, base, size); 08501 segdp->access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT | WRITEABLE); 08502 /* EXECUTABLE = 0, EXPAND_DOWN = 0, ACCESSED = 0 */ 08503 } 08505 /*===========================================================================* 08506 * sdesc * 08507 *===========================================================================*/ 08508 PRIVATE void sdesc(segdp, base, size) 08509 register struct segdesc_s *segdp; 08510 phys_bytes base; 08511 vir_bytes size; 08512 { 08513 /* Fill in the size fields (base, limit and granularity) of a descriptor. */ 08514 segdp->base_low = base; 08515 segdp->base_middle = base >> BASE_MIDDLE_SHIFT; 08516 segdp->base_high = base >> BASE_HIGH_SHIFT; 08517 08518 --size; /* convert to a limit, 0 size means 4G */ 08519 if (size > BYTE_GRAN_MAX) { File: Page: 740 kernel/protect.c 08520 segdp->limit_low = size >> PAGE_GRAN_SHIFT; 08521 segdp->granularity = GRANULAR | (size >> 08522 (PAGE_GRAN_SHIFT + GRANULARITY_SHIFT)); 08523 } else { 08524 segdp->limit_low = size; 08525 segdp->granularity = size >> GRANULARITY_SHIFT; 08526 } 08527 segdp->granularity |= DEFAULT; /* means BIG for data seg */ 08528 } 08530 /*===========================================================================* 08531 * seg2phys * 08532 *===========================================================================*/ 08533 PUBLIC phys_bytes seg2phys(seg) 08534 U16_t seg; 08535 { 08536 /* Return the base address of a segment, with seg being either a 8086 segment 08537 * register, or a 286/386 segment selector. 08538 */ 08539 phys_bytes base; 08540 struct segdesc_s *segdp; 08541 08542 if (! machine.protected) { 08543 base = hclick_to_physb(seg); 08544 } else { 08545 segdp = &gdt[seg >> 3]; 08546 base = ((u32_t) segdp->base_low << 0) 08547 | ((u32_t) segdp->base_middle << 16) 08548 | ((u32_t) segdp->base_high << 24); 08549 } 08550 return base; 08551 } 08553 /*===========================================================================* 08554 * phys2seg * 08555 *===========================================================================*/ 08556 PUBLIC void phys2seg(seg, off, phys) 08557 u16_t *seg; 08558 vir_bytes *off; 08559 phys_bytes phys; 08560 { 08561 /* Return a segment selector and offset that can be used to reach a physical 08562 * address, for use by a driver doing memory I/O in the A0000 - DFFFF range. 08563 */ 08564 *seg = FLAT_DS_SELECTOR; 08565 *off = phys; 08566 } 08568 /*===========================================================================* 08569 * int_gate * 08570 *===========================================================================*/ 08571 PRIVATE void int_gate(vec_nr, offset, dpl_type) 08572 unsigned vec_nr; 08573 vir_bytes offset; 08574 unsigned dpl_type; 08575 { 08576 /* Build descriptor for an interrupt gate. */ 08577 register struct gatedesc_s *idp; 08578 08579 idp = &idt[vec_nr]; File: Page: 741 kernel/protect.c 08580 idp->offset_low = offset; 08581 idp->selector = CS_SELECTOR; 08582 idp->p_dpl_type = dpl_type; 08583 idp->offset_high = offset >> OFFSET_HIGH_SHIFT; 08584 } 08586 /*===========================================================================* 08587 * enable_iop * 08588 *===========================================================================*/ 08589 PUBLIC void enable_iop(pp) 08590 struct proc *pp; 08591 { 08592 /* Allow a user process to use I/O instructions. Change the I/O Permission 08593 * Level bits in the psw. These specify least-privileged Current Permission 08594 * Level allowed to execute I/O instructions. Users and servers have CPL 3. 08595 * You can't have less privilege than that. Kernel has CPL 0, tasks CPL 1. 08596 */ 08597 pp->p_reg.psw |= 0x3000; 08598 } 08600 /*===========================================================================* 08601 * alloc_segments * 08602 *===========================================================================*/ 08603 PUBLIC void alloc_segments(rp) 08604 register struct proc *rp; 08605 { 08606 /* This is called at system initialization from main() and by do_newmap(). 08607 * The code has a separate function because of all hardware-dependencies. 08608 * Note that IDLE is part of the kernel and gets TASK_PRIVILEGE here. 08609 */ 08610 phys_bytes code_bytes; 08611 phys_bytes data_bytes; 08612 int privilege; 08613 08614 if (machine.protected) { 08615 data_bytes = (phys_bytes) (rp->p_memmap[S].mem_vir + 08616 rp->p_memmap[S].mem_len) << CLICK_SHIFT; 08617 if (rp->p_memmap[T].mem_len == 0) 08618 code_bytes = data_bytes; /* common I&D, poor protect */ 08619 else 08620 code_bytes = (phys_bytes) rp->p_memmap[T].mem_len << CLICK_SHIFT; 08621 privilege = (iskernelp(rp)) ? TASK_PRIVILEGE : USER_PRIVILEGE; 08622 init_codeseg(&rp->p_ldt[CS_LDT_INDEX], 08623 (phys_bytes) rp->p_memmap[T].mem_phys << CLICK_SHIFT, 08624 code_bytes, privilege); 08625 init_dataseg(&rp->p_ldt[DS_LDT_INDEX], 08626 (phys_bytes) rp->p_memmap[D].mem_phys << CLICK_SHIFT, 08627 data_bytes, privilege); 08628 rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege; 08629 rp->p_reg.gs = 08630 rp->p_reg.fs = 08631 rp->p_reg.ss = 08632 rp->p_reg.es = 08633 rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege; 08634 } else { 08635 rp->p_reg.cs = click_to_hclick(rp->p_memmap[T].mem_phys); 08636 rp->p_reg.ss = 08637 rp->p_reg.es = 08638 rp->p_reg.ds = click_to_hclick(rp->p_memmap[D].mem_phys); 08639 } File: Page: 742 kernel/protect.c 08640 } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/klib.s ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 08700 # 08701 ! Chooses between the 8086 and 386 versions of the low level kernel code. 08702 08703 #include 08704 #if _WORD_SIZE == 2 08705 #include "klib88.s" 08706 #else 08707 #include "klib386.s" 08708 #endif ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/klib386.s ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 08800 # 08801 ! sections 08802 08803 .sect .text; .sect .rom; .sect .data; .sect .bss 08804 08805 #include 08806 #include 08807 #include "const.h" 08808 #include "sconst.h" 08809 #include "protect.h" 08810 08811 ! This file contains a number of assembly code utility routines needed by the 08812 ! kernel. They are: 08813 08814 .define _monitor ! exit Minix and return to the monitor 08815 .define _int86 ! let the monitor make an 8086 interrupt call 08816 .define _cp_mess ! copies messages from source to destination 08817 .define _exit ! dummy for library routines 08818 .define __exit ! dummy for library routines 08819 .define ___exit ! dummy for library routines 08820 .define ___main ! dummy for GCC 08821 .define _phys_insw ! transfer data from (disk controller) port to memory 08822 .define _phys_insb ! likewise byte by byte 08823 .define _phys_outsw ! transfer data from memory to (disk controller) port 08824 .define _phys_outsb ! likewise byte by byte 08825 .define _enable_irq ! enable an irq at the 8259 controller 08826 .define _disable_irq ! disable an irq 08827 .define _phys_copy ! copy data from anywhere to anywhere in memory 08828 .define _phys_memset ! write pattern anywhere in memory 08829 .define _mem_rdw ! copy one word from [segment: offset] 08830 .define _reset ! reset the system 08831 .define _idle_task ! task executed when there is no work 08832 .define _level0 ! call a function at level 0 08833 .define _read_tsc ! read the cycle counter (Pentium and up) 08834 .define _read_cpu_flags ! read the cpu flags File: Page: 743 kernel/klib386.s 08835 08836 ! The routines only guarantee to preserve the registers the C compiler 08837 ! expects to be preserved (ebx, esi, edi, ebp, esp, segment registers, and 08838 ! direction bit in the flags). 08839 08840 .sect .text 08841 !*===========================================================================* 08842 !* monitor * 08843 !*===========================================================================* 08844 ! PUBLIC void monitor(); 08845 ! Return to the monitor. 08846 08847 _monitor: 08848 mov esp, (_mon_sp) ! restore monitor stack pointer 08849 o16 mov dx, SS_SELECTOR ! monitor data segment 08850 mov ds, dx 08851 mov es, dx 08852 mov fs, dx 08853 mov gs, dx 08854 mov ss, dx 08855 pop edi 08856 pop esi 08857 pop ebp 08858 o16 retf ! return to the monitor 08859 08860 08861 !*===========================================================================* 08862 !* int86 * 08863 !*===========================================================================* 08864 ! PUBLIC void int86(); 08865 _int86: 08866 cmpb (_mon_return), 0 ! is the monitor there? 08867 jnz 0f 08868 movb ah, 0x01 ! an int 13 error seems appropriate 08869 movb (_reg86+ 0), ah ! reg86.w.f = 1 (set carry flag) 08870 movb (_reg86+13), ah ! reg86.b.ah = 0x01 = "invalid command" 08871 ret 08872 0: push ebp ! save C registers 08873 push esi 08874 push edi 08875 push ebx 08876 pushf ! save flags 08877 cli ! no interruptions 08878 08879 inb INT2_CTLMASK 08880 movb ah, al 08881 inb INT_CTLMASK 08882 push eax ! save interrupt masks 08883 mov eax, (_irq_use) ! map of in-use IRQ's 08884 and eax, ~[1<irq < 8: 09123 ! if ((irq_actids[hook->irq] &= ~hook->id) == 0) 09124 ! outb(INT_CTLMASK, inb(INT_CTLMASK) & ~(1 << irq)); 09125 09126 .align 16 09127 _enable_irq: 09128 push ebp 09129 mov ebp, esp 09130 pushf 09131 cli 09132 mov eax, 8(ebp) ! hook 09133 mov ecx, 8(eax) ! irq 09134 mov eax, 12(eax) ! id bit File: Page: 748 kernel/klib386.s 09135 not eax 09136 and _irq_actids(ecx*4), eax ! clear this id bit 09137 jnz en_done ! still masked by other handlers? 09138 movb ah, ~1 09139 rolb ah, cl ! ah = ~(1 << (irq % 8)) 09140 mov edx, INT_CTLMASK ! enable irq < 8 at the master 8259 09141 cmpb cl, 8 09142 jb 0f 09143 mov edx, INT2_CTLMASK ! enable irq >= 8 at the slave 8259 09144 0: inb dx 09145 andb al, ah 09146 outb dx ! clear bit at the 8259 09147 en_done: popf 09148 leave 09149 ret 09150 09151 09152 !*==========================================================================* 09153 !* disable_irq * 09154 !*==========================================================================*/ 09155 ! PUBLIC int disable_irq(irq_hook_t *hook) 09156 ! Disable an interrupt request line by setting an 8259 bit. 09157 ! Equivalent C code for irq < 8: 09158 ! irq_actids[hook->irq] |= hook->id; 09159 ! outb(INT_CTLMASK, inb(INT_CTLMASK) | (1 << irq)); 09160 ! Returns true iff the interrupt was not already disabled. 09161 09162 .align 16 09163 _disable_irq: 09164 push ebp 09165 mov ebp, esp 09166 pushf 09167 cli 09168 mov eax, 8(ebp) ! hook 09169 mov ecx, 8(eax) ! irq 09170 mov eax, 12(eax) ! id bit 09171 or _irq_actids(ecx*4), eax ! set this id bit 09172 movb ah, 1 09173 rolb ah, cl ! ah = (1 << (irq % 8)) 09174 mov edx, INT_CTLMASK ! disable irq < 8 at the master 8259 09175 cmpb cl, 8 09176 jb 0f 09177 mov edx, INT2_CTLMASK ! disable irq >= 8 at the slave 8259 09178 0: inb dx 09179 testb al, ah 09180 jnz dis_already ! already disabled? 09181 orb al, ah 09182 outb dx ! set bit at the 8259 09183 mov eax, 1 ! disabled by this function 09184 popf 09185 leave 09186 ret 09187 dis_already: 09188 xor eax, eax ! already disabled 09189 popf 09190 leave 09191 ret 09192 09193 File: Page: 749 kernel/klib386.s 09194 !*===========================================================================* 09195 !* phys_copy * 09196 !*===========================================================================* 09197 ! PUBLIC void phys_copy(phys_bytes source, phys_bytes destination, 09198 ! phys_bytes bytecount); 09199 ! Copy a block of physical memory. 09200 09201 PC_ARGS = 4 + 4 + 4 + 4 ! 4 + 4 + 4 09202 ! es edi esi eip src dst len 09203 09204 .align 16 09205 _phys_copy: 09206 cld 09207 push esi 09208 push edi 09209 push es 09210 09211 mov eax, FLAT_DS_SELECTOR 09212 mov es, ax 09213 09214 mov esi, PC_ARGS(esp) 09215 mov edi, PC_ARGS+4(esp) 09216 mov eax, PC_ARGS+4+4(esp) 09217 09218 cmp eax, 10 ! avoid align overhead for small counts 09219 jb pc_small 09220 mov ecx, esi ! align source, hope target is too 09221 neg ecx 09222 and ecx, 3 ! count for alignment 09223 sub eax, ecx 09224 rep 09225 eseg movsb 09226 mov ecx, eax 09227 shr ecx, 2 ! count of dwords 09228 rep 09229 eseg movs 09230 and eax, 3 09231 pc_small: 09232 xchg ecx, eax ! remainder 09233 rep 09234 eseg movsb 09235 09236 pop es 09237 pop edi 09238 pop esi 09239 ret 09240 09241 !*===========================================================================* 09242 !* phys_memset * 09243 !*===========================================================================* 09244 ! PUBLIC void phys_memset(phys_bytes source, unsigned long pattern, 09245 ! phys_bytes bytecount); 09246 ! Fill a block of physical memory with pattern. 09247 09248 .align 16 09249 _phys_memset: 09250 push ebp 09251 mov ebp, esp 09252 push esi 09253 push ebx File: Page: 750 kernel/klib386.s 09254 push ds 09255 mov esi, 8(ebp) 09256 mov eax, 16(ebp) 09257 mov ebx, FLAT_DS_SELECTOR 09258 mov ds, bx 09259 mov ebx, 12(ebp) 09260 shr eax, 2 09261 fill_start: 09262 mov (esi), ebx 09263 add esi, 4 09264 dec eax 09265 jnz fill_start 09266 ! Any remaining bytes? 09267 mov eax, 16(ebp) 09268 and eax, 3 09269 remain_fill: 09270 cmp eax, 0 09271 jz fill_done 09272 movb bl, 12(ebp) 09273 movb (esi), bl 09274 add esi, 1 09275 inc ebp 09276 dec eax 09277 jmp remain_fill 09278 fill_done: 09279 pop ds 09280 pop ebx 09281 pop esi 09282 pop ebp 09283 ret 09284 09285 !*===========================================================================* 09286 !* mem_rdw * 09287 !*===========================================================================* 09288 ! PUBLIC u16_t mem_rdw(U16_t segment, u16_t *offset); 09289 ! Load and return word at far pointer segment: offset. 09290 09291 .align 16 09292 _mem_rdw: 09293 mov cx, ds 09294 mov ds, 4(esp) ! segment 09295 mov eax, 4+4(esp) ! offset 09296 movzx eax, (eax) ! word to return 09297 mov ds, cx 09298 ret 09299 09300 09301 !*===========================================================================* 09302 !* reset * 09303 !*===========================================================================* 09304 ! PUBLIC void reset(); 09305 ! Reset the system by loading IDT with offset 0 and interrupting. 09306 09307 _reset: 09308 lidt (idt_zero) 09309 int 3 ! anything goes, the 386 will not like it 09310 .sect .data 09311 idt_zero: .data4 0, 0 09312 .sect .text 09313 File: Page: 751 kernel/klib386.s 09314 09315 !*===========================================================================* 09316 !* idle_task * 09317 !*===========================================================================* 09318 _idle_task: 09319 ! This task is called when the system has nothing else to do. The HLT 09320 ! instruction puts the processor in a state where it draws minimum power. 09321 push halt 09322 call _level0 ! level0(halt) 09323 pop eax 09324 jmp _idle_task 09325 halt: 09326 sti 09327 hlt 09328 cli 09329 ret 09330 09331 !*===========================================================================* 09332 !* level0 * 09333 !*===========================================================================* 09334 ! PUBLIC void level0(void (*func)(void)) 09335 ! Call a function at permission level 0. This allows kernel tasks to do 09336 ! things that are only possible at the most privileged CPU level. 09337 ! 09338 _level0: 09339 mov eax, 4(esp) 09340 mov (_level0_func), eax 09341 int LEVEL0_VECTOR 09342 ret 09343 09344 09345 !*===========================================================================* 09346 !* read_tsc * 09347 !*===========================================================================* 09348 ! PUBLIC void read_tsc(unsigned long *high, unsigned long *low); 09349 ! Read the cycle counter of the CPU. Pentium and up. 09350 .align 16 09351 _read_tsc: 09352 .data1 0x0f ! this is the RDTSC instruction 09353 .data1 0x31 ! it places the TSC in EDX: EAX 09354 push ebp 09355 mov ebp, 8(esp) 09356 mov (ebp), edx 09357 mov ebp, 12(esp) 09358 mov (ebp), eax 09359 pop ebp 09360 ret 09361 09362 !*===========================================================================* 09363 !* read_flags * 09364 !*===========================================================================* 09365 ! PUBLIC unsigned long read_cpu_flags(void); 09366 ! Read CPU status flags from C. 09367 .align 16 09368 _read_cpu_flags: 09369 pushf 09370 mov eax, (esp) 09371 popf 09372 ret 09373 File: Page: 752 kernel/utility.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/utility.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 09400 /* This file contains a collection of miscellaneous procedures: 09401 * panic: abort MINIX due to a fatal error 09402 * kprintf: diagnostic output for the kernel 09403 * 09404 * Changes: 09405 * Dec 10, 2004 kernel printing to circular buffer (Jorrit N. Herder) 09406 * 09407 * This file contains the routines that take care of kernel messages, i.e., 09408 * diagnostic output within the kernel. Kernel messages are not directly 09409 * displayed on the console, because this must be done by the output driver. 09410 * Instead, the kernel accumulates characters in a buffer and notifies the 09411 * output driver when a new message is ready. 09412 */ 09413 09414 #include 09415 #include "kernel.h" 09416 #include 09417 #include 09418 #include 09419 #include 09420 #include 09421 #include "proc.h" 09422 09423 #define END_OF_KMESS -1 09424 FORWARD _PROTOTYPE(void kputc, (int c)); 09425 09426 /*===========================================================================* 09427 * panic * 09428 *===========================================================================*/ 09429 PUBLIC void panic(mess,nr) 09430 _CONST char *mess; 09431 int nr; 09432 { 09433 /* The system has run aground of a fatal kernel error. Terminate execution. */ 09434 static int panicking = 0; 09435 if (panicking ++) return; /* prevent recursive panics */ 09436 09437 if (mess != NULL) { 09438 kprintf("\nKernel panic: %s", mess); 09439 if (nr != NO_NUM) kprintf(" %d", nr); 09440 kprintf("\n",NO_NUM); 09441 } 09442 09443 /* Abort MINIX. */ 09444 prepare_shutdown(RBT_PANIC); 09445 } 09447 /*===========================================================================* 09448 * kprintf * 09449 *===========================================================================*/ 09450 PUBLIC void kprintf(const char *fmt, ...) /* format to be printed */ 09451 { 09452 int c; /* next character in fmt */ 09453 int d; 09454 unsigned long u; /* hold number argument */ File: Page: 753 kernel/utility.c 09455 int base; /* base of number arg */ 09456 int negative = 0; /* print minus sign */ 09457 static char x2c[] = "0123456789ABCDEF"; /* nr conversion table */ 09458 char ascii[8 * sizeof(long) / 3 + 2]; /* string for ascii number */ 09459 char *s = NULL; /* string to be printed */ 09460 va_list argp; /* optional arguments */ 09461 09462 va_start(argp, fmt); /* init variable arguments */ 09463 09464 while((c=*fmt++) != 0) { 09465 09466 if (c == '%') { /* expect format '%key' */ 09467 switch(c = *fmt++) { /* determine what to do */ 09468 09469 /* Known keys are %d, %u, %x, %s, and %%. This is easily extended 09470 * with number types like %b and %o by providing a different base. 09471 * Number type keys don't set a string to 's', but use the general 09472 * conversion after the switch statement. 09473 */ 09474 case 'd': /* output decimal */ 09475 d = va_arg(argp, signed int); 09476 if (d < 0) { negative = 1; u = -d; } else { u = d; } 09477 base = 10; 09478 break; 09479 case 'u': /* output unsigned long */ 09480 u = va_arg(argp, unsigned long); 09481 base = 10; 09482 break; 09483 case 'x': /* output hexadecimal */ 09484 u = va_arg(argp, unsigned long); 09485 base = 0x10; 09486 break; 09487 case 's': /* output string */ 09488 s = va_arg(argp, char *); 09489 if (s == NULL) s = "(null)"; 09490 break; 09491 case '%': /* output percent */ 09492 s = "%"; 09493 break; 09494 09495 /* Unrecognized key. */ 09496 default: /* echo back %key */ 09497 s = "%?"; 09498 s[1] = c; /* set unknown key */ 09499 } 09500 09501 /* Assume a number if no string is set. Convert to ascii. */ 09502 if (s == NULL) { 09503 s = ascii + sizeof(ascii)-1; 09504 *s = 0; 09505 do { *--s = x2c[(u % base)]; } /* work backwards */ 09506 while ((u /= base) > 0); 09507 } 09508 09509 /* This is where the actual output for format "%key" is done. */ 09510 if (negative) kputc('-'); /* print sign if negative */ 09511 while(*s != 0) { kputc(*s++); } /* print string/ number */ 09512 s = NULL; /* reset for next round */ 09513 } 09514 else { File: Page: 754 kernel/utility.c 09515 kputc(c); /* print and continue */ 09516 } 09517 } 09518 kputc(END_OF_KMESS); /* terminate output */ 09519 va_end(argp); /* end variable arguments */ 09520 } 09522 /*===========================================================================* 09523 * kputc * 09524 *===========================================================================*/ 09525 PRIVATE void kputc(c) 09526 int c; /* character to append */ 09527 { 09528 /* Accumulate a single character for a kernel message. Send a notification 09529 * to the output driver if an END_OF_KMESS is encountered. 09530 */ 09531 if (c != END_OF_KMESS) { 09532 kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */ 09533 if (kmess.km_size < KMESS_BUF_SIZE) 09534 kmess.km_size += 1; 09535 kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE; 09536 } else { 09537 send_sig(OUTPUT_PROC_NR, SIGKMESS); 09538 } 09539 } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/system.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 09600 /* Function prototypes for the system library. 09601 * The implementation is contained in src/kernel/system/. 09602 * 09603 * The system library allows access to system services by doing a kernel call. 09604 * Kernel calls are transformed into request messages to the SYS task that is 09605 * responsible for handling the call. By convention, sys_call() is transformed 09606 * into a message with type SYS_CALL that is handled in a function do_call(). 09607 */ 09608 09609 #ifndef SYSTEM_H 09610 #define SYSTEM_H 09611 09612 /* Common includes for the system library. */ 09613 #include "kernel.h" 09614 #include "proto.h" 09615 #include "proc.h" 09616 09617 /* Default handler for unused kernel calls. */ 09618 _PROTOTYPE( int do_unused, (message *m_ptr) ); 09619 _PROTOTYPE( int do_exec, (message *m_ptr) ); 09620 _PROTOTYPE( int do_fork, (message *m_ptr) ); 09621 _PROTOTYPE( int do_newmap, (message *m_ptr) ); 09622 _PROTOTYPE( int do_exit, (message *m_ptr) ); 09623 _PROTOTYPE( int do_trace, (message *m_ptr) ); 09624 _PROTOTYPE( int do_nice, (message *m_ptr) ); File: Page: 755 kernel/system.h 09625 _PROTOTYPE( int do_copy, (message *m_ptr) ); 09626 #define do_vircopy do_copy 09627 #define do_physcopy do_copy 09628 _PROTOTYPE( int do_vcopy, (message *m_ptr) ); 09629 #define do_virvcopy do_vcopy 09630 #define do_physvcopy do_vcopy 09631 _PROTOTYPE( int do_umap, (message *m_ptr) ); 09632 _PROTOTYPE( int do_memset, (message *m_ptr) ); 09633 _PROTOTYPE( int do_abort, (message *m_ptr) ); 09634 _PROTOTYPE( int do_getinfo, (message *m_ptr) ); 09635 _PROTOTYPE( int do_privctl, (message *m_ptr) ); 09636 _PROTOTYPE( int do_segctl, (message *m_ptr) ); 09637 _PROTOTYPE( int do_irqctl, (message *m_ptr) ); 09638 _PROTOTYPE( int do_devio, (message *m_ptr) ); 09639 _PROTOTYPE( int do_vdevio, (message *m_ptr) ); 09640 _PROTOTYPE( int do_int86, (message *m_ptr) ); 09641 _PROTOTYPE( int do_sdevio, (message *m_ptr) ); 09642 _PROTOTYPE( int do_kill, (message *m_ptr) ); 09643 _PROTOTYPE( int do_getksig, (message *m_ptr) ); 09644 _PROTOTYPE( int do_endksig, (message *m_ptr) ); 09645 _PROTOTYPE( int do_sigsend, (message *m_ptr) ); 09646 _PROTOTYPE( int do_sigreturn, (message *m_ptr) ); 09647 _PROTOTYPE( int do_times, (message *m_ptr) ); 09648 _PROTOTYPE( int do_setalarm, (message *m_ptr) ); 09649 09650 #endif /* SYSTEM_H */ 09651 09652 09653 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/system.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 09700 /* This task provides an interface between the kernel and user-space system 09701 * processes. System services can be accessed by doing a kernel call. Kernel 09702 * calls are transformed into request messages, which are handled by this 09703 * task. By convention, a sys_call() is transformed in a SYS_CALL request 09704 * message that is handled in a function named do_call(). 09705 * 09706 * A private call vector is used to map all kernel calls to the functions that 09707 * handle them. The actual handler functions are contained in separate files 09708 * to keep this file clean. The call vector is used in the system task's main 09709 * loop to handle all incoming requests. 09710 * 09711 * In addition to the main sys_task() entry point, which starts the main loop, 09712 * there are several other minor entry points: 09713 * get_priv: assign privilege structure to user or system process 09714 * send_sig: send a signal directly to a system process 09715 * cause_sig: take action to cause a signal to occur via PM 09716 * umap_local: map virtual address in LOCAL_SEG to physical 09717 * umap_remote: map virtual address in REMOTE_SEG to physical 09718 * umap_bios: map virtual address in BIOS_SEG to physical 09719 * virtual_copy: copy bytes from one virtual address to another 09720 * get_randomness: accumulate randomness in a buffer 09721 * 09722 * Changes: 09723 * Aug 04, 2005 check if kernel call is allowed (Jorrit N. Herder) 09724 * Jul 20, 2005 send signal to services with message (Jorrit N. Herder) File: Page: 756 kernel/system.c 09725 * Jan 15, 2005 new, generalized virtual copy function (Jorrit N. Herder) 09726 * Oct 10, 2004 dispatch system calls from call vector (Jorrit N. Herder) 09727 * Sep 30, 2004 source code documentation updated (Jorrit N. Herder) 09728 */ 09729 09730 #include "kernel.h" 09731 #include "system.h" 09732 #include 09733 #include 09734 #include 09735 #include 09736 #include 09737 #include "protect.h" 09738 09739 /* Declaration of the call vector that defines the mapping of kernel calls 09740 * to handler functions. The vector is initialized in sys_init() with map(), 09741 * which makes sure the kernel call numbers are ok. No space is allocated, 09742 * because the dummy is declared extern. If an illegal call is given, the 09743 * array size will be negative and this won't compile. 09744 */ 09745 PUBLIC int (*call_vec[NR_SYS_CALLS])(message *m_ptr); 09746 09747 #define map(call_nr, handler) \ 09748 {extern int dummy[NR_SYS_CALLS>(unsigned)(call_nr-KERNEL_CALL) ? 1: -1];} \ 09749 call_vec[(call_nr-KERNEL_CALL)] = (handler) 09750 09751 FORWARD _PROTOTYPE( void initialize, (void)); 09752 09753 /*===========================================================================* 09754 * sys_task * 09755 *===========================================================================*/ 09756 PUBLIC void sys_task() 09757 { 09758 /* Main entry point of sys_task. Get the message and dispatch on type. */ 09759 static message m; 09760 register int result; 09761 register struct proc *caller_ptr; 09762 unsigned int call_nr; 09763 int s; 09764 09765 /* Initialize the system task. */ 09766 initialize(); 09767 09768 while (TRUE) { 09769 /* Get work. Block and wait until a request message arrives. */ 09770 receive(ANY, &m); 09771 call_nr = (unsigned) m.m_type - KERNEL_CALL; 09772 caller_ptr = proc_addr(m.m_source); 09773 09774 /* See if the caller made a valid request and try to handle it. */ 09775 if (! (priv(caller_ptr)->s_call_mask & (1<= NR_SYS_CALLS) { /* check call number */ 09779 kprintf("SYSTEM: illegal request %d from %d.\n", call_nr,m.m_source); 09780 result = EBADREQUEST; /* illegal message type */ 09781 } 09782 else { 09783 result = (*call_vec[call_nr])(&m); /* handle the kernel call */ 09784 } File: Page: 757 kernel/system.c 09785 09786 /* Send a reply, unless inhibited by a handler function. Use the kernel 09787 * function lock_send() to prevent a system call trap. The destination 09788 * is known to be blocked waiting for a message. 09789 */ 09790 if (result != EDONTREPLY) { 09791 m.m_type = result; /* report status of call */ 09792 if (OK != (s=lock_send(m.m_source, &m))) { 09793 kprintf("SYSTEM, reply to %d failed: %d\n", m.m_source, s); 09794 } 09795 } 09796 } 09797 } 09799 /*===========================================================================* 09800 * initialize * 09801 *===========================================================================*/ 09802 PRIVATE void initialize(void) 09803 { 09804 register struct priv *sp; 09805 int i; 09806 09807 /* Initialize IRQ handler hooks. Mark all hooks available. */ 09808 for (i=0; is_alarm_timer)); 09815 } 09816 09817 /* Initialize the call vector to a safe default handler. Some kernel calls 09818 * may be disabled or nonexistant. Then explicitly map known calls to their 09819 * handler functions. This is done with a macro that gives a compile error 09820 * if an illegal call number is used. The ordering is not important here. 09821 */ 09822 for (i=0; is_proc_nr == NONE && sp->s_id != USER_PRIV_ID) break; 09884 if (sp->s_proc_nr != NONE) return(ENOSPC); 09885 rc->p_priv = sp; /* assign new slot */ 09886 rc->p_priv->s_proc_nr = proc_nr(rc); /* set association */ 09887 rc->p_priv->s_flags = SYS_PROC; /* mark as privileged */ 09888 } else { 09889 rc->p_priv = &priv[USER_PRIV_ID]; /* use shared slot */ 09890 rc->p_priv->s_proc_nr = INIT_PROC_NR; /* set association */ 09891 rc->p_priv->s_flags = 0; /* no initial flags */ 09892 } 09893 return(OK); 09894 } 09896 /*===========================================================================* 09897 * get_randomness * 09898 *===========================================================================*/ 09899 PUBLIC void get_randomness(source) 09900 int source; 09901 { 09902 /* On machines with the RDTSC (cycle counter read instruction - pentium 09903 * and up), use that for high-resolution raw entropy gathering. Otherwise, 09904 * use the realtime clock (tick resolution). File: Page: 759 kernel/system.c 09905 * 09906 * Unfortunately this test is run-time - we don't want to bother with 09907 * compiling different kernels for different machines. 09908 * 09909 * On machines without RDTSC, we use read_clock(). 09910 */ 09911 int r_next; 09912 unsigned long tsc_high, tsc_low; 09913 09914 source %= RANDOM_SOURCES; 09915 r_next= krandom.bin[source].r_next; 09916 if (machine.processor > 486) { 09917 read_tsc(&tsc_high, &tsc_low); 09918 krandom.bin[source].r_buf[r_next] = tsc_low; 09919 } else { 09920 krandom.bin[source].r_buf[r_next] = read_clock(); 09921 } 09922 if (krandom.bin[source].r_size < RANDOM_ELEMENTS) { 09923 krandom.bin[source].r_size ++; 09924 } 09925 krandom.bin[source].r_next = (r_next + 1 ) % RANDOM_ELEMENTS; 09926 } 09928 /*===========================================================================* 09929 * send_sig * 09930 *===========================================================================*/ 09931 PUBLIC void send_sig(proc_nr, sig_nr) 09932 int proc_nr; /* system process to be signalled */ 09933 int sig_nr; /* signal to be sent, 1 to _NSIG */ 09934 { 09935 /* Notify a system process about a signal. This is straightforward. Simply 09936 * set the signal that is to be delivered in the pending signals map and 09937 * send a notification with source SYSTEM. 09938 */ 09939 register struct proc *rp; 09940 09941 rp = proc_addr(proc_nr); 09942 sigaddset(&priv(rp)->s_sig_pending, sig_nr); 09943 lock_notify(SYSTEM, proc_nr); 09944 } 09946 /*===========================================================================* 09947 * cause_sig * 09948 *===========================================================================*/ 09949 PUBLIC void cause_sig(proc_nr, sig_nr) 09950 int proc_nr; /* process to be signalled */ 09951 int sig_nr; /* signal to be sent, 1 to _NSIG */ 09952 { 09953 /* A system process wants to send a signal to a process. Examples are: 09954 * - HARDWARE wanting to cause a SIGSEGV after a CPU exception 09955 * - TTY wanting to cause SIGINT upon getting a DEL 09956 * - FS wanting to cause SIGPIPE for a broken pipe 09957 * Signals are handled by sending a message to PM. This function handles the 09958 * signals and makes sure the PM gets them by sending a notification. The 09959 * process being signaled is blocked while PM has not finished all signals 09960 * for it. 09961 * Race conditions between calls to this function and the system calls that 09962 * process pending kernel signals cannot exist. Signal related functions are 09963 * only called when a user process causes a CPU exception and from the kernel 09964 * process level, which runs to completion. File: Page: 760 kernel/system.c 09965 */ 09966 register struct proc *rp; 09967 09968 /* Check if the signal is already pending. Process it otherwise. */ 09969 rp = proc_addr(proc_nr); 09970 if (! sigismember(&rp->p_pending, sig_nr)) { 09971 sigaddset(&rp->p_pending, sig_nr); 09972 if (! (rp->p_rts_flags & SIGNALED)) { /* other pending */ 09973 if (rp->p_rts_flags == 0) lock_dequeue(rp); /* make not ready */ 09974 rp->p_rts_flags |= SIGNALED | SIG_PENDING; /* update flags */ 09975 send_sig(PM_PROC_NR, SIGKSIG); 09976 } 09977 } 09978 } 09980 /*===========================================================================* 09981 * umap_local * 09982 *===========================================================================*/ 09983 PUBLIC phys_bytes umap_local(rp, seg, vir_addr, bytes) 09984 register struct proc *rp; /* pointer to proc table entry for process */ 09985 int seg; /* T, D, or S segment */ 09986 vir_bytes vir_addr; /* virtual address in bytes within the seg */ 09987 vir_bytes bytes; /* # of bytes to be copied */ 09988 { 09989 /* Calculate the physical memory address for a given virtual address. */ 09990 vir_clicks vc; /* the virtual address in clicks */ 09991 phys_bytes pa; /* intermediate variables as phys_bytes */ 09992 phys_bytes seg_base; 09993 09994 /* If 'seg' is D it could really be S and vice versa. T really means T. 09995 * If the virtual address falls in the gap, it causes a problem. On the 09996 * 8088 it is probably a legal stack reference, since "stackfaults" are 09997 * not detected by the hardware. On 8088s, the gap is called S and 09998 * accepted, but on other machines it is called D and rejected. 09999 * The Atari ST behaves like the 8088 in this respect. 10000 */ 10001 10002 if (bytes <= 0) return( (phys_bytes) 0); 10003 if (vir_addr + bytes <= vir_addr) return 0; /* overflow */ 10004 vc = (vir_addr + bytes - 1) >> CLICK_SHIFT; /* last click of data */ 10005 10006 if (seg != T) 10007 seg = (vc < rp->p_memmap[D].mem_vir + rp->p_memmap[D].mem_len ? D : S); 10008 10009 if ((vir_addr>>CLICK_SHIFT) >= rp->p_memmap[seg].mem_vir + 10010 rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 ); 10011 10012 if (vc >= rp->p_memmap[seg].mem_vir + 10013 rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 ); 10014 10015 seg_base = (phys_bytes) rp->p_memmap[seg].mem_phys; 10016 seg_base = seg_base << CLICK_SHIFT; /* segment origin in bytes */ 10017 pa = (phys_bytes) vir_addr; 10018 pa -= rp->p_memmap[seg].mem_vir << CLICK_SHIFT; 10019 return(seg_base + pa); 10020 } File: Page: 761 kernel/system.c 10022 /*===========================================================================* 10023 * umap_remote * 10024 *===========================================================================*/ 10025 PUBLIC phys_bytes umap_remote(rp, seg, vir_addr, bytes) 10026 register struct proc *rp; /* pointer to proc table entry for process */ 10027 int seg; /* index of remote segment */ 10028 vir_bytes vir_addr; /* virtual address in bytes within the seg */ 10029 vir_bytes bytes; /* # of bytes to be copied */ 10030 { 10031 /* Calculate the physical memory address for a given virtual address. */ 10032 struct far_mem *fm; 10033 10034 if (bytes <= 0) return( (phys_bytes) 0); 10035 if (seg < 0 || seg >= NR_REMOTE_SEGS) return( (phys_bytes) 0); 10036 10037 fm = &rp->p_priv->s_farmem[seg]; 10038 if (! fm->in_use) return( (phys_bytes) 0); 10039 if (vir_addr + bytes > fm->mem_len) return( (phys_bytes) 0); 10040 10041 return(fm->mem_phys + (phys_bytes) vir_addr); 10042 } 10044 /*===========================================================================* 10045 * umap_bios * 10046 *===========================================================================*/ 10047 PUBLIC phys_bytes umap_bios(rp, vir_addr, bytes) 10048 register struct proc *rp; /* pointer to proc table entry for process */ 10049 vir_bytes vir_addr; /* virtual address in BIOS segment */ 10050 vir_bytes bytes; /* # of bytes to be copied */ 10051 { 10052 /* Calculate the physical memory address at the BIOS. Note: currently, BIOS 10053 * address zero (the first BIOS interrupt vector) is not considered as an 10054 * error here, but since the physical address will be zero as well, the 10055 * calling function will think an error occurred. This is not a problem, 10056 * since no one uses the first BIOS interrupt vector. 10057 */ 10058 10059 /* Check all acceptable ranges. */ 10060 if (vir_addr >= BIOS_MEM_BEGIN && vir_addr + bytes <= BIOS_MEM_END) 10061 return (phys_bytes) vir_addr; 10062 else if (vir_addr >= BASE_MEM_TOP && vir_addr + bytes <= UPPER_MEM_END) 10063 return (phys_bytes) vir_addr; 10064 kprintf("Warning, error in umap_bios, virtual address 0x%x\n", vir_addr); 10065 return 0; 10066 } 10068 /*===========================================================================* 10069 * virtual_copy * 10070 *===========================================================================*/ 10071 PUBLIC int virtual_copy(src_addr, dst_addr, bytes) 10072 struct vir_addr *src_addr; /* source virtual address */ 10073 struct vir_addr *dst_addr; /* destination virtual address */ 10074 vir_bytes bytes; /* # of bytes to copy */ 10075 { 10076 /* Copy bytes from virtual address src_addr to virtual address dst_addr. 10077 * Virtual addresses can be in ABS, LOCAL_SEG, REMOTE_SEG, or BIOS_SEG. 10078 */ 10079 struct vir_addr *vir_addr[2]; /* virtual source and destination address */ 10080 phys_bytes phys_addr[2]; /* absolute source and destination */ 10081 int seg_index; File: Page: 762 kernel/system.c 10082 int i; 10083 10084 /* Check copy count. */ 10085 if (bytes <= 0) return(EDOM); 10086 10087 /* Do some more checks and map virtual addresses to physical addresses. */ 10088 vir_addr[_SRC_] = src_addr; 10089 vir_addr[_DST_] = dst_addr; 10090 for (i=_SRC_; i<=_DST_; i++) { 10091 10092 /* Get physical address. */ 10093 switch((vir_addr[i]->segment & SEGMENT_TYPE)) { 10094 case LOCAL_SEG: 10095 seg_index = vir_addr[i]->segment & SEGMENT_INDEX; 10096 phys_addr[i] = umap_local( proc_addr(vir_addr[i]->proc_nr), 10097 seg_index, vir_addr[i]->offset, bytes ); 10098 break; 10099 case REMOTE_SEG: 10100 seg_index = vir_addr[i]->segment & SEGMENT_INDEX; 10101 phys_addr[i] = umap_remote( proc_addr(vir_addr[i]->proc_nr), 10102 seg_index, vir_addr[i]->offset, bytes ); 10103 break; 10104 case BIOS_SEG: 10105 phys_addr[i] = umap_bios( proc_addr(vir_addr[i]->proc_nr), 10106 vir_addr[i]->offset, bytes ); 10107 break; 10108 case PHYS_SEG: 10109 phys_addr[i] = vir_addr[i]->offset; 10110 break; 10111 default: 10112 return(EINVAL); 10113 } 10114 10115 /* Check if mapping succeeded. */ 10116 if (phys_addr[i] <= 0 && vir_addr[i]->segment != PHYS_SEG) 10117 return(EFAULT); 10118 } 10119 10120 /* Now copy bytes between physical addresseses. */ 10121 phys_copy(phys_addr[_SRC_], phys_addr[_DST_], (phys_bytes) bytes); 10122 return(OK); 10123 } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/system/do_setalarm.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 10200 /* The kernel call implemented in this file: 10201 * m_type: SYS_SETALARM 10202 * 10203 * The parameters for this kernel call are: 10204 * m2_l1: ALRM_EXP_TIME (alarm's expiration time) 10205 * m2_i2: ALRM_ABS_TIME (expiration time is absolute?) 10206 * m2_l1: ALRM_TIME_LEFT (return seconds left of previous) 10207 */ 10208 10209 #include "../system.h" File: Page: 763 kernel/system/do_setalarm.c 10210 10211 #if USE_SETALARM 10212 10213 FORWARD _PROTOTYPE( void cause_alarm, (timer_t *tp) ); 10214 10215 /*===========================================================================* 10216 * do_setalarm * 10217 *===========================================================================*/ 10218 PUBLIC int do_setalarm(m_ptr) 10219 message *m_ptr; /* pointer to request message */ 10220 { 10221 /* A process requests a synchronous alarm, or wants to cancel its alarm. */ 10222 register struct proc *rp; /* pointer to requesting process */ 10223 int proc_nr; /* which process wants the alarm */ 10224 long exp_time; /* expiration time for this alarm */ 10225 int use_abs_time; /* use absolute or relative time */ 10226 timer_t *tp; /* the process' timer structure */ 10227 clock_t uptime; /* placeholder for current uptime */ 10228 10229 /* Extract shared parameters from the request message. */ 10230 exp_time = m_ptr->ALRM_EXP_TIME; /* alarm's expiration time */ 10231 use_abs_time = m_ptr->ALRM_ABS_TIME; /* flag for absolute time */ 10232 proc_nr = m_ptr->m_source; /* process to interrupt later */ 10233 rp = proc_addr(proc_nr); 10234 if (! (priv(rp)->s_flags & SYS_PROC)) return(EPERM); 10235 10236 /* Get the timer structure and set the parameters for this alarm. */ 10237 tp = &(priv(rp)->s_alarm_timer); 10238 tmr_arg(tp)->ta_int = proc_nr; 10239 tp->tmr_func = cause_alarm; 10240 10241 /* Return the ticks left on the previous alarm. */ 10242 uptime = get_uptime(); 10243 if ((tp->tmr_exp_time != TMR_NEVER) && (uptime < tp->tmr_exp_time) ) { 10244 m_ptr->ALRM_TIME_LEFT = (tp->tmr_exp_time - uptime); 10245 } else { 10246 m_ptr->ALRM_TIME_LEFT = 0; 10247 } 10248 10249 /* Finally, (re)set the timer depending on the expiration time. */ 10250 if (exp_time == 0) { 10251 reset_timer(tp); 10252 } else { 10253 tp->tmr_exp_time = (use_abs_time) ? exp_time : exp_time + get_uptime(); 10254 set_timer(tp, tp->tmr_exp_time, tp->tmr_func); 10255 } 10256 return(OK); 10257 } 10259 /*===========================================================================* 10260 * cause_alarm * 10261 *===========================================================================*/ 10262 PRIVATE void cause_alarm(tp) 10263 timer_t *tp; 10264 { 10265 /* Routine called if a timer goes off and the process requested a synchronous 10266 * alarm. The process number is stored in timer argument 'ta_int'. Notify that 10267 * process with a notification message from CLOCK. 10268 */ 10269 int proc_nr = tmr_arg(tp)->ta_int; /* get process number */ File: Page: 764 kernel/system/do_setalarm.c 10270 lock_notify(CLOCK, proc_nr); /* notify process */ 10271 } 10273 #endif /* USE_SETALARM */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/system/do_exec.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 10300 /* The kernel call implemented in this file: 10301 * m_type: SYS_EXEC 10302 * 10303 * The parameters for this kernel call are: 10304 * m1_i1: PR_PROC_NR (process that did exec call) 10305 * m1_p1: PR_STACK_PTR (new stack pointer) 10306 * m1_p2: PR_NAME_PTR (pointer to program name) 10307 * m1_p3: PR_IP_PTR (new instruction pointer) 10308 */ 10309 #include "../system.h" 10310 #include 10311 #include 10312 10313 #if USE_EXEC 10314 10315 /*===========================================================================* 10316 * do_exec * 10317 *===========================================================================*/ 10318 PUBLIC int do_exec(m_ptr) 10319 register message *m_ptr; /* pointer to request message */ 10320 { 10321 /* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */ 10322 register struct proc *rp; 10323 reg_t sp; /* new sp */ 10324 phys_bytes phys_name; 10325 char *np; 10326 10327 rp = proc_addr(m_ptr->PR_PROC_NR); 10328 sp = (reg_t) m_ptr->PR_STACK_PTR; 10329 rp->p_reg.sp = sp; /* set the stack pointer */ 10330 phys_memset(vir2phys(&rp->p_ldt[EXTRA_LDT_INDEX]), 0, 10331 (LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0])); 10332 rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */ 10333 rp->p_rts_flags &= ~RECEIVING; /* PM does not reply to EXEC call */ 10334 if (rp->p_rts_flags == 0) lock_enqueue(rp); 10335 10336 /* Save command name for debugging, ps(1) output, etc. */ 10337 phys_name = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->PR_NAME_PTR, 10338 (vir_bytes) P_NAME_LEN - 1); 10339 if (phys_name != 0) { 10340 phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) P_NAME_LEN - 1); 10341 for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {} 10342 *np = 0; /* mark end */ 10343 } else { 10344 strncpy(rp->p_name, "", P_NAME_LEN); 10345 } 10346 return(OK); 10347 } 10348 #endif /* USE_EXEC */ File: Page: 765 kernel/clock.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/clock.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 10400 /* This file contains the clock task, which handles time related functions. 10401 * Important events that are handled by the CLOCK include setting and 10402 * monitoring alarm timers and deciding when to (re)schedule processes. 10403 * The CLOCK offers a direct interface to kernel processes. System services 10404 * can access its services through system calls, such as sys_setalarm(). The 10405 * CLOCK task thus is hidden from the outside world. 10406 * 10407 * Changes: 10408 * Oct 08, 2005 reordering and comment editing (A. S. Woodhull) 10409 * Mar 18, 2004 clock interface moved to SYSTEM task (Jorrit N. Herder) 10410 * Sep 30, 2004 source code documentation updated (Jorrit N. Herder) 10411 * Sep 24, 2004 redesigned alarm timers (Jorrit N. Herder) 10412 * 10413 * The function do_clocktick() is triggered by the clock's interrupt 10414 * handler when a watchdog timer has expired or a process must be scheduled. 10415 * 10416 * In addition to the main clock_task() entry point, which starts the main 10417 * loop, there are several other minor entry points: 10418 * clock_stop: called just before MINIX shutdown 10419 * get_uptime: get realtime since boot in clock ticks 10420 * set_timer: set a watchdog timer (+) 10421 * reset_timer: reset a watchdog timer (+) 10422 * read_clock: read the counter of channel 0 of the 8253A timer 10423 * 10424 * (+) The CLOCK task keeps tracks of watchdog timers for the entire kernel. 10425 * The watchdog functions of expired timers are executed in do_clocktick(). 10426 * It is crucial that watchdog functions not block, or the CLOCK task may 10427 * be blocked. Do not send() a message when the receiver is not expecting it. 10428 * Instead, notify(), which always returns, should be used. 10429 */ 10430 10431 #include "kernel.h" 10432 #include "proc.h" 10433 #include 10434 #include 10435 10436 /* Function prototype for PRIVATE functions. */ 10437 FORWARD _PROTOTYPE( void init_clock, (void) ); 10438 FORWARD _PROTOTYPE( int clock_handler, (irq_hook_t *hook) ); 10439 FORWARD _PROTOTYPE( int do_clocktick, (message *m_ptr) ); 10440 10441 /* Clock parameters. */ 10442 #define COUNTER_FREQ (2*TIMER_FREQ) /* counter frequency using square wave */ 10443 #define LATCH_COUNT 0x00 /* cc00xxxx, c = channel, x = any */ 10444 #define SQUARE_WAVE 0x36 /* ccaammmb, a = access, m = mode, b = BCD */ 10445 /* 11x11, 11 = LSB then MSB, x11 = sq wave */ 10446 #define TIMER_COUNT ((unsigned) (TIMER_FREQ/HZ)) /* initial value for counter*/ 10447 #define TIMER_FREQ 1193182L /* clock frequency for timer in PC and AT */ 10448 10449 #define CLOCK_ACK_BIT 0x80 /* PS/2 clock interrupt acknowledge bit */ 10450 10451 /* The CLOCK's timers queue. The functions in operate on this. 10452 * Each system process possesses a single synchronous alarm timer. If other 10453 * kernel parts want to use additional timers, they must declare their own 10454 * persistent (static) timer structure, which can be passed to the clock File: Page: 766 kernel/clock.c 10455 * via (re)set_timer(). 10456 * When a timer expires its watchdog function is run by the CLOCK task. 10457 */ 10458 PRIVATE timer_t *clock_timers; /* queue of CLOCK timers */ 10459 PRIVATE clock_t next_timeout; /* realtime that next timer expires */ 10460 10461 /* The time is incremented by the interrupt handler on each clock tick. */ 10462 PRIVATE clock_t realtime; /* real time clock */ 10463 PRIVATE irq_hook_t clock_hook; /* interrupt handler hook */ 10464 10465 /*===========================================================================* 10466 * clock_task * 10467 *===========================================================================*/ 10468 PUBLIC void clock_task() 10469 { 10470 /* Main program of clock task. If the call is not HARD_INT it is an error. 10471 */ 10472 message m; /* message buffer for both input and output */ 10473 int result; /* result returned by the handler */ 10474 10475 init_clock(); /* initialize clock task */ 10476 10477 /* Main loop of the clock task. Get work, process it. Never reply. */ 10478 while (TRUE) { 10479 10480 /* Go get a message. */ 10481 receive(ANY, &m); 10482 10483 /* Handle the request. Only clock ticks are expected. */ 10484 switch (m.m_type) { 10485 case HARD_INT: 10486 result = do_clocktick(&m); /* handle clock tick */ 10487 break; 10488 default: /* illegal request type */ 10489 kprintf("CLOCK: illegal request %d from %d.\n", m.m_type,m.m_source); 10490 } 10491 } 10492 } 10494 /*===========================================================================* 10495 * do_clocktick * 10496 *===========================================================================*/ 10497 PRIVATE int do_clocktick(m_ptr) 10498 message *m_ptr; /* pointer to request message */ 10499 { 10500 /* Despite its name, this routine is not called on every clock tick. It 10501 * is called on those clock ticks when a lot of work needs to be done. 10502 */ 10503 10504 /* A process used up a full quantum. The interrupt handler stored this 10505 * process in 'prev_ptr'. First make sure that the process is not on the 10506 * scheduling queues. Then announce the process ready again. Since it has 10507 * no more time left, it gets a new quantum and is inserted at the right 10508 * place in the queues. As a side-effect a new process will be scheduled. 10509 */ 10510 if (prev_ptr->p_ticks_left <= 0 && priv(prev_ptr)->s_flags & PREEMPTIBLE) { 10511 lock_dequeue(prev_ptr); /* take it off the queues */ 10512 lock_enqueue(prev_ptr); /* and reinsert it again */ 10513 } 10514 File: Page: 767 kernel/clock.c 10515 /* Check if a clock timer expired and run its watchdog function. */ 10516 if (next_timeout <= realtime) { 10517 tmrs_exptimers(&clock_timers, realtime, NULL); 10518 next_timeout = clock_timers == NULL ? 10519 TMR_NEVER : clock_timers->tmr_exp_time; 10520 } 10521 10522 /* Inhibit sending a reply. */ 10523 return(EDONTREPLY); 10524 } 10526 /*===========================================================================* 10527 * init_clock * 10528 *===========================================================================*/ 10529 PRIVATE void init_clock() 10530 { 10531 /* Initialize the CLOCK's interrupt hook. */ 10532 clock_hook.proc_nr = CLOCK; 10533 10534 /* Initialize channel 0 of the 8253A timer to, e.g., 60 Hz. */ 10535 outb(TIMER_MODE, SQUARE_WAVE); /* set timer to run continuously */ 10536 outb(TIMER0, TIMER_COUNT); /* load timer low byte */ 10537 outb(TIMER0, TIMER_COUNT >> 8); /* load timer high byte */ 10538 put_irq_handler(&clock_hook, CLOCK_IRQ, clock_handler);/* register handler */ 10539 enable_irq(&clock_hook); /* ready for clock interrupts */ 10540 } 10542 /*===========================================================================* 10543 * clock_stop * 10544 *===========================================================================*/ 10545 PUBLIC void clock_stop() 10546 { 10547 /* Reset the clock to the BIOS rate. (For rebooting) */ 10548 outb(TIMER_MODE, 0x36); 10549 outb(TIMER0, 0); 10550 outb(TIMER0, 0); 10551 } 10553 /*===========================================================================* 10554 * clock_handler * 10555 *===========================================================================*/ 10556 PRIVATE int clock_handler(hook) 10557 irq_hook_t *hook; 10558 { 10559 /* This executes on each clock tick (i.e., every time the timer chip generates 10560 * an interrupt). It does a little bit of work so the clock task does not have 10561 * to be called on every tick. The clock task is called when: 10562 * 10563 * (1) the scheduling quantum of the running process has expired, or 10564 * (2) a timer has expired and the watchdog function should be run. 10565 * 10566 * Many global global and static variables are accessed here. The safety of 10567 * this must be justified. All scheduling and message passing code acquires a 10568 * lock by temporarily disabling interrupts, so no conflicts with calls from 10569 * the task level can occur. Furthermore, interrupts are not reentrant, the 10570 * interrupt handler cannot be bothered by other interrupts. 10571 * 10572 * Variables that are updated in the clock's interrupt handler: 10573 * lost_ticks: 10574 * Clock ticks counted outside the clock task. This for example File: Page: 768 kernel/clock.c 10575 * is used when the boot monitor processes a real mode interrupt. 10576 * realtime: 10577 * The current uptime is incremented with all outstanding ticks. 10578 * proc_ptr, bill_ptr: 10579 * These are used for accounting. It does not matter if proc.c 10580 * is changing them, provided they are always valid pointers, 10581 * since at worst the previous process would be billed. 10582 */ 10583 register unsigned ticks; 10584 10585 /* Acknowledge the PS/2 clock interrupt. */ 10586 if (machine.ps_mca) outb(PORT_B, inb(PORT_B) | CLOCK_ACK_BIT); 10587 10588 /* Get number of ticks and update realtime. */ 10589 ticks = lost_ticks + 1; 10590 lost_ticks = 0; 10591 realtime += ticks; 10592 10593 /* Update user and system accounting times. Charge the current process for 10594 * user time. If the current process is not billable, that is, if a non-user 10595 * process is running, charge the billable process for system time as well. 10596 * Thus the unbillable process' user time is the billable user's system time. 10597 */ 10598 proc_ptr->p_user_time += ticks; 10599 if (priv(proc_ptr)->s_flags & PREEMPTIBLE) { 10600 proc_ptr->p_ticks_left -= ticks; 10601 } 10602 if (! (priv(proc_ptr)->s_flags & BILLABLE)) { 10603 bill_ptr->p_sys_time += ticks; 10604 bill_ptr->p_ticks_left -= ticks; 10605 } 10606 10607 /* Check if do_clocktick() must be called. Done for alarms and scheduling. 10608 * Some processes, such as the kernel tasks, cannot be preempted. 10609 */ 10610 if ((next_timeout <= realtime) || (proc_ptr->p_ticks_left <= 0)) { 10611 prev_ptr = proc_ptr; /* store running process */ 10612 lock_notify(HARDWARE, CLOCK); /* send notification */ 10613 } 10614 return(1); /* reenable interrupts */ 10615 } 10617 /*===========================================================================* 10618 * get_uptime * 10619 *===========================================================================*/ 10620 PUBLIC clock_t get_uptime() 10621 { 10622 /* Get and return the current clock uptime in ticks. */ 10623 return(realtime); 10624 } 10626 /*===========================================================================* 10627 * set_timer * 10628 *===========================================================================*/ 10629 PUBLIC void set_timer(tp, exp_time, watchdog) 10630 struct timer *tp; /* pointer to timer structure */ 10631 clock_t exp_time; /* expiration realtime */ 10632 tmr_func_t watchdog; /* watchdog to be called */ 10633 { 10634 /* Insert the new timer in the active timers list. Always update the File: Page: 769 kernel/clock.c 10635 * next timeout time by setting it to the front of the active list. 10636 */ 10637 tmrs_settimer(&clock_timers, tp, exp_time, watchdog, NULL); 10638 next_timeout = clock_timers->tmr_exp_time; 10639 } 10641 /*===========================================================================* 10642 * reset_timer * 10643 *===========================================================================*/ 10644 PUBLIC void reset_timer(tp) 10645 struct timer *tp; /* pointer to timer structure */ 10646 { 10647 /* The timer pointed to by 'tp' is no longer needed. Remove it from both the 10648 * active and expired lists. Always update the next timeout time by setting 10649 * it to the front of the active list. 10650 */ 10651 tmrs_clrtimer(&clock_timers, tp, NULL); 10652 next_timeout = (clock_timers == NULL) ? 10653 TMR_NEVER : clock_timers->tmr_exp_time; 10654 } 10656 /*===========================================================================* 10657 * read_clock * 10658 *===========================================================================*/ 10659 PUBLIC unsigned long read_clock() 10660 { 10661 /* Read the counter of channel 0 of the 8253A timer. This counter counts 10662 * down at a rate of TIMER_FREQ and restarts at TIMER_COUNT-1 when it 10663 * reaches zero. A hardware interrupt (clock tick) occurs when the counter 10664 * gets to zero and restarts its cycle. 10665 */ 10666 unsigned count; 10667 10668 outb(TIMER_MODE, LATCH_COUNT); 10669 count = inb(TIMER0); 10670 count |= (inb(TIMER0) << 8); 10671 10672 return count; 10673 } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/drivers.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 10700 /* This is the master header for all device drivers. It includes some other 10701 * files and defines the principal constants. 10702 */ 10703 #define _POSIX_SOURCE 1 /* tell headers to include POSIX stuff */ 10704 #define _MINIX 1 /* tell headers to include MINIX stuff */ 10705 #define _SYSTEM 1 /* get negative error number in */ 10706 10707 /* The following are so basic, all the *.c files get them automatically. */ 10708 #include /* MUST be first */ 10709 #include /* MUST be second */ 10710 #include 10711 #include 10712 #include 10713 #include 10714 #include File: Page: 770 drivers/drivers.h 10715 #include 10716 #include 10717 #include 10718 #include 10719 #include 10720 10721 #include /* IRQ vectors and miscellaneous ports */ 10722 #include /* BIOS index numbers */ 10723 #include /* Well-known ports */ 10724 10725 #include 10726 #include 10727 #include 10728 #include 10729 #include 10730 #include 10731 #include 10732 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/libdriver/driver.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 10800 /* Types and constants shared between the generic and device dependent 10801 * device driver code. 10802 */ 10803 10804 #define _POSIX_SOURCE 1 /* tell headers to include POSIX stuff */ 10805 #define _MINIX 1 /* tell headers to include MINIX stuff */ 10806 #define _SYSTEM 1 /* get negative error number in */ 10807 10808 /* The following are so basic, all the *.c files get them automatically. */ 10809 #include /* MUST be first */ 10810 #include /* MUST be second */ 10811 #include 10812 #include 10813 #include 10814 #include 10815 #include 10816 #include 10817 #include 10818 #include 10819 10820 #include 10821 #include 10822 #include 10823 #include 10824 10825 #include 10826 #include 10827 10828 /* Info about and entry points into the device dependent code. */ 10829 struct driver { 10830 _PROTOTYPE( char *(*dr_name), (void) ); 10831 _PROTOTYPE( int (*dr_open), (struct driver *dp, message *m_ptr) ); 10832 _PROTOTYPE( int (*dr_close), (struct driver *dp, message *m_ptr) ); 10833 _PROTOTYPE( int (*dr_ioctl), (struct driver *dp, message *m_ptr) ); 10834 _PROTOTYPE( struct device *(*dr_prepare), (int device) ); File: Page: 771 drivers/libdriver/driver.h 10835 _PROTOTYPE( int (*dr_transfer), (int proc_nr, int opcode, off_t position, 10836 iovec_t *iov, unsigned nr_req) ); 10837 _PROTOTYPE( void (*dr_cleanup), (void) ); 10838 _PROTOTYPE( void (*dr_geometry), (struct partition *entry) ); 10839 _PROTOTYPE( void (*dr_signal), (struct driver *dp, message *m_ptr) ); 10840 _PROTOTYPE( void (*dr_alarm), (struct driver *dp, message *m_ptr) ); 10841 _PROTOTYPE( int (*dr_cancel), (struct driver *dp, message *m_ptr) ); 10842 _PROTOTYPE( int (*dr_select), (struct driver *dp, message *m_ptr) ); 10843 _PROTOTYPE( int (*dr_other), (struct driver *dp, message *m_ptr) ); 10844 _PROTOTYPE( int (*dr_hw_int), (struct driver *dp, message *m_ptr) ); 10845 }; 10846 10847 #if (CHIP == INTEL) 10848 10849 /* Number of bytes you can DMA before hitting a 64K boundary: */ 10850 #define dma_bytes_left(phys) \ 10851 ((unsigned) (sizeof(int) == 2 ? 0 : 0x10000) - (unsigned) ((phys) & 0xFFFF)) 10852 10853 #endif /* CHIP == INTEL */ 10854 10855 /* Base and size of a partition in bytes. */ 10856 struct device { 10857 u64_t dv_base; 10858 u64_t dv_size; 10859 }; 10860 10861 #define NIL_DEV ((struct device *) 0) 10862 10863 /* Functions defined by driver.c: */ 10864 _PROTOTYPE( void driver_task, (struct driver *dr) ); 10865 _PROTOTYPE( char *no_name, (void) ); 10866 _PROTOTYPE( int do_nop, (struct driver *dp, message *m_ptr) ); 10867 _PROTOTYPE( struct device *nop_prepare, (int device) ); 10868 _PROTOTYPE( void nop_cleanup, (void) ); 10869 _PROTOTYPE( void nop_task, (void) ); 10870 _PROTOTYPE( void nop_signal, (struct driver *dp, message *m_ptr) ); 10871 _PROTOTYPE( void nop_alarm, (struct driver *dp, message *m_ptr) ); 10872 _PROTOTYPE( int nop_cancel, (struct driver *dp, message *m_ptr) ); 10873 _PROTOTYPE( int nop_select, (struct driver *dp, message *m_ptr) ); 10874 _PROTOTYPE( int do_diocntl, (struct driver *dp, message *m_ptr) ); 10875 10876 /* Parameters for the disk drive. */ 10877 #define SECTOR_SIZE 512 /* physical sector size in bytes */ 10878 #define SECTOR_SHIFT 9 /* for division */ 10879 #define SECTOR_MASK 511 /* and remainder */ 10880 10881 /* Size of the DMA buffer buffer in bytes. */ 10882 #define USE_EXTRA_DMA_BUF 0 /* usually not needed */ 10883 #define DMA_BUF_SIZE (DMA_SECTORS * SECTOR_SIZE) 10884 10885 #if (CHIP == INTEL) 10886 extern u8_t *tmp_buf; /* the DMA buffer */ 10887 #else 10888 extern u8_t tmp_buf[]; /* the DMA buffer */ 10889 #endif 10890 extern phys_bytes tmp_phys; /* phys address of DMA buffer */ File: Page: 772 drivers/libdriver/drvlib.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/libdriver/drvlib.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 10900 /* IBM device driver definitions Author: Kees J. Bot 10901 * 7 Dec 1995 10902 */ 10903 10904 #include 10905 10906 _PROTOTYPE( void partition, (struct driver *dr, int device, int style, int atapi) ); 10907 10908 /* BIOS parameter table layout. */ 10909 #define bp_cylinders(t) (* (u16_t *) (&(t)[0])) 10910 #define bp_heads(t) (* (u8_t *) (&(t)[2])) 10911 #define bp_reduced_wr(t) (* (u16_t *) (&(t)[3])) 10912 #define bp_precomp(t) (* (u16_t *) (&(t)[5])) 10913 #define bp_max_ecc(t) (* (u8_t *) (&(t)[7])) 10914 #define bp_ctlbyte(t) (* (u8_t *) (&(t)[8])) 10915 #define bp_landingzone(t) (* (u16_t *) (&(t)[12])) 10916 #define bp_sectors(t) (* (u8_t *) (&(t)[14])) 10917 10918 /* Miscellaneous. */ 10919 #define DEV_PER_DRIVE (1 + NR_PARTITIONS) 10920 #define MINOR_t0 64 10921 #define MINOR_r0 120 10922 #define MINOR_d0p0s0 128 10923 #define MINOR_fd0p0 (28<<2) 10924 #define P_FLOPPY 0 10925 #define P_PRIMARY 1 10926 #define P_SUB 2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/libdriver/driver.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 11000 /* This file contains device independent device driver interface. 11001 * 11002 * Changes: 11003 * Jul 25, 2005 added SYS_SIG type for signals (Jorrit N. Herder) 11004 * Sep 15, 2004 added SYN_ALARM type for timeouts (Jorrit N. Herder) 11005 * Jul 23, 2004 removed kernel dependencies (Jorrit N. Herder) 11006 * Apr 02, 1992 constructed from AT wini and floppy driver (Kees J. Bot) 11007 * 11008 * 11009 * The drivers support the following operations (using message format m2): 11010 * 11011 * m_type DEVICE PROC_NR COUNT POSITION ADRRESS 11012 * ---------------------------------------------------------------- 11013 * | DEV_OPEN | device | proc nr | | | | 11014 * |------------+---------+---------+---------+---------+---------| 11015 * | DEV_CLOSE | device | proc nr | | | | 11016 * |------------+---------+---------+---------+---------+---------| 11017 * | DEV_READ | device | proc nr | bytes | offset | buf ptr | 11018 * |------------+---------+---------+---------+---------+---------| 11019 * | DEV_WRITE | device | proc nr | bytes | offset | buf ptr | File: Page: 773 drivers/libdriver/driver.c 11020 * |------------+---------+---------+---------+---------+---------| 11021 * | DEV_GATHER | device | proc nr | iov len | offset | iov ptr | 11022 * |------------+---------+---------+---------+---------+---------| 11023 * | DEV_SCATTER| device | proc nr | iov len | offset | iov ptr | 11024 * |------------+---------+---------+---------+---------+---------| 11025 * | DEV_IOCTL | device | proc nr |func code| | buf ptr | 11026 * |------------+---------+---------+---------+---------+---------| 11027 * | CANCEL | device | proc nr | r/w | | | 11028 * |------------+---------+---------+---------+---------+---------| 11029 * | HARD_STOP | | | | | | 11030 * ---------------------------------------------------------------- 11031 * 11032 * The file contains one entry point: 11033 * 11034 * driver_task: called by the device dependent task entry 11035 */ 11036 11037 #include "../drivers.h" 11038 #include 11039 #include "driver.h" 11040 11041 #define BUF_EXTRA 0 11042 11043 /* Claim space for variables. */ 11044 PRIVATE u8_t buffer[(unsigned) 2 * DMA_BUF_SIZE + BUF_EXTRA]; 11045 u8_t *tmp_buf; /* the DMA buffer eventually */ 11046 phys_bytes tmp_phys; /* phys address of DMA buffer */ 11047 11048 FORWARD _PROTOTYPE( void init_buffer, (void) ); 11049 FORWARD _PROTOTYPE( int do_rdwt, (struct driver *dr, message *mp) ); 11050 FORWARD _PROTOTYPE( int do_vrdwt, (struct driver *dr, message *mp) ); 11051 11052 int device_caller; 11053 11054 /*===========================================================================* 11055 * driver_task * 11056 *===========================================================================*/ 11057 PUBLIC void driver_task(dp) 11058 struct driver *dp; /* Device dependent entry points. */ 11059 { 11060 /* Main program of any device driver task. */ 11061 11062 int r, proc_nr; 11063 message mess; 11064 11065 /* Get a DMA buffer. */ 11066 init_buffer(); 11067 11068 /* Here is the main loop of the disk task. It waits for a message, carries 11069 * it out, and sends a reply. 11070 */ 11071 while (TRUE) { 11072 11073 /* Wait for a request to read or write a disk block. */ 11074 if(receive(ANY, &mess) != OK) continue; 11075 11076 device_caller = mess.m_source; 11077 proc_nr = mess.PROC_NR; 11078 11079 /* Now carry out the work. */ File: Page: 774 drivers/libdriver/driver.c 11080 switch(mess.m_type) { 11081 case DEV_OPEN: r = (*dp->dr_open)(dp, &mess); break; 11082 case DEV_CLOSE: r = (*dp->dr_close)(dp, &mess); break; 11083 case DEV_IOCTL: r = (*dp->dr_ioctl)(dp, &mess); break; 11084 case CANCEL: r = (*dp->dr_cancel)(dp, &mess);break; 11085 case DEV_SELECT: r = (*dp->dr_select)(dp, &mess);break; 11086 11087 case DEV_READ: 11088 case DEV_WRITE: r = do_rdwt(dp, &mess); break; 11089 case DEV_GATHER: 11090 case DEV_SCATTER: r = do_vrdwt(dp, &mess); break; 11091 11092 case HARD_INT: /* leftover interrupt or expired timer. */ 11093 if(dp->dr_hw_int) { 11094 (*dp->dr_hw_int)(dp, &mess); 11095 } 11096 continue; 11097 case SYS_SIG: (*dp->dr_signal)(dp, &mess); 11098 continue; /* don't reply */ 11099 case SYN_ALARM: (*dp->dr_alarm)(dp, &mess); 11100 continue; /* don't reply */ 11101 default: 11102 if(dp->dr_other) 11103 r = (*dp->dr_other)(dp, &mess); 11104 else 11105 r = EINVAL; 11106 break; 11107 } 11108 11109 /* Clean up leftover state. */ 11110 (*dp->dr_cleanup)(); 11111 11112 /* Finally, prepare and send the reply message. */ 11113 if (r != EDONTREPLY) { 11114 mess.m_type = TASK_REPLY; 11115 mess.REP_PROC_NR = proc_nr; 11116 /* Status is # of bytes transferred or error code. */ 11117 mess.REP_STATUS = r; 11118 send(device_caller, &mess); 11119 } 11120 } 11121 } 11123 /*===========================================================================* 11124 * init_buffer * 11125 *===========================================================================*/ 11126 PRIVATE void init_buffer() 11127 { 11128 /* Select a buffer that can safely be used for DMA transfers. It may also 11129 * be used to read partition tables and such. Its absolute address is 11130 * 'tmp_phys', the normal address is 'tmp_buf'. 11131 */ 11132 11133 unsigned left; 11134 11135 tmp_buf = buffer; 11136 sys_umap(SELF, D, (vir_bytes)buffer, (phys_bytes)sizeof(buffer), &tmp_phys); 11137 11138 if ((left = dma_bytes_left(tmp_phys)) < DMA_BUF_SIZE) { 11139 /* First half of buffer crosses a 64K boundary, can't DMA into that */ File: Page: 775 drivers/libdriver/driver.c 11140 tmp_buf += left; 11141 tmp_phys += left; 11142 } 11143 } 11145 /*===========================================================================* 11146 * do_rdwt * 11147 *===========================================================================*/ 11148 PRIVATE int do_rdwt(dp, mp) 11149 struct driver *dp; /* device dependent entry points */ 11150 message *mp; /* pointer to read or write message */ 11151 { 11152 /* Carry out a single read or write request. */ 11153 iovec_t iovec1; 11154 int r, opcode; 11155 phys_bytes phys_addr; 11156 11157 /* Disk address? Address and length of the user buffer? */ 11158 if (mp->COUNT < 0) return(EINVAL); 11159 11160 /* Check the user buffer. */ 11161 sys_umap(mp->PROC_NR, D, (vir_bytes) mp->ADDRESS, mp->COUNT, &phys_addr); 11162 if (phys_addr == 0) return(EFAULT); 11163 11164 /* Prepare for I/O. */ 11165 if ((*dp->dr_prepare)(mp->DEVICE) == NIL_DEV) return(ENXIO); 11166 11167 /* Create a one element scatter/gather vector for the buffer. */ 11168 opcode = mp->m_type == DEV_READ ? DEV_GATHER : DEV_SCATTER; 11169 iovec1.iov_addr = (vir_bytes) mp->ADDRESS; 11170 iovec1.iov_size = mp->COUNT; 11171 11172 /* Transfer bytes from/to the device. */ 11173 r = (*dp->dr_transfer)(mp->PROC_NR, opcode, mp->POSITION, &iovec1, 1); 11174 11175 /* Return the number of bytes transferred or an error code. */ 11176 return(r == OK ? (mp->COUNT - iovec1.iov_size) : r); 11177 } 11179 /*==========================================================================* 11180 * do_vrdwt * 11181 *==========================================================================*/ 11182 PRIVATE int do_vrdwt(dp, mp) 11183 struct driver *dp; /* device dependent entry points */ 11184 message *mp; /* pointer to read or write message */ 11185 { 11186 /* Carry out an device read or write to/from a vector of user addresses. 11187 * The "user addresses" are assumed to be safe, i.e. FS transferring to/from 11188 * its own buffers, so they are not checked. 11189 */ 11190 static iovec_t iovec[NR_IOREQS]; 11191 iovec_t *iov; 11192 phys_bytes iovec_size; 11193 unsigned nr_req; 11194 int r; 11195 11196 nr_req = mp->COUNT; /* Length of I/O vector */ 11197 11198 if (mp->m_source < 0) { 11199 /* Called by a task, no need to copy vector. */ File: Page: 776 drivers/libdriver/driver.c 11200 iov = (iovec_t *) mp->ADDRESS; 11201 } else { 11202 /* Copy the vector from the caller to kernel space. */ 11203 if (nr_req > NR_IOREQS) nr_req = NR_IOREQS; 11204 iovec_size = (phys_bytes) (nr_req * sizeof(iovec[0])); 11205 11206 if (OK != sys_datacopy(mp->m_source, (vir_bytes) mp->ADDRESS, 11207 SELF, (vir_bytes) iovec, iovec_size)) 11208 panic((*dp->dr_name)(),"bad I/O vector by", mp->m_source); 11209 iov = iovec; 11210 } 11211 11212 /* Prepare for I/O. */ 11213 if ((*dp->dr_prepare)(mp->DEVICE) == NIL_DEV) return(ENXIO); 11214 11215 /* Transfer bytes from/to the device. */ 11216 r = (*dp->dr_transfer)(mp->PROC_NR, mp->m_type, mp->POSITION, iov, nr_req); 11217 11218 /* Copy the I/O vector back to the caller. */ 11219 if (mp->m_source >= 0) { 11220 sys_datacopy(SELF, (vir_bytes) iovec, 11221 mp->m_source, (vir_bytes) mp->ADDRESS, iovec_size); 11222 } 11223 return(r); 11224 } 11226 /*===========================================================================* 11227 * no_name * 11228 *===========================================================================*/ 11229 PUBLIC char *no_name() 11230 { 11231 /* Use this default name if there is no specific name for the device. This was 11232 * originally done by fetching the name from the task table for this process: 11233 * "return(tasktab[proc_number(proc_ptr) + NR_TASKS].name);", but currently a 11234 * real "noname" is returned. Perhaps, some system information service can be 11235 * queried for a name at a later time. 11236 */ 11237 static char name[] = "noname"; 11238 return name; 11239 } 11241 /*============================================================================* 11242 * do_nop * 11243 *============================================================================*/ 11244 PUBLIC int do_nop(dp, mp) 11245 struct driver *dp; 11246 message *mp; 11247 { 11248 /* Nothing there, or nothing to do. */ 11249 11250 switch (mp->m_type) { 11251 case DEV_OPEN: return(ENODEV); 11252 case DEV_CLOSE: return(OK); 11253 case DEV_IOCTL: return(ENOTTY); 11254 default: return(EIO); 11255 } 11256 } File: Page: 777 drivers/libdriver/driver.c 11258 /*============================================================================* 11259 * nop_signal * 11260 *============================================================================*/ 11261 PUBLIC void nop_signal(dp, mp) 11262 struct driver *dp; 11263 message *mp; 11264 { 11265 /* Default action for signal is to ignore. */ 11266 } 11268 /*============================================================================* 11269 * nop_alarm * 11270 *============================================================================*/ 11271 PUBLIC void nop_alarm(dp, mp) 11272 struct driver *dp; 11273 message *mp; 11274 { 11275 /* Ignore the leftover alarm. */ 11276 } 11278 /*===========================================================================* 11279 * nop_prepare * 11280 *===========================================================================*/ 11281 PUBLIC struct device *nop_prepare(device) 11282 { 11283 /* Nothing to prepare for. */ 11284 return(NIL_DEV); 11285 } 11287 /*===========================================================================* 11288 * nop_cleanup * 11289 *===========================================================================*/ 11290 PUBLIC void nop_cleanup() 11291 { 11292 /* Nothing to clean up. */ 11293 } 11295 /*===========================================================================* 11296 * nop_cancel * 11297 *===========================================================================*/ 11298 PUBLIC int nop_cancel(struct driver *dr, message *m) 11299 { 11300 /* Nothing to do for cancel. */ 11301 return(OK); 11302 } 11304 /*===========================================================================* 11305 * nop_select * 11306 *===========================================================================*/ 11307 PUBLIC int nop_select(struct driver *dr, message *m) 11308 { 11309 /* Nothing to do for select. */ 11310 return(OK); 11311 } 11313 /*============================================================================* 11314 * do_diocntl * 11315 *============================================================================*/ 11316 PUBLIC int do_diocntl(dp, mp) 11317 struct driver *dp; File: Page: 778 drivers/libdriver/driver.c 11318 message *mp; /* pointer to ioctl request */ 11319 { 11320 /* Carry out a partition setting/getting request. */ 11321 struct device *dv; 11322 struct partition entry; 11323 int s; 11324 11325 if (mp->REQUEST != DIOCSETP && mp->REQUEST != DIOCGETP) { 11326 if(dp->dr_other) { 11327 return dp->dr_other(dp, mp); 11328 } else return(ENOTTY); 11329 } 11330 11331 /* Decode the message parameters. */ 11332 if ((dv = (*dp->dr_prepare)(mp->DEVICE)) == NIL_DEV) return(ENXIO); 11333 11334 if (mp->REQUEST == DIOCSETP) { 11335 /* Copy just this one partition table entry. */ 11336 if (OK != (s=sys_datacopy(mp->PROC_NR, (vir_bytes) mp->ADDRESS, 11337 SELF, (vir_bytes) &entry, sizeof(entry)))) 11338 return s; 11339 dv->dv_base = entry.base; 11340 dv->dv_size = entry.size; 11341 } else { 11342 /* Return a partition table entry and the geometry of the drive. */ 11343 entry.base = dv->dv_base; 11344 entry.size = dv->dv_size; 11345 (*dp->dr_geometry)(&entry); 11346 if (OK != (s=sys_datacopy(SELF, (vir_bytes) &entry, 11347 mp->PROC_NR, (vir_bytes) mp->ADDRESS, sizeof(entry)))) 11348 return s; 11349 } 11350 return(OK); 11351 } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/libdriver/drvlib.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 11400 /* IBM device driver utility functions. Author: Kees J. Bot 11401 * 7 Dec 1995 11402 * Entry point: 11403 * partition: partition a disk to the partition table(s) on it. 11404 */ 11405 11406 #include "driver.h" 11407 #include "drvlib.h" 11408 #include 11409 11410 /* Extended partition? */ 11411 #define ext_part(s) ((s) == 0x05 || (s) == 0x0F) 11412 11413 FORWARD _PROTOTYPE( void extpartition, (struct driver *dp, int extdev, 11414 unsigned long extbase) ); 11415 FORWARD _PROTOTYPE( int get_part_table, (struct driver *dp, int device, 11416 unsigned long offset, struct part_entry *table)); 11417 FORWARD _PROTOTYPE( void sort, (struct part_entry *table) ); 11418 11419 #ifndef CD_SECTOR_SIZE File: Page: 779 drivers/libdriver/drvlib.c 11420 #define CD_SECTOR_SIZE 2048 11421 #endif 11422 11423 /*============================================================================* 11424 * partition * 11425 *============================================================================*/ 11426 PUBLIC void partition(dp, device, style, atapi) 11427 struct driver *dp; /* device dependent entry points */ 11428 int device; /* device to partition */ 11429 int style; /* partitioning style: floppy, primary, sub. */ 11430 int atapi; /* atapi device */ 11431 { 11432 /* This routine is called on first open to initialize the partition tables 11433 * of a device. It makes sure that each partition falls safely within the 11434 * device's limits. Depending on the partition style we are either making 11435 * floppy partitions, primary partitions or subpartitions. Only primary 11436 * partitions are sorted, because they are shared with other operating 11437 * systems that expect this. 11438 */ 11439 struct part_entry table[NR_PARTITIONS], *pe; 11440 int disk, par; 11441 struct device *dv; 11442 unsigned long base, limit, part_limit; 11443 11444 /* Get the geometry of the device to partition */ 11445 if ((dv = (*dp->dr_prepare)(device)) == NIL_DEV 11446 || cmp64u(dv->dv_size, 0) == 0) return; 11447 base = div64u(dv->dv_base, SECTOR_SIZE); 11448 limit = base + div64u(dv->dv_size, SECTOR_SIZE); 11449 11450 /* Read the partition table for the device. */ 11451 if(!get_part_table(dp, device, 0L, table)) { 11452 return; 11453 } 11454 11455 /* Compute the device number of the first partition. */ 11456 switch (style) { 11457 case P_FLOPPY: 11458 device += MINOR_fd0p0; 11459 break; 11460 case P_PRIMARY: 11461 sort(table); /* sort a primary partition table */ 11462 device += 1; 11463 break; 11464 case P_SUB: 11465 disk = device / DEV_PER_DRIVE; 11466 par = device % DEV_PER_DRIVE - 1; 11467 device = MINOR_d0p0s0 + (disk * NR_PARTITIONS + par) * NR_PARTITIONS; 11468 } 11469 11470 /* Find an array of devices. */ 11471 if ((dv = (*dp->dr_prepare)(device)) == NIL_DEV) return; 11472 11473 /* Set the geometry of the partitions from the partition table. */ 11474 for (par = 0; par < NR_PARTITIONS; par++, dv++) { 11475 /* Shrink the partition to fit within the device. */ 11476 pe = &table[par]; 11477 part_limit = pe->lowsec + pe->size; 11478 if (part_limit < pe->lowsec) part_limit = limit; 11479 if (part_limit > limit) part_limit = limit; File: Page: 780 drivers/libdriver/drvlib.c 11480 if (pe->lowsec < base) pe->lowsec = base; 11481 if (part_limit < pe->lowsec) part_limit = pe->lowsec; 11482 11483 dv->dv_base = mul64u(pe->lowsec, SECTOR_SIZE); 11484 dv->dv_size = mul64u(part_limit - pe->lowsec, SECTOR_SIZE); 11485 11486 if (style == P_PRIMARY) { 11487 /* Each Minix primary partition can be subpartitioned. */ 11488 if (pe->sysind == MINIX_PART) 11489 partition(dp, device + par, P_SUB, atapi); 11490 11491 /* An extended partition has logical partitions. */ 11492 if (ext_part(pe->sysind)) 11493 extpartition(dp, device + par, pe->lowsec); 11494 } 11495 } 11496 } 11498 /*============================================================================* 11499 * extpartition * 11500 *============================================================================*/ 11501 PRIVATE void extpartition(dp, extdev, extbase) 11502 struct driver *dp; /* device dependent entry points */ 11503 int extdev; /* extended partition to scan */ 11504 unsigned long extbase; /* sector offset of the base extended partition */ 11505 { 11506 /* Extended partitions cannot be ignored alas, because people like to move 11507 * files to and from DOS partitions. Avoid reading this code, it's no fun. 11508 */ 11509 struct part_entry table[NR_PARTITIONS], *pe; 11510 int subdev, disk, par; 11511 struct device *dv; 11512 unsigned long offset, nextoffset; 11513 11514 disk = extdev / DEV_PER_DRIVE; 11515 par = extdev % DEV_PER_DRIVE - 1; 11516 subdev = MINOR_d0p0s0 + (disk * NR_PARTITIONS + par) * NR_PARTITIONS; 11517 11518 offset = 0; 11519 do { 11520 if (!get_part_table(dp, extdev, offset, table)) return; 11521 sort(table); 11522 11523 /* The table should contain one logical partition and optionally 11524 * another extended partition. (It's a linked list.) 11525 */ 11526 nextoffset = 0; 11527 for (par = 0; par < NR_PARTITIONS; par++) { 11528 pe = &table[par]; 11529 if (ext_part(pe->sysind)) { 11530 nextoffset = pe->lowsec; 11531 } else 11532 if (pe->sysind != NO_PART) { 11533 if ((dv = (*dp->dr_prepare)(subdev)) == NIL_DEV) return; 11534 11535 dv->dv_base = mul64u(extbase + offset + pe->lowsec, 11536 SECTOR_SIZE); 11537 dv->dv_size = mul64u(pe->size, SECTOR_SIZE); 11538 11539 /* Out of devices? */ File: Page: 781 drivers/libdriver/drvlib.c 11540 if (++subdev % NR_PARTITIONS == 0) return; 11541 } 11542 } 11543 } while ((offset = nextoffset) != 0); 11544 } 11546 /*============================================================================* 11547 * get_part_table * 11548 *============================================================================*/ 11549 PRIVATE int get_part_table(dp, device, offset, table) 11550 struct driver *dp; 11551 int device; 11552 unsigned long offset; /* sector offset to the table */ 11553 struct part_entry *table; /* four entries */ 11554 { 11555 /* Read the partition table for the device, return true iff there were no 11556 * errors. 11557 */ 11558 iovec_t iovec1; 11559 off_t position; 11560 static unsigned char partbuf[CD_SECTOR_SIZE]; 11561 11562 position = offset << SECTOR_SHIFT; 11563 iovec1.iov_addr = (vir_bytes) partbuf; 11564 iovec1.iov_size = CD_SECTOR_SIZE; 11565 if ((*dp->dr_prepare)(device) != NIL_DEV) { 11566 (void) (*dp->dr_transfer)(SELF, DEV_GATHER, position, &iovec1, 1); 11567 } 11568 if (iovec1.iov_size != 0) { 11569 return 0; 11570 } 11571 if (partbuf[510] != 0x55 || partbuf[511] != 0xAA) { 11572 /* Invalid partition table. */ 11573 return 0; 11574 } 11575 memcpy(table, (partbuf + PART_TABLE_OFF), NR_PARTITIONS * sizeof(table[0])); 11576 return 1; 11577 } 11579 /*===========================================================================* 11580 * sort * 11581 *===========================================================================*/ 11582 PRIVATE void sort(table) 11583 struct part_entry *table; 11584 { 11585 /* Sort a partition table. */ 11586 struct part_entry *pe, tmp; 11587 int n = NR_PARTITIONS; 11588 11589 do { 11590 for (pe = table; pe < table + NR_PARTITIONS-1; pe++) { 11591 if (pe[0].sysind == NO_PART 11592 || (pe[0].lowsec > pe[1].lowsec 11593 && pe[1].sysind != NO_PART)) { 11594 tmp = pe[0]; pe[0] = pe[1]; pe[1] = tmp; 11595 } 11596 } 11597 } while (--n > 0); 11598 } File: Page: 782 drivers/memory/memory.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/memory/memory.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 11600 /* This file contains the device dependent part of the drivers for the 11601 * following special files: 11602 * /dev/ram - RAM disk 11603 * /dev/mem - absolute memory 11604 * /dev/kmem - kernel virtual memory 11605 * /dev/null - null device (data sink) 11606 * /dev/boot - boot device loaded from boot image 11607 * /dev/zero - null byte stream generator 11608 * 11609 * Changes: 11610 * Apr 29, 2005 added null byte generator (Jorrit N. Herder) 11611 * Apr 09, 2005 added support for boot device (Jorrit N. Herder) 11612 * Jul 26, 2004 moved RAM driver to user-space (Jorrit N. Herder) 11613 * Apr 20, 1992 device dependent/independent split (Kees J. Bot) 11614 */ 11615 11616 #include "../drivers.h" 11617 #include "../libdriver/driver.h" 11618 #include 11619 #include "../../kernel/const.h" 11620 #include "../../kernel/config.h" 11621 #include "../../kernel/type.h" 11622 11623 #include "assert.h" 11624 11625 #define NR_DEVS 6 /* number of minor devices */ 11626 11627 PRIVATE struct device m_geom[NR_DEVS]; /* base and size of each device */ 11628 PRIVATE int m_seg[NR_DEVS]; /* segment index of each device */ 11629 PRIVATE int m_device; /* current device */ 11630 PRIVATE struct kinfo kinfo; /* kernel information */ 11631 PRIVATE struct machine machine; /* machine information */ 11632 11633 extern int errno; /* error number for PM calls */ 11634 11635 FORWARD _PROTOTYPE( char *m_name, (void) ); 11636 FORWARD _PROTOTYPE( struct device *m_prepare, (int device) ); 11637 FORWARD _PROTOTYPE( int m_transfer, (int proc_nr, int opcode, off_t position, 11638 iovec_t *iov, unsigned nr_req) ); 11639 FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr) ); 11640 FORWARD _PROTOTYPE( void m_init, (void) ); 11641 FORWARD _PROTOTYPE( int m_ioctl, (struct driver *dp, message *m_ptr) ); 11642 FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry) ); 11643 11644 /* Entry points to this driver. */ 11645 PRIVATE struct driver m_dtab = { 11646 m_name, /* current device's name */ 11647 m_do_open, /* open or mount */ 11648 do_nop, /* nothing on a close */ 11649 m_ioctl, /* specify ram disk geometry */ 11650 m_prepare, /* prepare for I/O on a given minor device */ 11651 m_transfer, /* do the I/O */ 11652 nop_cleanup, /* no need to clean up */ 11653 m_geometry, /* memory device "geometry" */ 11654 nop_signal, /* system signals */ File: Page: 783 drivers/memory/memory.c 11655 nop_alarm, 11656 nop_cancel, 11657 nop_select, 11658 NULL, 11659 NULL 11660 }; 11661 11662 /* Buffer for the /dev/zero null byte feed. */ 11663 #define ZERO_BUF_SIZE 1024 11664 PRIVATE char dev_zero[ZERO_BUF_SIZE]; 11665 11666 #define click_to_round_k(n) \ 11667 ((unsigned) ((((unsigned long) (n) << CLICK_SHIFT) + 512) / 1024)) 11668 11669 /*===========================================================================* 11670 * main * 11671 *===========================================================================*/ 11672 PUBLIC int main(void) 11673 { 11674 /* Main program. Initialize the memory driver and start the main loop. */ 11675 m_init(); 11676 driver_task(&m_dtab); 11677 return(OK); 11678 } 11680 /*===========================================================================* 11681 * m_name * 11682 *===========================================================================*/ 11683 PRIVATE char *m_name() 11684 { 11685 /* Return a name for the current device. */ 11686 static char name[] = "memory"; 11687 return name; 11688 } 11690 /*===========================================================================* 11691 * m_prepare * 11692 *===========================================================================*/ 11693 PRIVATE struct device *m_prepare(device) 11694 int device; 11695 { 11696 /* Prepare for I/O on a device: check if the minor device number is ok. */ 11697 if (device < 0 || device >= NR_DEVS) return(NIL_DEV); 11698 m_device = device; 11699 11700 return(&m_geom[device]); 11701 } 11703 /*===========================================================================* 11704 * m_transfer * 11705 *===========================================================================*/ 11706 PRIVATE int m_transfer(proc_nr, opcode, position, iov, nr_req) 11707 int proc_nr; /* process doing the request */ 11708 int opcode; /* DEV_GATHER or DEV_SCATTER */ 11709 off_t position; /* offset on device to read or write */ 11710 iovec_t *iov; /* pointer to read or write request vector */ 11711 unsigned nr_req; /* length of request vector */ 11712 { 11713 /* Read or write one the driver's minor devices. */ 11714 phys_bytes mem_phys; File: Page: 784 drivers/memory/memory.c 11715 int seg; 11716 unsigned count, left, chunk; 11717 vir_bytes user_vir; 11718 struct device *dv; 11719 unsigned long dv_size; 11720 int s; 11721 11722 /* Get minor device number and check for /dev/null. */ 11723 dv = &m_geom[m_device]; 11724 dv_size = cv64ul(dv->dv_size); 11725 11726 while (nr_req > 0) { 11727 11728 /* How much to transfer and where to / from. */ 11729 count = iov->iov_size; 11730 user_vir = iov->iov_addr; 11731 11732 switch (m_device) { 11733 11734 /* No copying; ignore request. */ 11735 case NULL_DEV: 11736 if (opcode == DEV_GATHER) return(OK); /* always at EOF */ 11737 break; 11738 11739 /* Virtual copying. For RAM disk, kernel memory and boot device. */ 11740 case RAM_DEV: 11741 case KMEM_DEV: 11742 case BOOT_DEV: 11743 if (position >= dv_size) return(OK); /* check for EOF */ 11744 if (position + count > dv_size) count = dv_size - position; 11745 seg = m_seg[m_device]; 11746 11747 if (opcode == DEV_GATHER) { /* copy actual data */ 11748 sys_vircopy(SELF,seg,position, proc_nr,D,user_vir, count); 11749 } else { 11750 sys_vircopy(proc_nr,D,user_vir, SELF,seg,position, count); 11751 } 11752 break; 11753 11754 /* Physical copying. Only used to access entire memory. */ 11755 case MEM_DEV: 11756 if (position >= dv_size) return(OK); /* check for EOF */ 11757 if (position + count > dv_size) count = dv_size - position; 11758 mem_phys = cv64ul(dv->dv_base) + position; 11759 11760 if (opcode == DEV_GATHER) { /* copy data */ 11761 sys_physcopy(NONE, PHYS_SEG, mem_phys, 11762 proc_nr, D, user_vir, count); 11763 } else { 11764 sys_physcopy(proc_nr, D, user_vir, 11765 NONE, PHYS_SEG, mem_phys, count); 11766 } 11767 break; 11768 11769 /* Null byte stream generator. */ 11770 case ZERO_DEV: 11771 if (opcode == DEV_GATHER) { 11772 left = count; 11773 while (left > 0) { 11774 chunk = (left > ZERO_BUF_SIZE) ? ZERO_BUF_SIZE : left; File: Page: 785 drivers/memory/memory.c 11775 if (OK != (s=sys_vircopy(SELF, D, (vir_bytes) dev_zero, 11776 proc_nr, D, user_vir, chunk))) 11777 report("MEM","sys_vircopy failed", s); 11778 left -= chunk; 11779 user_vir += chunk; 11780 } 11781 } 11782 break; 11783 11784 /* Unknown (illegal) minor device. */ 11785 default: 11786 return(EINVAL); 11787 } 11788 11789 /* Book the number of bytes transferred. */ 11790 position += count; 11791 iov->iov_addr += count; 11792 if ((iov->iov_size -= count) == 0) { iov++; nr_req--; } 11793 11794 } 11795 return(OK); 11796 } 11798 /*===========================================================================* 11799 * m_do_open * 11800 *===========================================================================*/ 11801 PRIVATE int m_do_open(dp, m_ptr) 11802 struct driver *dp; 11803 message *m_ptr; 11804 { 11805 /* Check device number on open. (This used to give I/O privileges to a 11806 * process opening /dev/mem or /dev/kmem. This may be needed in case of 11807 * memory mapped I/O. With system calls to do I/O this is no longer needed.) 11808 */ 11809 if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO); 11810 11811 return(OK); 11812 } 11814 /*===========================================================================* 11815 * m_init * 11816 *===========================================================================*/ 11817 PRIVATE void m_init() 11818 { 11819 /* Initialize this task. All minor devices are initialized one by one. */ 11820 int i, s; 11821 11822 if (OK != (s=sys_getkinfo(&kinfo))) { 11823 panic("MEM","Couldn't get kernel information.",s); 11824 } 11825 11826 /* Install remote segment for /dev/kmem memory. */ 11827 m_geom[KMEM_DEV].dv_base = cvul64(kinfo.kmem_base); 11828 m_geom[KMEM_DEV].dv_size = cvul64(kinfo.kmem_size); 11829 if (OK != (s=sys_segctl(&m_seg[KMEM_DEV], (u16_t *) &s, (vir_bytes *) &s, 11830 kinfo.kmem_base, kinfo.kmem_size))) { 11831 panic("MEM","Couldn't install remote segment.",s); 11832 } 11833 11834 /* Install remote segment for /dev/boot memory, if enabled. */ File: Page: 786 drivers/memory/memory.c 11835 m_geom[BOOT_DEV].dv_base = cvul64(kinfo.bootdev_base); 11836 m_geom[BOOT_DEV].dv_size = cvul64(kinfo.bootdev_size); 11837 if (kinfo.bootdev_base > 0) { 11838 if (OK != (s=sys_segctl(&m_seg[BOOT_DEV], (u16_t *) &s, (vir_bytes *) &s, 11839 kinfo.bootdev_base, kinfo.bootdev_size))) { 11840 panic("MEM","Couldn't install remote segment.",s); 11841 } 11842 } 11843 11844 /* Initialize /dev/zero. Simply write zeros into the buffer. */ 11845 for (i=0; iDEVICE)) == NIL_DEV) return(ENXIO); 11872 11873 switch (m_ptr->REQUEST) { 11874 case MIOCRAMSIZE: { 11875 /* FS wants to create a new RAM disk with the given size. */ 11876 phys_bytes ramdev_size; 11877 phys_bytes ramdev_base; 11878 int s; 11879 11880 if (m_ptr->PROC_NR != FS_PROC_NR) { 11881 report("MEM", "warning, MIOCRAMSIZE called by", m_ptr->PROC_NR); 11882 return(EPERM); 11883 } 11884 11885 /* Try to allocate a piece of memory for the RAM disk. */ 11886 ramdev_size = m_ptr->POSITION; 11887 if (allocmem(ramdev_size, &ramdev_base) < 0) { 11888 report("MEM", "warning, allocmem failed", errno); 11889 return(ENOMEM); 11890 } 11891 dv->dv_base = cvul64(ramdev_base); 11892 dv->dv_size = cvul64(ramdev_size); 11893 11894 if (OK != (s=sys_segctl(&m_seg[RAM_DEV], (u16_t *) &s, (vir_bytes *) &s, File: Page: 787 drivers/memory/memory.c 11895 ramdev_base, ramdev_size))) { 11896 panic("MEM","Couldn't install remote segment.",s); 11897 } 11898 break; 11899 } 11900 11901 default: 11902 return(do_diocntl(&m_dtab, m_ptr)); 11903 } 11904 return(OK); 11905 } 11907 /*===========================================================================* 11908 * m_geometry * 11909 *===========================================================================*/ 11910 PRIVATE void m_geometry(entry) 11911 struct partition *entry; 11912 { 11913 /* Memory devices don't have a geometry, but the outside world insists. */ 11914 entry->cylinders = div64u(m_geom[m_device].dv_size, SECTOR_SIZE) / (64 * 32); 11915 entry->heads = 64; 11916 entry->sectors = 32; 11917 } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/at_wini/at_wini.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 12000 #include "../drivers.h" 12001 #include "../libdriver/driver.h" 12002 #include "../libdriver/drvlib.h" 12003 12004 _PROTOTYPE(int main, (void)); 12005 12006 #define VERBOSE 0 /* display identify messages during boot */ 12007 #define ENABLE_ATAPI 0 /* add ATAPI cd-rom support to driver */ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/at_wini/at_wini.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 12100 /* This file contains the device dependent part of a driver for the IBM-AT 12101 * winchester controller. Written by Adri Koppes. 12102 * 12103 * The file contains one entry point: 12104 * 12105 * at_winchester_task: main entry when system is brought up 12106 * 12107 * Changes: 12108 * Aug 19, 2005 ata pci support, supports SATA (Ben Gras) 12109 * Nov 18, 2004 moved AT disk driver to user-space (Jorrit N. Herder) 12110 * Aug 20, 2004 watchdogs replaced by sync alarms (Jorrit N. Herder) 12111 * Mar 23, 2000 added ATAPI CDROM support (Michael Temari) 12112 * May 14, 2000 d-d/i rewrite (Kees J. Bot) 12113 * Apr 13, 1992 device dependent/independent split (Kees J. Bot) 12114 */ File: Page: 788 drivers/at_wini/at_wini.c 12115 12116 #include "at_wini.h" 12117 #include "../libpci/pci.h" 12118 12119 #include 12120 #include 12121 #include 12122 12123 #define ATAPI_DEBUG 0 /* To debug ATAPI code. */ 12124 12125 /* I/O Ports used by winchester disk controllers. */ 12126 12127 /* Read and write registers */ 12128 #define REG_CMD_BASE0 0x1F0 /* command base register of controller 0 */ 12129 #define REG_CMD_BASE1 0x170 /* command base register of controller 1 */ 12130 #define REG_CTL_BASE0 0x3F6 /* control base register of controller 0 */ 12131 #define REG_CTL_BASE1 0x376 /* control base register of controller 1 */ 12132 12133 #define REG_DATA 0 /* data register (offset from the base reg.) */ 12134 #define REG_PRECOMP 1 /* start of write precompensation */ 12135 #define REG_COUNT 2 /* sectors to transfer */ 12136 #define REG_SECTOR 3 /* sector number */ 12137 #define REG_CYL_LO 4 /* low byte of cylinder number */ 12138 #define REG_CYL_HI 5 /* high byte of cylinder number */ 12139 #define REG_LDH 6 /* lba, drive and head */ 12140 #define LDH_DEFAULT 0xA0 /* ECC enable, 512 bytes per sector */ 12141 #define LDH_LBA 0x40 /* Use LBA addressing */ 12142 #define ldh_init(drive) (LDH_DEFAULT | ((drive) << 4)) 12143 12144 /* Read only registers */ 12145 #define REG_STATUS 7 /* status */ 12146 #define STATUS_BSY 0x80 /* controller busy */ 12147 #define STATUS_RDY 0x40 /* drive ready */ 12148 #define STATUS_WF 0x20 /* write fault */ 12149 #define STATUS_SC 0x10 /* seek complete (obsolete) */ 12150 #define STATUS_DRQ 0x08 /* data transfer request */ 12151 #define STATUS_CRD 0x04 /* corrected data */ 12152 #define STATUS_IDX 0x02 /* index pulse */ 12153 #define STATUS_ERR 0x01 /* error */ 12154 #define STATUS_ADMBSY 0x100 /* administratively busy (software) */ 12155 #define REG_ERROR 1 /* error code */ 12156 #define ERROR_BB 0x80 /* bad block */ 12157 #define ERROR_ECC 0x40 /* bad ecc bytes */ 12158 #define ERROR_ID 0x10 /* id not found */ 12159 #define ERROR_AC 0x04 /* aborted command */ 12160 #define ERROR_TK 0x02 /* track zero error */ 12161 #define ERROR_DM 0x01 /* no data address mark */ 12162 12163 /* Write only registers */ 12164 #define REG_COMMAND 7 /* command */ 12165 #define CMD_IDLE 0x00 /* for w_command: drive idle */ 12166 #define CMD_RECALIBRATE 0x10 /* recalibrate drive */ 12167 #define CMD_READ 0x20 /* read data */ 12168 #define CMD_READ_EXT 0x24 /* read data (LBA48 addressed) */ 12169 #define CMD_WRITE 0x30 /* write data */ 12170 #define CMD_WRITE_EXT 0x34 /* write data (LBA48 addressed) */ 12171 #define CMD_READVERIFY 0x40 /* read verify */ 12172 #define CMD_FORMAT 0x50 /* format track */ 12173 #define CMD_SEEK 0x70 /* seek cylinder */ 12174 #define CMD_DIAG 0x90 /* execute device diagnostics */ File: Page: 789 drivers/at_wini/at_wini.c 12175 #define CMD_SPECIFY 0x91 /* specify parameters */ 12176 #define ATA_IDENTIFY 0xEC /* identify drive */ 12177 /* #define REG_CTL 0x206 */ /* control register */ 12178 #define REG_CTL 0 /* control register */ 12179 #define CTL_NORETRY 0x80 /* disable access retry */ 12180 #define CTL_NOECC 0x40 /* disable ecc retry */ 12181 #define CTL_EIGHTHEADS 0x08 /* more than eight heads */ 12182 #define CTL_RESET 0x04 /* reset controller */ 12183 #define CTL_INTDISABLE 0x02 /* disable interrupts */ 12184 12185 #define REG_STATUS 7 /* status */ 12186 #define STATUS_BSY 0x80 /* controller busy */ 12187 #define STATUS_DRDY 0x40 /* drive ready */ 12188 #define STATUS_DMADF 0x20 /* dma ready/drive fault */ 12189 #define STATUS_SRVCDSC 0x10 /* service or dsc */ 12190 #define STATUS_DRQ 0x08 /* data transfer request */ 12191 #define STATUS_CORR 0x04 /* correctable error occurred */ 12192 #define STATUS_CHECK 0x01 /* check error */ 12193 12194 /* Interrupt request lines. */ 12195 #define NO_IRQ 0 /* no IRQ set yet */ 12196 12197 #define ATAPI_PACKETSIZE 12 12198 #define SENSE_PACKETSIZE 18 12199 12200 /* Common command block */ 12201 struct command { 12202 u8_t precomp; /* REG_PRECOMP, etc. */ 12203 u8_t count; 12204 u8_t sector; 12205 u8_t cyl_lo; 12206 u8_t cyl_hi; 12207 u8_t ldh; 12208 u8_t command; 12209 }; 12210 12211 /* Error codes */ 12212 #define ERR (-1) /* general error */ 12213 #define ERR_BAD_SECTOR (-2) /* block marked bad detected */ 12214 12215 /* Some controllers don't interrupt, the clock will wake us up. */ 12216 #define WAKEUP (32*HZ) /* drive may be out for 31 seconds max */ 12217 12218 /* Miscellaneous. */ 12219 #define MAX_DRIVES 8 12220 #define COMPAT_DRIVES 4 12221 #define MAX_SECS 256 /* controller can transfer this many sectors */ 12222 #define MAX_ERRORS 4 /* how often to try rd/wt before quitting */ 12223 #define NR_MINORS (MAX_DRIVES * DEV_PER_DRIVE) 12224 #define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS) 12225 #define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE) 12226 #define DELAY_USECS 1000 /* controller timeout in microseconds */ 12227 #define DELAY_TICKS 1 /* controller timeout in ticks */ 12228 #define DEF_TIMEOUT_TICKS 300 /* controller timeout in ticks */ 12229 #define RECOVERY_USECS 500000 /* controller recovery time in microseconds */ 12230 #define RECOVERY_TICKS 30 /* controller recovery time in ticks */ 12231 #define INITIALIZED 0x01 /* drive is initialized */ 12232 #define DEAF 0x02 /* controller must be reset */ 12233 #define SMART 0x04 /* drive supports ATA commands */ 12234 #define ATAPI 0 /* don't bother with ATAPI; optimise out */ File: Page: 790 drivers/at_wini/at_wini.c 12235 #define IDENTIFIED 0x10 /* w_identify done successfully */ 12236 #define IGNORING 0x20 /* w_identify failed once */ 12237 12238 /* Timeouts and max retries. */ 12239 int timeout_ticks = DEF_TIMEOUT_TICKS, max_errors = MAX_ERRORS; 12240 int wakeup_ticks = WAKEUP; 12241 long w_standard_timeouts = 0, w_pci_debug = 0, w_instance = 0, 12242 w_lba48 = 0, atapi_debug = 0; 12243 12244 int w_testing = 0, w_silent = 0; 12245 12246 int w_next_drive = 0; 12247 12248 /* Variables. */ 12249 12250 /* wini is indexed by controller first, then drive (0-3). 12251 * controller 0 is always the 'compatability' ide controller, at 12252 * the fixed locations, whether present or not. 12253 */ 12254 PRIVATE struct wini { /* main drive struct, one entry per drive */ 12255 unsigned state; /* drive state: deaf, initialized, dead */ 12256 unsigned w_status; /* device status register */ 12257 unsigned base_cmd; /* command base register */ 12258 unsigned base_ctl; /* control base register */ 12259 unsigned irq; /* interrupt request line */ 12260 unsigned irq_mask; /* 1 << irq */ 12261 unsigned irq_need_ack; /* irq needs to be acknowledged */ 12262 int irq_hook_id; /* id of irq hook at the kernel */ 12263 int lba48; /* supports lba48 */ 12264 unsigned lcylinders; /* logical number of cylinders (BIOS) */ 12265 unsigned lheads; /* logical number of heads */ 12266 unsigned lsectors; /* logical number of sectors per track */ 12267 unsigned pcylinders; /* physical number of cylinders (translated) */ 12268 unsigned pheads; /* physical number of heads */ 12269 unsigned psectors; /* physical number of sectors per track */ 12270 unsigned ldhpref; /* top four bytes of the LDH (head) register */ 12271 unsigned precomp; /* write precompensation cylinder / 4 */ 12272 unsigned max_count; /* max request for this drive */ 12273 unsigned open_ct; /* in-use count */ 12274 struct device part[DEV_PER_DRIVE]; /* disks and partitions */ 12275 struct device subpart[SUB_PER_DRIVE]; /* subpartitions */ 12276 } wini[MAX_DRIVES], *w_wn; 12277 12278 PRIVATE int w_device = -1; 12279 PRIVATE int w_controller = -1; 12280 PRIVATE int w_major = -1; 12281 PRIVATE char w_id_string[40]; 12282 12283 PRIVATE int win_tasknr; /* my task number */ 12284 PRIVATE int w_command; /* current command in execution */ 12285 PRIVATE u8_t w_byteval; /* used for SYS_IRQCTL */ 12286 PRIVATE int w_drive; /* selected drive */ 12287 PRIVATE int w_controller; /* selected controller */ 12288 PRIVATE struct device *w_dv; /* device's base and size */ 12289 12290 FORWARD _PROTOTYPE( void init_params, (void) ); 12291 FORWARD _PROTOTYPE( void init_drive, (struct wini *, int, int, int, int, int, int)); 12292 FORWARD _PROTOTYPE( void init_params_pci, (int) ); 12293 FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) ); 12294 FORWARD _PROTOTYPE( struct device *w_prepare, (int dev) ); File: Page: 791 drivers/at_wini/at_wini.c 12295 FORWARD _PROTOTYPE( int w_identify, (void) ); 12296 FORWARD _PROTOTYPE( char *w_name, (void) ); 12297 FORWARD _PROTOTYPE( int w_specify, (void) ); 12298 FORWARD _PROTOTYPE( int w_io_test, (void) ); 12299 FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, off_t position, 12300 iovec_t *iov, unsigned nr_req) ); 12301 FORWARD _PROTOTYPE( int com_out, (struct command *cmd) ); 12302 FORWARD _PROTOTYPE( void w_need_reset, (void) ); 12303 FORWARD _PROTOTYPE( void ack_irqs, (unsigned int) ); 12304 FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) ); 12305 FORWARD _PROTOTYPE( int w_other, (struct driver *dp, message *m_ptr) ); 12306 FORWARD _PROTOTYPE( int w_hw_int, (struct driver *dp, message *m_ptr) ); 12307 FORWARD _PROTOTYPE( int com_simple, (struct command *cmd) ); 12308 FORWARD _PROTOTYPE( void w_timeout, (void) ); 12309 FORWARD _PROTOTYPE( int w_reset, (void) ); 12310 FORWARD _PROTOTYPE( void w_intr_wait, (void) ); 12311 FORWARD _PROTOTYPE( int at_intr_wait, (void) ); 12312 FORWARD _PROTOTYPE( int w_waitfor, (int mask, int value) ); 12313 FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry) ); 12314 12315 /* Entry points to this driver. */ 12316 PRIVATE struct driver w_dtab = { 12317 w_name, /* current device's name */ 12318 w_do_open, /* open or mount request, initialize device */ 12319 w_do_close, /* release device */ 12320 do_diocntl, /* get or set a partition's geometry */ 12321 w_prepare, /* prepare for I/O on a given minor device */ 12322 w_transfer, /* do the I/O */ 12323 nop_cleanup, /* nothing to clean up */ 12324 w_geometry, /* tell the geometry of the disk */ 12325 nop_signal, /* no cleanup needed on shutdown */ 12326 nop_alarm, /* ignore leftover alarms */ 12327 nop_cancel, /* ignore CANCELs */ 12328 nop_select, /* ignore selects */ 12329 w_other, /* catch-all for unrecognized commands and ioctls */ 12330 w_hw_int /* leftover hardware interrupts */ 12331 }; 12332 12333 /*===========================================================================* 12334 * at_winchester_task * 12335 *===========================================================================*/ 12336 PUBLIC int main() 12337 { 12338 /* Set special disk parameters then call the generic main loop. */ 12339 init_params(); 12340 driver_task(&w_dtab); 12341 return(OK); 12342 } 12344 /*===========================================================================* 12345 * init_params * 12346 *===========================================================================*/ 12347 PRIVATE void init_params() 12348 { 12349 /* This routine is called at startup to initialize the drive parameters. */ 12350 12351 u16_t parv[2]; 12352 unsigned int vector, size; 12353 int drive, nr_drives; 12354 struct wini *wn; File: Page: 792 drivers/at_wini/at_wini.c 12355 u8_t params[16]; 12356 int s; 12357 12358 /* Boot variables. */ 12359 env_parse("ata_std_timeout", "d", 0, &w_standard_timeouts, 0, 1); 12360 env_parse("ata_pci_debug", "d", 0, &w_pci_debug, 0, 1); 12361 env_parse("ata_instance", "d", 0, &w_instance, 0, 8); 12362 env_parse("ata_lba48", "d", 0, &w_lba48, 0, 1); 12363 env_parse("atapi_debug", "d", 0, &atapi_debug, 0, 1); 12364 12365 if (w_instance == 0) { 12366 /* Get the number of drives from the BIOS data area */ 12367 if ((s=sys_vircopy(SELF, BIOS_SEG, NR_HD_DRIVES_ADDR, 12368 SELF, D, (vir_bytes) params, NR_HD_DRIVES_SIZE)) != OK) 12369 panic(w_name(), "Couldn't read BIOS", s); 12370 if ((nr_drives = params[0]) > 2) nr_drives = 2; 12371 12372 for (drive = 0, wn = wini; drive < COMPAT_DRIVES; drive++, wn++) { 12373 if (drive < nr_drives) { 12374 /* Copy the BIOS parameter vector */ 12375 vector = (drive == 0) ? BIOS_HD0_PARAMS_ADDR: BIOS_HD1_PARAMS_ADDR; 12376 size = (drive == 0) ? BIOS_HD0_PARAMS_SIZE: BIOS_HD1_PARAMS_SIZE; 12377 if ((s=sys_vircopy(SELF, BIOS_SEG, vector, 12378 SELF, D, (vir_bytes) parv, size)) != OK) 12379 panic(w_name(), "Couldn't read BIOS", s); 12380 12381 /* Calculate the address of the parameters and copy them */ 12382 if ((s=sys_vircopy( 12383 SELF, BIOS_SEG, hclick_to_physb(parv[1]) + parv[0], 12384 SELF, D, (phys_bytes) params, 16L))!=OK) 12385 panic(w_name(),"Couldn't copy parameters", s); 12386 12387 /* Copy the parameters to the structures of the drive */ 12388 wn->lcylinders = bp_cylinders(params); 12389 wn->lheads = bp_heads(params); 12390 wn->lsectors = bp_sectors(params); 12391 wn->precomp = bp_precomp(params) >> 2; 12392 } 12393 12394 /* Fill in non-BIOS parameters. */ 12395 init_drive(wn, 12396 drive < 2 ? REG_CMD_BASE0 : REG_CMD_BASE1, 12397 drive < 2 ? REG_CTL_BASE0 : REG_CTL_BASE1, 12398 NO_IRQ, 0, 0, drive); 12399 w_next_drive++; 12400 } 12401 } 12402 12403 /* Look for controllers on the pci bus. Skip none the first instance, 12404 * skip one and then 2 for every instance, for every next instance. 12405 */ 12406 if (w_instance == 0) 12407 init_params_pci(0); 12408 else 12409 init_params_pci(w_instance*2-1); 12410 12411 } 12413 #define ATA_IF_NOTCOMPAT1 (1L << 0) 12414 #define ATA_IF_NOTCOMPAT2 (1L << 2) File: Page: 793 drivers/at_wini/at_wini.c 12415 12416 /*===========================================================================* 12417 * init_drive * 12418 *===========================================================================*/ 12419 PRIVATE void init_drive(struct wini *w, int base_cmd, int base_ctl, int irq, int ack, int hook, int drive) 12420 { 12421 w->state = 0; 12422 w->w_status = 0; 12423 w->base_cmd = base_cmd; 12424 w->base_ctl = base_ctl; 12425 w->irq = irq; 12426 w->irq_mask = 1 << irq; 12427 w->irq_need_ack = ack; 12428 w->irq_hook_id = hook; 12429 w->ldhpref = ldh_init(drive); 12430 w->max_count = MAX_SECS << SECTOR_SHIFT; 12431 w->lba48 = 0; 12432 } 12434 /*===========================================================================* 12435 * init_params_pci * 12436 *===========================================================================*/ 12437 PRIVATE void init_params_pci(int skip) 12438 { 12439 int r, devind, drive; 12440 u16_t vid, did; 12441 pci_init(); 12442 for(drive = w_next_drive; drive < MAX_DRIVES; drive++) 12443 wini[drive].state = IGNORING; 12444 for(r = pci_first_dev(&devind, &vid, &did); 12445 r != 0 && w_next_drive < MAX_DRIVES; r = pci_next_dev(&devind, &vid, &did)) { 12446 int interface, irq, irq_hook; 12447 /* Base class must be 01h (mass storage), subclass must 12448 * be 01h (ATA). 12449 */ 12450 if (pci_attr_r8(devind, PCI_BCR) != 0x01 || 12451 pci_attr_r8(devind, PCI_SCR) != 0x01) { 12452 continue; 12453 } 12454 /* Found a controller. 12455 * Programming interface register tells us more. 12456 */ 12457 interface = pci_attr_r8(devind, PCI_PIFR); 12458 irq = pci_attr_r8(devind, PCI_ILR); 12459 12460 /* Any non-compat drives? */ 12461 if (interface & (ATA_IF_NOTCOMPAT1 | ATA_IF_NOTCOMPAT2)) { 12462 int s; 12463 irq_hook = irq; 12464 if (skip > 0) { 12465 if (w_pci_debug) printf("atapci skipping controller (remain %d)\n", skip); 12466 skip--; 12467 continue; 12468 } 12469 if ((s=sys_irqsetpolicy(irq, 0, &irq_hook)) != OK) { 12470 printf("atapci: couldn't set IRQ policy %d\n", irq); 12471 continue; 12472 } 12473 if ((s=sys_irqenable(&irq_hook)) != OK) { 12474 printf("atapci: couldn't enable IRQ line %d\n", irq); File: Page: 794 drivers/at_wini/at_wini.c 12475 continue; 12476 } 12477 } else { 12478 /* If not.. this is not the ata-pci controller we're 12479 * looking for. 12480 */ 12481 if (w_pci_debug) printf("atapci skipping compatability controller\n"); 12482 continue; 12483 } 12484 12485 /* Primary channel not in compatability mode? */ 12486 if (interface & ATA_IF_NOTCOMPAT1) { 12487 u32_t base_cmd, base_ctl; 12488 base_cmd = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0; 12489 base_ctl = pci_attr_r32(devind, PCI_BAR_2) & 0xffffffe0; 12490 if (base_cmd != REG_CMD_BASE0 && base_cmd != REG_CMD_BASE1) { 12491 init_drive(&wini[w_next_drive], 12492 base_cmd, base_ctl, irq, 1, irq_hook, 0); 12493 init_drive(&wini[w_next_drive+1], 12494 base_cmd, base_ctl, irq, 1, irq_hook, 1); 12495 if (w_pci_debug) 12496 printf("atapci %d: 0x%x 0x%x irq %d\n", devind, base_cmd, base_ctl, irq); 12497 } else printf("atapci: ignored drives on primary channel, base %x\n", base_cmd); 12498 } 12499 12500 /* Secondary channel not in compatability mode? */ 12501 if (interface & ATA_IF_NOTCOMPAT2) { 12502 u32_t base_cmd, base_ctl; 12503 base_cmd = pci_attr_r32(devind, PCI_BAR_3) & 0xffffffe0; 12504 base_ctl = pci_attr_r32(devind, PCI_BAR_4) & 0xffffffe0; 12505 if (base_cmd != REG_CMD_BASE0 && base_cmd != REG_CMD_BASE1) { 12506 init_drive(&wini[w_next_drive+2], 12507 base_cmd, base_ctl, irq, 1, irq_hook, 2); 12508 init_drive(&wini[w_next_drive+3], 12509 base_cmd, base_ctl, irq, 1, irq_hook, 3); 12510 if (w_pci_debug) 12511 printf("atapci %d: 0x%x 0x%x irq %d\n", devind, base_cmd, base_ctl, irq); 12512 } else printf("atapci: ignored drives on secondary channel, base %x\n", base_cmd); 12513 } 12514 w_next_drive += 4; 12515 } 12516 } 12518 /*===========================================================================* 12519 * w_do_open * 12520 *===========================================================================*/ 12521 PRIVATE int w_do_open(dp, m_ptr) 12522 struct driver *dp; 12523 message *m_ptr; 12524 { 12525 /* Device open: Initialize the controller and read the partition table. */ 12526 12527 struct wini *wn; 12528 12529 if (w_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO); 12530 12531 wn = w_wn; 12532 12533 /* If we've probed it before and it failed, don't probe it again. */ 12534 if (wn->state & IGNORING) return ENXIO; File: Page: 795 drivers/at_wini/at_wini.c 12535 12536 /* If we haven't identified it yet, or it's gone deaf, 12537 * (re-)identify it. 12538 */ 12539 if (!(wn->state & IDENTIFIED) || (wn->state & DEAF)) { 12540 /* Try to identify the device. */ 12541 if (w_identify() != OK) { 12542 if (wn->state & DEAF) w_reset(); 12543 wn->state = IGNORING; 12544 return(ENXIO); 12545 } 12546 /* Do a test transaction unless it's a CD drive (then 12547 * we can believe the controller, and a test may fail 12548 * due to no CD being in the drive). If it fails, ignore 12549 * the device forever. 12550 */ 12551 if (!(wn->state & ATAPI) && w_io_test() != OK) { 12552 wn->state |= IGNORING; 12553 return(ENXIO); 12554 } 12555 } 12556 12557 /* If it's not an ATAPI device, then don't open with RO_BIT. */ 12558 if (!(wn->state & ATAPI) && (m_ptr->COUNT & RO_BIT)) return EACCES; 12559 12560 /* Partition the drive if it's being opened for the first time, 12561 * or being opened after being closed. 12562 */ 12563 if (wn->open_ct == 0) { 12564 12565 /* Partition the disk. */ 12566 memset(wn->part, sizeof(wn->part), 0); 12567 memset(wn->subpart, sizeof(wn->subpart), 0); 12568 partition(&w_dtab, w_drive * DEV_PER_DRIVE, P_PRIMARY, wn->state & ATAPI); 12569 } 12570 wn->open_ct++; 12571 return(OK); 12572 } 12574 /*===========================================================================* 12575 * w_prepare * 12576 *===========================================================================*/ 12577 PRIVATE struct device *w_prepare(int device) 12578 { 12579 /* Prepare for I/O on a device. */ 12580 struct wini *prev_wn; 12581 prev_wn = w_wn; 12582 w_device = device; 12583 12584 if (device < NR_MINORS) { /* d0, d0p[0-3], d1, ... */ 12585 w_drive = device / DEV_PER_DRIVE; /* save drive number */ 12586 w_wn = &wini[w_drive]; 12587 w_dv = &w_wn->part[device % DEV_PER_DRIVE]; 12588 } else 12589 if ((unsigned) (device -= MINOR_d0p0s0) < NR_SUBDEVS) {/*d[0-7]p[0-3]s[0-3]*/ 12590 w_drive = device / SUB_PER_DRIVE; 12591 w_wn = &wini[w_drive]; 12592 w_dv = &w_wn->subpart[device % SUB_PER_DRIVE]; 12593 } else { 12594 w_device = -1; File: Page: 796 drivers/at_wini/at_wini.c 12595 return(NIL_DEV); 12596 } 12597 return(w_dv); 12598 } 12600 /*===========================================================================* 12601 * w_identify * 12602 *===========================================================================*/ 12603 PRIVATE int w_identify() 12604 { 12605 /* Find out if a device exists, if it is an old AT disk, or a newer ATA 12606 * drive, a removable media device, etc. 12607 */ 12608 12609 struct wini *wn = w_wn; 12610 struct command cmd; 12611 int i, s; 12612 unsigned long size; 12613 #define id_byte(n) (&tmp_buf[2 * (n)]) 12614 #define id_word(n) (((u16_t) id_byte(n)[0] << 0) \ 12615 |((u16_t) id_byte(n)[1] << 8)) 12616 #define id_longword(n) (((u32_t) id_byte(n)[0] << 0) \ 12617 |((u32_t) id_byte(n)[1] << 8) \ 12618 |((u32_t) id_byte(n)[2] << 16) \ 12619 |((u32_t) id_byte(n)[3] << 24)) 12620 12621 /* Try to identify the device. */ 12622 cmd.ldh = wn->ldhpref; 12623 cmd.command = ATA_IDENTIFY; 12624 if (com_simple(&cmd) == OK) { 12625 /* This is an ATA device. */ 12626 wn->state |= SMART; 12627 12628 /* Device information. */ 12629 if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, SECTOR_SIZE)) != OK) 12630 panic(w_name(),"Call to sys_insw() failed", s); 12631 12632 /* Why are the strings byte swapped??? */ 12633 for (i = 0; i < 40; i++) w_id_string[i] = id_byte(27)[i^1]; 12634 12635 /* Preferred CHS translation mode. */ 12636 wn->pcylinders = id_word(1); 12637 wn->pheads = id_word(3); 12638 wn->psectors = id_word(6); 12639 size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors; 12640 12641 if ((id_byte(49)[1] & 0x02) && size > 512L*1024*2) { 12642 /* Drive is LBA capable and is big enough to trust it to 12643 * not make a mess of it. 12644 */ 12645 wn->ldhpref |= LDH_LBA; 12646 size = id_longword(60); 12647 12648 if (w_lba48 && ((id_word(83)) & (1L << 10))) { 12649 /* Drive is LBA48 capable (and LBA48 is turned on). */ 12650 if (id_word(102) || id_word(103)) { 12651 /* If no. of sectors doesn't fit in 32 bits, 12652 * trunacte to this. So it's LBA32 for now. 12653 * This can still address devices up to 2TB 12654 * though. File: Page: 797 drivers/at_wini/at_wini.c 12655 */ 12656 size = ULONG_MAX; 12657 } else { 12658 /* Actual number of sectors fits in 32 bits. */ 12659 size = id_longword(100); 12660 } 12661 12662 wn->lba48 = 1; 12663 } 12664 } 12665 12666 if (wn->lcylinders == 0) { 12667 /* No BIOS parameters? Then make some up. */ 12668 wn->lcylinders = wn->pcylinders; 12669 wn->lheads = wn->pheads; 12670 wn->lsectors = wn->psectors; 12671 while (wn->lcylinders > 1024) { 12672 wn->lheads *= 2; 12673 wn->lcylinders /= 2; 12674 } 12675 } 12676 } else { 12677 /* Not an ATA device; no translations, no special features. Don't 12678 * touch it unless the BIOS knows about it. 12679 */ 12680 if (wn->lcylinders == 0) { return(ERR); } /* no BIOS parameters */ 12681 wn->pcylinders = wn->lcylinders; 12682 wn->pheads = wn->lheads; 12683 wn->psectors = wn->lsectors; 12684 size = (u32_t) wn->pcylinders * wn->pheads * wn->psectors; 12685 } 12686 12687 /* Size of the whole drive */ 12688 wn->part[0].dv_size = mul64u(size, SECTOR_SIZE); 12689 12690 /* Reset/calibrate (where necessary) */ 12691 if (w_specify() != OK && w_specify() != OK) { 12692 return(ERR); 12693 } 12694 12695 if (wn->irq == NO_IRQ) { 12696 /* Everything looks OK; register IRQ so we can stop polling. */ 12697 wn->irq = w_drive < 2 ? AT_WINI_0_IRQ : AT_WINI_1_IRQ; 12698 wn->irq_hook_id = wn->irq; /* id to be returned if interrupt occurs */ 12699 if ((s=sys_irqsetpolicy(wn->irq, IRQ_REENABLE, &wn->irq_hook_id)) != OK) 12700 panic(w_name(), "couldn't set IRQ policy", s); 12701 if ((s=sys_irqenable(&wn->irq_hook_id)) != OK) 12702 panic(w_name(), "couldn't enable IRQ line", s); 12703 } 12704 wn->state |= IDENTIFIED; 12705 return(OK); 12706 } 12708 /*===========================================================================* 12709 * w_name * 12710 *===========================================================================*/ 12711 PRIVATE char *w_name() 12712 { 12713 /* Return a name for the current device. */ 12714 static char name[] = "AT-D0"; File: Page: 798 drivers/at_wini/at_wini.c 12715 12716 name[4] = '0' + w_drive; 12717 return name; 12718 } 12720 /*===========================================================================* 12721 * w_io_test * 12722 *===========================================================================*/ 12723 PRIVATE int w_io_test(void) 12724 { 12725 int r, save_dev; 12726 int save_timeout, save_errors, save_wakeup; 12727 iovec_t iov; 12728 static char buf[SECTOR_SIZE]; 12729 iov.iov_addr = (vir_bytes) buf; 12730 iov.iov_size = sizeof(buf); 12731 save_dev = w_device; 12732 12733 /* Reduce timeout values for this test transaction. */ 12734 save_timeout = timeout_ticks; 12735 save_errors = max_errors; 12736 save_wakeup = wakeup_ticks; 12737 12738 if (!w_standard_timeouts) { 12739 timeout_ticks = HZ * 4; 12740 wakeup_ticks = HZ * 6; 12741 max_errors = 3; 12742 } 12743 12744 w_testing = 1; 12745 12746 /* Try I/O on the actual drive (not any (sub)partition). */ 12747 if (w_prepare(w_drive * DEV_PER_DRIVE) == NIL_DEV) 12748 panic(w_name(), "Couldn't switch devices", NO_NUM); 12749 12750 r = w_transfer(SELF, DEV_GATHER, 0, &iov, 1); 12751 12752 /* Switch back. */ 12753 if (w_prepare(save_dev) == NIL_DEV) 12754 panic(w_name(), "Couldn't switch back devices", NO_NUM); 12755 12756 /* Restore parameters. */ 12757 timeout_ticks = save_timeout; 12758 max_errors = save_errors; 12759 wakeup_ticks = save_wakeup; 12760 w_testing = 0; 12761 12762 /* Test if everything worked. */ 12763 if (r != OK || iov.iov_size != 0) { 12764 return ERR; 12765 } 12766 12767 /* Everything worked. */ 12768 12769 return OK; 12770 } File: Page: 799 drivers/at_wini/at_wini.c 12772 /*===========================================================================* 12773 * w_specify * 12774 *===========================================================================*/ 12775 PRIVATE int w_specify() 12776 { 12777 /* Routine to initialize the drive after boot or when a reset is needed. */ 12778 12779 struct wini *wn = w_wn; 12780 struct command cmd; 12781 12782 if ((wn->state & DEAF) && w_reset() != OK) { 12783 return(ERR); 12784 } 12785 12786 if (!(wn->state & ATAPI)) { 12787 /* Specify parameters: precompensation, number of heads and sectors. */ 12788 cmd.precomp = wn->precomp; 12789 cmd.count = wn->psectors; 12790 cmd.ldh = w_wn->ldhpref | (wn->pheads - 1); 12791 cmd.command = CMD_SPECIFY; /* Specify some parameters */ 12792 12793 /* Output command block and see if controller accepts the parameters. */ 12794 if (com_simple(&cmd) != OK) return(ERR); 12795 12796 if (!(wn->state & SMART)) { 12797 /* Calibrate an old disk. */ 12798 cmd.sector = 0; 12799 cmd.cyl_lo = 0; 12800 cmd.cyl_hi = 0; 12801 cmd.ldh = w_wn->ldhpref; 12802 cmd.command = CMD_RECALIBRATE; 12803 12804 if (com_simple(&cmd) != OK) return(ERR); 12805 } 12806 } 12807 wn->state |= INITIALIZED; 12808 return(OK); 12809 } 12811 /*===========================================================================* 12812 * do_transfer * 12813 *===========================================================================*/ 12814 PRIVATE int do_transfer(struct wini *wn, unsigned int precomp, unsigned int count, 12815 unsigned int sector, unsigned int opcode) 12816 { 12817 struct command cmd; 12818 unsigned secspcyl = wn->pheads * wn->psectors; 12819 12820 cmd.precomp = precomp; 12821 cmd.count = count; 12822 cmd.command = opcode == DEV_SCATTER ? CMD_WRITE : CMD_READ; 12823 /* 12824 if (w_lba48 && wn->lba48) { 12825 } else */ 12826 if (wn->ldhpref & LDH_LBA) { 12827 cmd.sector = (sector >> 0) & 0xFF; 12828 cmd.cyl_lo = (sector >> 8) & 0xFF; 12829 cmd.cyl_hi = (sector >> 16) & 0xFF; 12830 cmd.ldh = wn->ldhpref | ((sector >> 24) & 0xF); 12831 } else { File: Page: 800 drivers/at_wini/at_wini.c 12832 int cylinder, head, sec; 12833 cylinder = sector / secspcyl; 12834 head = (sector % secspcyl) / wn->psectors; 12835 sec = sector % wn->psectors; 12836 cmd.sector = sec + 1; 12837 cmd.cyl_lo = cylinder & BYTE; 12838 cmd.cyl_hi = (cylinder >> 8) & BYTE; 12839 cmd.ldh = wn->ldhpref | head; 12840 } 12841 12842 return com_out(&cmd); 12843 } 12845 /*===========================================================================* 12846 * w_transfer * 12847 *===========================================================================*/ 12848 PRIVATE int w_transfer(proc_nr, opcode, position, iov, nr_req) 12849 int proc_nr; /* process doing the request */ 12850 int opcode; /* DEV_GATHER or DEV_SCATTER */ 12851 off_t position; /* offset on device to read or write */ 12852 iovec_t *iov; /* pointer to read or write request vector */ 12853 unsigned nr_req; /* length of request vector */ 12854 { 12855 struct wini *wn = w_wn; 12856 iovec_t *iop, *iov_end = iov + nr_req; 12857 int r, s, errors; 12858 unsigned long block; 12859 unsigned long dv_size = cv64ul(w_dv->dv_size); 12860 unsigned cylinder, head, sector, nbytes; 12861 12862 /* Check disk address. */ 12863 if ((position & SECTOR_MASK) != 0) return(EINVAL); 12864 12865 errors = 0; 12866 12867 while (nr_req > 0) { 12868 /* How many bytes to transfer? */ 12869 nbytes = 0; 12870 for (iop = iov; iop < iov_end; iop++) nbytes += iop->iov_size; 12871 if ((nbytes & SECTOR_MASK) != 0) return(EINVAL); 12872 12873 /* Which block on disk and how close to EOF? */ 12874 if (position >= dv_size) return(OK); /* At EOF */ 12875 if (position + nbytes > dv_size) nbytes = dv_size - position; 12876 block = div64u(add64ul(w_dv->dv_base, position), SECTOR_SIZE); 12877 12878 if (nbytes >= wn->max_count) { 12879 /* The drive can't do more then max_count at once. */ 12880 nbytes = wn->max_count; 12881 } 12882 12883 /* First check to see if a reinitialization is needed. */ 12884 if (!(wn->state & INITIALIZED) && w_specify() != OK) return(EIO); 12885 12886 /* Tell the controller to transfer nbytes bytes. */ 12887 r = do_transfer(wn, wn->precomp, ((nbytes >> SECTOR_SHIFT) & BYTE), 12888 block, opcode); 12889 12890 while (r == OK && nbytes > 0) { 12891 /* For each sector, wait for an interrupt and fetch the data File: Page: 801 drivers/at_wini/at_wini.c 12892 * (read), or supply data to the controller and wait for an 12893 * interrupt (write). 12894 */ 12895 12896 if (opcode == DEV_GATHER) { 12897 /* First an interrupt, then data. */ 12898 if ((r = at_intr_wait()) != OK) { 12899 /* An error, send data to the bit bucket. */ 12900 if (w_wn->w_status & STATUS_DRQ) { 12901 if ((s=sys_insw(wn->base_cmd + REG_DATA, SELF, tmp_buf, SECTOR_SIZE)) != OK) 12902 panic(w_name(),"Call to sys_insw() failed", s); 12903 } 12904 break; 12905 } 12906 } 12907 12908 /* Wait for data transfer requested. */ 12909 if (!w_waitfor(STATUS_DRQ, STATUS_DRQ)) { r = ERR; break; } 12910 12911 /* Copy bytes to or from the device's buffer. */ 12912 if (opcode == DEV_GATHER) { 12913 if ((s=sys_insw(wn->base_cmd + REG_DATA, proc_nr, (void *) iov->iov_addr, SECTOR_SIZE)) != OK) 12914 panic(w_name(),"Call to sys_insw() failed", s); 12915 } else { 12916 if ((s=sys_outsw(wn->base_cmd + REG_DATA, proc_nr, (void *) iov->iov_addr, SECTOR_SIZE)) != OK) 12917 panic(w_name(),"Call to sys_insw() failed", s); 12918 12919 /* Data sent, wait for an interrupt. */ 12920 if ((r = at_intr_wait()) != OK) break; 12921 } 12922 12923 /* Book the bytes successfully transferred. */ 12924 nbytes -= SECTOR_SIZE; 12925 position += SECTOR_SIZE; 12926 iov->iov_addr += SECTOR_SIZE; 12927 if ((iov->iov_size -= SECTOR_SIZE) == 0) { iov++; nr_req--; } 12928 } 12929 12930 /* Any errors? */ 12931 if (r != OK) { 12932 /* Don't retry if sector marked bad or too many errors. */ 12933 if (r == ERR_BAD_SECTOR || ++errors == max_errors) { 12934 w_command = CMD_IDLE; 12935 return(EIO); 12936 } 12937 } 12938 } 12939 12940 w_command = CMD_IDLE; 12941 return(OK); 12942 } 12944 /*===========================================================================* 12945 * com_out * 12946 *===========================================================================*/ 12947 PRIVATE int com_out(cmd) 12948 struct command *cmd; /* Command block */ 12949 { 12950 /* Output the command block to the winchester controller and return status */ 12951 File: Page: 802 drivers/at_wini/at_wini.c 12952 struct wini *wn = w_wn; 12953 unsigned base_cmd = wn->base_cmd; 12954 unsigned base_ctl = wn->base_ctl; 12955 pvb_pair_t outbyte[7]; /* vector for sys_voutb() */ 12956 int s; /* status for sys_(v)outb() */ 12957 12958 if (w_wn->state & IGNORING) return ERR; 12959 12960 if (!w_waitfor(STATUS_BSY, 0)) { 12961 printf("%s: controller not ready\n", w_name()); 12962 return(ERR); 12963 } 12964 12965 /* Select drive. */ 12966 if ((s=sys_outb(base_cmd + REG_LDH, cmd->ldh)) != OK) 12967 panic(w_name(),"Couldn't write register to select drive",s); 12968 12969 if (!w_waitfor(STATUS_BSY, 0)) { 12970 printf("%s: com_out: drive not ready\n", w_name()); 12971 return(ERR); 12972 } 12973 12974 /* Schedule a wakeup call, some controllers are flaky. This is done with 12975 * a synchronous alarm. If a timeout occurs a SYN_ALARM message is sent 12976 * from HARDWARE, so that w_intr_wait() can call w_timeout() in case the 12977 * controller was not able to execute the command. Leftover timeouts are 12978 * simply ignored by the main loop. 12979 */ 12980 sys_setalarm(wakeup_ticks, 0); 12981 12982 wn->w_status = STATUS_ADMBSY; 12983 w_command = cmd->command; 12984 pv_set(outbyte[0], base_ctl + REG_CTL, wn->pheads >= 8 ? CTL_EIGHTHEADS : 0); 12985 pv_set(outbyte[1], base_cmd + REG_PRECOMP, cmd->precomp); 12986 pv_set(outbyte[2], base_cmd + REG_COUNT, cmd->count); 12987 pv_set(outbyte[3], base_cmd + REG_SECTOR, cmd->sector); 12988 pv_set(outbyte[4], base_cmd + REG_CYL_LO, cmd->cyl_lo); 12989 pv_set(outbyte[5], base_cmd + REG_CYL_HI, cmd->cyl_hi); 12990 pv_set(outbyte[6], base_cmd + REG_COMMAND, cmd->command); 12991 if ((s=sys_voutb(outbyte,7)) != OK) 12992 panic(w_name(),"Couldn't write registers with sys_voutb()",s); 12993 return(OK); 12994 } 12996 /*===========================================================================* 12997 * w_need_reset * 12998 *===========================================================================*/ 12999 PRIVATE void w_need_reset() 13000 { 13001 /* The controller needs to be reset. */ 13002 struct wini *wn; 13003 int dr = 0; 13004 13005 for (wn = wini; wn < &wini[MAX_DRIVES]; wn++, dr++) { 13006 if (wn->base_cmd == w_wn->base_cmd) { 13007 wn->state |= DEAF; 13008 wn->state &= ~INITIALIZED; 13009 } 13010 } 13011 } File: Page: 803 drivers/at_wini/at_wini.c 13013 /*===========================================================================* 13014 * w_do_close * 13015 *===========================================================================*/ 13016 PRIVATE int w_do_close(dp, m_ptr) 13017 struct driver *dp; 13018 message *m_ptr; 13019 { 13020 /* Device close: Release a device. */ 13021 if (w_prepare(m_ptr->DEVICE) == NIL_DEV) 13022 return(ENXIO); 13023 w_wn->open_ct--; 13024 return(OK); 13025 } 13027 /*===========================================================================* 13028 * com_simple * 13029 *===========================================================================*/ 13030 PRIVATE int com_simple(cmd) 13031 struct command *cmd; /* Command block */ 13032 { 13033 /* A simple controller command, only one interrupt and no data-out phase. */ 13034 int r; 13035 13036 if (w_wn->state & IGNORING) return ERR; 13037 13038 if ((r = com_out(cmd)) == OK) r = at_intr_wait(); 13039 w_command = CMD_IDLE; 13040 return(r); 13041 } 13043 /*===========================================================================* 13044 * w_timeout * 13045 *===========================================================================*/ 13046 PRIVATE void w_timeout(void) 13047 { 13048 struct wini *wn = w_wn; 13049 13050 switch (w_command) { 13051 case CMD_IDLE: 13052 break; /* fine */ 13053 case CMD_READ: 13054 case CMD_WRITE: 13055 /* Impossible, but not on PC's: The controller does not respond. */ 13056 13057 /* Limiting multisector I/O seems to help. */ 13058 if (wn->max_count > 8 * SECTOR_SIZE) { 13059 wn->max_count = 8 * SECTOR_SIZE; 13060 } else { 13061 wn->max_count = SECTOR_SIZE; 13062 } 13063 /*FALL THROUGH*/ 13064 default: 13065 /* Some other command. */ 13066 if (w_testing) wn->state |= IGNORING; /* Kick out this drive. */ 13067 else if (!w_silent) printf("%s: timeout on command %02x\n", w_name(), w_command); 13068 w_need_reset(); 13069 wn->w_status = 0; 13070 } 13071 } File: Page: 804 drivers/at_wini/at_wini.c 13073 /*===========================================================================* 13074 * w_reset * 13075 *===========================================================================*/ 13076 PRIVATE int w_reset() 13077 { 13078 /* Issue a reset to the controller. This is done after any catastrophe, 13079 * like the controller refusing to respond. 13080 */ 13081 int s; 13082 struct wini *wn = w_wn; 13083 13084 /* Don't bother if this drive is forgotten. */ 13085 if (w_wn->state & IGNORING) return ERR; 13086 13087 /* Wait for any internal drive recovery. */ 13088 tickdelay(RECOVERY_TICKS); 13089 13090 /* Strobe reset bit */ 13091 if ((s=sys_outb(wn->base_ctl + REG_CTL, CTL_RESET)) != OK) 13092 panic(w_name(),"Couldn't strobe reset bit",s); 13093 tickdelay(DELAY_TICKS); 13094 if ((s=sys_outb(wn->base_ctl + REG_CTL, 0)) != OK) 13095 panic(w_name(),"Couldn't strobe reset bit",s); 13096 tickdelay(DELAY_TICKS); 13097 13098 /* Wait for controller ready */ 13099 if (!w_waitfor(STATUS_BSY, 0)) { 13100 printf("%s: reset failed, drive busy\n", w_name()); 13101 return(ERR); 13102 } 13103 13104 /* The error register should be checked now, but some drives mess it up. */ 13105 13106 for (wn = wini; wn < &wini[MAX_DRIVES]; wn++) { 13107 if (wn->base_cmd == w_wn->base_cmd) { 13108 wn->state &= ~DEAF; 13109 if (w_wn->irq_need_ack) { 13110 /* Make sure irq is actually enabled.. */ 13111 sys_irqenable(&w_wn->irq_hook_id); 13112 } 13113 } 13114 } 13115 13116 13117 return(OK); 13118 } 13120 /*===========================================================================* 13121 * w_intr_wait * 13122 *===========================================================================*/ 13123 PRIVATE void w_intr_wait() 13124 { 13125 /* Wait for a task completion interrupt. */ 13126 13127 message m; 13128 13129 if (w_wn->irq != NO_IRQ) { 13130 /* Wait for an interrupt that sets w_status to "not busy". */ 13131 while (w_wn->w_status & (STATUS_ADMBSY|STATUS_BSY)) { File: Page: 805 drivers/at_wini/at_wini.c 13132 receive(ANY, &m); /* expect HARD_INT message */ 13133 if (m.m_type == SYN_ALARM) { /* but check for timeout */ 13134 w_timeout(); /* a.o. set w_status */ 13135 } else if (m.m_type == HARD_INT) { 13136 sys_inb(w_wn->base_cmd + REG_STATUS, &w_wn->w_status); 13137 ack_irqs(m.NOTIFY_ARG); 13138 } else { 13139 printf("AT_WINI got unexpected message %d from %d\n", 13140 m.m_type, m.m_source); 13141 } 13142 } 13143 } else { 13144 /* Interrupt not yet allocated; use polling. */ 13145 (void) w_waitfor(STATUS_BSY, 0); 13146 } 13147 } 13149 /*===========================================================================* 13150 * at_intr_wait * 13151 *===========================================================================*/ 13152 PRIVATE int at_intr_wait() 13153 { 13154 /* Wait for an interrupt, study the status bits and return error/success. */ 13155 int r; 13156 int s,inbval; /* read value with sys_inb */ 13157 13158 w_intr_wait(); 13159 if ((w_wn->w_status & (STATUS_BSY | STATUS_WF | STATUS_ERR)) == 0) { 13160 r = OK; 13161 } else { 13162 if ((s=sys_inb(w_wn->base_cmd + REG_ERROR, &inbval)) != OK) 13163 panic(w_name(),"Couldn't read register",s); 13164 if ((w_wn->w_status & STATUS_ERR) && (inbval & ERROR_BB)) { 13165 r = ERR_BAD_SECTOR; /* sector marked bad, retries won't help */ 13166 } else { 13167 r = ERR; /* any other error */ 13168 } 13169 } 13170 w_wn->w_status |= STATUS_ADMBSY; /* assume still busy with I/O */ 13171 return(r); 13172 } 13174 /*===========================================================================* 13175 * w_waitfor * 13176 *===========================================================================*/ 13177 PRIVATE int w_waitfor(mask, value) 13178 int mask; /* status mask */ 13179 int value; /* required status */ 13180 { 13181 /* Wait until controller is in the required state. Return zero on timeout. 13182 * An alarm that set a timeout flag is used. TIMEOUT is in micros, we need 13183 * ticks. Disabling the alarm is not needed, because a static flag is used 13184 * and a leftover timeout cannot do any harm. 13185 */ 13186 clock_t t0, t1; 13187 int s; 13188 getuptime(&t0); 13189 do { 13190 if ((s=sys_inb(w_wn->base_cmd + REG_STATUS, &w_wn->w_status)) != OK) 13191 panic(w_name(),"Couldn't read register",s); File: Page: 806 drivers/at_wini/at_wini.c 13192 if ((w_wn->w_status & mask) == value) { 13193 return 1; 13194 } 13195 } while ((s=getuptime(&t1)) == OK && (t1-t0) < timeout_ticks ); 13196 if (OK != s) printf("AT_WINI: warning, get_uptime failed: %d\n",s); 13197 13198 w_need_reset(); /* controller gone deaf */ 13199 return(0); 13200 } 13202 /*===========================================================================* 13203 * w_geometry * 13204 *===========================================================================*/ 13205 PRIVATE void w_geometry(entry) 13206 struct partition *entry; 13207 { 13208 struct wini *wn = w_wn; 13209 13210 if (wn->state & ATAPI) { /* Make up some numbers. */ 13211 entry->cylinders = div64u(wn->part[0].dv_size, SECTOR_SIZE) / (64*32); 13212 entry->heads = 64; 13213 entry->sectors = 32; 13214 } else { /* Return logical geometry. */ 13215 entry->cylinders = wn->lcylinders; 13216 entry->heads = wn->lheads; 13217 entry->sectors = wn->lsectors; 13218 } 13219 } 13221 /*===========================================================================* 13222 * w_other * 13223 *===========================================================================*/ 13224 PRIVATE int w_other(dr, m) 13225 struct driver *dr; 13226 message *m; 13227 { 13228 int r, timeout, prev; 13229 13230 if (m->m_type != DEV_IOCTL ) { 13231 return EINVAL; 13232 } 13233 13234 if (m->REQUEST == DIOCTIMEOUT) { 13235 if ((r=sys_datacopy(m->PROC_NR, (vir_bytes)m->ADDRESS, 13236 SELF, (vir_bytes)&timeout, sizeof(timeout))) != OK) 13237 return r; 13238 13239 if (timeout == 0) { 13240 /* Restore defaults. */ 13241 timeout_ticks = DEF_TIMEOUT_TICKS; 13242 max_errors = MAX_ERRORS; 13243 wakeup_ticks = WAKEUP; 13244 w_silent = 0; 13245 } else if (timeout < 0) { 13246 return EINVAL; 13247 } else { 13248 prev = wakeup_ticks; 13249 13250 if (!w_standard_timeouts) { 13251 /* Set (lower) timeout, lower error File: Page: 807 drivers/at_wini/at_wini.c 13252 * tolerance and set silent mode. 13253 */ 13254 wakeup_ticks = timeout; 13255 max_errors = 3; 13256 w_silent = 1; 13257 13258 if (timeout_ticks > timeout) 13259 timeout_ticks = timeout; 13260 } 13261 13262 if ((r=sys_datacopy(SELF, (vir_bytes)&prev, 13263 m->PROC_NR, (vir_bytes)m->ADDRESS, sizeof(prev))) != OK) 13264 return r; 13265 } 13266 13267 return OK; 13268 } else if (m->REQUEST == DIOCOPENCT) { 13269 int count; 13270 if (w_prepare(m->DEVICE) == NIL_DEV) return ENXIO; 13271 count = w_wn->open_ct; 13272 if ((r=sys_datacopy(SELF, (vir_bytes)&count, 13273 m->PROC_NR, (vir_bytes)m->ADDRESS, sizeof(count))) != OK) 13274 return r; 13275 return OK; 13276 } 13277 return EINVAL; 13278 } 13280 /*===========================================================================* 13281 * w_hw_int * 13282 *===========================================================================*/ 13283 PRIVATE int w_hw_int(dr, m) 13284 struct driver *dr; 13285 message *m; 13286 { 13287 /* Leftover interrupt(s) received; ack it/them. */ 13288 ack_irqs(m->NOTIFY_ARG); 13289 13290 return OK; 13291 } 13294 /*===========================================================================* 13295 * ack_irqs * 13296 *===========================================================================*/ 13297 PRIVATE void ack_irqs(unsigned int irqs) 13298 { 13299 unsigned int drive; 13300 for (drive = 0; drive < MAX_DRIVES && irqs; drive++) { 13301 if (!(wini[drive].state & IGNORING) && wini[drive].irq_need_ack && 13302 (wini[drive].irq_mask & irqs)) { 13303 if (sys_inb((wini[drive].base_cmd + REG_STATUS), &wini[drive].w_status) != OK) 13304 printf("couldn't ack irq on drive %d\n", drive); 13305 if (sys_irqenable(&wini[drive].irq_hook_id) != OK) 13306 printf("couldn't re-enable drive %d\n", drive); 13307 irqs &= ~wini[drive].irq_mask; 13308 } 13309 } 13310 } File: Page: 808 drivers/at_wini/at_wini.c 13313 #define STSTR(a) if (status & STATUS_ ## a) { strcat(str, #a); strcat(str, " "); } 13314 #define ERRSTR(a) if (e & ERROR_ ## a) { strcat(str, #a); strcat(str, " "); } 13315 char *strstatus(int status) 13316 { 13317 static char str[200]; 13318 str[0] = '\0'; 13319 13320 STSTR(BSY); 13321 STSTR(DRDY); 13322 STSTR(DMADF); 13323 STSTR(SRVCDSC); 13324 STSTR(DRQ); 13325 STSTR(CORR); 13326 STSTR(CHECK); 13327 return str; 13328 } 13330 char *strerr(int e) 13331 { 13332 static char str[200]; 13333 str[0] = '\0'; 13334 13335 ERRSTR(BB); 13336 ERRSTR(ECC); 13337 ERRSTR(ID); 13338 ERRSTR(AC); 13339 ERRSTR(TK); 13340 ERRSTR(DM); 13341 13342 return str; 13343 } ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/tty/tty.h ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 13400 /* tty.h - Terminals */ 13401 13402 #include 13403 13404 /* First minor numbers for the various classes of TTY devices. */ 13405 #define CONS_MINOR 0 13406 #define LOG_MINOR 15 13407 #define RS232_MINOR 16 13408 #define TTYPX_MINOR 128 13409 #define PTYPX_MINOR 192 13410 13411 #define LINEWRAP 1 /* console.c - wrap lines at column 80 */ 13412 13413 #define TTY_IN_BYTES 256 /* tty input queue size */ 13414 #define TAB_SIZE 8 /* distance between tab stops */ 13415 #define TAB_MASK 7 /* mask to compute a tab stop position */ 13416 13417 #define ESC '\33' /* escape */ 13418 13419 #define O_NOCTTY 00400 /* from , or cc will choke */ File: Page: 809 drivers/tty/tty.h 13420 #define O_NONBLOCK 04000 13421 13422 struct tty; 13423 typedef _PROTOTYPE( int (*devfun_t), (struct tty *tp, int try_only) ); 13424 typedef _PROTOTYPE( void (*devfunarg_t), (struct tty *tp, int c) ); 13425 13426 typedef struct tty { 13427 int tty_events; /* set when TTY should inspect this line */ 13428 int tty_index; /* index into TTY table */ 13429 int tty_minor; /* device minor number */ 13430 13431 /* Input queue. Typed characters are stored here until read by a program. */ 13432 u16_t *tty_inhead; /* pointer to place where next char goes */ 13433 u16_t *tty_intail; /* pointer to next char to be given to prog */ 13434 int tty_incount; /* # chars in the input queue */ 13435 int tty_eotct; /* number of "line breaks" in input queue */ 13436 devfun_t tty_devread; /* routine to read from low level buffers */ 13437 devfun_t tty_icancel; /* cancel any device input */ 13438 int tty_min; /* minimum requested #chars in input queue */ 13439 timer_t tty_tmr; /* the timer for this tty */ 13440 13441 /* Output section. */ 13442 devfun_t tty_devwrite; /* routine to start actual device output */ 13443 devfunarg_t tty_echo; /* routine to echo characters input */ 13444 devfun_t tty_ocancel; /* cancel any ongoing device output */ 13445 devfun_t tty_break; /* let the device send a break */ 13446 13447 /* Terminal parameters and status. */ 13448 int tty_position; /* current position on the screen for echoing */ 13449 char tty_reprint; /* 1 when echoed input messed up, else 0 */ 13450 char tty_escaped; /* 1 when LNEXT (^V) just seen, else 0 */ 13451 char tty_inhibited; /* 1 when STOP (^S) just seen (stops output) */ 13452 char tty_pgrp; /* slot number of controlling process */ 13453 char tty_openct; /* count of number of opens of this tty */ 13454 13455 /* Information about incomplete I/O requests is stored here. */ 13456 char tty_inrepcode; /* reply code, TASK_REPLY or REVIVE */ 13457 char tty_inrevived; /* set to 1 if revive callback is pending */ 13458 char tty_incaller; /* process that made the call (usually FS) */ 13459 char tty_inproc; /* process that wants to read from tty */ 13460 vir_bytes tty_in_vir; /* virtual address where data is to go */ 13461 int tty_inleft; /* how many chars are still needed */ 13462 int tty_incum; /* # chars input so far */ 13463 char tty_outrepcode; /* reply code, TASK_REPLY or REVIVE */ 13464 char tty_outrevived; /* set to 1 if revive callback is pending */ 13465 char tty_outcaller; /* process that made the call (usually FS) */ 13466 char tty_outproc; /* process that wants to write to tty */ 13467 vir_bytes tty_out_vir; /* virtual address where data comes from */ 13468 int tty_outleft; /* # chars yet to be output */ 13469 int tty_outcum; /* # chars output so far */ 13470 char tty_iocaller; /* process that made the call (usually FS) */ 13471 char tty_ioproc; /* process that wants to do an ioctl */ 13472 int tty_ioreq; /* ioctl request code */ 13473 vir_bytes tty_iovir; /* virtual address of ioctl buffer */ 13474 13475 /* select() data */ 13476 int tty_select_ops; /* which operations are interesting */ 13477 int tty_select_proc; /* which process wants notification */ 13478 13479 /* Miscellaneous. */ File: Page: 810 drivers/tty/tty.h 13480 devfun_t tty_ioctl; /* set line speed, etc. at the device level */ 13481 devfun_t tty_close; /* tell the device that the tty is closed */ 13482 void *tty_priv; /* pointer to per device private data */ 13483 struct termios tty_termios; /* terminal attributes */ 13484 struct winsize tty_winsize; /* window size (#lines and #columns) */ 13485 13486 u16_t tty_inbuf[TTY_IN_BYTES];/* tty input buffer */ 13487 13488 } tty_t; 13489 13490 /* Memory allocated in tty.c, so extern here. */ 13491 extern tty_t tty_table[NR_CONS+NR_RS_LINES+NR_PTYS]; 13492 extern int ccurrent; /* currently visible console */ 13493 extern int irq_hook_id; /* hook id for keyboard irq */ 13494 13495 extern unsigned long kbd_irq_set; 13496 extern unsigned long rs_irq_set; 13497 13498 /* Values for the fields. */ 13499 #define NOT_ESCAPED 0 /* previous character is not LNEXT (^V) */ 13500 #define ESCAPED 1 /* previous character was LNEXT (^V) */ 13501 #define RUNNING 0 /* no STOP (^S) has been typed to stop output */ 13502 #define STOPPED 1 /* STOP (^S) has been typed to stop output */ 13503 13504 /* Fields and flags on characters in the input queue. */ 13505 #define IN_CHAR 0x00FF /* low 8 bits are the character itself */ 13506 #define IN_LEN 0x0F00 /* length of char if it has been echoed */ 13507 #define IN_LSHIFT 8 /* length = (c & IN_LEN) >> IN_LSHIFT */ 13508 #define IN_EOT 0x1000 /* char is a line break (^D, LF) */ 13509 #define IN_EOF 0x2000 /* char is EOF (^D), do not return to user */ 13510 #define IN_ESC 0x4000 /* escaped by LNEXT (^V), no interpretation */ 13511 13512 /* Times and timeouts. */ 13513 #define force_timeout() ((void) (0)) 13514 13515 /* Memory allocated in tty.c, so extern here. */ 13516 extern timer_t *tty_timers; /* queue of TTY timers */ 13517 extern clock_t tty_next_timeout; /* next TTY timeout */ 13518 13519 /* Number of elements and limit of a buffer. */ 13520 #define buflen(buf) (sizeof(buf) / sizeof((buf)[0])) 13521 #define bufend(buf) ((buf) + buflen(buf)) 13522 13523 /* Memory allocated in tty.c, so extern here. */ 13524 extern struct machine machine; /* machine information (a.o.: pc_at, ega) */ 13525 13526 /* Function prototypes for TTY driver. */ 13527 /* tty.c */ 13528 _PROTOTYPE( void handle_events, (struct tty *tp) ); 13529 _PROTOTYPE( void sigchar, (struct tty *tp, int sig) ); 13530 _PROTOTYPE( void tty_task, (void) ); 13531 _PROTOTYPE( int in_process, (struct tty *tp, char *buf, int count) ); 13532 _PROTOTYPE( void out_process, (struct tty *tp, char *bstart, char *bpos, 13533 char *bend, int *icount, int *ocount) ); 13534 _PROTOTYPE( void tty_wakeup, (clock_t now) ); 13535 _PROTOTYPE( void tty_reply, (int code, int replyee, int proc_nr, 13536 int status) ); 13537 _PROTOTYPE( int tty_devnop, (struct tty *tp, int try) ); 13538 _PROTOTYPE( int select_try, (struct tty *tp, int ops) ); 13539 _PROTOTYPE( int select_retry, (struct tty *tp) ); File: Page: 811 drivers/tty/tty.h 13540 13541 /* console.c */ 13542 _PROTOTYPE( void kputc, (int c) ); 13543 _PROTOTYPE( void cons_stop, (void) ); 13544 _PROTOTYPE( void do_new_kmess, (message *m) ); 13545 _PROTOTYPE( void do_diagnostics, (message *m) ); 13546 _PROTOTYPE( void scr_init, (struct tty *tp) ); 13547 _PROTOTYPE( void toggle_scroll, (void) ); 13548 _PROTOTYPE( int con_loadfont, (message *m) ); 13549 _PROTOTYPE( void select_console, (int cons_line) ); 13550 13551 /* keyboard.c */ 13552 _PROTOTYPE( void kb_init, (struct tty *tp) ); 13553 _PROTOTYPE( void kb_init_once, (void) ); 13554 _PROTOTYPE( int kbd_loadmap, (message *m) ); 13555 _PROTOTYPE( void do_panic_dumps, (message *m) ); 13556 _PROTOTYPE( void do_fkey_ctl, (message *m) ); 13557 _PROTOTYPE( void kbd_interrupt, (message *m) ); 13558 13559 /* vidcopy.s */ 13560 _PROTOTYPE( void vid_vid_copy, (unsigned src, unsigned dst, unsigned count)); 13561 _PROTOTYPE( void mem_vid_copy, (u16_t *src, unsigned dst, unsigned count)); ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/tty/tty.c ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 13600 /* This file contains the terminal driver, both for the IBM console and regular 13601 * ASCII terminals. It handles only the device-independent part of a TTY, the 13602 * device dependent parts are in console.c, rs232.c, etc. This file contains 13603 * two main entry points, tty_task() and tty_wakeup(), and several minor entry 13604 * points for use by the device-dependent code. 13605 * 13606 * The device-independent part accepts "keyboard" input from the device- 13607 * dependent part, performs input processing (special key interpretation), 13608 * and sends the input to a process reading from the TTY. Output to a TTY 13609 * is sent to the device-dependent code for output processing and "screen" 13610 * display. Input processing is done by the device by calling 'in_process' 13611 * on the input characters, output processing may be done by the device itself 13612 * or by calling 'out_process'. The TTY takes care of input queuing, the 13613 * device does the output queuing. If a device receives an external signal, 13614 * like an interrupt, then it causes tty_wakeup() to be run by the CLOCK task 13615 * to, you guessed it, wake up the TTY to check if input or output can 13616 * continue. 13617 * 13618 * The valid messages and their parameters are: 13619 * 13620 * HARD_INT: output has been completed or input has arrived 13621 * SYS_SIG: e.g., MINIX wants to shutdown; run code to cleanly stop 13622 * DEV_READ: a process wants to read from a terminal 13623 * DEV_WRITE: a process wants to write on a terminal 13624 * DEV_IOCTL: a process wants to change a terminal's parameters 13625 * DEV_OPEN: a tty line has been opened 13626 * DEV_CLOSE: a tty line has been closed 13627 * DEV_SELECT: start select notification request 13628 * DEV_STATUS: FS wants to know status for SELECT or REVIVE 13629 * CANCEL: terminate a previous incomplete system call immediately File: Page: 812 drivers/tty/tty.c 13630 * 13631 * m_type TTY_LINE PROC_NR COUNT TTY_SPEK TTY_FLAGS ADDRESS 13632 * --------------------------------------------------------------------------- 13633 * | HARD_INT | | | | | | | 13634 * |-------------+---------+---------+---------+---------+---------+---------| 13635 * | SYS_SIG | sig set | | | | | | 13636 * |-------------+---------+---------+---------+---------+---------+---------| 13637 * | DEV_READ |minor dev| proc nr | count | O_NONBLOCK| buf ptr | 13638 * |-------------+---------+---------+---------+---------+---------+---------| 13639 * | DEV_WRITE |minor dev| proc nr | count | | | buf ptr | 13640 * |-------------+---------+---------+---------+---------+---------+---------| 13641 * | DEV_IOCTL |minor dev| proc nr |func code|erase etc| flags | | 13642 * |-------------+---------+---------+---------+---------+---------+---------| 13643 * | DEV_OPEN |minor dev| proc nr | O_NOCTTY| | | | 13644 * |-------------+---------+---------+---------+---------+---------+---------| 13645 * | DEV_CLOSE |minor dev| proc nr | | | | | 13646 * |-------------+---------+---------+---------+---------+---------+---------| 13647 * | DEV_STATUS | | | | | | | 13648 * |-------------+---------+---------+---------+---------+---------+---------| 13649 * | CANCEL |minor dev| proc nr | | | | | 13650 * --------------------------------------------------------------------------- 13651 * 13652 * Changes: 13653 * Jan 20, 2004 moved TTY driver to user-space (Jorrit N. Herder) 13654 * Sep 20, 2004 local timer management/ sync alarms (Jorrit N. Herder) 13655 * Jul 13, 2004 support for function key observers (Jorrit N. Herder) 13656 */ 13657 13658 #include "../drivers.h" 13659 #include "../drivers.h" 13660 #include 13661 #include 13662 #include 13663 #include 13664 #include 13665 #include "tty.h" 13666 13667 #include 13668 #include 13669 13670 extern int irq_hook_id; 13671 13672 unsigned long kbd_irq_set = 0; 13673 unsigned long rs_irq_set = 0; 13674 13675 /* Address of a tty structure. */ 13676 #define tty_addr(line) (&tty_table[line]) 13677 13678 /* Macros for magic tty types. */ 13679 #define isconsole(tp) ((tp) < tty_addr(NR_CONS)) 13680 #define ispty(tp) ((tp) >= tty_addr(NR_CONS+NR_RS_LINES)) 13681 13682 /* Macros for magic tty structure pointers. */ 13683 #define FIRST_TTY tty_addr(0) 13684 #define END_TTY tty_addr(sizeof(tty_table) / sizeof(tty_table[0])) 13685 13686 /* A device exists if at least its 'devread' function is defined. */ 13687 #define tty_active(tp) ((tp)->tty_devread != NULL) 13688 13689 /* RS232 lines or pseudo terminals can be completely configured out. */ File: Page: 813 drivers/tty/tty.c 13690 #if NR_RS_LINES == 0 13691 #define rs_init(tp) ((void) 0) 13692 #endif 13693 #if NR_PTYS == 0 13694 #define pty_init(tp) ((void) 0) 13695 #define do_pty(tp, mp) ((void) 0) 13696 #endif 13697 13698 FORWARD _PROTOTYPE( void tty_timed_out, (timer_t *tp) ); 13699 FORWARD _PROTOTYPE( void expire_timers, (void) ); 13700 FORWARD _PROTOTYPE( void settimer, (tty_t *tty_ptr, int enable) ); 13701 FORWARD _PROTOTYPE( void do_cancel, (tty_t *tp, message *m_ptr) ); 13702 FORWARD _PROTOTYPE( void do_ioctl, (tty_t *tp, message *m_ptr) ); 13703 FORWARD _PROTOTYPE( void do_open, (tty_t *tp, message *m_ptr) ); 13704 FORWARD _PROTOTYPE( void do_close, (tty_t *tp, message *m_ptr) ); 13705 FORWARD _PROTOTYPE( void do_read, (tty_t *tp, message *m_ptr) ); 13706 FORWARD _PROTOTYPE( void do_write, (tty_t *tp, message *m_ptr) ); 13707 FORWARD _PROTOTYPE( void do_select, (tty_t *tp, message *m_ptr) ); 13708 FORWARD _PROTOTYPE( void do_status, (message *m_ptr) ); 13709 FORWARD _PROTOTYPE( void in_transfer, (tty_t *tp) ); 13710 FORWARD _PROTOTYPE( int tty_echo, (tty_t *tp, int ch) ); 13711 FORWARD _PROTOTYPE( void rawecho, (tty_t *tp, int ch) ); 13712 FORWARD _PROTOTYPE( int back_over, (tty_t *tp) ); 13713 FORWARD _PROTOTYPE( void reprint, (tty_t *tp) ); 13714 FORWARD _PROTOTYPE( void dev_ioctl, (tty_t *tp) ); 13715 FORWARD _PROTOTYPE( void setattr, (tty_t *tp) ); 13716 FORWARD _PROTOTYPE( void tty_icancel, (tty_t *tp) ); 13717 FORWARD _PROTOTYPE( void tty_init, (void) ); 13718 13719 /* Default attributes. */ 13720 PRIVATE struct termios termios_defaults = { 13721 TINPUT_DEF, TOUTPUT_DEF, TCTRL_DEF, TLOCAL_DEF, TSPEED_DEF, TSPEED_DEF, 13722 { 13723 TEOF_DEF, TEOL_DEF, TERASE_DEF, TINTR_DEF, TKILL_DEF, TMIN_DEF, 13724 TQUIT_DEF, TTIME_DEF, TSUSP_DEF, TSTART_DEF, TSTOP_DEF, 13725 TREPRINT_DEF, TLNEXT_DEF, TDISCARD_DEF, 13726 }, 13727 }; 13728 PRIVATE struct winsize winsize_defaults; /* = all zeroes */ 13729 13730 /* Global variables for the TTY task (declared extern in tty.h). */ 13731 PUBLIC tty_t tty_table[NR_CONS+NR_RS_LINES+NR_PTYS]; 13732 PUBLIC int ccurrent; /* currently active console */ 13733 PUBLIC timer_t *tty_timers; /* queue of TTY timers */ 13734 PUBLIC clock_t tty_next_timeout; /* time that the next alarm is due */ 13735 PUBLIC struct machine machine; /* kernel environment variables */ 13736 13737 /*===========================================================================* 13738 * tty_task * 13739 *===========================================================================*/ 13740 PUBLIC void main(void) 13741 { 13742 /* Main routine of the terminal task. */ 13743 13744 message tty_mess; /* buffer for all incoming messages */ 13745 unsigned line; 13746 int s; 13747 char *types[] = {"task","driver","server", "user"}; 13748 register struct proc *rp; 13749 register tty_t *tp; File: Page: 814 drivers/tty/tty.c 13750 13751 /* Initialize the TTY driver. */ 13752 tty_init(); 13753 13754 /* Get kernel environment (protected_mode, pc_at and ega are needed). */ 13755 if (OK != (s=sys_getmachine(&machine))) { 13756 panic("TTY","Couldn't obtain kernel environment.", s); 13757 } 13758 13759 /* Final one-time keyboard initialization. */ 13760 kb_init_once(); 13761 13762 printf("\n"); 13763 13764 while (TRUE) { 13765 13766 /* Check for and handle any events on any of the ttys. */ 13767 for (tp = FIRST_TTY; tp < END_TTY; tp++) { 13768 if (tp->tty_events) handle_events(tp); 13769 } 13770 13771 /* Get a request message. */ 13772 receive(ANY, &tty_mess); 13773 13774 /* First handle all kernel notification types that the TTY supports. 13775 * - An alarm went off, expire all timers and handle the events. 13776 * - A hardware interrupt also is an invitation to check for events. 13777 * - A new kernel message is available for printing. 13778 * - Reset the console on system shutdown. 13779 * Then see if this message is different from a normal device driver 13780 * request and should be handled separately. These extra functions 13781 * do not operate on a device, in constrast to the driver requests. 13782 */ 13783 switch (tty_mess.m_type) { 13784 case SYN_ALARM: /* fall through */ 13785 expire_timers(); /* run watchdogs of expired timers */ 13786 continue; /* contine to check for events */ 13787 case HARD_INT: { /* hardware interrupt notification */ 13788 if (tty_mess.NOTIFY_ARG & kbd_irq_set) 13789 kbd_interrupt(&tty_mess);/* fetch chars from keyboard */ 13790 #if NR_RS_LINES > 0 13791 if (tty_mess.NOTIFY_ARG & rs_irq_set) 13792 rs_interrupt(&tty_mess);/* serial I/O */ 13793 #endif 13794 expire_timers(); /* run watchdogs of expired timers */ 13795 continue; /* contine to check for events */ 13796 } 13797 case SYS_SIG: { /* system signal */ 13798 sigset_t sigset = (sigset_t) tty_mess.NOTIFY_ARG; 13799 13800 if (sigismember(&sigset, SIGKSTOP)) { 13801 cons_stop(); /* switch to primary console */ 13802 if (irq_hook_id != -1) { 13803 sys_irqdisable(&irq_hook_id); 13804 sys_irqrmpolicy(KEYBOARD_IRQ, &irq_hook_id); 13805 } 13806 } 13807 if (sigismember(&sigset, SIGTERM)) cons_stop(); 13808 if (sigismember(&sigset, SIGKMESS)) do_new_kmess(&tty_mess); 13809 continue; File: Page: 815 drivers/tty/tty.c 13810 } 13811 case PANIC_DUMPS: /* allow panic dumps */ 13812 cons_stop(); /* switch to primary console */ 13813 do_panic_dumps(&tty_mess); 13814 continue; 13815 case DIAGNOSTICS: /* a server wants to print some */ 13816 do_diagnostics(&tty_mess); 13817 continue; 13818 case FKEY_CONTROL: /* (un)register a fkey observer */ 13819 do_fkey_ctl(&tty_mess); 13820 continue; 13821 default: /* should be a driver request */ 13822 ; /* do nothing; end switch */ 13823 } 13824 13825 /* Only device requests should get to this point. All requests, 13826 * except DEV_STATUS, have a minor device number. Check this 13827 * exception and get the minor device number otherwise. 13828 */ 13829 if (tty_mess.m_type == DEV_STATUS) { 13830 do_status(&tty_mess); 13831 continue; 13832 } 13833 line = tty_mess.TTY_LINE; 13834 if ((line - CONS_MINOR) < NR_CONS) { 13835 tp = tty_addr(line - CONS_MINOR); 13836 } else if (line == LOG_MINOR) { 13837 tp = tty_addr(0); 13838 } else if ((line - RS232_MINOR) < NR_RS_LINES) { 13839 tp = tty_addr(line - RS232_MINOR + NR_CONS); 13840 } else if ((line - TTYPX_MINOR) < NR_PTYS) { 13841 tp = tty_addr(line - TTYPX_MINOR + NR_CONS + NR_RS_LINES); 13842 } else if ((line - PTYPX_MINOR) < NR_PTYS) { 13843 tp = tty_addr(line - PTYPX_MINOR + NR_CONS + NR_RS_LINES); 13844 if (tty_mess.m_type != DEV_IOCTL) { 13845 do_pty(tp, &tty_mess); 13846 continue; 13847 } 13848 } else { 13849 tp = NULL; 13850 } 13851 13852 /* If the device doesn't exist or is not configured return ENXIO. */ 13853 if (tp == NULL || ! tty_active(tp)) { 13854 printf("Warning, TTY got illegal request %d from %d\n", 13855 tty_mess.m_type, tty_mess.m_source); 13856 tty_reply(TASK_REPLY, tty_mess.m_source, 13857 tty_mess.PROC_NR, ENXIO); 13858 continue; 13859 } 13860 13861 /* Execute the requested device driver function. */ 13862 switch (tty_mess.m_type) { 13863 case DEV_READ: do_read(tp, &tty_mess); break; 13864 case DEV_WRITE: do_write(tp, &tty_mess); break; 13865 case DEV_IOCTL: do_ioctl(tp, &tty_mess); break; 13866 case DEV_OPEN: do_open(tp, &tty_mess); break; 13867 case DEV_CLOSE: do_close(tp, &tty_mess); break; 13868 case DEV_SELECT: do_select(tp, &tty_mess); break; 13869 case CANCEL: do_cancel(tp, &tty_mess); break; File: Page: 816 drivers/tty/tty.c 13870 default: 13871 printf("Warning, TTY got unexpected request %d from %d\n", 13872 tty_mess.m_type, tty_mess.m_source); 13873 tty_reply(TASK_REPLY, tty_mess.m_source, 13874 tty_mess.PROC_NR, EINVAL); 13875 } 13876 } 13877 } 13879 /*===========================================================================* 13880 * do_status * 13881 *===========================================================================*/ 13882 PRIVATE void do_status(m_ptr) 13883 message *m_ptr; 13884 { 13885 register struct tty *tp; 13886 int event_found; 13887 int status; 13888 int ops; 13889 13890 /* Check for select or revive events on any of the ttys. If we found an, 13891 * event return a single status message for it. The FS will make another 13892 * call to see if there is more. 13893 */ 13894 event_found = 0; 13895 for (tp = FIRST_TTY; tp < END_TTY; tp++) { 13896 if ((ops = select_try(tp, tp->tty_select_ops)) && 13897 tp->tty_select_proc == m_ptr->m_source) { 13898 13899 /* I/O for a selected minor device is ready. */ 13900 m_ptr->m_type = DEV_IO_READY; 13901 m_ptr->DEV_MINOR = tp->tty_index; 13902 m_ptr->DEV_SEL_OPS = ops; 13903 13904 tp->tty_select_ops &= ~ops; /* unmark select event */ 13905 event_found = 1; 13906 break; 13907 } 13908 else if (tp->tty_inrevived && tp->tty_incaller == m_ptr->m_source) { 13909 13910 /* Suspended request finished. Send a REVIVE. */ 13911 m_ptr->m_type = DEV_REVIVE; 13912 m_ptr->REP_PROC_NR = tp->tty_inproc; 13913 m_ptr->REP_STATUS = tp->tty_incum; 13914 13915 tp->tty_inleft = tp->tty_incum = 0; 13916 tp->tty_inrevived = 0; /* unmark revive event */ 13917 event_found = 1; 13918 break; 13919 } 13920 else if (tp->tty_outrevived && tp->tty_outcaller == m_ptr->m_source) { 13921 13922 /* Suspended request finished. Send a REVIVE. */ 13923 m_ptr->m_type = DEV_REVIVE; 13924 m_ptr->REP_PROC_NR = tp->tty_outproc; 13925 m_ptr->REP_STATUS = tp->tty_outcum; 13926 13927 tp->tty_outcum = 0; 13928 tp->tty_outrevived = 0; /* unmark revive event */ 13929 event_found = 1; File: Page: 817 drivers/tty/tty.c 13930 break; 13931 } 13932 } 13933 13934 #if NR_PTYS > 0 13935 if (!event_found) 13936 event_found = pty_status(m_ptr); 13937 #endif 13938 13939 if (! event_found) { 13940 /* No events of interest were found. Return an empty message. */ 13941 m_ptr->m_type = DEV_NO_STATUS; 13942 } 13943 13944 /* Almost done. Send back the reply message to the caller. */ 13945 if ((status = send(m_ptr->m_source, m_ptr)) != OK) { 13946 panic("TTY","send in do_status failed, status\n", status); 13947 } 13948 } 13950 /*===========================================================================* 13951 * do_read * 13952 *===========================================================================*/ 13953 PRIVATE void do_read(tp, m_ptr) 13954 register tty_t *tp; /* pointer to tty struct */ 13955 register message *m_ptr; /* pointer to message sent to the task */ 13956 { 13957 /* A process wants to read from a terminal. */ 13958 int r, status; 13959 phys_bytes phys_addr; 13960 13961 /* Check if there is already a process hanging in a read, check if the 13962 * parameters are correct, do I/O. 13963 */ 13964 if (tp->tty_inleft > 0) { 13965 r = EIO; 13966 } else 13967 if (m_ptr->COUNT <= 0) { 13968 r = EINVAL; 13969 } else 13970 if (sys_umap(m_ptr->PROC_NR, D, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT, 13971 &phys_addr) != OK) { 13972 r = EFAULT; 13973 } else { 13974 /* Copy information from the message to the tty struct. */ 13975 tp->tty_inrepcode = TASK_REPLY; 13976 tp->tty_incaller = m_ptr->m_source; 13977 tp->tty_inproc = m_ptr->PROC_NR; 13978 tp->tty_in_vir = (vir_bytes) m_ptr->ADDRESS; 13979 tp->tty_inleft = m_ptr->COUNT; 13980 13981 if (!(tp->tty_termios.c_lflag & ICANON) 13982 && tp->tty_termios.c_cc[VTIME] > 0) { 13983 if (tp->tty_termios.c_cc[VMIN] == 0) { 13984 /* MIN & TIME specify a read timer that finishes the 13985 * read in TIME/10 seconds if no bytes are available. 13986 */ 13987 settimer(tp, TRUE); 13988 tp->tty_min = 1; 13989 } else { File: Page: 818 drivers/tty/tty.c 13990 /* MIN & TIME specify an inter-byte timer that may 13991 * have to be cancelled if there are no bytes yet. 13992 */ 13993 if (tp->tty_eotct == 0) { 13994 settimer(tp, FALSE); 13995