[logo]     MINIX 3 - Appendix B [logo]

Index PostScript PDF ASCII text Tar file


_________________________ 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