_________________________ Page 639 File: _________________________
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/ansi.h
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00000 /* The <ansi.h> 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
_________________________ Page 640 File: 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 <limits.h> 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 <sys/dir.h>
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 */
_________________________ Page 641 File: 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 <errno.h> 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 <errno.h> is already included */
_________________________ Page 642 File: 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 */
_________________________ Page 643 File: 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 <unistd.h> header contains a few miscellaneous manifest constants. */
00401
00402 #ifndef _UNISTD_H
00403 #define _UNISTD_H
00404
00405 #ifndef _TYPES_H
00406 #include <sys/types.h>
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
_________________________ Page 644 File: 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 <unistd.h> 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)
_________________________ Page 645 File: 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
_________________________ Page 646 File: include/unistd.h _________________________
00540 #ifdef _MINIX
00541 #ifndef _TYPE_H
00542 #include <minix/type.h>
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 <string.h> 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
_________________________ Page 647 File: 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 <ansi.h>
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 */
_________________________ Page 648 File: include/string.h _________________________
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/signal.h
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00700 /* The <signal.h> 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 <ansi.h>
00710 #endif
00711 #ifdef _POSIX_SOURCE
00712 #ifndef _TYPES_H
00713 #include <sys/types.h>
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 */
_________________________ Page 649 File: 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,
_________________________ Page 650 File: 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 <fcntl.h> 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 <sys/types.h>
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. */
_________________________ Page 651 File: 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 <termios.h> 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 */
_________________________ Page 652 File: 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 */
_________________________ Page 653 File: 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 <ansi.h>
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
_________________________ Page 654 File: 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 */
_________________________ Page 655 File: include/termios.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 <jnherder@cs.vu.nl>
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 <limits.h>
01318 #include <sys/types.h>
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.
_________________________ Page 656 File: 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 <sys/types.h> 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 <ansi.h>
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
_________________________ Page 657 File: 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;
_________________________ Page 658 File: 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 <ansi.h>
01610 #endif
01611
01612 #ifndef _MINIX_SYS_CONFIG_H
01613 #include <minix/sys_config.h>
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;
_________________________ Page 659 File: 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 <minix/jmp_buf.h>. */
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 */
_________________________ Page 660 File: include/sys/sigcontext.h _____________________
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/sys/stat.h
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
01700 /* The <sys/stat.h> 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 <sys/types.h>
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-- */
_________________________ Page 661 File: 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 <dir.h> header gives the layout of a directory. */
01801
01802 #ifndef _DIR_H
01803 #define _DIR_H
01804
01805 #include <sys/types.h>
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 <sys/wait.h> 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 *
_________________________ Page 662 File: 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 <sys/types.h>
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 <sys/ioc_tty.h> /* 'T' 't' 'k' */
02016 #include <sys/ioc_disk.h> /* 'd' */
02017 #include <sys/ioc_memory.h> /* 'm' */
02018 #include <sys/ioc_cmos.h> /* 'c' */
02019
_________________________ Page 663 File: 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 <minix/ioctl.h>
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 <sys/types.h>
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
_________________________ Page 664 File: 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) <
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 <minix/machine.h>.
02325 */
02326 #include <minix/sys_config.h>
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
_________________________ Page 665 File: 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 */
_________________________ Page 666 File: 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
_________________________ Page 667 File: include/minix/sys_config.h ___________________
02540 error "In <minix/sys_config.h> please define _MINIX_MACHINE"
02541 #endif
02542
02543 #ifndef _MINIX_CHIP
02544 error "In <minix/sys_config.h> please define _MINIX_MACHINE to have a legal valu
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) */
_________________________ Page 668 File: 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 */
_________________________ Page 669 File: 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 <minix/sys_config.h>
02805 #endif
02806
02807 #ifndef _TYPES_H
02808 #include <sys/types.h>
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 {
_________________________ Page 670 File: 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 */
_________________________ Page 671 File: 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
_________________________ Page 672 File: 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) );
_________________________ Page 673 File: 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 <sys/types.h>
03207 #endif
03208
03209 #ifndef _IPC_H
03210 #include <minix/ipc.h>
03211 #endif
03212
03213 #ifndef _DEVIO_H
03214 #include <minix/devio.h>
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,
_________________________ Page 674 File: 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)
_________________________ Page 675 File: 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
_________________________ Page 676 File: 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
_________________________ Page 677 File: 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 */
_________________________ Page 678 File: 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 <minix/config.h>. */
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
_________________________ Page 679 File: 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
_________________________ Page 680 File: 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. */
_________________________ Page 681 File: 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 */
_________________________ Page 682 File: 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 */
_________________________ Page 683 File: 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 */
_________________________ Page 684 File: 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 */
_________________________ Page 685 File: 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 <minix/sys_config.h> /* needed to include <minix/type.h> */
04112 #include <sys/types.h> /* 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 <ibm/portio.h>, 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 <minix/sys_config.h>
04204 #include <minix/ipc.h>
04205
_________________________ Page 686 File: 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) device
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 */
_________________________ Page 687 File: include/minix/dmap.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 <sys/types.h>
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 */
_________________________ Page 688 File: 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) */
_________________________ Page 689 File: 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 <minix/config.h> /* global configuration, MUST be first */
04612 #include <ansi.h> /* C style: ANSI or K&R, MUST be second */
04613 #include <sys/types.h> /* general system types */
04614 #include <minix/const.h> /* MINIX specific constants */
04615 #include <minix/type.h> /* MINIX specific types, e.g. message */
04616 #include <minix/ipc.h> /* MINIX run-time system */
04617 #include <timers.h> /* watchdog timer management */
04618 #include <errno.h> /* return codes and error numbers */
04619 #include <ibm/portio.h> /* 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 */
_________________________ Page 690 File: 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 */
_________________________ Page 691 File: 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 <ibm/interrupt.h> /* interrupt numbers and hardware vectors */
04805 #include <ibm/ports.h> /* port addresses and magic numbers */
04806 #include <ibm/bios.h> /* BIOS addresses, sizes and magic numbers */
04807 #include <ibm/cpu.h> /* BIOS addresses, sizes and magic numbers */
04808 #include <minix/config.h>
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) )
_________________________ Page 692 File: 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 */
_________________________ Page 693 File: 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; /* | */
_________________________ Page 694 File: 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) );
_________________________ Page 695 File: 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)) );
_________________________ Page 696 File: 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) );
_________________________ Page 697 File: 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 <minix/config.h>
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
_________________________ Page 698 File: 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 <minix/com.h>
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.
_________________________ Page 699 File: kernel/proc.h _________________________
05510 */
05511 #include <minix/com.h>
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. */
_________________________ Page 700 File: 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
_________________________ Page 701 File: 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 <minix/com.h>
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
_________________________ Page 702 File: 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
_________________________ Page 703 File: 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 */
_________________________ Page 704 File: 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
_________________________ Page 705 File: 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 <minix/com.h>
06034 #include <ibm/int86.h>
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.
_________________________ Page 706 File: 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 <minix/config.h>
06204 #if _WORD_SIZE == 2
_________________________ Page 707 File: 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
_________________________ Page 708 File: kernel/mpx386.s _________________________
06350 begdata:
06351 .sect .bss
06352 begbss:
06353
06354 #include <minix/config.h>
06355 #include <minix/const.h>
06356 #include <minix/com.h>
06357 #include <ibm/interrupt.h>
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
_________________________ Page 709 File: 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
_________________________ Page 710 File: 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<<irq] /* mask irq */ ;
06524 outb INT_CTLMASK /* disable the irq */;\
06525 0: movb al, END_OF_INT ;\
06526 outb INT_CTL /* reenable master 8259 */;\
06527 ret /* restart (another) process */
06528
06529 ! Each of these entry points is an expansion of the hwint_master macro
_________________________ Page 711 File: kernel/mpx386.s _________________________
06530 .align 16
06531 _hwint00: ! Interrupt routine for irq 0 (the clock).
06532 hwint_master(0)
06533
06534 .align 16
06535 _hwint01: ! Interrupt routine for irq 1 (keyboard)
06536 hwint_master(1)
06537
06538 .align 16
06539 _hwint02: ! Interrupt routine for irq 2 (cascade!)
06540 hwint_master(2)
06541
06542 .align 16
06543 _hwint03: ! Interrupt routine for irq 3 (second serial)
06544 hwint_master(3)
06545
06546 .align 16
06547 _hwint04: ! Interrupt routine for irq 4 (first serial)
06548 hwint_master(4)
06549
06550 .align 16
06551 _hwint05: ! Interrupt routine for irq 5 (XT winchester)
06552 hwint_master(5)
06553
06554 .align 16
06555 _hwint06: ! Interrupt routine for irq 6 (floppy)
06556 hwint_master(6)
06557
06558 .align 16
06559 _hwint07: ! Interrupt routine for irq 7 (printer)
06560 hwint_master(7)
06561
06562 !*===========================================================================*
06563 !* hwint08 - 15 *
06564 !*===========================================================================*
06565 ! Note this is a macro, it just looks like a subroutine.
06566 #define hwint_slave(irq) \
06567 call save /* save interrupted process state */;\
06568 push (_irq_handlers+4*irq) /* irq_handlers[irq] */;\
06569 call _intr_handle /* intr_handle(irq_handlers[irq]) */;\
06570 pop ecx ;\
06571 cmp (_irq_actids+4*irq), 0 /* interrupt still active? */;\
06572 jz 0f ;\
06573 inb INT2_CTLMASK ;\
06574 orb al, [1<<[irq-8]] ;
06575 outb INT2_CTLMASK /* disable the irq */;\
06576 0: movb al, END_OF_INT ;\
06577 outb INT_CTL /* reenable master 8259 */;\
06578 outb INT2_CTL /* reenable slave 8259 */;\
06579 ret /* restart (another) process */
06580
06581 ! Each of these entry points is an expansion of the hwint_slave macro
06582 .align 16
06583 _hwint08: ! Interrupt routine for irq 8 (realtime clock)
06584 hwint_slave(8)
06585
06586 .align 16
06587 _hwint09: ! Interrupt routine for irq 9 (irq 2 redirected)
06588 hwint_slave(9)
06589
_________________________ Page 712 File: kernel/mpx386.s _________________________
06590 .align 16
06591 _hwint10: ! Interrupt routine for irq 10
06592 hwint_slave(10)
06593
06594 .align 16
06595 _hwint11: ! Interrupt routine for irq 11
06596 hwint_slave(11)
06597
06598 .align 16
06599 _hwint12: ! Interrupt routine for irq 12
06600 hwint_slave(12)
06601
06602 .align 16
06603 _hwint13: ! Interrupt routine for irq 13 (FPU exception)
06604 hwint_slave(13)
06605
06606 .align 16
06607 _hwint14: ! Interrupt routine for irq 14 (AT winchester)
06608 hwint_slave(14)
06609
06610 .align 16
06611 _hwint15: ! Interrupt routine for irq 15
06612 hwint_slave(15)
06613
06614 !*===========================================================================*
06615 !* save *
06616 !*===========================================================================*
06617 ! Save for protected mode.
06618 ! This is much simpler than for 8086 mode, because the stack already points
06619 ! into the process table, or has already been switched to the kernel stack.
06620
06621 .align 16
06622 save:
06623 cld ! set direction flag to a known value
06624 pushad ! save "general" registers
06625 o16 push ds ! save ds
06626 o16 push es ! save es
06627 o16 push fs ! save fs
06628 o16 push gs ! save gs
06629 mov dx, ss ! ss is kernel data segment
06630 mov ds, dx ! load rest of kernel segments
06631 mov es, dx ! kernel does not use fs, gs
06632 mov eax, esp ! prepare to return
06633 incb (_k_reenter) ! from -1 if not reentering
06634 jnz set_restart1 ! stack is already kernel stack
06635 mov esp, k_stktop
06636 push _restart ! build return address for int handler
06637 xor ebp, ebp ! for stacktrace
06638 jmp RETADR-P_STACKBASE(eax)
06639
06640 .align 4
06641 set_restart1:
06642 push restart1
06643 jmp RETADR-P_STACKBASE(eax)
06644
06645 !*===========================================================================*
06646 !* _s_call *
06647 !*===========================================================================*
06648 .align 16
06649 _s_call:
_________________________ Page 713 File: kernel/mpx386.s _________________________
06650 _p_s_call:
06651 cld ! set direction flag to a known value
06652 sub esp, 6*4 ! skip RETADR, eax, ecx, edx, ebx, est
06653 push ebp ! stack already points into proc table
06654 push esi
06655 push edi
06656 o16 push ds
06657 o16 push es
06658 o16 push fs
06659 o16 push gs
06660 mov dx, ss
06661 mov ds, dx
06662 mov es, dx
06663 incb (_k_reenter)
06664 mov esi, esp ! assumes P_STACKBASE == 0
06665 mov esp, k_stktop
06666 xor ebp, ebp ! for stacktrace
06667 ! end of inline save
06668 ! now set up parameters for sys_call()
06669 push ebx ! pointer to user message
06670 push eax ! src/dest
06671 push ecx ! SEND/RECEIVE/BOTH
06672 call _sys_call ! sys_call(function, src_dest, m_ptr)
06673 ! caller is now explicitly in proc_ptr
06674 mov AXREG(esi), eax ! sys_call MUST PRESERVE si
06675
06676 ! Fall into code to restart proc/task running.
06677
06678 !*===========================================================================*
06679 !* restart *
06680 !*===========================================================================*
06681 _restart:
06682
06683 ! Restart the current process or the next process if it is set.
06684
06685 cmp (_next_ptr), 0 ! see if another process is scheduled
06686 jz 0f
06687 mov eax, (_next_ptr)
06688 mov (_proc_ptr), eax ! schedule new process
06689 mov (_next_ptr), 0
06690 0: mov esp, (_proc_ptr) ! will assume P_STACKBASE == 0
06691 lldt P_LDT_SEL(esp) ! enable process' segment descriptors
06692 lea eax, P_STACKTOP(esp) ! arrange for next interrupt
06693 mov (_tss+TSS3_S_SP0), eax ! to save state in process table
06694 restart1:
06695 decb (_k_reenter)
06696 o16 pop gs
06697 o16 pop fs
06698 o16 pop es
06699 o16 pop ds
06700 popad
06701 add esp, 4 ! skip return adr
06702 iretd ! continue process
06703
06704 !*===========================================================================*
06705 !* exception handlers *
06706 !*===========================================================================*
06707 _divide_error:
06708 push DIVIDE_VECTOR
06709 jmp exception
_________________________ Page 714 File: kernel/mpx386.s _________________________
06710
06711 _single_step_exception:
06712 push DEBUG_VECTOR
06713 jmp exception
06714
06715 _nmi:
06716 push NMI_VECTOR
06717 jmp exception
06718
06719 _breakpoint_exception:
06720 push BREAKPOINT_VECTOR
06721 jmp exception
06722
06723 _overflow:
06724 push OVERFLOW_VECTOR
06725 jmp exception
06726
06727 _bounds_check:
06728 push BOUNDS_VECTOR
06729 jmp exception
06730
06731 _inval_opcode:
06732 push INVAL_OP_VECTOR
06733 jmp exception
06734
06735 _copr_not_available:
06736 push COPROC_NOT_VECTOR
06737 jmp exception
06738
06739 _double_fault:
06740 push DOUBLE_FAULT_VECTOR
06741 jmp errexception
06742
06743 _copr_seg_overrun:
06744 push COPROC_SEG_VECTOR
06745 jmp exception
06746
06747 _inval_tss:
06748 push INVAL_TSS_VECTOR
06749 jmp errexception
06750
06751 _segment_not_present:
06752 push SEG_NOT_VECTOR
06753 jmp errexception
06754
06755 _stack_exception:
06756 push STACK_FAULT_VECTOR
06757 jmp errexception
06758
06759 _general_protection:
06760 push PROTECTION_VECTOR
06761 jmp errexception
06762
06763 _page_fault:
06764 push PAGE_FAULT_VECTOR
06765 jmp errexception
06766
06767 _copr_error:
06768 push COPROC_ERR_VECTOR
06769 jmp exception
_________________________ Page 715 File: kernel/mpx386.s _________________________
06770
06771 !*===========================================================================*
06772 !* exception *
06773 !*===========================================================================*
06774 ! This is called for all exceptions which do not push an error code.
06775
06776 .align 16
06777 exception:
06778 sseg mov (trap_errno), 0 ! clear trap_errno
06779 sseg pop (ex_number)
06780 jmp exception1
06781
06782 !*===========================================================================*
06783 !* errexception *
06784 !*===========================================================================*
06785 ! This is called for all exceptions which push an error code.
06786
06787 .align 16
06788 errexception:
06789 sseg pop (ex_number)
06790 sseg pop (trap_errno)
06791 exception1: ! Common for all exceptions.
06792 push eax ! eax is scratch register
06793 mov eax, 0+4(esp) ! old eip
06794 sseg mov (old_eip), eax
06795 movzx eax, 4+4(esp) ! old cs
06796 sseg mov (old_cs), eax
06797 mov eax, 8+4(esp) ! old eflags
06798 sseg mov (old_eflags), eax
06799 pop eax
06800 call save
06801 push (old_eflags)
06802 push (old_cs)
06803 push (old_eip)
06804 push (trap_errno)
06805 push (ex_number)
06806 call _exception ! (ex_number, trap_errno, old_eip,
06807 ! old_cs, old_eflags)
06808 add esp, 5*4
06809 ret
06810
06811 !*===========================================================================*
06812 !* level0_call *
06813 !*===========================================================================*
06814 _level0_call:
06815 call save
06816 jmp (_level0_func)
06817
06818 !*===========================================================================*
06819 !* data *
06820 !*===========================================================================*
06821
06822 .sect .rom ! Before the string table please
06823 .data2 0x526F ! this must be the first data entry (magic #)
06824
06825 .sect .bss
06826 k_stack:
06827 .space K_STACK_BYTES ! kernel stack
06828 k_stktop: ! top of kernel stack
06829 .comm ex_number, 4
_________________________ Page 716 File: kernel/mpx386.s _________________________
06830 .comm trap_errno, 4
06831 .comm old_eip, 4
06832 .comm old_cs, 4
06833 .comm old_eflags, 4
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
kernel/start.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
06900 /* This file contains the C startup code for Minix on Intel processors.
06901 * It cooperates with mpx.s to set up a good environment for main().
06902 *
06903 * This code runs in real mode for a 16 bit kernel and may have to switch
06904 * to protected mode for a 286.
06905 * For a 32 bit kernel this already runs in protected mode, but the selectors
06906 * are still those given by the BIOS with interrupts disabled, so the
06907 * descriptors need to be reloaded and interrupt descriptors made.
06908 */
06909
06910 #include "kernel.h"
06911 #include "protect.h"
06912 #include "proc.h"
06913 #include <stdlib.h>
06914 #include <string.h>
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
_________________________ Page 717 File: 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 ;
_________________________ Page 718 File: 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 <signal.h>
07116 #include <string.h>
07117 #include <unistd.h>
07118 #include <a.out.h>
07119 #include <minix/callnr.h>
07120 #include <minix/com.h>
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);
_________________________ Page 719 File: 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 */
_________________________ Page 720 File: 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
_________________________ Page 721 File: 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; rp<END_PROC_ADDR; rp++) {
07300 if (!isemptyp(rp) && (priv(rp)->s_flags & SYS_PROC) && !i
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;
_________________________ Page 722 File: 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 *
_________________________ Page 723 File: 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 <minix/com.h>
07439 #include <minix/callnr.h>
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
_________________________ Page 724 File: 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) {
_________________________ Page 725 File: 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 {
_________________________ Page 726 File: 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;
_________________________ Page 727 File: 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]; chu
07671
07672 /* Find a pending notification from the requested source. */
07673 if (! *chunk) continue; /* no bits in chunk */
07674 for (i=0; ! (*chunk & (1<<i)); ++i) {} /* look up the bi
07675 src_id = (chunk - &map->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 pend
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 }
_________________________ Page 728 File: 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. */
_________________________ Page 729 File: 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)) {
_________________________ Page 730 File: 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 */
_________________________ Page 731 File: 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");
_________________________ Page 732 File: 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 <signal.h>
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 },
_________________________ Page 733 File: 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 <minix/com.h>
_________________________ Page 734 File: 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;
_________________________ Page 735 File: 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. */
_________________________ Page 736 File: 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;
_________________________ Page 737 File: 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 },
_________________________ Page 738 File: 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;
_________________________ Page 739 File: 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) {
_________________________ Page 740 File: 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];
_________________________ Page 741 File: 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 }
_________________________ Page 742 File: 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 <minix/config.h>
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 <minix/config.h>
08806 #include <minix/const.h>
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
_________________________ Page 743 File: 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<<CLOCK_IRQ] ! keep the clock ticking
08885 outb INT_CTLMASK ! enable all unused IRQ's and vv.
08886 movb al, ah
08887 outb INT2_CTLMASK
08888
08889 mov eax, SS_SELECTOR ! monitor data segment
08890 mov ss, ax
08891 xchg esp, (_mon_sp) ! switch stacks
08892 push (_reg86+36) ! parameters used in INT call
08893 push (_reg86+32)
08894 push (_reg86+28)
_________________________ Page 744 File: kernel/klib386.s _________________________
08895 push (_reg86+24)
08896 push (_reg86+20)
08897 push (_reg86+16)
08898 push (_reg86+12)
08899 push (_reg86+ 8)
08900 push (_reg86+ 4)
08901 push (_reg86+ 0)
08902 mov ds, ax ! remaining data selectors
08903 mov es, ax
08904 mov fs, ax
08905 mov gs, ax
08906 push cs
08907 push return ! kernel return address and selector
08908 o16 jmpf 20+2*4+10*4+2*4(esp) ! make the call
08909 return:
08910 pop (_reg86+ 0)
08911 pop (_reg86+ 4)
08912 pop (_reg86+ 8)
08913 pop (_reg86+12)
08914 pop (_reg86+16)
08915 pop (_reg86+20)
08916 pop (_reg86+24)
08917 pop (_reg86+28)
08918 pop (_reg86+32)
08919 pop (_reg86+36)
08920 lgdt (_gdt+GDT_SELECTOR) ! reload global descriptor table
08921 jmpf CS_SELECTOR:csinit ! restore everything
08922 csinit: mov eax, DS_SELECTOR
08923 mov ds, ax
08924 mov es, ax
08925 mov fs, ax
08926 mov gs, ax
08927 mov ss, ax
08928 xchg esp, (_mon_sp) ! unswitch stacks
08929 lidt (_gdt+IDT_SELECTOR) ! reload interrupt descriptor table
08930 andb (_gdt+TSS_SELECTOR+DESC_ACCESS), ~0x02 ! clear TSS busy bit
08931 mov eax, TSS_SELECTOR
08932 ltr ax ! set TSS register
08933
08934 pop eax
08935 outb INT_CTLMASK ! restore interrupt masks
08936 movb al, ah
08937 outb INT2_CTLMASK
08938
08939 add (_lost_ticks), ecx ! record lost clock ticks
08940
08941 popf ! restore flags
08942 pop ebx ! restore C registers
08943 pop edi
08944 pop esi
08945 pop ebp
08946 ret
08947
08948
08949 !*===========================================================================*
08950 !* cp_mess *
08951 !*===========================================================================*
08952 ! PUBLIC void cp_mess(int src, phys_clicks src_clicks, vir_bytes src_offset,
08953 ! phys_clicks dst_clicks, vir_bytes dst_offset);
08954 ! This routine makes a fast copy of a message from anywhere in the address
_________________________ Page 745 File: kernel/klib386.s _________________________
08955 ! space to anywhere else. It also copies the source address provided as a
08956 ! parameter to the call into the first word of the destination message.
08957 !
08958 ! Note that the message size, "Msize" is in DWORDS (not bytes) and must be set
08959 ! correctly. Changing the definition of message in the type file and not
08960 ! changing it here will lead to total disaster.
08961
08962 CM_ARGS = 4 + 4 + 4 + 4 + 4 ! 4 + 4 + 4 + 4 + 4
08963 ! es ds edi esi eip proc scl sof dcl dof
08964
08965 .align 16
08966 _cp_mess:
08967 cld
08968 push esi
08969 push edi
08970 push ds
08971 push es
08972
08973 mov eax, FLAT_DS_SELECTOR
08974 mov ds, ax
08975 mov es, ax
08976
08977 mov esi, CM_ARGS+4(esp) ! src clicks
08978 shl esi, CLICK_SHIFT
08979 add esi, CM_ARGS+4+4(esp) ! src offset
08980 mov edi, CM_ARGS+4+4+4(esp) ! dst clicks
08981 shl edi, CLICK_SHIFT
08982 add edi, CM_ARGS+4+4+4+4(esp) ! dst offset
08983
08984 mov eax, CM_ARGS(esp) ! process number of sender
08985 stos ! copy number of sender to dest message
08986 add esi, 4 ! do not copy first word
08987 mov ecx, Msize - 1 ! remember, first word does not count
08988 rep
08989 movs ! copy the message
08990
08991 pop es
08992 pop ds
08993 pop edi
08994 pop esi
08995 ret ! that is all folks!
08996
08997
08998 !*===========================================================================*
08999 !* exit *
09000 !*===========================================================================*
09001 ! PUBLIC void exit();
09002 ! Some library routines use exit, so provide a dummy version.
09003 ! Actual calls to exit cannot occur in the kernel.
09004 ! GNU CC likes to call ___main from main() for nonobvious reasons.
09005
09006 _exit:
09007 __exit:
09008 ___exit:
09009 sti
09010 jmp ___exit
09011
09012 ___main:
09013 ret
09014
_________________________ Page 746 File: kernel/klib386.s _________________________
09015
09016 !*===========================================================================*
09017 !* phys_insw *
09018 !*===========================================================================*
09019 ! PUBLIC void phys_insw(Port_t port, phys_bytes buf, size_t count);
09020 ! Input an array from an I/O port. Absolute address version of insw().
09021
09022 _phys_insw:
09023 push ebp
09024 mov ebp, esp
09025 cld
09026 push edi
09027 push es
09028 mov ecx, FLAT_DS_SELECTOR
09029 mov es, cx
09030 mov edx, 8(ebp) ! port to read from
09031 mov edi, 12(ebp) ! destination addr
09032 mov ecx, 16(ebp) ! byte count
09033 shr ecx, 1 ! word count
09034 rep o16 ins ! input many words
09035 pop es
09036 pop edi
09037 pop ebp
09038 ret
09039
09040
09041 !*===========================================================================*
09042 !* phys_insb *
09043 !*===========================================================================*
09044 ! PUBLIC void phys_insb(Port_t port, phys_bytes buf, size_t count);
09045 ! Input an array from an I/O port. Absolute address version of insb().
09046
09047 _phys_insb:
09048 push ebp
09049 mov ebp, esp
09050 cld
09051 push edi
09052 push es
09053 mov ecx, FLAT_DS_SELECTOR
09054 mov es, cx
09055 mov edx, 8(ebp) ! port to read from
09056 mov edi, 12(ebp) ! destination addr
09057 mov ecx, 16(ebp) ! byte count
09058 ! shr ecx, 1 ! word count
09059 rep insb ! input many bytes
09060 pop es
09061 pop edi
09062 pop ebp
09063 ret
09064
09065
09066 !*===========================================================================*
09067 !* phys_outsw *
09068 !*===========================================================================*
09069 ! PUBLIC void phys_outsw(Port_t port, phys_bytes buf, size_t count);
09070 ! Output an array to an I/O port. Absolute address version of outsw().
09071
09072 .align 16
09073 _phys_outsw:
09074 push ebp
_________________________ Page 747 File: kernel/klib386.s _________________________
09075 mov ebp, esp
09076 cld
09077 push esi
09078 push ds
09079 mov ecx, FLAT_DS_SELECTOR
09080 mov ds, cx
09081 mov edx, 8(ebp) ! port to write to
09082 mov esi, 12(ebp) ! source addr
09083 mov ecx, 16(ebp) ! byte count
09084 shr ecx, 1 ! word count
09085 rep o16 outs ! output many words
09086 pop ds
09087 pop esi
09088 pop ebp
09089 ret
09090
09091
09092 !*===========================================================================*
09093 !* phys_outsb *
09094 !*===========================================================================*
09095 ! PUBLIC void phys_outsb(Port_t port, phys_bytes buf, size_t count);
09096 ! Output an array to an I/O port. Absolute address version of outsb().
09097
09098 .align 16
09099 _phys_outsb:
09100 push ebp
09101 mov ebp, esp
09102 cld
09103 push esi
09104 push ds
09105 mov ecx, FLAT_DS_SELECTOR
09106 mov ds, cx
09107 mov edx, 8(ebp) ! port to write to
09108 mov esi, 12(ebp) ! source addr
09109 mov ecx, 16(ebp) ! byte count
09110 rep outsb ! output many bytes
09111 pop ds
09112 pop esi
09113 pop ebp
09114 ret
09115
09116
09117 !*==========================================================================*
09118 !* enable_irq *
09119 !*==========================================================================*/
09120 ! PUBLIC void enable_irq(irq_hook_t *hook)
09121 ! Enable an interrupt request line by clearing an 8259 bit.
09122 ! Equivalent C code for hook->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
_________________________ Page 748 File: 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
_________________________ Page 749 File: 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
_________________________ Page 750 File: 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
_________________________ Page 751 File: 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
_________________________ Page 752 File: kernel/klib386.s _________________________
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 <minix/com.h>
09415 #include "kernel.h"
09416 #include <stdarg.h>
09417 #include <unistd.h>
09418 #include <stddef.h>
09419 #include <stdlib.h>
09420 #include <signal.h>
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 */
_________________________ Page 753 File: 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 {
_________________________ Page 754 File: 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) );
_________________________ Page 755 File: 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)
_________________________ Page 756 File: 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 <stdlib.h>
09733 #include <signal.h>
09734 #include <unistd.h>
09735 #include <sys/sigcontext.h>
09736 #include <ibm/memory.h>
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<<call_nr))) {
09776 kprintf("SYSTEM: request %d from %d denied.\n", call_nr,m.m_source);
09777 result = ECALLDENIED; /* illegal message type */
09778 } else if (call_nr >= 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 }
_________________________ Page 757 File: 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; i<NR_IRQ_HOOKS; i++) {
09809 irq_hooks[i].proc_nr = NONE;
09810 }
09811
09812 /* Initialize all alarm timers for all processes. */
09813 for (sp=BEG_PRIV_ADDR; sp < END_PRIV_ADDR; sp++) {
09814 tmr_inittimer(&(sp->s_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; i<NR_SYS_CALLS; i++) {
09823 call_vec[i] = do_unused;
09824 }
09825
09826 /* Process management. */
09827 map(SYS_FORK, do_fork); /* a process forked a new process */
09828 map(SYS_EXEC, do_exec); /* update process after execute */
09829 map(SYS_EXIT, do_exit); /* clean up after process exit */
09830 map(SYS_NICE, do_nice); /* set scheduling priority */
09831 map(SYS_PRIVCTL, do_privctl); /* system privileges control */
09832 map(SYS_TRACE, do_trace); /* request a trace operation */
09833
09834 /* Signal handling. */
09835 map(SYS_KILL, do_kill); /* cause a process to be signaled */
09836 map(SYS_GETKSIG, do_getksig); /* PM checks for pending signals */
09837 map(SYS_ENDKSIG, do_endksig); /* PM finished processing signal */
09838 map(SYS_SIGSEND, do_sigsend); /* start POSIX-style signal */
09839 map(SYS_SIGRETURN, do_sigreturn); /* return from POSIX-style signal */
09840
09841 /* Device I/O. */
09842 map(SYS_IRQCTL, do_irqctl); /* interrupt control operations */
09843 map(SYS_DEVIO, do_devio); /* inb, inw, inl, outb, outw, outl */
09844 map(SYS_SDEVIO, do_sdevio); /* phys_insb, _insw, _outsb, _outsw */
_________________________ Page 758 File: kernel/system.c _________________________
09845 map(SYS_VDEVIO, do_vdevio); /* vector with devio requests */
09846 map(SYS_INT86, do_int86); /* real-mode BIOS calls */
09847
09848 /* Memory management. */
09849 map(SYS_NEWMAP, do_newmap); /* set up a process memory map */
09850 map(SYS_SEGCTL, do_segctl); /* add segment and get selector */
09851 map(SYS_MEMSET, do_memset); /* write char to memory area */
09852
09853 /* Copying. */
09854 map(SYS_UMAP, do_umap); /* map virtual to physical address */
09855 map(SYS_VIRCOPY, do_vircopy); /* use pure virtual addressing */
09856 map(SYS_PHYSCOPY, do_physcopy); /* use physical addressing */
09857 map(SYS_VIRVCOPY, do_virvcopy); /* vector with copy requests */
09858 map(SYS_PHYSVCOPY, do_physvcopy); /* vector with copy requests */
09859
09860 /* Clock functionality. */
09861 map(SYS_TIMES, do_times); /* get uptime and process times */
09862 map(SYS_SETALARM, do_setalarm); /* schedule a synchronous alarm */
09863
09864 /* System control. */
09865 map(SYS_ABORT, do_abort); /* abort MINIX */
09866 map(SYS_GETINFO, do_getinfo); /* request system information */
09867 }
09869 /*===========================================================================*
09870 * get_priv *
09871 *===========================================================================*/
09872 PUBLIC int get_priv(rc, proc_type)
09873 register struct proc *rc; /* new (child) process pointer */
09874 int proc_type; /* system or user process flag */
09875 {
09876 /* Get a privilege structure. All user processes share the same privilege
09877 * structure. System processes get their own privilege structure.
09878 */
09879 register struct priv *sp; /* privilege structure */
09880
09881 if (proc_type == SYS_PROC) { /* find a new slot */
09882 for (sp = BEG_PRIV_ADDR; sp < END_PRIV_ADDR; ++sp)
09883 if (sp->s_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).
_________________________ Page 759 File: 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.
_________________________ Page 760 File: 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 }
_________________________ Page 761 File: 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;
_________________________ Page 762 File: 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"
_________________________ Page 763 File: 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 */
_________________________ Page 764 File: 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 <string.h>
10311 #include <signal.h>
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, "<unset>", P_NAME_LEN);
10345 }
10346 return(OK);
10347 }
10348 #endif /* USE_EXEC */
_________________________ Page 765 File: kernel/system/do_exec.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 <signal.h>
10434 #include <minix/com.h>
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 <timers.h> 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
_________________________ Page 766 File: 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 & PREEM
10511 lock_dequeue(prev_ptr); /* take it off the queues */
10512 lock_enqueue(prev_ptr); /* and reinsert it again */
10513 }
10514
_________________________ Page 767 File: 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
_________________________ Page 768 File: 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
_________________________ Page 769 File: 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 <errno.h> */
10706
10707 /* The following are so basic, all the *.c files get them automatically. */
10708 #include <minix/config.h> /* MUST be first */
10709 #include <ansi.h> /* MUST be second */
10710 #include <minix/type.h>
10711 #include <minix/com.h>
10712 #include <minix/dmap.h>
10713 #include <minix/callnr.h>
10714 #include <sys/types.h>
_________________________ Page 770 File: drivers/drivers.h _________________________
10715 #include <minix/const.h>
10716 #include <minix/devio.h>
10717 #include <minix/syslib.h>
10718 #include <minix/sysutil.h>
10719 #include <minix/bitmap.h>
10720
10721 #include <ibm/interrupt.h> /* IRQ vectors and miscellaneous ports */
10722 #include <ibm/bios.h> /* BIOS index numbers */
10723 #include <ibm/ports.h> /* Well-known ports */
10724
10725 #include <string.h>
10726 #include <signal.h>
10727 #include <stdlib.h>
10728 #include <limits.h>
10729 #include <stddef.h>
10730 #include <errno.h>
10731 #include <unistd.h>
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 <errno.h> */
10807
10808 /* The following are so basic, all the *.c files get them automatically. */
10809 #include <minix/config.h> /* MUST be first */
10810 #include <ansi.h> /* MUST be second */
10811 #include <minix/type.h>
10812 #include <minix/ipc.h>
10813 #include <minix/com.h>
10814 #include <minix/callnr.h>
10815 #include <sys/types.h>
10816 #include <minix/const.h>
10817 #include <minix/syslib.h>
10818 #include <minix/sysutil.h>
10819
10820 #include <string.h>
10821 #include <limits.h>
10822 #include <stddef.h>
10823 #include <errno.h>
10824
10825 #include <minix/partition.h>
10826 #include <minix/u64.h>
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) );
_________________________ Page 771 File: 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 */
_________________________ Page 772 File: drivers/libdriver/driver.h ___________________
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
drivers/libdriver/drvlib.h
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10900 /* IBM device driver definitions Author: Kees J. Bot
10901 * 7 Dec 1995
10902 */
10903
10904 #include <ibm/partition.h>
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 |
_________________________ Page 773 File: 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 <sys/ioc_disk.h>
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. */
_________________________ Page 774 File: 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 */
_________________________ Page 775 File: 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. */
_________________________ Page 776 File: 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 }
_________________________ Page 777 File: 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;
_________________________ Page 778 File: 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 <unistd.h>
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
_________________________ Page 779 File: 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;
_________________________ Page 780 File: 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? */
_________________________ Page 781 File: 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 }
_________________________ Page 782 File: drivers/libdriver/drvlib.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 <sys/ioc_memory.h>
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 */
_________________________ Page 783 File: 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;
_________________________ Page 784 File: 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;
_________________________ Page 785 File: 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 *) & ...
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. */
_________________________ Page 786 File: 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 *)
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; i<ZERO_BUF_SIZE; i++) {
11846 dev_zero[i] = '\0';
11847 }
11848
11849 /* Set up memory ranges for /dev/mem. */
11850 if (OK != (s=sys_getmachine(&machine))) {
11851 panic("MEM","Couldn't get machine information.",s);
11852 }
11853 if (! machine.protected) {
11854 m_geom[MEM_DEV].dv_size = cvul64(0x100000); /* 1M for 8086 systems */
11855 } else {
11856 m_geom[MEM_DEV].dv_size = cvul64(0xFFFFFFFF); /* 4G-1 for 386 systems */
11857 }
11858 }
11860 /*===========================================================================*
11861 * m_ioctl *
11862 *===========================================================================*/
11863 PRIVATE int m_ioctl(dp, m_ptr)
11864 struct driver *dp; /* pointer to driver structure */
11865 message *m_ptr; /* pointer to control message */
11866 {
11867 /* I/O controls for the memory driver. Currently there is one I/O control:
11868 * - MIOCRAMSIZE: to set the size of the RAM disk.
11869 */
11870 struct device *dv;
11871 if ((dv = m_prepare(m_ptr->DEVICE)) == 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 *
_________________________ Page 787 File: 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 */
_________________________ Page 788 File: drivers/at_wini/at_wini.c ____________________
12115
12116 #include "at_wini.h"
12117 #include "../libpci/pci.h"
12118
12119 #include <minix/sysutil.h>
12120 #include <minix/keymap.h>
12121 #include <sys/ioc_disk.h>
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 */
_________________________ Page 789 File: 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 */
_________________________ Page 790 File: 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) );
_________________________ Page 791 File: 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;
_________________________ Page 792 File: 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_AD
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)
_________________________ Page 793 File: 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 ac
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(&devin
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
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);
_________________________ Page 794 File: 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, bas
12497 } else printf("atapci: ignored drives on primary channel, base %x\n
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, bas
12512 } else printf("atapci: ignored drives on secondary channel, base %x
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;
_________________________ Page 795 File: 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 EACC
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 &
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;
_________________________ Page 796 File: 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