BOOK.T
上传用户:datang2001
上传日期:2007-02-01
资源大小:53269k
文件大小:987k
源码类别:

操作系统开发

开发平台:

C/C++

  1. 04202  */
  2. 04203 #define _POSIX_SOURCE      1    /* tell headers to include POSIX stuff */
  3. 04204 #define _MINIX             1    /* tell headers to include MINIX stuff */
  4. 04205 #define _SYSTEM            1    /* tell headers that this is the kernel */
  5. 04206
  6. 04207 /* The following are so basic, all the *.c files get them automatically. */
  7. 04208 #include <minix/config.h>       /* MUST be first */
  8. 04209 #include <ansi.h>               /* MUST be second */
  9. 04210 #include <sys/types.h>
  10. 04211 #include <minix/const.h>
  11. 04212 #include <minix/type.h>
  12. 04213 #include <minix/syslib.h>
  13. 04214
  14. 04215 #include <string.h>
  15. 04216 #include <limits.h>
  16. 04217 #include <errno.h>
  17. 04218
  18. 04219 #include "const.h"
  19. 04220 #include "type.h"
  20. 04221 #include "proto.h"
  21. 04222 #include "glo.h"
  22. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  23. src/kernel/const.h    
  24. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  25. 04300 /* General constants used by the kernel. */
  26. 04301
  27. 04302 #if (CHIP == INTEL)
  28. 04303
  29. 04304 #define K_STACK_BYTES   1024    /* how many bytes for the kernel stack */
  30. 04305
  31. 04306 #define INIT_PSW      0x0200    /* initial psw */
  32. 04307 #define INIT_TASK_PSW 0x1200    /* initial psw for tasks (with IOPL 1) */
  33. 04308 #define TRACEBIT       0x100    /* OR this with psw in proc[] for tracing */
  34. 04309 #define SETPSW(rp, new) /* permits only certain bits to be set */ 
  35. 04310         ((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xCD5 | (new) & 0xCD5)
  36. 04311
  37. 04312 /* Initial sp for mm, fs and init.
  38. 04313  *      2 bytes for short jump
  39. 04314  *      2 bytes unused
  40. .Op 49 src/kernel/const.h
  41. 04315  *      3 words for init_org[] used by fs only
  42. 04316  *      3 words for real mode debugger trap (actually needs 1 more)
  43. 04317  *      3 words for save and restart temporaries
  44. 04318  *      3 words for interrupt
  45. 04319  * Leave no margin, to flush bugs early.
  46. 04320  */
  47. 04321 #define INIT_SP (2 + 2 + 3 * 2 + 3 * 2 + 3 * 2 + 3 * 2)
  48. 04322
  49. 04323 #define HCLICK_SHIFT       4    /* log2 of HCLICK_SIZE */
  50. 04324 #define HCLICK_SIZE       16    /* hardware segment conversion magic */
  51. 04325 #if CLICK_SIZE >= HCLICK_SIZE
  52. 04326 #define click_to_hclick(n) ((n) << (CLICK_SHIFT - HCLICK_SHIFT))
  53. 04327 #else
  54. 04328 #define click_to_hclick(n) ((n) >> (HCLICK_SHIFT - CLICK_SHIFT))
  55. 04329 #endif
  56. 04330 #define hclick_to_physb(n) ((phys_bytes) (n) << HCLICK_SHIFT)
  57. 04331 #define physb_to_hclick(n) ((n) >> HCLICK_SHIFT)
  58. 04332
  59. 04333 /* Interrupt vectors defined/reserved by processor. */
  60. 04334 #define DIVIDE_VECTOR      0    /* divide error */
  61. 04335 #define DEBUG_VECTOR       1    /* single step (trace) */
  62. 04336 #define NMI_VECTOR         2    /* non-maskable interrupt */
  63. 04337 #define BREAKPOINT_VECTOR  3    /* software breakpoint */
  64. 04338 #define OVERFLOW_VECTOR    4    /* from INTO */
  65. 04339
  66. 04340 /* Fixed system call vector. */
  67. 04341 #define SYS_VECTOR        32    /* system calls are made with int SYSVEC */
  68. 04342 #define SYS386_VECTOR     33    /* except 386 system calls use this */
  69. 04343 #define LEVEL0_VECTOR     34    /* for execution of a function at level 0 */
  70. 04344
  71. 04345 /* Suitable irq bases for hardware interrupts.  Reprogram the 8259(s) from
  72. 04346  * the PC BIOS defaults since the BIOS doesn't respect all the processor's
  73. 04347  * reserved vectors (0 to 31).
  74. 04348  */
  75. 04349 #define BIOS_IRQ0_VEC   0x08    /* base of IRQ0-7 vectors used by BIOS */
  76. 04350 #define BIOS_IRQ8_VEC   0x70    /* base of IRQ8-15 vectors used by BIOS */
  77. 04351 #define IRQ0_VECTOR     0x28    /* more or less arbitrary, but > SYS_VECTOR */
  78. 04352 #define IRQ8_VECTOR     0x30    /* together for simplicity */
  79. 04353
  80. 04354 /* Hardware interrupt numbers. */
  81. 04355 #define NR_IRQ_VECTORS    16
  82. 04356 #define CLOCK_IRQ          0
  83. 04357 #define KEYBOARD_IRQ       1
  84. 04358 #define CASCADE_IRQ        2    /* cascade enable for 2nd AT controller */
  85. 04359 #define ETHER_IRQ          3    /* default ethernet interrupt vector */
  86. 04360 #define SECONDARY_IRQ      3    /* RS232 interrupt vector for port 2 */
  87. 04361 #define RS232_IRQ          4    /* RS232 interrupt vector for port 1 */
  88. 04362 #define XT_WINI_IRQ        5    /* xt winchester */
  89. 04363 #define FLOPPY_IRQ         6    /* floppy disk */
  90. 04364 #define PRINTER_IRQ        7
  91. 04365 #define AT_WINI_IRQ       14    /* at winchester */
  92. 04366
  93. 04367 /* Interrupt number to hardware vector. */
  94. 04368 #define BIOS_VECTOR(irq)        
  95. 04369         (((irq) < 8 ? BIOS_IRQ0_VEC : BIOS_IRQ8_VEC) + ((irq) & 0x07))
  96. 04370 #define VECTOR(irq)     
  97. 04371         (((irq) < 8 ? IRQ0_VECTOR : IRQ8_VECTOR) + ((irq) & 0x07))
  98. 04372
  99. 04373 /* BIOS hard disk parameter vectors. */
  100. 04374 #define WINI_0_PARM_VEC 0x41
  101. .Ep 50 src/kernel/const.h
  102. 04375 #define WINI_1_PARM_VEC 0x46
  103. 04376
  104. 04377 /* 8259A interrupt controller ports. */
  105. 04378 #define INT_CTL         0x20    /* I/O port for interrupt controller */
  106. 04379 #define INT_CTLMASK     0x21    /* setting bits in this port disables ints */
  107. 04380 #define INT2_CTL        0xA0    /* I/O port for second interrupt controller */
  108. 04381 #define INT2_CTLMASK    0xA1    /* setting bits in this port disables ints */
  109. 04382
  110. 04383 /* Magic numbers for interrupt controller. */
  111. 04384 #define ENABLE          0x20    /* code used to re-enable after an interrupt */
  112. 04385
  113. 04386 /* Sizes of memory tables. */
  114. 04387 #define NR_MEMS            3    /* number of chunks of memory */
  115. 04388
  116. 04389 /* Miscellaneous ports. */
  117. 04390 #define PCR             0x65    /* Planar Control Register */
  118. 04391 #define PORT_B          0x61    /* I/O port for 8255 port B (kbd, beeper...) */
  119. 04392 #define TIMER0          0x40    /* I/O port for timer channel 0 */
  120. 04393 #define TIMER2          0x42    /* I/O port for timer channel 2 */
  121. 04394 #define TIMER_MODE      0x43    /* I/O port for timer mode control */
  122. 04395
  123. 04396 #endif /* (CHIP == INTEL) */
  124. 04397
  125. 04398 #if (CHIP == M68000)
  126. 04399
  127. 04400 #define K_STACK_BYTES   1024    /* how many bytes for the kernel stack */
  128. 04401
  129. 04402 /* Sizes of memory tables. */
  130. 04403 #define NR_MEMS            2    /* number of chunks of memory */
  131. 04404
  132. 04405 /* p_reg contains: d0-d7, a0-a6,   in that order. */
  133. 04406 #define NR_REGS           15    /* number of general regs in each proc slot */
  134. 04407  
  135. 04408 #define TRACEBIT      0x8000    /* or this with psw in proc[] for tracing */
  136. 04409 #define SETPSW(rp, new)         /* permits only certain bits to be set */ 
  137. 04410         ((rp)->p_reg.psw = (rp)->p_reg.psw & ~0xFF | (new) & 0xFF)
  138. 04411  
  139. 04412 #define MEM_BYTES  0xffffffff   /* memory size for /dev/mem */
  140. 04413  
  141. 04414 #ifdef __ACK__
  142. 04415 #define FSTRUCOPY
  143. 04416 #endif
  144. 04417
  145. 04418 #endif /* (CHIP == M68000) */
  146. 04419
  147. 04420 /* The following items pertain to the scheduling queues. */
  148. 04421 #define TASK_Q             0    /* ready tasks are scheduled via queue 0 */
  149. 04422 #define SERVER_Q           1    /* ready servers are scheduled via queue 1 */
  150. 04423 #define USER_Q             2    /* ready users are scheduled via queue 2 */
  151. 04424
  152. 04425 #if (MACHINE == ATARI)
  153. 04426 #define SHADOW_Q           3    /* runnable, but shadowed processes */
  154. 04427 #define NQ                 4    /* # of scheduling queues */
  155. 04428 #else
  156. 04429 #define NQ                 3    /* # of scheduling queues */
  157. 04430 #endif
  158. 04431
  159. 04432 /* Env_parse() return values. */
  160. 04433 #define EP_UNSET        0       /* variable not set */
  161. 04434 #define EP_OFF          1       /* var = off */
  162. .Op 51 src/kernel/const.h
  163. 04435 #define EP_ON           2       /* var = on (or field left blank) */
  164. 04436 #define EP_SET          3       /* var = 1:2:3 (nonblank field) */
  165. 04437
  166. 04438 /* To translate an address in kernel space to a physical address.  This is
  167. 04439  * the same as umap(proc_ptr, D, vir, sizeof(*vir)), but a lot less costly.
  168. 04440  */
  169. 04441 #define vir2phys(vir)   (data_base + (vir_bytes) (vir))
  170. 04442
  171. 04443 #define printf        printk    /* the kernel really uses printk, not printf */
  172. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  173. src/kernel/type.h    
  174. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  175. 04500 #ifndef TYPE_H
  176. 04501 #define TYPE_H
  177. 04502
  178. 04503 typedef _PROTOTYPE( void task_t, (void) );
  179. 04504 typedef _PROTOTYPE( int (*rdwt_t), (message *m_ptr) );
  180. 04505 typedef _PROTOTYPE( void (*watchdog_t), (void) );
  181. 04506
  182. 04507 struct tasktab {
  183. 04508   task_t *initial_pc;
  184. 04509   int stksize;
  185. 04510   char name[8];
  186. 04511 };
  187. 04512
  188. 04513 struct memory {
  189. 04514   phys_clicks base;
  190. 04515   phys_clicks size;
  191. 04516 };
  192. 04517
  193. 04518 /* Administration for clock polling. */
  194. 04519 struct milli_state {
  195. 04520   unsigned long accum_count;    /* accumulated clock ticks */
  196. 04521   unsigned prev_count;          /* previous clock value */
  197. 04522 };
  198. 04523
  199. 04524 #if (CHIP == INTEL)
  200. 04525 typedef unsigned port_t;
  201. 04526 typedef unsigned segm_t;
  202. 04527 typedef unsigned reg_t;         /* machine register */
  203. 04528
  204. 04529 /* The stack frame layout is determined by the software, but for efficiency
  205. 04530  * it is laid out so the assembly code to use it is as simple as possible.
  206. 04531  * 80286 protected mode and all real modes use the same frame, built with
  207. 04532  * 16-bit registers.  Real mode lacks an automatic stack switch, so little
  208. 04533  * is lost by using the 286 frame for it.  The 386 frame differs only in
  209. 04534  * having 32-bit registers and more segment registers.  The same names are
  210. 04535  * used for the larger registers to avoid differences in the code.
  211. 04536  */
  212. 04537 struct stackframe_s {           /* proc_ptr points here */
  213. 04538 #if _WORD_SIZE == 4
  214. 04539   u16_t gs;                     /* last item pushed by save */
  215. 04540   u16_t fs;                     /*  ^ */
  216. 04541 #endif
  217. 04542   u16_t es;                     /*  | */
  218. 04543   u16_t ds;                     /*  | */
  219. 04544   reg_t di;                     /* di through cx are not accessed in C */
  220. .Ep 52 src/kernel/type.h
  221. 04545   reg_t si;                     /* order is to match pusha/popa */
  222. 04546   reg_t fp;                     /* bp */
  223. 04547   reg_t st;                     /* hole for another copy of sp */
  224. 04548   reg_t bx;                     /*  | */
  225. 04549   reg_t dx;                     /*  | */
  226. 04550   reg_t cx;                     /*  | */
  227. 04551   reg_t retreg;                 /* ax and above are all pushed by save */
  228. 04552   reg_t retadr;                 /* return address for assembly code save() */
  229. 04553   reg_t pc;                     /*  ^  last item pushed by interrupt */
  230. 04554   reg_t cs;                     /*  | */
  231. 04555   reg_t psw;                    /*  | */
  232. 04556   reg_t sp;                     /*  | */
  233. 04557   reg_t ss;                     /* these are pushed by CPU during interrupt */
  234. 04558 };
  235. 04559
  236. 04560 struct segdesc_s {              /* segment descriptor for protected mode */
  237. 04561   u16_t limit_low;
  238. 04562   u16_t base_low;
  239. 04563   u8_t base_middle;
  240. 04564   u8_t access;                  /* |P|DL|1|X|E|R|A| */
  241. 04565 #if _WORD_SIZE == 4
  242. 04566   u8_t granularity;             /* |G|X|0|A|LIMT| */
  243. 04567   u8_t base_high;
  244. 04568 #else
  245. 04569   u16_t reserved;
  246. 04570 #endif
  247. 04571 };
  248. 04572
  249. 04573 typedef _PROTOTYPE( int (*irq_handler_t), (int irq) );
  250. 04574
  251. 04575 #endif /* (CHIP == INTEL) */
  252. 04576
  253. 04577 #if (CHIP == M68000)
  254. 04578 typedef _PROTOTYPE( void (*dmaint_t), (void) );
  255. 04579
  256. 04580 typedef u32_t reg_t;            /* machine register */
  257. 04581
  258. 04582 /* The name and fields of this struct were chosen for PC compatibility. */
  259. 04583 struct stackframe_s {
  260. 04584   reg_t retreg;                 /* d0 */
  261. 04585   reg_t d1;
  262. 04586   reg_t d2;
  263. 04587   reg_t d3;
  264. 04588   reg_t d4;
  265. 04589   reg_t d5;
  266. 04590   reg_t d6;
  267. 04591   reg_t d7;
  268. 04592   reg_t a0;
  269. 04593   reg_t a1;
  270. 04594   reg_t a2;
  271. 04595   reg_t a3;
  272. 04596   reg_t a4;
  273. 04597   reg_t a5;
  274. 04598   reg_t fp;                     /* also known as a6 */
  275. 04599   reg_t sp;                     /* also known as a7 */
  276. 04600   reg_t pc;
  277. 04601   u16_t psw;
  278. 04602   u16_t dummy;                  /* make size multiple of reg_t for system.c */
  279. 04603 };
  280. 04604
  281. .Op 53 src/kernel/type.h
  282. 04605 struct fsave {
  283. 04606   struct cpu_state {
  284. 04607         u16_t i_format;
  285. 04608         u32_t i_addr;
  286. 04609         u16_t i_state[4];
  287. 04610   } cpu_state;
  288. 04611   struct state_frame {
  289. 04612         u8_t frame_type;
  290. 04613         u8_t frame_size;
  291. 04614         u16_t reserved;
  292. 04615         u8_t frame[212];
  293. 04616   } state_frame;
  294. 04617   struct fpp_model {
  295. 04618         u32_t fpcr;
  296. 04619         u32_t fpsr;
  297. 04620         u32_t fpiar;
  298. 04621         struct fpN {
  299. 04622                 u32_t high;
  300. 04623                 u32_t low;
  301. 04624                 u32_t mid;
  302. 04625         } fpN[8];
  303. 04626   } fpp_model;
  304. 04627 };
  305. 04628 #endif /* (CHIP == M68000) */
  306. 04629
  307. 04630 #endif /* TYPE_H */
  308. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  309. src/kernel/proto.h    
  310. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  311. 04700 /* Function prototypes. */
  312. 04701
  313. 04702 #ifndef PROTO_H
  314. 04703 #define PROTO_H
  315. 04704
  316. 04705 /* Struct declarations. */
  317. 04706 struct proc;
  318. 04707 struct tty;
  319. 04708
  320. 04709 /* at_wini.c, wini.c */
  321. 04710 _PROTOTYPE( void winchester_task, (void)                                );
  322. 04711 _PROTOTYPE( void at_winchester_task, (void)                             );
  323. 04712
  324. 04713 /* clock.c */
  325. 04714 _PROTOTYPE( void clock_task, (void)                                     );
  326. 04715 _PROTOTYPE( void clock_stop, (void)                                     );
  327. 04716 _PROTOTYPE( clock_t get_uptime, (void)                                  );
  328. 04717 _PROTOTYPE( void syn_alrm_task, (void)                                  );
  329. 04718
  330. 04719 /* dmp.c */
  331. 04720 _PROTOTYPE( void map_dmp, (void)                                        );
  332. 04721 _PROTOTYPE( void p_dmp, (void)                                          );
  333. 04722 _PROTOTYPE( void reg_dmp, (struct proc *rp)                             );
  334. 04723
  335. 04724 /* dp8390.c */
  336. .Ep 54 src/kernel/proto.h
  337. 04725 _PROTOTYPE( void dp8390_task, (void)                                    );
  338. 04726 _PROTOTYPE( void dp_dump, (void)                                        );
  339. 04727 _PROTOTYPE( void dp8390_stop, (void)                                    );
  340. 04728
  341. 04729 /* floppy.c, stfloppy.c */
  342. 04730 _PROTOTYPE( void floppy_task, (void)                                    );
  343. 04731 _PROTOTYPE( void floppy_stop, (void)                                    );
  344. 04732
  345. 04733 /* main.c, stmain.c */
  346. 04734 _PROTOTYPE( void main, (void)                                           );
  347. 04735 _PROTOTYPE( void panic, (const char *s, int n)                          );
  348. 04736
  349. 04737 /* memory.c */
  350. 04738 _PROTOTYPE( void mem_task, (void)                                       );
  351. 04739
  352. 04740 /* misc.c */
  353. 04741 _PROTOTYPE( int env_parse, (char *env, char *fmt, int field,
  354. 04742                         long *param, long min, long max)                );
  355. 04743
  356. 04744 /* printer.c, stprint.c */
  357. 04745 _PROTOTYPE( void printer_task, (void)                                   );
  358. 04746
  359. 04747 /* proc.c */
  360. 04748 _PROTOTYPE( void interrupt, (int task)                                  );
  361. 04749 _PROTOTYPE( int lock_mini_send, (struct proc *caller_ptr,
  362. 04750                 int dest, message *m_ptr)                               );
  363. 04751 _PROTOTYPE( void lock_pick_proc, (void)                                 );
  364. 04752 _PROTOTYPE( void lock_ready, (struct proc *rp)                          );
  365. 04753 _PROTOTYPE( void lock_sched, (void)                                     );
  366. 04754 _PROTOTYPE( void lock_unready, (struct proc *rp)                        );
  367. 04755 _PROTOTYPE( int sys_call, (int function, int src_dest, message *m_ptr)  );
  368. 04756 _PROTOTYPE( void unhold, (void)                                         );
  369. 04757
  370. 04758 /* rs232.c */
  371. 04759 _PROTOTYPE( void rs_init, (struct tty *tp)                              );
  372. 04760
  373. 04761 /* system.c */
  374. 04762 _PROTOTYPE( void cause_sig, (int proc_nr, int sig_nr)                   );
  375. 04763 _PROTOTYPE( void inform, (void)                                         );
  376. 04764 _PROTOTYPE( phys_bytes numap, (int proc_nr, vir_bytes vir_addr, 
  377. 04765                 vir_bytes bytes)                                        );
  378. 04766 _PROTOTYPE( void sys_task, (void)                                       );
  379. 04767 _PROTOTYPE( phys_bytes umap, (struct proc *rp, int seg, vir_bytes vir_addr,
  380. 04768                 vir_bytes bytes)                                        );
  381. 04769
  382. 04770 /* tty.c */
  383. 04771 _PROTOTYPE( void handle_events, (struct tty *tp)                        );
  384. 04772 _PROTOTYPE( void sigchar, (struct tty *tp, int sig)                     );
  385. 04773 _PROTOTYPE( void tty_task, (void)                                       );
  386. 04774 _PROTOTYPE( int in_process, (struct tty *tp, char *buf, int count)      );
  387. 04775 _PROTOTYPE( void out_process, (struct tty *tp, char *bstart, char *bpos,
  388. 04776                                 char *bend, int *icount, int *ocount)   );
  389. 04777 _PROTOTYPE( void tty_wakeup, (clock_t now)                              );
  390. 04778 _PROTOTYPE( void tty_reply, (int code, int replyee, int proc_nr,
  391. 04779                                                         int status)     );
  392. 04780 _PROTOTYPE( void tty_devnop, (struct tty *tp)                           );
  393. 04781
  394. 04782 /* library */
  395. 04783 _PROTOTYPE( void *memcpy, (void *_s1, const void *_s2, size_t _n)       );
  396. 04784
  397. .Op 55 src/kernel/proto.h
  398. 04785 #if (CHIP == INTEL)
  399. 04786
  400. 04787 /* clock.c */
  401. 04788 _PROTOTYPE( void milli_start, (struct milli_state *msp)                 );
  402. 04789 _PROTOTYPE( unsigned milli_elapsed, (struct milli_state *msp)           );
  403. 04790 _PROTOTYPE( void milli_delay, (unsigned millisec)                       );
  404. 04791
  405. 04792 /* console.c */
  406. 04793 _PROTOTYPE( void cons_stop, (void)                                      );
  407. 04794 _PROTOTYPE( void putk, (int c)                                          );
  408. 04795 _PROTOTYPE( void scr_init, (struct tty *tp)                             );
  409. 04796 _PROTOTYPE( void toggle_scroll, (void)                                  );
  410. 04797 _PROTOTYPE( int con_loadfont, (phys_bytes user_phys)                    );
  411. 04798 _PROTOTYPE( void select_console, (int cons_line)                        );
  412. 04799
  413. 04800 /* cstart.c */
  414. 04801 _PROTOTYPE( void cstart, (U16_t cs, U16_t ds, U16_t mcs, U16_t mds,
  415. 04802                                 U16_t parmoff, U16_t parmsize)          );
  416. 04803 _PROTOTYPE( char *k_getenv, (char *name)                                );
  417. 04804
  418. 04805 /* exception.c */
  419. 04806 _PROTOTYPE( void exception, (unsigned vec_nr)                           );
  420. 04807
  421. 04808 /* i8259.c */
  422. 04809 _PROTOTYPE( irq_handler_t get_irq_handler, (int irq)                    );
  423. 04810 _PROTOTYPE( void put_irq_handler, (int irq, irq_handler_t handler)      );
  424. 04811 _PROTOTYPE( void intr_init, (int mine)                                  );
  425. 04812
  426. 04813 /* keyboard.c */
  427. 04814 _PROTOTYPE( void kb_init, (struct tty *tp)                              );
  428. 04815 _PROTOTYPE( int kbd_loadmap, (phys_bytes user_phys)                     );
  429. 04816 _PROTOTYPE( void wreboot, (int how)                                     );
  430. 04817
  431. 04818 /* klib*.s */
  432. 04819 _PROTOTYPE( void bios13, (void)                                         );
  433. 04820 _PROTOTYPE( phys_bytes check_mem, (phys_bytes base, phys_bytes size)    );
  434. 04821 _PROTOTYPE( void cp_mess, (int src,phys_clicks src_clicks,vir_bytes src_offset,
  435. 04822                 phys_clicks dst_clicks, vir_bytes dst_offset)           );
  436. 04823 _PROTOTYPE( int in_byte, (port_t port)                                  );
  437. 04824 _PROTOTYPE( int in_word, (port_t port)                                  );
  438. 04825 _PROTOTYPE( void lock, (void)                                           );
  439. 04826 _PROTOTYPE( void unlock, (void)                                         );
  440. 04827 _PROTOTYPE( void enable_irq, (unsigned irq)                             );
  441. 04828 _PROTOTYPE( int disable_irq, (unsigned irq)                             );
  442. 04829 _PROTOTYPE( u16_t mem_rdw, (segm_t segm, vir_bytes offset)              );
  443. 04830 _PROTOTYPE( void out_byte, (port_t port, int value)                     );
  444. 04831 _PROTOTYPE( void out_word, (port_t port, int value)                     );
  445. 04832 _PROTOTYPE( void phys_copy, (phys_bytes source, phys_bytes dest,
  446. 04833                 phys_bytes count)                                       );
  447. 04834 _PROTOTYPE( void port_read, (unsigned port, phys_bytes destination,
  448. 04835                 unsigned bytcount)                                      );
  449. 04836 _PROTOTYPE( void port_read_byte, (unsigned port, phys_bytes destination,
  450. 04837                 unsigned bytcount)                                      );
  451. 04838 _PROTOTYPE( void port_write, (unsigned port, phys_bytes source,
  452. 04839                 unsigned bytcount)                                      );
  453. 04840 _PROTOTYPE( void port_write_byte, (unsigned port, phys_bytes source,
  454. 04841                 unsigned bytcount)                                      );
  455. 04842 _PROTOTYPE( void reset, (void)                                          );
  456. 04843 _PROTOTYPE( void vid_vid_copy, (unsigned src, unsigned dst, unsigned count));
  457. 04844 _PROTOTYPE( void mem_vid_copy, (u16_t *src, unsigned dst, unsigned count));
  458. .Ep 56 src/kernel/proto.h
  459. 04845 _PROTOTYPE( void level0, (void (*func)(void))                           );
  460. 04846 _PROTOTYPE( void monitor, (void)                                        );
  461. 04847
  462. 04848 /* misc.c */
  463. 04849 _PROTOTYPE( void mem_init, (void)                                       );
  464. 04850
  465. 04851 /* mpx*.s */
  466. 04852 _PROTOTYPE( void idle_task, (void)                                      );
  467. 04853 _PROTOTYPE( void restart, (void)                                        );
  468. 04854
  469. 04855 /* The following are never called from C (pure asm procs). */
  470. 04856
  471. 04857 /* Exception handlers (real or protected mode), in numerical order. */
  472. 04858 void _PROTOTYPE( int00, (void) ), _PROTOTYPE( divide_error, (void) );
  473. 04859 void _PROTOTYPE( int01, (void) ), _PROTOTYPE( single_step_exception, (void) );
  474. 04860 void _PROTOTYPE( int02, (void) ), _PROTOTYPE( nmi, (void) );
  475. 04861 void _PROTOTYPE( int03, (void) ), _PROTOTYPE( breakpoint_exception, (void) );
  476. 04862 void _PROTOTYPE( int04, (void) ), _PROTOTYPE( overflow, (void) );
  477. 04863 void _PROTOTYPE( int05, (void) ), _PROTOTYPE( bounds_check, (void) );
  478. 04864 void _PROTOTYPE( int06, (void) ), _PROTOTYPE( inval_opcode, (void) );
  479. 04865 void _PROTOTYPE( int07, (void) ), _PROTOTYPE( copr_not_available, (void) );
  480. 04866 void                              _PROTOTYPE( double_fault, (void) );
  481. 04867 void                              _PROTOTYPE( copr_seg_overrun, (void) );
  482. 04868 void                              _PROTOTYPE( inval_tss, (void) );
  483. 04869 void                              _PROTOTYPE( segment_not_present, (void) );
  484. 04870 void                              _PROTOTYPE( stack_exception, (void) );
  485. 04871 void                              _PROTOTYPE( general_protection, (void) );
  486. 04872 void                              _PROTOTYPE( page_fault, (void) );
  487. 04873 void                              _PROTOTYPE( copr_error, (void) );
  488. 04874
  489. 04875 /* Hardware interrupt handlers. */
  490. 04876 _PROTOTYPE( void hwint00, (void) );
  491. 04877 _PROTOTYPE( void hwint01, (void) );
  492. 04878 _PROTOTYPE( void hwint02, (void) );
  493. 04879 _PROTOTYPE( void hwint03, (void) );
  494. 04880 _PROTOTYPE( void hwint04, (void) );
  495. 04881 _PROTOTYPE( void hwint05, (void) );
  496. 04882 _PROTOTYPE( void hwint06, (void) );
  497. 04883 _PROTOTYPE( void hwint07, (void) );
  498. 04884 _PROTOTYPE( void hwint08, (void) );
  499. 04885 _PROTOTYPE( void hwint09, (void) );
  500. 04886 _PROTOTYPE( void hwint10, (void) );
  501. 04887 _PROTOTYPE( void hwint11, (void) );
  502. 04888 _PROTOTYPE( void hwint12, (void) );
  503. 04889 _PROTOTYPE( void hwint13, (void) );
  504. 04890 _PROTOTYPE( void hwint14, (void) );
  505. 04891 _PROTOTYPE( void hwint15, (void) );
  506. 04892
  507. 04893 /* Software interrupt handlers, in numerical order. */
  508. 04894 _PROTOTYPE( void trp, (void) );
  509. 04895 _PROTOTYPE( void s_call, (void) ), _PROTOTYPE( p_s_call, (void) );
  510. 04896 _PROTOTYPE( void level0_call, (void) );
  511. 04897
  512. 04898 /* printer.c */
  513. 04899 _PROTOTYPE( void pr_restart, (void)                                     );
  514. 04900
  515. 04901 /* protect.c */
  516. 04902 _PROTOTYPE( void prot_init, (void)                                      );
  517. 04903 _PROTOTYPE( void init_codeseg, (struct segdesc_s *segdp, phys_bytes base,
  518. 04904                 phys_bytes size, int privilege)                         );
  519. .Op 57 src/kernel/proto.h
  520. 04905 _PROTOTYPE( void init_dataseg, (struct segdesc_s *segdp, phys_bytes base,
  521. 04906                 phys_bytes size, int privilege)                         );
  522. 04907 _PROTOTYPE( phys_bytes seg2phys, (U16_t seg)                            );
  523. 04908 _PROTOTYPE( void enable_iop, (struct proc *pp)                          );
  524. 04909
  525. 04910 /* pty.c */
  526. 04911 _PROTOTYPE( void do_pty, (struct tty *tp, message *m_ptr)               );
  527. 04912 _PROTOTYPE( void pty_init, (struct tty *tp)                             );
  528. 04913
  529. 04914 /* system.c */
  530. 04915 _PROTOTYPE( void alloc_segments, (struct proc *rp)                      );
  531. 04916
  532. 04917 #endif /* (CHIP == INTEL) */
  533. 04918
  534. 04919 #endif /* PROTO_H */
  535. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  536. src/kernel/glo.h    
  537. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  538. 05000 /* Global variables used in the kernel. */
  539. 05001
  540. 05002 /* EXTERN is defined as extern except in table.c. */
  541. 05003 #ifdef _TABLE
  542. 05004 #undef EXTERN
  543. 05005 #define EXTERN
  544. 05006 #endif
  545. 05007
  546. 05008 /* Kernel memory. */
  547. 05009 EXTERN phys_bytes code_base;    /* base of kernel code */
  548. 05010 EXTERN phys_bytes data_base;    /* base of kernel data */
  549. 05011
  550. 05012 /* Low level interrupt communications. */
  551. 05013 EXTERN struct proc *held_head;  /* head of queue of held-up interrupts */
  552. 05014 EXTERN struct proc *held_tail;  /* tail of queue of held-up interrupts */
  553. 05015 EXTERN unsigned char k_reenter; /* kernel reentry count (entry count less 1)*/
  554. 05016
  555. 05017 /* Process table.  Here to stop too many things having to include proc.h. */
  556. 05018 EXTERN struct proc *proc_ptr;   /* pointer to currently running process */
  557. 05019
  558. 05020 /* Signals. */
  559. 05021 EXTERN int sig_procs;           /* number of procs with p_pending != 0 */
  560. 05022
  561. 05023 /* Memory sizes. */
  562. 05024 EXTERN struct memory mem[NR_MEMS];      /* base and size of chunks of memory */
  563. 05025 EXTERN phys_clicks tot_mem_size;        /* total system memory size */
  564. 05026
  565. 05027 /* Miscellaneous. */
  566. 05028 extern u16_t sizes[];           /* table filled in by boot monitor */
  567. 05029 extern struct tasktab tasktab[];/* initialized in table.c, so extern here */
  568. 05030 extern char *t_stack[];         /* initialized in table.c, so extern here */
  569. 05031 EXTERN unsigned lost_ticks;     /* clock ticks counted outside the clock task */
  570. 05032 EXTERN clock_t tty_timeout;     /* time to wake up the TTY task */
  571. 05033 EXTERN int current;             /* currently visible console */
  572. 05034
  573. .Ep 58 src/kernel/glo.h
  574. 05035 #if (CHIP == INTEL)
  575. 05036
  576. 05037 /* Machine type. */
  577. 05038 EXTERN int pc_at;               /* PC-AT compatible hardware interface */
  578. 05039 EXTERN int ps_mca;              /* PS/2 with Micro Channel */
  579. 05040 EXTERN unsigned int processor;  /* 86, 186, 286, 386, ... */
  580. 05041 #if _WORD_SIZE == 2
  581. 05042 EXTERN int protected_mode;      /* nonzero if running in Intel protected mode*/
  582. 05043 #else
  583. 05044 #define protected_mode  1       /* 386 mode implies protected mode */
  584. 05045 #endif
  585. 05046
  586. 05047 /* Video card types. */
  587. 05048 EXTERN int ega;                 /* nonzero if console is EGA or VGA */
  588. 05049 EXTERN int vga;                 /* nonzero if console is VGA */
  589. 05050
  590. 05051 /* Memory sizes. */
  591. 05052 EXTERN unsigned ext_memsize;    /* initialized by assembler startup code */
  592. 05053 EXTERN unsigned low_memsize;
  593. 05054
  594. 05055 /* Miscellaneous. */
  595. 05056 EXTERN irq_handler_t irq_table[NR_IRQ_VECTORS];
  596. 05057 EXTERN int irq_use;             /* bit map of all in-use irq's */
  597. 05058 EXTERN reg_t mon_ss, mon_sp;    /* monitor stack */
  598. 05059 EXTERN int mon_return;          /* true if return to the monitor possible */
  599. 05060 EXTERN phys_bytes reboot_code;  /* program for the boot monitor */
  600. 05061
  601. 05062 /* Variables that are initialized elsewhere are just extern here. */
  602. 05063 extern struct segdesc_s gdt[];  /* global descriptor table for protected mode*/
  603. 05064
  604. 05065 EXTERN _PROTOTYPE( void (*level0_func), (void) );
  605. 05066 #endif /* (CHIP == INTEL) */
  606. 05067
  607. 05068 #if (CHIP == M68000)
  608. 05069 /* Variables that are initialized elsewhere are just extern here. */
  609. 05070 extern int keypad;              /* Flag for keypad mode */
  610. 05071 extern int app_mode;            /* Flag for arrow key application mode */
  611. 05072 extern int STdebKey;            /* nonzero if ctl-alt-Fx detected */
  612. 05073 extern struct tty *cur_cons;    /* virtual cons currently displayed */
  613. 05074 extern unsigned char font8[];   /* 8 pixel wide font table (initialized) */
  614. 05075 extern unsigned char font12[];  /* 12 pixel wide font table (initialized) */
  615. 05076 extern unsigned char font16[];  /* 16 pixel wide font table (initialized) */
  616. 05077 extern unsigned short resolution; /* screen res; ST_RES_LOW..TT_RES_HIGH */
  617. 05078 #endif
  618. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  619. src/kernel/proc.h    
  620. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  621. 05100 #ifndef PROC_H
  622. 05101 #define PROC_H
  623. 05102
  624. 05103 /* Here is the declaration of the process table.  It contains the process'
  625. 05104  * registers, memory map, accounting, and message send/receive information.
  626. 05105  * Many assembly code routines reference fields in it.  The offsets to these
  627. 05106  * fields are defined in the assembler include file sconst.h.  When changing
  628. 05107  * 'proc', be sure to change sconst.h to match.
  629. 05108  */
  630. 05109
  631. .Op 59 src/kernel/proc.h
  632. 05110 struct proc {
  633. 05111   struct stackframe_s p_reg;    /* process' registers saved in stack frame */
  634. 05112
  635. 05113 #if (CHIP == INTEL)
  636. 05114   reg_t p_ldt_sel;              /* selector in gdt giving ldt base and limit*/
  637. 05115   struct segdesc_s p_ldt[2];    /* local descriptors for code and data */
  638. 05116                                 /* 2 is LDT_SIZE - avoid include protect.h */
  639. 05117 #endif /* (CHIP == INTEL) */
  640. 05118
  641. 05119   reg_t *p_stguard;             /* stack guard word */
  642. 05120
  643. 05121   int p_nr;                     /* number of this process (for fast access) */
  644. 05122
  645. 05123   int p_int_blocked;            /* nonzero if int msg blocked by busy task */
  646. 05124   int p_int_held;               /* nonzero if int msg held by busy syscall */
  647. 05125   struct proc *p_nextheld;      /* next in chain of held-up int processes */
  648. 05126
  649. 05127   int p_flags;                  /* P_SLOT_FREE, SENDING, RECEIVING, etc. */
  650. 05128   struct mem_map p_map[NR_SEGS];/* memory map */
  651. 05129   pid_t p_pid;                  /* process id passed in from MM */
  652. 05130
  653. 05131   clock_t user_time;            /* user time in ticks */
  654. 05132   clock_t sys_time;             /* sys time in ticks */
  655. 05133   clock_t child_utime;          /* cumulative user time of children */
  656. 05134   clock_t child_stime;          /* cumulative sys time of children */
  657. 05135   clock_t p_alarm;              /* time of next alarm in ticks, or 0 */
  658. 05136
  659. 05137   struct proc *p_callerq;       /* head of list of procs wishing to send */
  660. 05138   struct proc *p_sendlink;      /* link to next proc wishing to send */
  661. 05139   message *p_messbuf;           /* pointer to message buffer */
  662. 05140   int p_getfrom;                /* from whom does process want to receive? */
  663. 05141   int p_sendto;
  664. 05142
  665. 05143   struct proc *p_nextready;     /* pointer to next ready process */
  666. 05144   sigset_t p_pending;           /* bit map for pending signals */
  667. 05145   unsigned p_pendcount;         /* count of pending and unfinished signals */
  668. 05146
  669. 05147   char p_name[16];              /* name of the process */
  670. 05148 };
  671. 05149
  672. 05150 /* Guard word for task stacks. */
  673. 05151 #define STACK_GUARD     ((reg_t) (sizeof(reg_t) == 2 ? 0xBEEF : 0xDEADBEEF))
  674. 05152
  675. 05153 /* Bits for p_flags in proc[].  A process is runnable iff p_flags == 0. */
  676. 05154 #define P_SLOT_FREE      001    /* set when slot is not in use */
  677. 05155 #define NO_MAP           002    /* keeps unmapped forked child from running */
  678. 05156 #define SENDING          004    /* set when process blocked trying to send */
  679. 05157 #define RECEIVING        010    /* set when process blocked trying to recv */
  680. 05158 #define PENDING          020    /* set when inform() of signal pending */
  681. 05159 #define SIG_PENDING      040    /* keeps to-be-signalled proc from running */
  682. 05160 #define P_STOP          0100    /* set when process is being traced */
  683. 05161
  684. 05162 /* Magic process table addresses. */
  685. 05163 #define BEG_PROC_ADDR (&proc[0])
  686. 05164 #define END_PROC_ADDR (&proc[NR_TASKS + NR_PROCS])
  687. 05165 #define END_TASK_ADDR (&proc[NR_TASKS])
  688. 05166 #define BEG_SERV_ADDR (&proc[NR_TASKS])
  689. 05167 #define BEG_USER_ADDR (&proc[NR_TASKS + LOW_USER])
  690. 05168
  691. 05169 #define NIL_PROC          ((struct proc *) 0)
  692. .Ep 60 src/kernel/proc.h
  693. 05170 #define isidlehardware(n) ((n) == IDLE || (n) == HARDWARE)
  694. 05171 #define isokprocn(n)      ((unsigned) ((n) + NR_TASKS) < NR_PROCS + NR_TASKS)
  695. 05172 #define isoksrc_dest(n)   (isokprocn(n) || (n) == ANY)
  696. 05173 #define isoksusern(n)     ((unsigned) (n) < NR_PROCS)
  697. 05174 #define isokusern(n)      ((unsigned) ((n) - LOW_USER) < NR_PROCS - LOW_USER)
  698. 05175 #define isrxhardware(n)   ((n) == ANY || (n) == HARDWARE)
  699. 05176 #define issysentn(n)      ((n) == FS_PROC_NR || (n) == MM_PROC_NR)
  700. 05177 #define istaskp(p)        ((p) < END_TASK_ADDR && (p) != proc_addr(IDLE))
  701. 05178 #define isuserp(p)        ((p) >= BEG_USER_ADDR)
  702. 05179 #define proc_addr(n)      (pproc_addr + NR_TASKS)[(n)]
  703. 05180 #define cproc_addr(n)     (&(proc + NR_TASKS)[(n)])
  704. 05181 #define proc_number(p)    ((p)->p_nr)
  705. 05182 #define proc_vir2phys(p, vir) 
  706. 05183                           (((phys_bytes)(p)->p_map[D].mem_phys << CLICK_SHIFT) 
  707. 05184                                                         + (vir_bytes) (vir))
  708. 05185
  709. 05186 EXTERN struct proc proc[NR_TASKS + NR_PROCS];   /* process table */
  710. 05187 EXTERN struct proc *pproc_addr[NR_TASKS + NR_PROCS];
  711. 05188 /* ptrs to process table slots; fast because now a process entry can be found
  712. 05189    by indexing the pproc_addr array, while accessing an element i requires
  713. 05190    a multiplication with sizeof(struct proc) to determine the address */
  714. 05191 EXTERN struct proc *bill_ptr;   /* ptr to process to bill for clock ticks */
  715. 05192 EXTERN struct proc *rdy_head[NQ];       /* pointers to ready list headers */
  716. 05193 EXTERN struct proc *rdy_tail[NQ];       /* pointers to ready list tails */
  717. 05194
  718. 05195 #endif /* PROC_H */
  719. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  720. src/kernel/protect.h    
  721. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  722. 05200 /* Constants for protected mode. */
  723. 05201
  724. 05202 /* Table sizes. */
  725. 05203 #define GDT_SIZE (FIRST_LDT_INDEX + NR_TASKS + NR_PROCS) /* spec. and LDT's */
  726. 05204 #define IDT_SIZE (IRQ8_VECTOR + 8)      /* only up to the highest vector */
  727. 05205 #define LDT_SIZE         2      /* contains CS and DS only */
  728. 05206
  729. 05207 /* Fixed global descriptors.  1 to 7 are prescribed by the BIOS. */
  730. 05208 #define GDT_INDEX        1      /* GDT descriptor */
  731. 05209 #define IDT_INDEX        2      /* IDT descriptor */
  732. 05210 #define DS_INDEX         3      /* kernel DS */
  733. 05211 #define ES_INDEX         4      /* kernel ES (386: flag 4 Gb at startup) */
  734. 05212 #define SS_INDEX         5      /* kernel SS (386: monitor SS at startup) */
  735. 05213 #define CS_INDEX         6      /* kernel CS */
  736. 05214 #define MON_CS_INDEX     7      /* temp for BIOS (386: monitor CS at startup) */
  737. 05215 #define TSS_INDEX        8      /* kernel TSS */
  738. 05216 #define DS_286_INDEX     9      /* scratch 16-bit source segment */
  739. 05217 #define ES_286_INDEX    10      /* scratch 16-bit destination segment */
  740. 05218 #define VIDEO_INDEX     11      /* video memory segment */
  741. 05219 #define DP_ETH0_INDEX   12      /* Western Digital Etherplus buffer */
  742. 05220 #define DP_ETH1_INDEX   13      /* Western Digital Etherplus buffer */
  743. 05221 #define FIRST_LDT_INDEX 14      /* rest of descriptors are LDT's */
  744. 05222
  745. 05223 #define GDT_SELECTOR      0x08  /* (GDT_INDEX * DESC_SIZE) bad for asld */
  746. 05224 #define IDT_SELECTOR      0x10  /* (IDT_INDEX * DESC_SIZE) */
  747. .Op 61 src/kernel/protect.h
  748. 05225 #define DS_SELECTOR       0x18  /* (DS_INDEX * DESC_SIZE) */
  749. 05226 #define ES_SELECTOR       0x20  /* (ES_INDEX * DESC_SIZE) */
  750. 05227 #define FLAT_DS_SELECTOR  0x21  /* less privileged ES */
  751. 05228 #define SS_SELECTOR       0x28  /* (SS_INDEX * DESC_SIZE) */
  752. 05229 #define CS_SELECTOR       0x30  /* (CS_INDEX * DESC_SIZE) */
  753. 05230 #define MON_CS_SELECTOR   0x38  /* (MON_CS_INDEX * DESC_SIZE) */
  754. 05231 #define TSS_SELECTOR      0x40  /* (TSS_INDEX * DESC_SIZE) */
  755. 05232 #define DS_286_SELECTOR   0x49  /* (DS_286_INDEX * DESC_SIZE + 1) */
  756. 05233 #define ES_286_SELECTOR   0x51  /* (ES_286_INDEX * DESC_SIZE + 1) */
  757. 05234 #define VIDEO_SELECTOR    0x59  /* (VIDEO_INDEX * DESC_SIZE + 1) */
  758. 05235 #define DP_ETH0_SELECTOR  0x61  /* (DP_ETH0_INDEX * DESC_SIZE) */
  759. 05236 #define DP_ETH1_SELECTOR  0x69  /* (DP_ETH1_INDEX * DESC_SIZE) */
  760. 05237
  761. 05238 /* Fixed local descriptors. */
  762. 05239 #define CS_LDT_INDEX     0      /* process CS */
  763. 05240 #define DS_LDT_INDEX     1      /* process DS=ES=FS=GS=SS */
  764. 05241
  765. 05242 /* Privileges. */
  766. 05243 #define INTR_PRIVILEGE   0      /* kernel and interrupt handlers */
  767. 05244 #define TASK_PRIVILEGE   1
  768. 05245 #define USER_PRIVILEGE   3
  769. 05246
  770. 05247 /* 286 hardware constants. */
  771. 05248
  772. 05249 /* Exception vector numbers. */
  773. 05250 #define BOUNDS_VECTOR       5   /* bounds check failed */
  774. 05251 #define INVAL_OP_VECTOR     6   /* invalid opcode */
  775. 05252 #define COPROC_NOT_VECTOR   7   /* coprocessor not available */
  776. 05253 #define DOUBLE_FAULT_VECTOR 8
  777. 05254 #define COPROC_SEG_VECTOR   9   /* coprocessor segment overrun */
  778. 05255 #define INVAL_TSS_VECTOR   10   /* invalid TSS */
  779. 05256 #define SEG_NOT_VECTOR     11   /* segment not present */
  780. 05257 #define STACK_FAULT_VECTOR 12   /* stack exception */
  781. 05258 #define PROTECTION_VECTOR  13   /* general protection */
  782. 05259
  783. 05260 /* Selector bits. */
  784. 05261 #define TI            0x04      /* table indicator */
  785. 05262 #define RPL           0x03      /* requester privilege level */
  786. 05263
  787. 05264 /* Descriptor structure offsets. */
  788. 05265 #define DESC_BASE        2      /* to base_low */
  789. 05266 #define DESC_BASE_MIDDLE 4      /* to base_middle */
  790. 05267 #define DESC_ACCESS      5      /* to access byte */
  791. 05268 #define DESC_SIZE        8      /* sizeof (struct segdesc_s) */
  792. 05269
  793. 05270 /* Segment sizes. */
  794. 05271 #define MAX_286_SEG_SIZE 0x10000L
  795. 05272
  796. 05273 /* Base and limit sizes and shifts. */
  797. 05274 #define BASE_MIDDLE_SHIFT   16  /* shift for base --> base_middle */
  798. 05275
  799. 05276 /* Access-byte and type-byte bits. */
  800. 05277 #define PRESENT       0x80      /* set for descriptor present */
  801. 05278 #define DPL           0x60      /* descriptor privilege level mask */
  802. 05279 #define DPL_SHIFT        5
  803. 05280 #define SEGMENT       0x10      /* set for segment-type descriptors */
  804. 05281
  805. 05282 /* Access-byte bits. */
  806. 05283 #define EXECUTABLE    0x08      /* set for executable segment */
  807. 05284 #define CONFORMING    0x04      /* set for conforming segment if executable */
  808. .Ep 62 src/kernel/protect.h
  809. 05285 #define EXPAND_DOWN   0x04      /* set for expand-down segment if !executable*/
  810. 05286 #define READABLE      0x02      /* set for readable segment if executable */
  811. 05287 #define WRITEABLE     0x02      /* set for writeable segment if !executable */
  812. 05288 #define TSS_BUSY      0x02      /* set if TSS descriptor is busy */
  813. 05289 #define ACCESSED      0x01      /* set if segment accessed */
  814. 05290
  815. 05291 /* Special descriptor types. */
  816. 05292 #define AVL_286_TSS      1      /* available 286 TSS */
  817. 05293 #define LDT              2      /* local descriptor table */
  818. 05294 #define BUSY_286_TSS     3      /* set transparently to the software */
  819. 05295 #define CALL_286_GATE    4      /* not used */
  820. 05296 #define TASK_GATE        5      /* only used by debugger */
  821. 05297 #define INT_286_GATE     6      /* interrupt gate, used for all vectors */
  822. 05298 #define TRAP_286_GATE    7      /* not used */
  823. 05299
  824. 05300 /* Extra 386 hardware constants. */
  825. 05301
  826. 05302 /* Exception vector numbers. */
  827. 05303 #define PAGE_FAULT_VECTOR   14
  828. 05304 #define COPROC_ERR_VECTOR   16  /* coprocessor error */
  829. 05305
  830. 05306 /* Descriptor structure offsets. */
  831. 05307 #define DESC_GRANULARITY     6  /* to granularity byte */
  832. 05308 #define DESC_BASE_HIGH       7  /* to base_high */
  833. 05309
  834. 05310 /* Base and limit sizes and shifts. */
  835. 05311 #define BASE_HIGH_SHIFT     24  /* shift for base --> base_high */
  836. 05312 #define BYTE_GRAN_MAX   0xFFFFFL   /* maximum size for byte granular segment */
  837. 05313 #define GRANULARITY_SHIFT   16  /* shift for limit --> granularity */
  838. 05314 #define OFFSET_HIGH_SHIFT   16  /* shift for (gate) offset --> offset_high */
  839. 05315 #define PAGE_GRAN_SHIFT     12  /* extra shift for page granular limits */
  840. 05316
  841. 05317 /* Type-byte bits. */
  842. 05318 #define DESC_386_BIT      0x08  /* 386 types are obtained by ORing with this */
  843. 05319                                 /* LDT's and TASK_GATE's don't need it */
  844. 05320
  845. 05321 /* Granularity byte. */
  846. 05322 #define GRANULAR          0x80  /* set for 4K granularilty */
  847. 05323 #define DEFAULT           0x40  /* set for 32-bit defaults (executable seg) */
  848. 05324 #define BIG               0x40  /* set for "BIG" (expand-down seg) */
  849. 05325 #define AVL               0x10  /* 0 for available */
  850. 05326 #define LIMIT_HIGH        0x0F  /* mask for high bits of limit */
  851. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  852. src/kernel/sconst.h    
  853. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  854. 05400 ! Miscellaneous constants used in assembler code.
  855. 05401 W               =       _WORD_SIZE      ! Machine word size.
  856. 05402
  857. 05403 ! Offsets in struct proc. They MUST match proc.h.
  858. 05404 P_STACKBASE     =       0
  859. 05405 #if _WORD_SIZE == 2
  860. 05406 ESREG           =       P_STACKBASE
  861. 05407 #else
  862. 05408 GSREG           =       P_STACKBASE
  863. 05409 FSREG           =       GSREG + 2       ! 386 introduces FS and GS segments
  864. .Op 63 src/kernel/sconst.h
  865. 05410 ESREG           =       FSREG + 2
  866. 05411 #endif
  867. 05412 DSREG           =       ESREG + 2
  868. 05413 DIREG           =       DSREG + 2
  869. 05414 SIREG           =       DIREG + W
  870. 05415 BPREG           =       SIREG + W
  871. 05416 STREG           =       BPREG + W       ! hole for another SP
  872. 05417 BXREG           =       STREG + W
  873. 05418 DXREG           =       BXREG + W
  874. 05419 CXREG           =       DXREG + W
  875. 05420 AXREG           =       CXREG + W
  876. 05421 RETADR          =       AXREG + W       ! return address for save() call
  877. 05422 PCREG           =       RETADR + W
  878. 05423 CSREG           =       PCREG + W
  879. 05424 PSWREG          =       CSREG + W
  880. 05425 SPREG           =       PSWREG + W
  881. 05426 SSREG           =       SPREG + W
  882. 05427 P_STACKTOP      =       SSREG + W
  883. 05428 P_LDT_SEL       =       P_STACKTOP
  884. 05429 P_LDT           =       P_LDT_SEL + W
  885. 05430
  886. 05431 #if _WORD_SIZE == 2
  887. 05432 Msize           =       12              ! size of a message in 16-bit words
  888. 05433 #else
  889. 05434 Msize           =       9               ! size of a message in 32-bit words
  890. 05435 #endif
  891. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  892. src/kernel/assert.h    
  893. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  894. 05500 /*
  895. 05501 assert.h
  896. 05502 */
  897. 05503 #ifndef ASSERT_H
  898. 05504 #define ASSERT_H
  899. 05505
  900. 05506 #if DEBUG
  901. 05507
  902. 05508 #define INIT_ASSERT     static char *assert_file= __FILE__;
  903. 05509
  904. 05510 void bad_assertion(char *file, int line, char *what);
  905. 05511 void bad_compare(char *file, int line, int lhs, char *what, int rhs);
  906. 05512
  907. 05513 #define assert(x)       (!(x) ? bad_assertion(assert_file, __LINE__, #x) 
  908. 05514                                                                 : (void) 0)
  909. 05515 #define compare(a,t,b)  (!((a) t (b)) ? bad_compare(assert_file, __LINE__, 
  910. 05516                                 (a), #a " " #t " " #b, (b)) : (void) 0)
  911. 05517 #else /* !DEBUG */
  912. 05518
  913. 05519 #define INIT_ASSERT     /* nothing */
  914. 05520
  915. 05521 #define assert(x)       (void)0
  916. 05522 #define compare(a,t,b)  (void)0
  917. 05523
  918. 05524 #endif /* !DEBUG */
  919. .Ep 64 src/kernel/assert.h
  920. 05525
  921. 05526 #endif /* ASSERT_H */
  922. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  923. src/kernel/table.c    
  924. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  925. 05600 /* The object file of "table.c" contains all the data.  In the *.h files, 
  926. 05601  * declared variables appear with EXTERN in front of them, as in
  927. 05602  *
  928. 05603  *    EXTERN int x;
  929. 05604  *
  930. 05605  * Normally EXTERN is defined as extern, so when they are included in another
  931. 05606  * file, no storage is allocated.  If the EXTERN were not present, but just
  932. 05607  * say,
  933. 05608  *
  934. 05609  *    int x;
  935. 05610  *
  936. 05611  * then including this file in several source files would cause 'x' to be
  937. 05612  * declared several times.  While some linkers accept this, others do not,
  938. 05613  * so they are declared extern when included normally.  However, it must
  939. 05614  * be declared for real somewhere.  That is done here, by redefining
  940. 05615  * EXTERN as the null string, so the inclusion of all the *.h files in
  941. 05616  * table.c actually generates storage for them.  All the initialized
  942. 05617  * variables are also declared here, since
  943. 05618  *
  944. 05619  * extern int x = 4;
  945. 05620  *
  946. 05621  * is not allowed.  If such variables are shared, they must also be declared
  947. 05622  * in one of the *.h files without the initialization.
  948. 05623  */
  949. 05624
  950. 05625 #define _TABLE
  951. 05626
  952. 05627 #include "kernel.h"
  953. 05628 #include <termios.h>
  954. 05629 #include <minix/com.h>
  955. 05630 #include "proc.h"
  956. 05631 #include "tty.h"
  957. 05632
  958. 05633 /* The startup routine of each task is given below, from -NR_TASKS upwards.
  959. 05634  * The order of the names here MUST agree with the numerical values assigned to
  960. 05635  * the tasks in <minix/com.h>.
  961. 05636  */
  962. 05637 #define SMALL_STACK     (128 * sizeof(char *))
  963. 05638
  964. 05639 #define TTY_STACK       (3 * SMALL_STACK)
  965. 05640 #define SYN_ALRM_STACK  SMALL_STACK
  966. 05641
  967. 05642 #define DP8390_STACK    (SMALL_STACK * ENABLE_NETWORKING)
  968. 05643
  969. 05644 #if (CHIP == INTEL)
  970. 05645 #define IDLE_STACK      ((3+3+4) * sizeof(char *))  /* 3 intr, 3 temps, 4 db */
  971. 05646 #else
  972. 05647 #define IDLE_STACK      SMALL_STACK
  973. 05648 #endif
  974. 05649
  975. .Op 65 src/kernel/table.c
  976. 05650 #define PRINTER_STACK   SMALL_STACK
  977. 05651
  978. 05652 #if (CHIP == INTEL)
  979. 05653 #define WINCH_STACK     (2 * SMALL_STACK * ENABLE_WINI)
  980. 05654 #else
  981. 05655 #define WINCH_STACK     (3 * SMALL_STACK * ENABLE_WINI)
  982. 05656 #endif
  983. 05657
  984. 05658 #if (MACHINE == ATARI)
  985. 05659 #define SCSI_STACK      (3 * SMALL_STACK)
  986. 05660 #endif
  987. 05661
  988. 05662 #if (MACHINE == IBM_PC)
  989. 05663 #define SCSI_STACK      (2 * SMALL_STACK * ENABLE_SCSI)
  990. 05664 #endif
  991. 05665
  992. 05666 #define CDROM_STACK     (4 * SMALL_STACK * ENABLE_CDROM)
  993. 05667 #define AUDIO_STACK     (4 * SMALL_STACK * ENABLE_AUDIO)
  994. 05668 #define MIXER_STACK     (4 * SMALL_STACK * ENABLE_AUDIO)
  995. 05669
  996. 05670 #define FLOP_STACK      (3 * SMALL_STACK)
  997. 05671 #define MEM_STACK       SMALL_STACK
  998. 05672 #define CLOCK_STACK     SMALL_STACK
  999. 05673 #define SYS_STACK       SMALL_STACK
  1000. 05674 #define HARDWARE_STACK  0               /* dummy task, uses kernel stack */
  1001. 05675
  1002. 05676
  1003. 05677 #define TOT_STACK_SPACE         (TTY_STACK + DP8390_STACK + SCSI_STACK + 
  1004. 05678         SYN_ALRM_STACK + IDLE_STACK + HARDWARE_STACK + PRINTER_STACK + 
  1005. 05679         WINCH_STACK + FLOP_STACK + MEM_STACK + CLOCK_STACK + SYS_STACK + 
  1006. 05680         CDROM_STACK + AUDIO_STACK + MIXER_STACK)
  1007. 05681
  1008. 05682
  1009. 05683 /* SCSI, CDROM and AUDIO may in the future have different choices like
  1010. 05684  * WINCHESTER, but for now the choice is fixed.
  1011. 05685  */
  1012. 05686 #define scsi_task       aha_scsi_task
  1013. 05687 #define cdrom_task      mcd_task
  1014. 05688 #define audio_task      dsp_task
  1015. 05689
  1016. 05690
  1017. 05691 /*
  1018. 05692  * Some notes about the following table:
  1019. 05693  *  1) The tty_task should always be first so that other tasks can use printf
  1020. 05694  *     if their initialisation has problems.
  1021. 05695  *  2) If you add a new kernel task, add it before the printer task.
  1022. 05696  *  3) The task name is used for the process name (p_name).
  1023. 05697  */
  1024. 05698
  1025. 05699 PUBLIC struct tasktab tasktab[] = {
  1026. 05700         { tty_task,             TTY_STACK,      "TTY"           },
  1027. 05701 #if ENABLE_NETWORKING
  1028. 05702         { dp8390_task,          DP8390_STACK,   "DP8390"        },
  1029. 05703 #endif
  1030. 05704 #if ENABLE_CDROM
  1031. 05705         { cdrom_task,           CDROM_STACK,    "CDROM"         },
  1032. 05706 #endif
  1033. 05707 #if ENABLE_AUDIO
  1034. 05708         { audio_task,           AUDIO_STACK,    "AUDIO"         },
  1035. 05709         { mixer_task,           MIXER_STACK,    "MIXER"         },
  1036. .Ep 66 src/kernel/table.c
  1037. 05710 #endif
  1038. 05711 #if ENABLE_SCSI
  1039. 05712         { scsi_task,            SCSI_STACK,     "SCSI"          },
  1040. 05713 #endif
  1041. 05714 #if ENABLE_WINI
  1042. 05715         { winchester_task,      WINCH_STACK,    "WINCH"         },
  1043. 05716 #endif
  1044. 05717         { syn_alrm_task,        SYN_ALRM_STACK, "SYN_AL"        },
  1045. 05718         { idle_task,            IDLE_STACK,     "IDLE"          },
  1046. 05719         { printer_task,         PRINTER_STACK,  "PRINTER"       },
  1047. 05720         { floppy_task,          FLOP_STACK,     "FLOPPY"        },
  1048. 05721         { mem_task,             MEM_STACK,      "MEMORY"        },
  1049. 05722         { clock_task,           CLOCK_STACK,    "CLOCK"         },
  1050. 05723         { sys_task,             SYS_STACK,      "SYS"           },
  1051. 05724         { 0,                    HARDWARE_STACK, "HARDWAR"       },
  1052. 05725         { 0,                    0,              "MM"            },
  1053. 05726         { 0,                    0,              "FS"            },
  1054. 05727 #if ENABLE_NETWORKING
  1055. 05728         { 0,                    0,              "INET"          },
  1056. 05729 #endif
  1057. 05730         { 0,                    0,              "INIT"          },
  1058. 05731 };
  1059. 05732
  1060. 05733 /* Stack space for all the task stacks.  (Declared as (char *) to align it.) */
  1061. 05734 PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
  1062. 05735
  1063. 05736 /*
  1064. 05737  * The number of kernel tasks must be the same as NR_TASKS.
  1065. 05738  * If NR_TASKS is not correct then you will get the compile error:
  1066. 05739  *   "array size is negative"
  1067. 05740  */
  1068. 05741
  1069. 05742 #define NKT (sizeof tasktab / sizeof (struct tasktab) - (INIT_PROC_NR + 1))
  1070. 05743
  1071. 05744 extern int dummy_tasktab_check[NR_TASKS == NKT ? 1 : -1];
  1072. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1073. src/kernel/mpx.s    
  1074. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1075. 05800 #
  1076. 05801 ! Chooses between the 8086 and 386 versions of the Minix startup code.
  1077. 05802
  1078. 05803 #include <minix/config.h>
  1079. 05804 #if _WORD_SIZE == 2
  1080. 05805 #include "mpx88.s"
  1081. 05806 #else
  1082. 05807 #include "mpx386.s"
  1083. 05808 #endif
  1084. .Op 67 src/kernel/mpx386.s
  1085. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1086. src/kernel/mpx386.s    
  1087. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1088. 05900 #
  1089. 05901 ! This file contains the assembler startup code for Minix and the 32-bit
  1090. 05902 ! interrupt handlers.  It cooperates with start.c to set up a good
  1091. 05903 ! environment for main().
  1092. 05904
  1093. 05905 ! This file is part of the lowest layer of the MINIX kernel.  The other part
  1094. 05906 ! is "proc.c".  The lowest layer does process switching and message handling.
  1095. 05907
  1096. 05908 ! Every transition to the kernel goes through this file.  Transitions are
  1097. 05909 ! caused by sending/receiving messages and by most interrupts.  (RS232
  1098. 05910 ! interrupts may be handled in the file "rs2.s" and then they rarely enter
  1099. 05911 ! the kernel.)
  1100. 05912
  1101. 05913 ! Transitions to the kernel may be nested.  The initial entry may be with a
  1102. 05914 ! system call, exception or hardware interrupt; reentries may only be made
  1103. 05915 ! by hardware interrupts.  The count of reentries is kept in "k_reenter".
  1104. 05916 ! It is important for deciding whether to switch to the kernel stack and
  1105. 05917 ! for protecting the message passing code in "proc.c".
  1106. 05918
  1107. 05919 ! For the message passing trap, most of the machine state is saved in the
  1108. 05920 ! proc table.  (Some of the registers need not be saved.)  Then the stack is
  1109. 05921 ! switched to "k_stack", and interrupts are reenabled.  Finally, the system
  1110. 05922 ! call handler (in C) is called.  When it returns, interrupts are disabled
  1111. 05923 ! again and the code falls into the restart routine, to finish off held-up
  1112. 05924 ! interrupts and run the process or task whose pointer is in "proc_ptr".
  1113. 05925
  1114. 05926 ! Hardware interrupt handlers do the same, except  (1) The entire state must
  1115. 05927 ! be saved.  (2) There are too many handlers to do this inline, so the save
  1116. 05928 ! routine is called.  A few cycles are saved by pushing the address of the
  1117. 05929 ! appropiate restart routine for a return later.  (3) A stack switch is
  1118. 05930 ! avoided when the stack is already switched.  (4) The (master) 8259 interrupt
  1119. 05931 ! controller is reenabled centrally in save().  (5) Each interrupt handler
  1120. 05932 ! masks its interrupt line using the 8259 before enabling (other unmasked)
  1121. 05933 ! interrupts, and unmasks it after servicing the interrupt.  This limits the
  1122. 05934 ! nest level to the number of lines and protects the handler from itself.
  1123. 05935
  1124. 05936 ! For communication with the boot monitor at startup time some constant
  1125. 05937 ! data are compiled into the beginning of the text segment. This facilitates 
  1126. 05938 ! reading the data at the start of the boot process, since only the first
  1127. 05939 ! sector of the file needs to be read.
  1128. 05940
  1129. 05941 ! Some data storage is also allocated at the end of this file. This data 
  1130. 05942 ! will be at the start of the data segment of the kernel and will be read
  1131. 05943 ! and modified by the boot monitor before the kernel starts.
  1132. 05944
  1133. 05945 ! sections
  1134. 05946
  1135. 05947 .sect .text
  1136. 05948 begtext:
  1137. 05949 .sect .rom
  1138. 05950 begrom:
  1139. 05951 .sect .data
  1140. 05952 begdata:
  1141. 05953 .sect .bss
  1142. 05954 begbss:
  1143. .Ep 68 src/kernel/mpx386.s
  1144. 05955
  1145. 05956 #include <minix/config.h>
  1146. 05957 #include <minix/const.h>
  1147. 05958 #include <minix/com.h>
  1148. 05959 #include "const.h"
  1149. 05960 #include "protect.h"
  1150. 05961 #include "sconst.h"
  1151. 05962
  1152. 05963 /* Selected 386 tss offsets. */
  1153. 05964 #define TSS3_S_SP0      4
  1154. 05965
  1155. 05966 ! Exported functions
  1156. 05967 ! Note: in assembly language the .define statement applied to a function name 
  1157. 05968 ! is loosely equivalent to a prototype in C code -- it makes it possible to
  1158. 05969 ! link to an entity declared in the assembly code but does not create
  1159. 05970 ! the entity.
  1160. 05971
  1161. 05972 .define _idle_task
  1162. 05973 .define _restart
  1163. 05974 .define save
  1164. 05975
  1165. 05976 .define _divide_error
  1166. 05977 .define _single_step_exception
  1167. 05978 .define _nmi
  1168. 05979 .define _breakpoint_exception
  1169. 05980 .define _overflow
  1170. 05981 .define _bounds_check
  1171. 05982 .define _inval_opcode
  1172. 05983 .define _copr_not_available
  1173. 05984 .define _double_fault
  1174. 05985 .define _copr_seg_overrun
  1175. 05986 .define _inval_tss
  1176. 05987 .define _segment_not_present
  1177. 05988 .define _stack_exception
  1178. 05989 .define _general_protection
  1179. 05990 .define _page_fault
  1180. 05991 .define _copr_error
  1181. 05992
  1182. 05993 .define _hwint00        ! handlers for hardware interrupts
  1183. 05994 .define _hwint01
  1184. 05995 .define _hwint02
  1185. 05996 .define _hwint03
  1186. 05997 .define _hwint04
  1187. 05998 .define _hwint05
  1188. 05999 .define _hwint06
  1189. 06000 .define _hwint07
  1190. 06001 .define _hwint08
  1191. 06002 .define _hwint09
  1192. 06003 .define _hwint10
  1193. 06004 .define _hwint11
  1194. 06005 .define _hwint12
  1195. 06006 .define _hwint13
  1196. 06007 .define _hwint14
  1197. 06008 .define _hwint15
  1198. 06009
  1199. 06010 .define _s_call
  1200. 06011 .define _p_s_call
  1201. 06012 .define _level0_call
  1202. 06013
  1203. 06014 ! Imported functions.
  1204. .Op 69 src/kernel/mpx386.s
  1205. 06015
  1206. 06016 .extern _cstart
  1207. 06017 .extern _main
  1208. 06018 .extern _exception
  1209. 06019 .extern _interrupt
  1210. 06020 .extern _sys_call
  1211. 06021 .extern _unhold
  1212. 06022
  1213. 06023 ! Exported variables.
  1214. 06024 ! Note: when used with a variable the .define does not reserve storage,
  1215. 06025 ! it makes the name externally visible so it may be linked to. 
  1216. 06026
  1217. 06027 .define begbss
  1218. 06028 .define begdata
  1219. 06029 .define _sizes
  1220. 06030
  1221. 06031 ! Imported variables.
  1222. 06032
  1223. 06033 .extern _gdt
  1224. 06034 .extern _code_base
  1225. 06035 .extern _data_base
  1226. 06036 .extern _held_head
  1227. 06037 .extern _k_reenter
  1228. 06038 .extern _pc_at
  1229. 06039 .extern _proc_ptr
  1230. 06040 .extern _ps_mca
  1231. 06041 .extern _tss
  1232. 06042 .extern _level0_func
  1233. 06043 .extern _mon_sp
  1234. 06044 .extern _mon_return
  1235. 06045 .extern _reboot_code
  1236. 06046
  1237. 06047 .sect .text
  1238. 06048 !*===========================================================================*
  1239. 06049 !*                              MINIX                                        *
  1240. 06050 !*===========================================================================*
  1241. 06051 MINIX:                          ! this is the entry point for the MINIX kernel
  1242. 06052         jmp     over_flags      ! skip over the next few bytes
  1243. 06053         .data2  CLICK_SHIFT     ! for the monitor: memory granularity
  1244. 06054 flags:
  1245. 06055         .data2  0x002D          ! boot monitor flags:
  1246. 06056                                 !       call in 386 mode, make stack,
  1247. 06057                                 !       load high, will return
  1248. 06058         nop                     ! extra byte to sync up disassembler
  1249. 06059 over_flags:
  1250. 06060
  1251. 06061 ! Set up a C stack frame on the monitor stack.  (The monitor sets cs and ds
  1252. 06062 ! right.  The ss descriptor still references the monitor data segment.)
  1253. 06063         movzx   esp, sp         ! monitor stack is a 16 bit stack
  1254. 06064         push    ebp
  1255. 06065         mov     ebp, esp
  1256. 06066         push    esi
  1257. 06067         push    edi
  1258. 06068         cmp     4(ebp), 0       ! nonzero if return possible
  1259. 06069         jz      noret
  1260. 06070         inc     (_mon_return)
  1261. 06071 noret:  mov     (_mon_sp), esp  ! save stack pointer for later return
  1262. 06072
  1263. 06073 ! Copy the monitor global descriptor table to the address space of kernel and
  1264. 06074 ! switch over to it.  Prot_init() can then update it with immediate effect.
  1265. .Ep 70 src/kernel/mpx386.s
  1266. 06075
  1267. 06076         sgdt    (_gdt+GDT_SELECTOR)             ! get the monitor gdtr
  1268. 06077         mov     esi, (_gdt+GDT_SELECTOR+2)      ! absolute address of GDT
  1269. 06078         mov     ebx, _gdt                       ! address of kernel GDT
  1270. 06079         mov     ecx, 8*8                        ! copying eight descriptors
  1271. 06080 copygdt:
  1272. 06081  eseg   movb    al, (esi)
  1273. 06082         movb    (ebx), al
  1274. 06083         inc     esi
  1275. 06084         inc     ebx
  1276. 06085         loop    copygdt
  1277. 06086         mov     eax, (_gdt+DS_SELECTOR+2)       ! base of kernel data
  1278. 06087         and     eax, 0x00FFFFFF                 ! only 24 bits
  1279. 06088         add     eax, _gdt                       ! eax = vir2phys(gdt)
  1280. 06089         mov     (_gdt+GDT_SELECTOR+2), eax      ! set base of GDT
  1281. 06090         lgdt    (_gdt+GDT_SELECTOR)             ! switch over to kernel GDT
  1282. 06091
  1283. 06092 ! Locate boot parameters, set up kernel segment registers and stack.
  1284. 06093         mov     ebx, 8(ebp)     ! boot parameters offset
  1285. 06094         mov     edx, 12(ebp)    ! boot parameters length
  1286. 06095         mov     ax, ds          ! kernel data
  1287. 06096         mov     es, ax
  1288. 06097         mov     fs, ax
  1289. 06098         mov     gs, ax
  1290. 06099         mov     ss, ax
  1291. 06100         mov     esp, k_stktop   ! set sp to point to the top of kernel stack
  1292. 06101
  1293. 06102 ! Call C startup code to set up a proper environment to run main().
  1294. 06103         push    edx
  1295. 06104         push    ebx
  1296. 06105         push    SS_SELECTOR
  1297. 06106         push    MON_CS_SELECTOR
  1298. 06107         push    DS_SELECTOR
  1299. 06108         push    CS_SELECTOR
  1300. 06109         call    _cstart         ! cstart(cs, ds, mcs, mds, parmoff, parmlen)
  1301. 06110         add     esp, 6*4
  1302. 06111
  1303. 06112 ! Reload gdtr, idtr and the segment registers to global descriptor table set
  1304. 06113 ! up by prot_init().
  1305. 06114
  1306. 06115         lgdt    (_gdt+GDT_SELECTOR)
  1307. 06116         lidt    (_gdt+IDT_SELECTOR)
  1308. 06117
  1309. 06118         jmpf    CS_SELECTOR:csinit
  1310. 06119 csinit:
  1311. 06120     o16 mov     ax, DS_SELECTOR
  1312. 06121         mov     ds, ax
  1313. 06122         mov     es, ax
  1314. 06123         mov     fs, ax
  1315. 06124         mov     gs, ax
  1316. 06125         mov     ss, ax
  1317. 06126     o16 mov     ax, TSS_SELECTOR        ! no other TSS is used
  1318. 06127         ltr     ax
  1319. 06128         push    0                       ! set flags to known good state
  1320. 06129         popf                            ! esp, clear nested task and int enable
  1321. 06130
  1322. 06131         jmp     _main                   ! main()
  1323. 06132
  1324. 06133
  1325. 06134 !*===========================================================================*
  1326. .Op 71 src/kernel/mpx386.s
  1327. 06135 !*                              interrupt handlers                           *
  1328. 06136 !*              interrupt handlers for 386 32-bit protected mode             *
  1329. 06137 !*===========================================================================*
  1330. 06138
  1331. 06139 !*===========================================================================*
  1332. 06140 !*                              hwint00 - 07                                 *
  1333. 06141 !*===========================================================================*
  1334. 06142 ! Note this is a macro, it looks like a subroutine.
  1335. 06143 #define hwint_master(irq)       
  1336. 06144         call    save                    /* save interrupted process state */;
  1337. 06145         inb     INT_CTLMASK                                                 ;
  1338. 06146         orb     al, [1<<irq]                                                ;
  1339. 06147         outb    INT_CTLMASK             /* disable the irq                */;
  1340. 06148         movb    al, ENABLE                                                  ;
  1341. 06149         outb    INT_CTL                 /* reenable master 8259           */;
  1342. 06150         sti                             /* enable interrupts              */;
  1343. 06151         push    irq                     /* irq                            */;
  1344. 06152         call    (_irq_table + 4*irq)    /* eax = (*irq_table[irq])(irq)   */;
  1345. 06153         pop     ecx                                                         ;
  1346. 06154         cli                             /* disable interrupts             */;
  1347. 06155         test    eax, eax                /* need to reenable irq?          */;
  1348. 06156         jz      0f                                                          ;
  1349. 06157         inb     INT_CTLMASK                                                 ;
  1350. 06158         andb    al, ~[1<<irq]                                               ;
  1351. 06159         outb    INT_CTLMASK             /* enable the irq                 */;
  1352. 06160 0:      ret                             /* restart (another) process      */
  1353. 06161
  1354. 06162 ! Each of these entry points is an expansion of the hwint_master macro
  1355. 06163         .align  16
  1356. 06164 _hwint00:               ! Interrupt routine for irq 0 (the clock).
  1357. 06165         hwint_master(0)
  1358. 06166
  1359. 06167         .align  16
  1360. 06168 _hwint01:               ! Interrupt routine for irq 1 (keyboard)
  1361. 06169         hwint_master(1)
  1362. 06170
  1363. 06171         .align  16
  1364. 06172 _hwint02:               ! Interrupt routine for irq 2 (cascade!)
  1365. 06173         hwint_master(2)
  1366. 06174
  1367. 06175         .align  16
  1368. 06176 _hwint03:               ! Interrupt routine for irq 3 (second serial)
  1369. 06177         hwint_master(3)
  1370. 06178
  1371. 06179         .align  16
  1372. 06180 _hwint04:               ! Interrupt routine for irq 4 (first serial)
  1373. 06181         hwint_master(4)
  1374. 06182
  1375. 06183         .align  16
  1376. 06184 _hwint05:               ! Interrupt routine for irq 5 (XT winchester)
  1377. 06185         hwint_master(5)
  1378. 06186
  1379. 06187         .align  16
  1380. 06188 _hwint06:               ! Interrupt routine for irq 6 (floppy)
  1381. 06189         hwint_master(6)
  1382. 06190
  1383. 06191         .align  16
  1384. 06192 _hwint07:               ! Interrupt routine for irq 7 (printer)
  1385. 06193         hwint_master(7)
  1386. 06194
  1387. .Ep 72 src/kernel/mpx386.s
  1388. 06195 !*===========================================================================*
  1389. 06196 !*                              hwint08 - 15                                 *
  1390. 06197 !*===========================================================================*
  1391. 06198 ! Note this is a macro, it looks like a subroutine.
  1392. 06199 #define hwint_slave(irq)        
  1393. 06200         call    save                    /* save interrupted process state */;
  1394. 06201         inb     INT2_CTLMASK                                                ;
  1395. 06202         orb     al, [1<<[irq-8]]                                            ;
  1396. 06203         outb    INT2_CTLMASK            /* disable the irq                */;
  1397. 06204         movb    al, ENABLE                                                  ;
  1398. 06205         outb    INT_CTL                 /* reenable master 8259           */;
  1399. 06206         jmp     .+2                     /* delay                          */;
  1400. 06207         outb    INT2_CTL                /* reenable slave 8259            */;
  1401. 06208         sti                             /* enable interrupts              */;
  1402. 06209         push    irq                     /* irq                            */;
  1403. 06210         call    (_irq_table + 4*irq)    /* eax = (*irq_table[irq])(irq)   */;
  1404. 06211         pop     ecx                                                         ;
  1405. 06212         cli                             /* disable interrupts             */;
  1406. 06213         test    eax, eax                /* need to reenable irq?          */;
  1407. 06214         jz      0f                                                          ;
  1408. 06215         inb     INT2_CTLMASK                                                ;
  1409. 06216         andb    al, ~[1<<[irq-8]]                                           ;
  1410. 06217         outb    INT2_CTLMASK            /* enable the irq                 */;
  1411. 06218 0:      ret                             /* restart (another) process      */
  1412. 06219
  1413. 06220 ! Each of these entry points is an expansion of the hwint_slave macro
  1414. 06221         .align  16
  1415. 06222 _hwint08:               ! Interrupt routine for irq 8 (realtime clock)
  1416. 06223         hwint_slave(8)
  1417. 06224
  1418. 06225         .align  16
  1419. 06226 _hwint09:               ! Interrupt routine for irq 9 (irq 2 redirected)
  1420. 06227         hwint_slave(9)
  1421. 06228
  1422. 06229         .align  16
  1423. 06230 _hwint10:               ! Interrupt routine for irq 10
  1424. 06231         hwint_slave(10)
  1425. 06232
  1426. 06233         .align  16
  1427. 06234 _hwint11:               ! Interrupt routine for irq 11
  1428. 06235         hwint_slave(11)
  1429. 06236
  1430. 06237         .align  16
  1431. 06238 _hwint12:               ! Interrupt routine for irq 12
  1432. 06239         hwint_slave(12)
  1433. 06240
  1434. 06241         .align  16
  1435. 06242 _hwint13:               ! Interrupt routine for irq 13 (FPU exception)
  1436. 06243         hwint_slave(13)
  1437. 06244
  1438. 06245         .align  16
  1439. 06246 _hwint14:               ! Interrupt routine for irq 14 (AT winchester)
  1440. 06247         hwint_slave(14)
  1441. 06248
  1442. 06249         .align  16
  1443. 06250 _hwint15:               ! Interrupt routine for irq 15
  1444. 06251         hwint_slave(15)
  1445. 06252
  1446. 06253 !*===========================================================================*
  1447. 06254 !*                              save                                         *
  1448. .Op 73 src/kernel/mpx386.s
  1449. 06255 !*===========================================================================*
  1450. 06256 ! Save for protected mode.
  1451. 06257 ! This is much simpler than for 8086 mode, because the stack already points
  1452. 06258 ! into the process table, or has already been switched to the kernel stack.
  1453. 06259
  1454. 06260         .align  16
  1455. 06261 save:
  1456. 06262         cld                     ! set direction flag to a known value
  1457. 06263         pushad                  ! save "general" registers
  1458. 06264     o16 push    ds              ! save ds
  1459. 06265     o16 push    es              ! save es
  1460. 06266     o16 push    fs              ! save fs
  1461. 06267     o16 push    gs              ! save gs
  1462. 06268         mov     dx, ss          ! ss is kernel data segment
  1463. 06269         mov     ds, dx          ! load rest of kernel segments
  1464. 06270         mov     es, dx          ! kernel does not use fs, gs
  1465. 06271         mov     eax, esp        ! prepare to return
  1466. 06272         incb    (_k_reenter)    ! from -1 if not reentering
  1467. 06273         jnz     set_restart1    ! stack is already kernel stack
  1468. 06274         mov     esp, k_stktop
  1469. 06275         push    _restart        ! build return address for int handler
  1470. 06276         xor     ebp, ebp        ! for stacktrace
  1471. 06277         jmp     RETADR-P_STACKBASE(eax)
  1472. 06278
  1473. 06279         .align  4
  1474. 06280 set_restart1:
  1475. 06281         push    restart1
  1476. 06282         jmp     RETADR-P_STACKBASE(eax)
  1477. 06283
  1478. 06284 !*===========================================================================*
  1479. 06285 !*                              _s_call                                      *
  1480. 06286 !*===========================================================================*
  1481. 06287         .align  16
  1482. 06288 _s_call:
  1483. 06289 _p_s_call:
  1484. 06290         cld                     ! set direction flag to a known value
  1485. 06291         sub     esp, 6*4        ! skip RETADR, eax, ecx, edx, ebx, est
  1486. 06292         push    ebp             ! stack already points into proc table
  1487. 06293         push    esi
  1488. 06294         push    edi
  1489. 06295     o16 push    ds
  1490. 06296     o16 push    es
  1491. 06297     o16 push    fs
  1492. 06298     o16 push    gs
  1493. 06299         mov     dx, ss
  1494. 06300         mov     ds, dx
  1495. 06301         mov     es, dx
  1496. 06302         incb    (_k_reenter)
  1497. 06303         mov     esi, esp        ! assumes P_STACKBASE == 0
  1498. 06304         mov     esp, k_stktop
  1499. 06305         xor     ebp, ebp        ! for stacktrace
  1500. 06306                                 ! end of inline save
  1501. 06307         sti                     ! allow SWITCHER to be interrupted
  1502. 06308                                 ! now set up parameters for sys_call()
  1503. 06309         push    ebx             ! pointer to user message
  1504. 06310         push    eax             ! src/dest
  1505. 06311         push    ecx             ! SEND/RECEIVE/BOTH
  1506. 06312         call    _sys_call       ! sys_call(function, src_dest, m_ptr)
  1507. 06313                                 ! caller is now explicitly in proc_ptr
  1508. 06314         mov     AXREG(esi), eax ! sys_call MUST PRESERVE si
  1509. .Ep 74 src/kernel/mpx386.s
  1510. 06315         cli                     ! disable interrupts 
  1511. 06316
  1512. 06317 ! Fall into code to restart proc/task running.
  1513. 06318
  1514. 06319 !*===========================================================================*
  1515. 06320 !*                              restart                                      *
  1516. 06321 !*===========================================================================*
  1517. 06322 _restart:
  1518. 06323
  1519. 06324 ! Flush any held-up interrupts.
  1520. 06325 ! This reenables interrupts, so the current interrupt handler may reenter.
  1521. 06326 ! This does not matter, because the current handler is about to exit and no
  1522. 06327 ! other handlers can reenter since flushing is only done when k_reenter == 0.
  1523. 06328
  1524. 06329         cmp     (_held_head), 0 ! do fast test to usually avoid function call
  1525. 06330         jz      over_call_unhold
  1526. 06331         call    _unhold         ! this is rare so overhead acceptable
  1527. 06332 over_call_unhold:
  1528. 06333         mov     esp, (_proc_ptr)        ! will assume P_STACKBASE == 0
  1529. 06334         lldt    P_LDT_SEL(esp)          ! enable segment descriptors for task
  1530. 06335         lea     eax, P_STACKTOP(esp)    ! arrange for next interrupt
  1531. 06336         mov     (_tss+TSS3_S_SP0), eax  ! to save state in process table
  1532. 06337 restart1:
  1533. 06338         decb    (_k_reenter)
  1534. 06339     o16 pop     gs
  1535. 06340     o16 pop     fs
  1536. 06341     o16 pop     es
  1537. 06342     o16 pop     ds
  1538. 06343         popad
  1539. 06344         add     esp, 4          ! skip return adr
  1540. 06345         iretd                   ! continue process
  1541. 06346
  1542. 06347 !*===========================================================================*
  1543. 06348 !*                              exception handlers                           *
  1544. 06349 !*===========================================================================*
  1545. 06350 _divide_error:
  1546. 06351         push    DIVIDE_VECTOR
  1547. 06352         jmp     exception
  1548. 06353
  1549. 06354 _single_step_exception:
  1550. 06355         push    DEBUG_VECTOR
  1551. 06356         jmp     exception
  1552. 06357
  1553. 06358 _nmi:
  1554. 06359         push    NMI_VECTOR
  1555. 06360         jmp     exception
  1556. 06361
  1557. 06362 _breakpoint_exception:
  1558. 06363         push    BREAKPOINT_VECTOR
  1559. 06364         jmp     exception
  1560. 06365
  1561. 06366 _overflow:
  1562. 06367         push    OVERFLOW_VECTOR
  1563. 06368         jmp     exception
  1564. 06369
  1565. 06370 _bounds_check:
  1566. 06371         push    BOUNDS_VECTOR
  1567. 06372         jmp     exception
  1568. 06373
  1569. 06374 _inval_opcode:
  1570. .Op 75 src/kernel/mpx386.s
  1571. 06375         push    INVAL_OP_VECTOR
  1572. 06376         jmp     exception
  1573. 06377
  1574. 06378 _copr_not_available:
  1575. 06379         push    COPROC_NOT_VECTOR
  1576. 06380         jmp     exception
  1577. 06381
  1578. 06382 _double_fault:
  1579. 06383         push    DOUBLE_FAULT_VECTOR
  1580. 06384         jmp     errexception
  1581. 06385
  1582. 06386 _copr_seg_overrun:
  1583. 06387         push    COPROC_SEG_VECTOR
  1584. 06388         jmp     exception
  1585. 06389
  1586. 06390 _inval_tss:
  1587. 06391         push    INVAL_TSS_VECTOR
  1588. 06392         jmp     errexception
  1589. 06393
  1590. 06394 _segment_not_present:
  1591. 06395         push    SEG_NOT_VECTOR
  1592. 06396         jmp     errexception
  1593. 06397
  1594. 06398 _stack_exception:
  1595. 06399         push    STACK_FAULT_VECTOR
  1596. 06400         jmp     errexception
  1597. 06401
  1598. 06402 _general_protection:
  1599. 06403         push    PROTECTION_VECTOR
  1600. 06404         jmp     errexception
  1601. 06405
  1602. 06406 _page_fault:
  1603. 06407         push    PAGE_FAULT_VECTOR
  1604. 06408         jmp     errexception
  1605. 06409
  1606. 06410 _copr_error:
  1607. 06411         push    COPROC_ERR_VECTOR
  1608. 06412         jmp     exception
  1609. 06413
  1610. 06414 !*===========================================================================*
  1611. 06415 !*                              exception                                    *
  1612. 06416 !*===========================================================================*
  1613. 06417 ! This is called for all exceptions which do not push an error code.
  1614. 06418
  1615. 06419         .align  16
  1616. 06420 exception:
  1617. 06421  sseg   mov     (trap_errno), 0         ! clear trap_errno
  1618. 06422  sseg   pop     (ex_number)
  1619. 06423         jmp     exception1
  1620. 06424
  1621. 06425 !*===========================================================================*
  1622. 06426 !*                              errexception                                 *
  1623. 06427 !*===========================================================================*
  1624. 06428 ! This is called for all exceptions which push an error code.
  1625. 06429
  1626. 06430         .align  16
  1627. 06431 errexception:
  1628. 06432  sseg   pop     (ex_number)
  1629. 06433  sseg   pop     (trap_errno)
  1630. 06434 exception1:                             ! Common for all exceptions.
  1631. .Ep 76 src/kernel/mpx386.s
  1632. 06435         push    eax                     ! eax is scratch register
  1633. 06436         mov     eax, 0+4(esp)           ! old eip
  1634. 06437  sseg   mov     (old_eip), eax
  1635. 06438         movzx   eax, 4+4(esp)           ! old cs
  1636. 06439  sseg   mov     (old_cs), eax
  1637. 06440         mov     eax, 8+4(esp)           ! old eflags
  1638. 06441  sseg   mov     (old_eflags), eax
  1639. 06442         pop     eax
  1640. 06443         call    save
  1641. 06444         push    (old_eflags)
  1642. 06445         push    (old_cs)
  1643. 06446         push    (old_eip)
  1644. 06447         push    (trap_errno)
  1645. 06448         push    (ex_number)
  1646. 06449         call    _exception              ! (ex_number, trap_errno, old_eip,
  1647. 06450                                         !       old_cs, old_eflags)
  1648. 06451         add     esp, 5*4
  1649. 06452         cli
  1650. 06453         ret
  1651. 06454
  1652. 06455 !*===========================================================================*
  1653. 06456 !*                              level0_call                                  *
  1654. 06457 !*===========================================================================*
  1655. 06458 _level0_call:
  1656. 06459         call    save
  1657. 06460         jmp     (_level0_func)
  1658. 06461
  1659. 06462 !*===========================================================================*
  1660. 06463 !*                              idle_task                                    *
  1661. 06464 !*===========================================================================*
  1662. 06465 _idle_task:                     ! executed when there is no work
  1663. 06466         jmp     _idle_task      ! a "hlt" before this fails in protected mode
  1664. 06467
  1665. 06468 !*===========================================================================*
  1666. 06469 !*                              data                                         *
  1667. 06470 !*===========================================================================*
  1668. 06471 ! These declarations assure that storage will be allocated at the very 
  1669. 06472 ! beginning of the kernel data section, so the boot monitor can be easily 
  1670. 06473 ! told how to patch these locations. Note that the magic number is put
  1671. 06474 ! here by the compiler, but will be read by, and then overwritten by,
  1672. 06475 ! the boot monitor. When the kernel starts the sizes array will be
  1673. 06476 ! found here, as if it had been initialized by the compiler.
  1674. 06477
  1675. 06478 .sect .rom      ! Before the string table please
  1676. 06479 _sizes:                         ! sizes of kernel, mm, fs filled in by boot
  1677. 06480         .data2  0x526F          ! this must be the first data entry (magic #)
  1678. 06481         .space  16*2*2-2        ! monitor uses previous word and this space
  1679. 06482                                 ! extra space allows for additional servers
  1680. 06483 .sect .bss
  1681. 06484 k_stack:
  1682. 06485         .space  K_STACK_BYTES   ! kernel stack
  1683. 06486 k_stktop:                       ! top of kernel stack
  1684. 06487         .comm   ex_number, 4
  1685. 06488         .comm   trap_errno, 4
  1686. 06489         .comm   old_eip, 4
  1687. 06490         .comm   old_cs, 4
  1688. 06491         .comm   old_eflags, 4
  1689. .Op 77 src/kernel/start.c
  1690. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1691. src/kernel/start.c    
  1692. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1693. 06500 /* This file contains the C startup code for Minix on Intel processors.
  1694. 06501  * It cooperates with mpx.s to set up a good environment for main().
  1695. 06502  *
  1696. 06503  * This code runs in real mode for a 16 bit kernel and may have to switch
  1697. 06504  * to protected mode for a 286.
  1698. 06505  *
  1699. 06506  * For a 32 bit kernel this already runs in protected mode, but the selectors
  1700. 06507  * are still those given by the BIOS with interrupts disabled, so the
  1701. 06508  * descriptors need to be reloaded and interrupt descriptors made.
  1702. 06509  */
  1703. 06510
  1704. 06511 #include "kernel.h"
  1705. 06512 #include <stdlib.h>
  1706. 06513 #include <minix/boot.h>
  1707. 06514 #include "protect.h"
  1708. 06515
  1709. 06516 PRIVATE char k_environ[256];    /* environment strings passed by loader */
  1710. 06517
  1711. 06518 FORWARD _PROTOTYPE( int k_atoi, (char *s) );
  1712. 06519
  1713. 06520
  1714. 06521 /*==========================================================================*
  1715. 06522  *                              cstart                                      *
  1716. 06523  *==========================================================================*/
  1717. 06524 PUBLIC void cstart(cs, ds, mcs, mds, parmoff, parmsize)
  1718. 06525 U16_t cs, ds;                   /* Kernel code and data segment */
  1719. 06526 U16_t mcs, mds;                 /* Monitor code and data segment */
  1720. 06527 U16_t parmoff, parmsize;        /* boot parameters offset and length */
  1721. 06528 {
  1722. 06529 /* Perform system initializations prior to calling main(). */
  1723. 06530
  1724. 06531   register char *envp;
  1725. 06532   phys_bytes mcode_base, mdata_base;
  1726. 06533   unsigned mon_start;
  1727. 06534
  1728. 06535   /* Record where the kernel and the monitor are. */
  1729. 06536   code_base = seg2phys(cs);
  1730. 06537   data_base = seg2phys(ds);
  1731. 06538   mcode_base = seg2phys(mcs);
  1732. 06539   mdata_base = seg2phys(mds);
  1733. 06540
  1734. 06541   /* Initialize protected mode descriptors. */
  1735. 06542   prot_init();
  1736. 06543
  1737. 06544   /* Copy the boot parameters to kernel memory. */
  1738. 06545   if (parmsize > sizeof k_environ - 2) parmsize = sizeof k_environ - 2;
  1739. 06546   phys_copy(mdata_base + parmoff, vir2phys(k_environ), (phys_bytes) parmsize);
  1740. 06547
  1741. 06548   /* Convert important boot environment variables. */
  1742. 06549   boot_parameters.bp_rootdev = k_atoi(k_getenv("rootdev"));
  1743. 06550   boot_parameters.bp_ramimagedev = k_atoi(k_getenv("ramimagedev"));
  1744. 06551   boot_parameters.bp_ramsize = k_atoi(k_getenv("ramsize"));
  1745. 06552   boot_parameters.bp_processor = k_atoi(k_getenv("processor"));
  1746. 06553
  1747. 06554   /* Type of VDU: */
  1748. .Ep 78 src/kernel/start.c
  1749. 06555   envp = k_getenv("video");
  1750. 06556   if (strcmp(envp, "ega") == 0) ega = TRUE;
  1751. 06557   if (strcmp(envp, "vga") == 0) vga = ega = TRUE;
  1752. 06558
  1753. 06559   /* Memory sizes: */
  1754. 06560   low_memsize = k_atoi(k_getenv("memsize"));
  1755. 06561   ext_memsize = k_atoi(k_getenv("emssize"));
  1756. 06562
  1757. 06563   /* Processor? */
  1758. 06564   processor = boot_parameters.bp_processor;     /* 86, 186, 286, 386, ... */
  1759. 06565
  1760. 06566   /* XT, AT or MCA bus? */
  1761. 06567   envp = k_getenv("bus");
  1762. 06568   if (envp == NIL_PTR || strcmp(envp, "at") == 0) {
  1763. 06569         pc_at = TRUE;
  1764. 06570   } else
  1765. 06571   if (strcmp(envp, "mca") == 0) {
  1766. 06572         pc_at = ps_mca = TRUE;
  1767. 06573   }
  1768. 06574
  1769. 06575   /* Decide if mode is protected. */
  1770. 06576 #if _WORD_SIZE == 2
  1771. 06577   protected_mode = processor >= 286;
  1772. 06578 #endif
  1773. 06579
  1774. 06580   /* Is there a monitor to return to?  If so then keep it safe. */
  1775. 06581   if (!protected_mode) mon_return = 0;
  1776. 06582   mon_start = mcode_base / 1024;
  1777. 06583   if (mon_return && low_memsize > mon_start) low_memsize = mon_start;
  1778. 06584
  1779. 06585   /* Return to assembler code to switch to protected mode (if 286), reload
  1780. 06586    * selectors and call main().
  1781. 06587    */
  1782. 06588 }
  1783. 06591 /*==========================================================================*
  1784. 06592  *                              k_atoi                                      *
  1785. 06593  *==========================================================================*/
  1786. 06594 PRIVATE int k_atoi(s)
  1787. 06595 register char *s;
  1788. 06596 {
  1789. 06597 /* Convert string to integer. */
  1790. 06598
  1791. 06599   return strtol(s, (char **) NULL, 10);
  1792. 06600 }
  1793. 06603 /*==========================================================================*
  1794. 06604  *                              k_getenv                                    *
  1795. 06605  *==========================================================================*/
  1796. 06606 PUBLIC char *k_getenv(name)
  1797. 06607 char *name;
  1798. 06608 {
  1799. 06609 /* Get environment value - kernel version of getenv to avoid setting up the
  1800. 06610  * usual environment array.
  1801. 06611  */
  1802. 06612
  1803. 06613   register char *namep;
  1804. 06614   register char *envp;
  1805. .Op 79 src/kernel/start.c
  1806. 06615
  1807. 06616   for (envp = k_environ; *envp != 0;) {
  1808. 06617         for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++)
  1809. 06618                 ;
  1810. 06619         if (*namep == '' && *envp == '=') return(envp + 1);
  1811. 06620         while (*envp++ != 0)
  1812. 06621                 ;
  1813. 06622   }
  1814. 06623   return(NIL_PTR);
  1815. 06624 }
  1816. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1817. src/kernel/main.c    
  1818. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1819. 06700 /* This file contains the main program of MINIX.  The routine main()
  1820. 06701  * initializes the system and starts the ball rolling by setting up the proc
  1821. 06702  * table, interrupt vectors, and scheduling each task to run to initialize
  1822. 06703  * itself.
  1823. 06704  *
  1824. 06705  * The entries into this file are:
  1825. 06706  *   main:              MINIX main program
  1826. 06707  *   panic:             abort MINIX due to a fatal error
  1827. 06708  */
  1828. 06709
  1829. 06710 #include "kernel.h"
  1830. 06711 #include <signal.h>
  1831. 06712 #include <unistd.h>
  1832. 06713 #include <minix/callnr.h>
  1833. 06714 #include <minix/com.h>
  1834. 06715 #include "proc.h"
  1835. 06716
  1836. 06717
  1837. 06718 /*===========================================================================*
  1838. 06719  *                                   main                                    *
  1839. 06720  *===========================================================================*/
  1840. 06721 PUBLIC void main()
  1841. 06722 {
  1842. 06723 /* Start the ball rolling. */
  1843. 06724
  1844. 06725   register struct proc *rp;
  1845. 06726   register int t;
  1846. 06727   int sizeindex;
  1847. 06728   phys_clicks text_base;
  1848. 06729   vir_clicks text_clicks;
  1849. 06730   vir_clicks data_clicks;
  1850. 06731   phys_bytes phys_b;
  1851. 06732   reg_t ktsb;                   /* kernel task stack base */
  1852. 06733   struct memory *memp;
  1853. 06734   struct tasktab *ttp;
  1854. 06735
  1855. 06736   /* Initialize the interrupt controller. */
  1856. 06737   intr_init(1);
  1857. 06738
  1858. 06739   /* Interpret memory sizes. */
  1859. .Ep 80 src/kernel/main.c
  1860. 06740   mem_init();
  1861. 06741
  1862. 06742   /* Clear the process table.
  1863. 06743    * Set up mappings for proc_addr() and proc_number() macros.
  1864. 06744    */
  1865. 06745   for (rp = BEG_PROC_ADDR, t = -NR_TASKS; rp < END_PROC_ADDR; ++rp, ++t) {
  1866. 06746         rp->p_flags = P_SLOT_FREE;
  1867. 06747         rp->p_nr = t;           /* proc number from ptr */
  1868. 06748         (pproc_addr + NR_TASKS)[t] = rp;        /* proc ptr from number */
  1869. 06749   }
  1870. 06750
  1871. 06751   /* Set up proc table entries for tasks and servers.  The stacks of the
  1872. 06752    * kernel tasks are initialized to an array in data space.  The stacks
  1873. 06753    * of the servers have been added to the data segment by the monitor, so
  1874. 06754    * the stack pointer is set to the end of the data segment.  All the
  1875. 06755    * processes are in low memory on the 8086.  On the 386 only the kernel
  1876. 06756    * is in low memory, the rest if loaded in extended memory.
  1877. 06757    */
  1878. 06758
  1879. 06759   /* Task stacks. */
  1880. 06760   ktsb = (reg_t) t_stack;
  1881. 06761
  1882. 06762   for (t = -NR_TASKS; t <= LOW_USER; ++t) {
  1883. 06763         rp = proc_addr(t);                      /* t's process slot */
  1884. 06764         ttp = &tasktab[t + NR_TASKS];           /* t's task attributes */
  1885. 06765         strcpy(rp->p_name, ttp->name);
  1886. 06766         if (t < 0) {
  1887. 06767                 if (ttp->stksize > 0) {
  1888. 06768                         rp->p_stguard = (reg_t *) ktsb;
  1889. 06769                         *rp->p_stguard = STACK_GUARD;
  1890. 06770                 }
  1891. 06771                 ktsb += ttp->stksize;
  1892. 06772                 rp->p_reg.sp = ktsb;
  1893. 06773                 text_base = code_base >> CLICK_SHIFT;
  1894. 06774                                         /* tasks are all in the kernel */
  1895. 06775                 sizeindex = 0;          /* and use the full kernel sizes */
  1896. 06776                 memp = &mem[0];         /* remove from this memory chunk */
  1897. 06777         } else {
  1898. 06778                 sizeindex = 2 * t + 2;  /* MM, FS, INIT have their own sizes */
  1899. 06779         }
  1900. 06780         rp->p_reg.pc = (reg_t) ttp->initial_pc;
  1901. 06781         rp->p_reg.psw = istaskp(rp) ? INIT_TASK_PSW : INIT_PSW;
  1902. 06782
  1903. 06783         text_clicks = sizes[sizeindex];
  1904. 06784         data_clicks = sizes[sizeindex + 1];
  1905. 06785         rp->p_map[T].mem_phys = text_base;
  1906. 06786         rp->p_map[T].mem_len  = text_clicks;
  1907. 06787         rp->p_map[D].mem_phys = text_base + text_clicks;
  1908. 06788         rp->p_map[D].mem_len  = data_clicks;
  1909. 06789         rp->p_map[S].mem_phys = text_base + text_clicks + data_clicks;
  1910. 06790         rp->p_map[S].mem_vir  = data_clicks;    /* empty - stack is in data */
  1911. 06791         text_base += text_clicks + data_clicks; /* ready for next, if server */
  1912. 06792         memp->size -= (text_base - memp->base);
  1913. 06793         memp->base = text_base;                 /* memory no longer free */
  1914. 06794
  1915. 06795         if (t >= 0) {
  1916. 06796                 /* Initialize the server stack pointer.  Take it down one word
  1917. 06797                  * to give crtso.s something to use as "argc".
  1918. 06798                  */
  1919. 06799                 rp->p_reg.sp = (rp->p_map[S].mem_vir +
  1920. .Op 81 src/kernel/main.c
  1921. 06800                                 rp->p_map[S].mem_len) << CLICK_SHIFT;
  1922. 06801                 rp->p_reg.sp -= sizeof(reg_t);
  1923. 06802         }
  1924. 06803
  1925. 06804 #if _WORD_SIZE == 4
  1926. 06805         /* Servers are loaded in extended memory if in 386 mode. */
  1927. 06806         if (t < 0) {
  1928. 06807                 memp = &mem[1];
  1929. 06808                 text_base = 0x100000 >> CLICK_SHIFT;
  1930. 06809         }
  1931. 06810 #endif
  1932. 06811         if (!isidlehardware(t)) lock_ready(rp); /* IDLE, HARDWARE neveready */
  1933. 06812         rp->p_flags = 0;
  1934. 06813
  1935. 06814         alloc_segments(rp);
  1936. 06815   }
  1937. 06816
  1938. 06817   proc[NR_TASKS+INIT_PROC_NR].p_pid = 1;/* INIT of course has pid 1 */
  1939. 06818   bill_ptr = proc_addr(IDLE);           /* it has to point somewhere */
  1940. 06819   lock_pick_proc();
  1941. 06820
  1942. 06821   /* Now go to the assembly code to start running the current process. */
  1943. 06822   restart();
  1944. 06823 }
  1945. 06826 /*===========================================================================*
  1946. 06827  *                                   panic                                   *
  1947. 06828  *===========================================================================*/
  1948. 06829 PUBLIC void panic(s,n)
  1949. 06830 _CONST char *s;
  1950. 06831 int n;
  1951. 06832 {
  1952. 06833 /* The system has run aground of a fatal error.  Terminate execution.
  1953. 06834  * If the panic originated in MM or FS, the string will be empty and the
  1954. 06835  * file system already syncked.  If the panic originates in the kernel, we are
  1955. 06836  * kind of stuck.
  1956. 06837  */
  1957. 06838
  1958. 06839   if (*s != 0) {
  1959. 06840         printf("nKernel panic: %s",s);
  1960. 06841         if (n != NO_NUM) printf(" %d", n);
  1961. 06842         printf("n");
  1962. 06843   }
  1963. 06844   wreboot(RBT_PANIC);
  1964. 06845 }
  1965. .Ep 82 src/kernel/proc.c
  1966. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1967. src/kernel/proc.c    
  1968. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1969. 06900 /* This file contains essentially all of the process and message handling.
  1970. 06901  * It has two main entry points from the outside:
  1971. 06902  *
  1972. 06903  *   sys_call:   called when a process or task does SEND, RECEIVE or SENDREC
  1973. 06904  *   interrupt: called by interrupt routines to send a message to task
  1974. 06905  *
  1975. 06906  * It also has several minor entry points:
  1976. 06907  *
  1977. 06908  *   lock_ready:      put a process on one of the ready queues so it can be run
  1978. 06909  *   lock_unready:    remove a process from the ready queues
  1979. 06910  *   lock_sched:      a process has run too long; schedule another one
  1980. 06911  *   lock_mini_send:  send a message (used by interrupt signals, etc.)
  1981. 06912  *   lock_pick_proc:  pick a process to run (used by system initialization)
  1982. 06913  *   unhold:          repeat all held-up interrupts
  1983. 06914  */
  1984. 06915
  1985. 06916 #include "kernel.h"
  1986. 06917 #include <minix/callnr.h>
  1987. 06918 #include <minix/com.h>
  1988. 06919 #include "proc.h"
  1989. 06920
  1990. 06921 PRIVATE unsigned char switching;        /* nonzero to inhibit interrupt() */
  1991. 06922
  1992. 06923 FORWARD _PROTOTYPE( int mini_send, (struct proc *caller_ptr, int dest,
  1993. 06924                 message *m_ptr) );
  1994. 06925 FORWARD _PROTOTYPE( int mini_rec, (struct proc *caller_ptr, int src,
  1995. 06926                 message *m_ptr) );
  1996. 06927 FORWARD _PROTOTYPE( void ready, (struct proc *rp) );
  1997. 06928 FORWARD _PROTOTYPE( void sched, (void) );
  1998. 06929 FORWARD _PROTOTYPE( void unready, (struct proc *rp) );
  1999. 06930 FORWARD _PROTOTYPE( void pick_proc, (void) );
  2000. 06931
  2001. 06932 #define CopyMess(s,sp,sm,dp,dm) 
  2002. 06933         cp_mess(s, (sp)->p_map[D].mem_phys, (vir_bytes)sm, (dp)->p_map[D].mem_phys, (vir_bytes)dm)
  2003. 06934
  2004. 06935 /*===========================================================================*
  2005. 06936  *                              interrupt                                    * 
  2006. 06937  *===========================================================================*/
  2007. 06938 PUBLIC void interrupt(task)
  2008. 06939 int task;                       /* number of task to be started */
  2009. 06940 {
  2010. 06941 /* An interrupt has occurred.  Schedule the task that handles it. */
  2011. 06942
  2012. 06943   register struct proc *rp;     /* pointer to task's proc entry */
  2013. 06944
  2014. 06945   rp = proc_addr(task);
  2015. 06946
  2016. 06947   /* If this call would compete with other process-switching functions, put
  2017. 06948    * it on the 'held' queue to be flushed at the next non-competing restart().
  2018. 06949    * The competing conditions are:
  2019. 06950    * (1) k_reenter == (typeof k_reenter) -1:
  2020. 06951    *     Call from the task level, typically from an output interrupt
  2021. 06952    *     routine.  An interrupt handler might reenter interrupt().  Rare,
  2022. 06953    *     so not worth special treatment.
  2023. 06954    * (2) k_reenter > 0:
  2024. .Op 83 src/kernel/proc.c
  2025. 06955    *     Call from a nested interrupt handler.  A previous interrupt handler
  2026. 06956    *     might be inside interrupt() or sys_call().
  2027. 06957    * (3) switching != 0:
  2028. 06958    *     Some process-switching function other than interrupt() is being
  2029. 06959    *     called from the task level, typically sched() from CLOCK.  An
  2030. 06960    *     interrupt handler might call interrupt and pass the k_reenter test.
  2031. 06961    */
  2032. 06962   if (k_reenter != 0 || switching) {
  2033. 06963         lock();
  2034. 06964         if (!rp->p_int_held) {
  2035. 06965                 rp->p_int_held = TRUE;
  2036. 06966                 if (held_head != NIL_PROC)
  2037. 06967                         held_tail->p_nextheld = rp;
  2038. 06968                 else
  2039. 06969                         held_head = rp;
  2040. 06970                 held_tail = rp;
  2041. 06971                 rp->p_nextheld = NIL_PROC;
  2042. 06972         }
  2043. 06973         unlock();
  2044. 06974         return;
  2045. 06975   }
  2046. 06976
  2047. 06977   /* If task is not waiting for an interrupt, record the blockage. */
  2048. 06978   if ( (rp->p_flags & (RECEIVING | SENDING)) != RECEIVING ||
  2049. 06979       !isrxhardware(rp->p_getfrom)) {
  2050. 06980         rp->p_int_blocked = TRUE;
  2051. 06981         return;
  2052. 06982   }
  2053. 06983
  2054. 06984   /* Destination is waiting for an interrupt.
  2055. 06985    * Send it a message with source HARDWARE and type HARD_INT.
  2056. 06986    * No more information can be reliably provided since interrupt messages
  2057. 06987    * are not queued.
  2058. 06988    */
  2059. 06989   rp->p_messbuf->m_source = HARDWARE;
  2060. 06990   rp->p_messbuf->m_type = HARD_INT;
  2061. 06991   rp->p_flags &= ~RECEIVING;
  2062. 06992   rp->p_int_blocked = FALSE;
  2063. 06993
  2064. 06994    /* Make rp ready and run it unless a task is already running.  This is
  2065. 06995     * ready(rp) in-line for speed.
  2066. 06996     */
  2067. 06997   if (rdy_head[TASK_Q] != NIL_PROC)
  2068. 06998         rdy_tail[TASK_Q]->p_nextready = rp;
  2069. 06999   else
  2070. 07000         proc_ptr = rdy_head[TASK_Q] = rp;
  2071. 07001   rdy_tail[TASK_Q] = rp;
  2072. 07002   rp->p_nextready = NIL_PROC;
  2073. 07003 }
  2074. 07005 /*===========================================================================*
  2075. 07006  *                              sys_call                                     * 
  2076. 07007  *===========================================================================*/
  2077. 07008 PUBLIC int sys_call(function, src_dest, m_ptr)
  2078. 07009 int function;                   /* SEND, RECEIVE, or BOTH */
  2079. 07010 int src_dest;                   /* source to receive from or dest to send to */
  2080. 07011 message *m_ptr;                 /* pointer to message */
  2081. 07012 {
  2082. 07013 /* The only system calls that exist in MINIX are sending and receiving
  2083. 07014  * messages.  These are done by trapping to the kernel with an INT instruction.
  2084. .Ep 84 src/kernel/proc.c
  2085. 07015  * The trap is caught and sys_call() is called to send or receive a message
  2086. 07016  * (or both). The caller is always given by proc_ptr.
  2087. 07017  */
  2088. 07018
  2089. 07019   register struct proc *rp;
  2090. 07020   int n;
  2091. 07021
  2092. 07022   /* Check for bad system call parameters. */
  2093. 07023   if (!isoksrc_dest(src_dest)) return(E_BAD_SRC);
  2094. 07024   rp = proc_ptr;
  2095. 07025
  2096. 07026   if (isuserp(rp) && function != BOTH) return(E_NO_PERM);
  2097. 07027   
  2098. 07028   /* The parameters are ok. Do the call. */
  2099. 07029   if (function & SEND) {
  2100. 07030         /* Function = SEND or BOTH. */
  2101. 07031         n = mini_send(rp, src_dest, m_ptr);
  2102. 07032         if (function == SEND || n != OK)
  2103. 07033                 return(n);      /* done, or SEND failed */
  2104. 07034   }
  2105. 07035
  2106. 07036   /* Function = RECEIVE or BOTH.
  2107. 07037    * We have checked user calls are BOTH, and trust 'function' otherwise.
  2108. 07038    */
  2109. 07039   return(mini_rec(rp, src_dest, m_ptr));
  2110. 07040 }
  2111. 07042 /*===========================================================================*
  2112. 07043  *                              mini_send                                    * 
  2113. 07044  *===========================================================================*/
  2114. 07045 PRIVATE int mini_send(caller_ptr, dest, m_ptr)
  2115. 07046 register struct proc *caller_ptr;       /* who is trying to send a message? */
  2116. 07047 int dest;                       /* to whom is message being sent? */
  2117. 07048 message *m_ptr;                 /* pointer to message buffer */
  2118. 07049 {
  2119. 07050 /* Send a message from 'caller_ptr' to 'dest'. If 'dest' is blocked waiting
  2120. 07051  * for this message, copy the message to it and unblock 'dest'. If 'dest' is
  2121. 07052  * not waiting at all, or is waiting for another source, queue 'caller_ptr'.
  2122. 07053  */
  2123. 07054
  2124. 07055   register struct proc *dest_ptr, *next_ptr;
  2125. 07056   vir_bytes vb;                 /* message buffer pointer as vir_bytes */
  2126. 07057   vir_clicks vlo, vhi;          /* virtual clicks containing message to send */
  2127. 07058
  2128. 07059   /* User processes are only allowed to send to FS and MM.  Check for this. */
  2129. 07060   if (isuserp(caller_ptr) && !issysentn(dest)) return(E_BAD_DEST);
  2130. 07061   dest_ptr = proc_addr(dest);   /* pointer to destination's proc entry */
  2131. 07062   if (dest_ptr->p_flags & P_SLOT_FREE) return(E_BAD_DEST);      /* dead dest */
  2132. 07063
  2133. 07064   /* This check allows a message to be anywhere in data or stack or gap. 
  2134. 07065    * It will have to be made more elaborate later for machines which
  2135. 07066    * don't have the gap mapped.
  2136. 07067    */
  2137. 07068   vb = (vir_bytes) m_ptr;
  2138. 07069   vlo = vb >> CLICK_SHIFT;      /* vir click for bottom of message */
  2139. 07070   vhi = (vb + MESS_SIZE - 1) >> CLICK_SHIFT;    /* vir click for top of msg */
  2140. 07071   if (vlo < caller_ptr->p_map[D].mem_vir || vlo > vhi ||
  2141. 07072       vhi >= caller_ptr->p_map[S].mem_vir + caller_ptr->p_map[S].mem_len)
  2142. 07073         return(EFAULT); 
  2143. 07074
  2144. .Op 85 src/kernel/proc.c
  2145. 07075   /* Check for deadlock by 'caller_ptr' and 'dest' sending to each other. */
  2146. 07076   if (dest_ptr->p_flags & SENDING) {
  2147. 07077         next_ptr = proc_addr(dest_ptr->p_sendto);
  2148. 07078         while (TRUE) {
  2149. 07079                 if (next_ptr == caller_ptr) return(ELOCKED);
  2150. 07080                 if (next_ptr->p_flags & SENDING)
  2151. 07081                         next_ptr = proc_addr(next_ptr->p_sendto);
  2152. 07082                 else
  2153. 07083                         break;
  2154. 07084         }
  2155. 07085   }
  2156. 07086
  2157. 07087   /* Check to see if 'dest' is blocked waiting for this message. */
  2158. 07088   if ( (dest_ptr->p_flags & (RECEIVING | SENDING)) == RECEIVING &&
  2159. 07089        (dest_ptr->p_getfrom == ANY ||
  2160. 07090         dest_ptr->p_getfrom == proc_number(caller_ptr))) {
  2161. 07091         /* Destination is indeed waiting for this message. */
  2162. 07092         CopyMess(proc_number(caller_ptr), caller_ptr, m_ptr, dest_ptr,
  2163. 07093                  dest_ptr->p_messbuf);
  2164. 07094         dest_ptr->p_flags &= ~RECEIVING;        /* deblock destination */
  2165. 07095         if (dest_ptr->p_flags == 0) ready(dest_ptr);
  2166. 07096   } else {
  2167. 07097         /* Destination is not waiting.  Block and queue caller. */
  2168. 07098         caller_ptr->p_messbuf = m_ptr;
  2169. 07099         if (caller_ptr->p_flags == 0) unready(caller_ptr);
  2170. 07100         caller_ptr->p_flags |= SENDING;
  2171. 07101         caller_ptr->p_sendto= dest;
  2172. 07102
  2173. 07103         /* Process is now blocked.  Put in on the destination's queue. */
  2174. 07104         if ( (next_ptr = dest_ptr->p_callerq) == NIL_PROC)
  2175. 07105                 dest_ptr->p_callerq = caller_ptr;
  2176. 07106         else {
  2177. 07107                 while (next_ptr->p_sendlink != NIL_PROC)
  2178. 07108                         next_ptr = next_ptr->p_sendlink;
  2179. 07109                 next_ptr->p_sendlink = caller_ptr;
  2180. 07110         }
  2181. 07111         caller_ptr->p_sendlink = NIL_PROC;
  2182. 07112   }
  2183. 07113   return(OK);
  2184. 07114 }
  2185. 07116 /*===========================================================================*
  2186. 07117  *                              mini_rec                                     * 
  2187. 07118  *===========================================================================*/
  2188. 07119 PRIVATE int mini_rec(caller_ptr, src, m_ptr)
  2189. 07120 register struct proc *caller_ptr;       /* process trying to get message */
  2190. 07121 int src;                        /* which message source is wanted (or ANY) */
  2191. 07122 message *m_ptr;                 /* pointer to message buffer */
  2192. 07123 {
  2193. 07124 /* A process or task wants to get a message.  If one is already queued,
  2194. 07125  * acquire it and deblock the sender.  If no message from the desired source
  2195. 07126  * is available, block the caller.  No need to check parameters for validity.
  2196. 07127  * Users calls are always sendrec(), and mini_send() has checked already.  
  2197. 07128  * Calls from the tasks, MM, and FS are trusted.
  2198. 07129  */
  2199. 07130
  2200. 07131   register struct proc *sender_ptr;
  2201. 07132   register struct proc *previous_ptr;
  2202. 07133
  2203. 07134   /* Check to see if a message from desired source is already available. */
  2204. .Ep 86 src/kernel/proc.c
  2205. 07135   if (!(caller_ptr->p_flags & SENDING)) {
  2206. 07136         /* Check caller queue. */
  2207. 07137     for (sender_ptr = caller_ptr->p_callerq; sender_ptr != NIL_PROC;
  2208. 07138          previous_ptr = sender_ptr, sender_ptr = sender_ptr->p_sendlink) {
  2209. 07139         if (src == ANY || src == proc_number(sender_ptr)) {
  2210. 07140                 /* An acceptable message has been found. */
  2211. 07141                 CopyMess(proc_number(sender_ptr), sender_ptr,
  2212. 07142                          sender_ptr->p_messbuf, caller_ptr, m_ptr);
  2213. 07143                 if (sender_ptr == caller_ptr->p_callerq)
  2214. 07144                         caller_ptr->p_callerq = sender_ptr->p_sendlink;
  2215. 07145                 else
  2216. 07146                         previous_ptr->p_sendlink = sender_ptr->p_sendlink;
  2217. 07147                 if ((sender_ptr->p_flags &= ~SENDING) == 0)
  2218. 07148                         ready(sender_ptr);      /* deblock sender */
  2219. 07149                 return(OK);
  2220. 07150         }
  2221. 07151     }
  2222. 07152
  2223. 07153     /* Check for blocked interrupt. */
  2224. 07154     if (caller_ptr->p_int_blocked && isrxhardware(src)) {
  2225. 07155         m_ptr->m_source = HARDWARE;
  2226. 07156         m_ptr->m_type = HARD_INT;
  2227. 07157         caller_ptr->p_int_blocked = FALSE;
  2228. 07158         return(OK);
  2229. 07159     }
  2230. 07160   }
  2231. 07161
  2232. 07162   /* No suitable message is available.  Block the process trying to receive. */
  2233. 07163   caller_ptr->p_getfrom = src;
  2234. 07164   caller_ptr->p_messbuf = m_ptr;
  2235. 07165   if (caller_ptr->p_flags == 0) unready(caller_ptr);
  2236. 07166   caller_ptr->p_flags |= RECEIVING;
  2237. 07167
  2238. 07168   /* If MM has just blocked and there are kernel signals pending, now is the
  2239. 07169    * time to tell MM about them, since it will be able to accept the message.
  2240. 07170    */
  2241. 07171   if (sig_procs > 0 && proc_number(caller_ptr) == MM_PROC_NR && src == ANY)
  2242. 07172         inform();
  2243. 07173   return(OK);
  2244. 07174 }
  2245. 07176 /*===========================================================================*
  2246. 07177  *                              pick_proc                                    * 
  2247. 07178  *===========================================================================*/
  2248. 07179 PRIVATE void pick_proc()
  2249. 07180 {
  2250. 07181 /* Decide who to run now.  A new process is selected by setting 'proc_ptr'.
  2251. 07182  * When a fresh user (or idle) process is selected, record it in 'bill_ptr',
  2252. 07183  * so the clock task can tell who to bill for system time.
  2253. 07184  */
  2254. 07185
  2255. 07186   register struct proc *rp;     /* process to run */
  2256. 07187
  2257. 07188   if ( (rp = rdy_head[TASK_Q]) != NIL_PROC) {
  2258. 07189         proc_ptr = rp;
  2259. 07190         return;
  2260. 07191   }
  2261. 07192   if ( (rp = rdy_head[SERVER_Q]) != NIL_PROC) {
  2262. 07193         proc_ptr = rp;
  2263. 07194         return;
  2264. .Op 87 src/kernel/proc.c
  2265. 07195   }
  2266. 07196   if ( (rp = rdy_head[USER_Q]) != NIL_PROC) {
  2267. 07197         proc_ptr = rp;
  2268. 07198         bill_ptr = rp;
  2269. 07199         return;
  2270. 07200   }
  2271. 07201   /* No one is ready.  Run the idle task.  The idle task might be made an
  2272. 07202    * always-ready user task to avoid this special case.
  2273. 07203    */
  2274. 07204   bill_ptr = proc_ptr = proc_addr(IDLE);
  2275. 07205 }
  2276. 07207 /*===========================================================================*
  2277. 07208  *                              ready                                        * 
  2278. 07209  *===========================================================================*/
  2279. 07210 PRIVATE void ready(rp)
  2280. 07211 register struct proc *rp;       /* this process is now runnable */
  2281. 07212 {
  2282. 07213 /* Add 'rp' to the end of one of the queues of runnable processes. Three
  2283. 07214  * queues are maintained:
  2284. 07215  *   TASK_Q   - (highest priority) for runnable tasks
  2285. 07216  *   SERVER_Q - (middle priority) for MM and FS only
  2286. 07217  *   USER_Q   - (lowest priority) for user processes
  2287. 07218  */
  2288. 07219
  2289. 07220   if (istaskp(rp)) {
  2290. 07221         if (rdy_head[TASK_Q] != NIL_PROC)
  2291. 07222                 /* Add to tail of nonempty queue. */
  2292. 07223                 rdy_tail[TASK_Q]->p_nextready = rp;
  2293. 07224         else {
  2294. 07225                 proc_ptr =              /* run fresh task next */
  2295. 07226                 rdy_head[TASK_Q] = rp;  /* add to empty queue */
  2296. 07227         }
  2297. 07228         rdy_tail[TASK_Q] = rp;
  2298. 07229         rp->p_nextready = NIL_PROC;     /* new entry has no successor */
  2299. 07230         return;
  2300. 07231   }
  2301. 07232   if (!isuserp(rp)) {           /* others are similar */
  2302. 07233         if (rdy_head[SERVER_Q] != NIL_PROC)
  2303. 07234                 rdy_tail[SERVER_Q]->p_nextready = rp;
  2304. 07235         else
  2305. 07236                 rdy_head[SERVER_Q] = rp;
  2306. 07237         rdy_tail[SERVER_Q] = rp;
  2307. 07238         rp->p_nextready = NIL_PROC;
  2308. 07239         return;
  2309. 07240   }
  2310. 07241   if (rdy_head[USER_Q] == NIL_PROC)
  2311. 07242         rdy_tail[USER_Q] = rp;
  2312. 07243   rp->p_nextready = rdy_head[USER_Q];
  2313. 07244   rdy_head[USER_Q] = rp;
  2314. 07245 /*
  2315. 07246   if (rdy_head[USER_Q] != NIL_PROC)
  2316. 07247         rdy_tail[USER_Q]->p_nextready = rp;
  2317. 07248   else
  2318. 07249         rdy_head[USER_Q] = rp;
  2319. 07250   rdy_tail[USER_Q] = rp;
  2320. 07251   rp->p_nextready = NIL_PROC;
  2321. 07252 */
  2322. 07253 }
  2323. .Ep 88 src/kernel/proc.c
  2324. 07255 /*===========================================================================*
  2325. 07256  *                              unready                                      * 
  2326. 07257  *===========================================================================*/
  2327. 07258 PRIVATE void unready(rp)
  2328. 07259 register struct proc *rp;       /* this process is no longer runnable */
  2329. 07260 {
  2330. 07261 /* A process has blocked. */
  2331. 07262
  2332. 07263   register struct proc *xp;
  2333. 07264   register struct proc **qtail;  /* TASK_Q, SERVER_Q, or USER_Q rdy_tail */
  2334. 07265
  2335. 07266   if (istaskp(rp)) {
  2336. 07267         /* task stack still ok? */
  2337. 07268         if (*rp->p_stguard != STACK_GUARD)
  2338. 07269                 panic("stack overrun by task", proc_number(rp));
  2339. 07270
  2340. 07271         if ( (xp = rdy_head[TASK_Q]) == NIL_PROC) return;
  2341. 07272         if (xp == rp) {
  2342. 07273                 /* Remove head of queue */
  2343. 07274                 rdy_head[TASK_Q] = xp->p_nextready;
  2344. 07275                 if (rp == proc_ptr) pick_proc();
  2345. 07276                 return;
  2346. 07277         }
  2347. 07278         qtail = &rdy_tail[TASK_Q];
  2348. 07279   }
  2349. 07280   else if (!isuserp(rp)) {
  2350. 07281         if ( (xp = rdy_head[SERVER_Q]) == NIL_PROC) return;
  2351. 07282         if (xp == rp) {
  2352. 07283                 rdy_head[SERVER_Q] = xp->p_nextready;
  2353. 07284                 pick_proc();
  2354. 07285                 return;
  2355. 07286         }
  2356. 07287         qtail = &rdy_tail[SERVER_Q];
  2357. 07288   } else
  2358. 07289   {
  2359. 07290         if ( (xp = rdy_head[USER_Q]) == NIL_PROC) return;
  2360. 07291         if (xp == rp) {
  2361. 07292                 rdy_head[USER_Q] = xp->p_nextready;
  2362. 07293                 pick_proc();
  2363. 07294                 return;
  2364. 07295         }
  2365. 07296         qtail = &rdy_tail[USER_Q];
  2366. 07297   }
  2367. 07298
  2368. 07299   /* Search body of queue.  A process can be made unready even if it is
  2369. 07300    * not running by being sent a signal that kills it.
  2370. 07301    */
  2371. 07302   while (xp->p_nextready != rp)
  2372. 07303         if ( (xp = xp->p_nextready) == NIL_PROC) return;
  2373. 07304   xp->p_nextready = xp->p_nextready->p_nextready;
  2374. 07305   if (*qtail == rp) *qtail = xp;
  2375. 07306 }
  2376. 07308 /*===========================================================================*
  2377. 07309  *                              sched                                        * 
  2378. 07310  *===========================================================================*/
  2379. 07311 PRIVATE void sched()
  2380. 07312 {
  2381. 07313 /* The current process has run too long.  If another low priority (user)
  2382. 07314  * process is runnable, put the current process on the end of the user queue,
  2383. .Op 89 src/kernel/proc.c
  2384. 07315  * possibly promoting another user to head of the queue.
  2385. 07316  */
  2386. 07317
  2387. 07318   if (rdy_head[USER_Q] == NIL_PROC) return;
  2388. 07319
  2389. 07320   /* One or more user processes queued. */
  2390. 07321   rdy_tail[USER_Q]->p_nextready = rdy_head[USER_Q];
  2391. 07322   rdy_tail[USER_Q] = rdy_head[USER_Q];
  2392. 07323   rdy_head[USER_Q] = rdy_head[USER_Q]->p_nextready;
  2393. 07324   rdy_tail[USER_Q]->p_nextready = NIL_PROC;
  2394. 07325   pick_proc();
  2395. 07326 }
  2396. 07328 /*==========================================================================*
  2397. 07329  *                              lock_mini_send                              *
  2398. 07330  *==========================================================================*/
  2399. 07331 PUBLIC int lock_mini_send(caller_ptr, dest, m_ptr)
  2400. 07332 struct proc *caller_ptr;        /* who is trying to send a message? */
  2401. 07333 int dest;                       /* to whom is message being sent? */
  2402. 07334 message *m_ptr;                 /* pointer to message buffer */
  2403. 07335 {
  2404. 07336 /* Safe gateway to mini_send() for tasks. */
  2405. 07337
  2406. 07338   int result;
  2407. 07339
  2408. 07340   switching = TRUE;
  2409. 07341   result = mini_send(caller_ptr, dest, m_ptr);
  2410. 07342   switching = FALSE;
  2411. 07343   return(result);
  2412. 07344 }
  2413. 07346 /*==========================================================================*
  2414. 07347  *                              lock_pick_proc                              *
  2415. 07348  *==========================================================================*/
  2416. 07349 PUBLIC void lock_pick_proc()
  2417. 07350 {
  2418. 07351 /* Safe gateway to pick_proc() for tasks. */
  2419. 07352
  2420. 07353   switching = TRUE;
  2421. 07354   pick_proc();
  2422. 07355   switching = FALSE;
  2423. 07356 }
  2424. 07358 /*==========================================================================*
  2425. 07359  *                              lock_ready                                  *
  2426. 07360  *==========================================================================*/
  2427. 07361 PUBLIC void lock_ready(rp)
  2428. 07362 struct proc *rp;                /* this process is now runnable */
  2429. 07363 {
  2430. 07364 /* Safe gateway to ready() for tasks. */
  2431. 07365
  2432. 07366   switching = TRUE;
  2433. 07367   ready(rp);
  2434. 07368   switching = FALSE;
  2435. 07369 }
  2436. 07372 /*==========================================================================*
  2437. 07373  *                              lock_unready                                *
  2438. 07374  *==========================================================================*/
  2439. .Ep 90 src/kernel/proc.c
  2440. 07375 PUBLIC void lock_unready(rp)
  2441. 07376 struct proc *rp;                /* this process is no longer runnable */
  2442. 07377 {
  2443. 07378 /* Safe gateway to unready() for tasks. */
  2444. 07379
  2445. 07380   switching = TRUE;
  2446. 07381   unready(rp);
  2447. 07382   switching = FALSE;
  2448. 07383 }
  2449. 07385 /*==========================================================================*
  2450. 07386  *                              lock_sched                                  *
  2451. 07387  *==========================================================================*/
  2452. 07388 PUBLIC void lock_sched()
  2453. 07389 {
  2454. 07390 /* Safe gateway to sched() for tasks. */
  2455. 07391
  2456. 07392   switching = TRUE;
  2457. 07393   sched();
  2458. 07394   switching = FALSE;
  2459. 07395 }
  2460. 07397 /*==========================================================================*
  2461. 07398  *                              unhold                                      *
  2462. 07399  *==========================================================================*/
  2463. 07400 PUBLIC void unhold()
  2464. 07401 {
  2465. 07402 /* Flush any held-up interrupts.  k_reenter must be 0.  held_head must not
  2466. 07403  * be NIL_PROC.  Interrupts must be disabled.  They will be enabled but will
  2467. 07404  * be disabled when this returns.
  2468. 07405  */
  2469. 07406
  2470. 07407   register struct proc *rp;     /* current head of held queue */
  2471. 07408
  2472. 07409   if (switching) return;
  2473. 07410   rp = held_head;
  2474. 07411   do {
  2475. 07412         if ( (held_head = rp->p_nextheld) == NIL_PROC) held_tail = NIL_PROC;
  2476. 07413         rp->p_int_held = FALSE;
  2477. 07414         unlock();               /* reduce latency; held queue may change! */
  2478. 07415         interrupt(proc_number(rp));
  2479. 07416         lock();                 /* protect the held queue again */
  2480. 07417   }
  2481. 07418   while ( (rp = held_head) != NIL_PROC);
  2482. 07419 }
  2483. .Op 91 src/kernel/exception.c
  2484. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2485. src/kernel/exception.c    
  2486. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2487. 07500 /* This file contains a simple exception handler.  Exceptions in user
  2488. 07501  * processes are converted to signals.  Exceptions in the kernel, MM and
  2489. 07502  * FS cause a panic.
  2490. 07503  */
  2491. 07504
  2492. 07505 #include "kernel.h"
  2493. 07506 #include <signal.h>
  2494. 07507 #include "proc.h"
  2495. 07508
  2496. 07509 /*==========================================================================*
  2497. 07510  *                              exception                                   *
  2498. 07511  *==========================================================================*/
  2499. 07512 PUBLIC void exception(vec_nr)
  2500. 07513 unsigned vec_nr;
  2501. 07514 {
  2502. 07515 /* An exception or unexpected interrupt has occurred. */
  2503. 07516
  2504. 07517   struct ex_s {
  2505. 07518         char *msg;
  2506. 07519         int signum;
  2507. 07520         int minprocessor;
  2508. 07521   };
  2509. 07522   static struct ex_s ex_data[] = {
  2510. 07523         "Divide error", SIGFPE, 86,
  2511. 07524         "Debug exception", SIGTRAP, 86,
  2512. 07525         "Nonmaskable interrupt", SIGBUS, 86,
  2513. 07526         "Breakpoint", SIGEMT, 86,
  2514. 07527         "Overflow", SIGFPE, 86,
  2515. 07528         "Bounds check", SIGFPE, 186,
  2516. 07529         "Invalid opcode", SIGILL, 186,
  2517. 07530         "Coprocessor not available", SIGFPE, 186,
  2518. 07531         "Double fault", SIGBUS, 286,
  2519. 07532         "Copressor segment overrun", SIGSEGV, 286,
  2520. 07533         "Invalid TSS", SIGSEGV, 286,
  2521. 07534         "Segment not present", SIGSEGV, 286,
  2522. 07535         "Stack exception", SIGSEGV, 286,        /* STACK_FAULT already used */
  2523. 07536         "General protection", SIGSEGV, 286,
  2524. 07537         "Page fault", SIGSEGV, 386,             /* not close */
  2525. 07538         NIL_PTR, SIGILL, 0,                     /* probably software trap */
  2526. 07539         "Coprocessor error", SIGFPE, 386,
  2527. 07540   };
  2528. 07541   register struct ex_s *ep;
  2529. 07542   struct proc *saved_proc;
  2530. 07543
  2531. 07544   saved_proc= proc_ptr; /* Save proc_ptr, because it may be changed by debug 
  2532. 07545                          * statements.
  2533. 07546                          */
  2534. 07547
  2535. 07548   ep = &ex_data[vec_nr];
  2536. 07549
  2537. 07550   if (vec_nr == 2) {            /* spurious NMI on some machines */
  2538. 07551         printf("got spurious NMIn");
  2539. 07552         return;
  2540. 07553   }
  2541. 07554
  2542. .Ep 92 src/kernel/exception.c
  2543. 07555   if (k_reenter == 0 && isuserp(saved_proc)) {
  2544. 07556         unlock();               /* this is protected like sys_call() */
  2545. 07557         cause_sig(proc_number(saved_proc), ep->signum);
  2546. 07558         return;
  2547. 07559   }
  2548. 07560
  2549. 07561   /* This is not supposed to happen. */
  2550. 07562   if (ep->msg == NIL_PTR || processor < ep->minprocessor)
  2551. 07563         printf("nIntel-reserved exception %dn", vec_nr);
  2552. 07564   else
  2553. 07565         printf("n%sn", ep->msg);
  2554. 07566   printf("process number %d, pc = 0x%04x:0x%08xn",
  2555. 07567         proc_number(saved_proc),
  2556. 07568         (unsigned) saved_proc->p_reg.cs,
  2557. 07569         (unsigned) saved_proc->p_reg.pc);
  2558. 07570   panic("exception in system code", NO_NUM);
  2559. 07571 }
  2560. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2561. src/kernel/i8259.c    
  2562. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2563. 07600 /* This file contains routines for initializing the 8259 interrupt controller:
  2564. 07601  *      get_irq_handler: address of handler for a given interrupt
  2565. 07602  *      put_irq_handler: register an interrupt handler
  2566. 07603  *      intr_init:      initialize the interrupt controller(s)
  2567. 07604  */
  2568. 07605
  2569. 07606 #include "kernel.h"
  2570. 07607
  2571. 07608 #define ICW1_AT         0x11    /* edge triggered, cascade, need ICW4 */
  2572. 07609 #define ICW1_PC         0x13    /* edge triggered, no cascade, need ICW4 */
  2573. 07610 #define ICW1_PS         0x19    /* level triggered, cascade, need ICW4 */
  2574. 07611 #define ICW4_AT         0x01    /* not SFNM, not buffered, normal EOI, 8086 */
  2575. 07612 #define ICW4_PC         0x09    /* not SFNM, buffered, normal EOI, 8086 */
  2576. 07613
  2577. 07614 FORWARD _PROTOTYPE( int spurious_irq, (int irq) );
  2578. 07615
  2579. 07616 #define set_vec(nr, addr)       ((void)0) /* kluge for protected mode */
  2580. 07617
  2581. 07618 /*==========================================================================*
  2582. 07619  *                              intr_init                                   *
  2583. 07620  *==========================================================================*/
  2584. 07621 PUBLIC void intr_init(mine)
  2585. 07622 int mine;
  2586. 07623 {
  2587. 07624 /* Initialize the 8259s, finishing with all interrupts disabled.  This is
  2588. 07625  * only done in protected mode, in real mode we don't touch the 8259s, but
  2589. 07626  * use the BIOS locations instead.  The flag "mine" is set if the 8259s are
  2590. 07627  * to be programmed for Minix, or to be reset to what the BIOS expects.
  2591. 07628  */
  2592. 07629
  2593. 07630   int i;
  2594. 07631
  2595. 07632   lock();
  2596. 07633   /* The AT and newer PS/2 have two interrupt controllers, one master,
  2597. 07634    * one slaved at IRQ 2.  (We don't have to deal with the PC that
  2598. .Op 93 src/kernel/i8259.c
  2599. 07635    * has just one controller, because it must run in real mode.)
  2600. 07636    */
  2601. 07637   out_byte(INT_CTL, ps_mca ? ICW1_PS : ICW1_AT);
  2602. 07638   out_byte(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC);
  2603. 07639                                                 /* ICW2 for master */
  2604. 07640   out_byte(INT_CTLMASK, (1 << CASCADE_IRQ));    /* ICW3 tells slaves */
  2605. 07641   out_byte(INT_CTLMASK, ICW4_AT);
  2606. 07642   out_byte(INT_CTLMASK, ~(1 << CASCADE_IRQ));   /* IRQ 0-7 mask */
  2607. 07643   out_byte(INT2_CTL, ps_mca ? ICW1_PS : ICW1_AT);
  2608. 07644   out_byte(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC);
  2609. 07645                                                 /* ICW2 for slave */
  2610. 07646   out_byte(INT2_CTLMASK, CASCADE_IRQ);          /* ICW3 is slave nr */
  2611. 07647   out_byte(INT2_CTLMASK, ICW4_AT);
  2612. 07648   out_byte(INT2_CTLMASK, ~0);                   /* IRQ 8-15 mask */
  2613. 07649
  2614. 07650   /* Initialize the table of interrupt handlers. */
  2615. 07651   for (i = 0; i < NR_IRQ_VECTORS; i++) irq_table[i] = spurious_irq;
  2616. 07652 }
  2617. 07654 /*=========================================================================*
  2618. 07655  *                              spurious_irq                               *
  2619. 07656  *=========================================================================*/
  2620. 07657 PRIVATE int spurious_irq(irq)
  2621. 07658 int irq;
  2622. 07659 {
  2623. 07660 /* Default interrupt handler.  It complains a lot. */
  2624. 07661
  2625. 07662   if (irq < 0 || irq >= NR_IRQ_VECTORS)
  2626. 07663         panic("invalid call to spurious_irq", irq);
  2627. 07664
  2628. 07665   printf("spurious irq %dn", irq);
  2629. 07666
  2630. 07667   return 1;     /* Reenable interrupt */
  2631. 07668 }
  2632. 07670 /*=========================================================================*
  2633. 07671  *                              put_irq_handler                            *
  2634. 07672  *=========================================================================*/
  2635. 07673 PUBLIC void put_irq_handler(irq, handler)
  2636. 07674 int irq;
  2637. 07675 irq_handler_t handler;
  2638. 07676 {
  2639. 07677 /* Register an interrupt handler. */
  2640. 07678
  2641. 07679   if (irq < 0 || irq >= NR_IRQ_VECTORS)
  2642. 07680         panic("invalid call to put_irq_handler", irq);
  2643. 07681
  2644. 07682   if (irq_table[irq] == handler)
  2645. 07683         return;         /* extra initialization */
  2646. 07684
  2647. 07685   if (irq_table[irq] != spurious_irq)
  2648. 07686         panic("attempt to register second irq handler for irq", irq);
  2649. 07687
  2650. 07688   disable_irq(irq);
  2651. 07689   if (!protected_mode) set_vec(BIOS_VECTOR(irq), irq_vec[irq]);
  2652. 07690   irq_table[irq]= handler;
  2653. 07691   irq_use |= 1 << irq;
  2654. 07692 }
  2655. .Ep 94 src/kernel/protect.c
  2656. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2657. src/kernel/protect.c    
  2658. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2659. 07700 /* This file contains code for initialization of protected mode, to initialize
  2660. 07701  * code and data segment descriptors, and to initialize global descriptors
  2661. 07702  * for local descriptors in the process table.
  2662. 07703  */
  2663. 07704
  2664. 07705 #include "kernel.h"
  2665. 07706 #include "proc.h"
  2666. 07707 #include "protect.h"
  2667. 07708
  2668. 07709 #define INT_GATE_TYPE   (INT_286_GATE | DESC_386_BIT)
  2669. 07710 #define TSS_TYPE        (AVL_286_TSS  | DESC_386_BIT)
  2670. 07711
  2671. 07712 struct desctableptr_s {
  2672. 07713   char limit[sizeof(u16_t)];
  2673. 07714   char base[sizeof(u32_t)];             /* really u24_t + pad for 286 */
  2674. 07715 };
  2675. 07716
  2676. 07717 struct gatedesc_s {
  2677. 07718   u16_t offset_low;
  2678. 07719   u16_t selector;
  2679. 07720   u8_t pad;                     /* |000|XXXXX| ig & trpg, |XXXXXXXX| task g */
  2680. 07721   u8_t p_dpl_type;              /* |P|DL|0|TYPE| */
  2681. 07722   u16_t offset_high;
  2682. 07723 };
  2683. 07724
  2684. 07725 struct tss_s {
  2685. 07726   reg_t backlink;
  2686. 07727   reg_t sp0;                    /* stack pointer to use during interrupt */
  2687. 07728   reg_t ss0;                    /*   "   segment  "  "    "        "     */
  2688. 07729   reg_t sp1;
  2689. 07730   reg_t ss1;
  2690. 07731   reg_t sp2;
  2691. 07732   reg_t ss2;
  2692. 07733   reg_t cr3;
  2693. 07734   reg_t ip;
  2694. 07735   reg_t flags;
  2695. 07736   reg_t ax;
  2696. 07737   reg_t cx;
  2697. 07738   reg_t dx;
  2698. 07739   reg_t bx;
  2699. 07740   reg_t sp;
  2700. 07741   reg_t bp;
  2701. 07742   reg_t si;
  2702. 07743   reg_t di;
  2703. 07744   reg_t es;
  2704. 07745   reg_t cs;
  2705. 07746   reg_t ss;
  2706. 07747   reg_t ds;
  2707. 07748   reg_t fs;
  2708. 07749   reg_t gs;
  2709. 07750   reg_t ldt;
  2710. 07751   u16_t trap;
  2711. 07752   u16_t iobase;
  2712. 07753 };
  2713. 07754
  2714. .Op 95 src/kernel/protect.c
  2715. 07755 PUBLIC struct segdesc_s gdt[GDT_SIZE];
  2716. 07756 PRIVATE struct gatedesc_s idt[IDT_SIZE];        /* zero-init so none present */
  2717. 07757 PUBLIC struct tss_s tss;        /* zero init */
  2718. 07758
  2719. 07759 FORWARD _PROTOTYPE( void int_gate, (unsigned vec_nr, phys_bytes base,
  2720. 07760                 unsigned dpl_type) );
  2721. 07761 FORWARD _PROTOTYPE( void sdesc, (struct segdesc_s *segdp, phys_bytes base,
  2722. 07762                 phys_bytes size) );
  2723. 07763
  2724. 07764 /*=========================================================================*
  2725. 07765  *                              prot_init                                  *
  2726. 07766  *=========================================================================*/
  2727. 07767 PUBLIC void prot_init()
  2728. 07768 {
  2729. 07769 /* Set up tables for protected mode.
  2730. 07770  * All GDT slots are allocated at compile time.
  2731. 07771  */
  2732. 07772
  2733. 07773   phys_bytes code_bytes;
  2734. 07774   phys_bytes data_bytes;
  2735. 07775   struct gate_table_s *gtp;
  2736. 07776   struct desctableptr_s *dtp;
  2737. 07777   unsigned ldt_selector;
  2738. 07778   register struct proc *rp;
  2739. 07779
  2740. 07780   static struct gate_table_s {
  2741. 07781         _PROTOTYPE( void (*gate), (void) );
  2742. 07782         unsigned char vec_nr;
  2743. 07783         unsigned char privilege;
  2744. 07784   }
  2745. 07785   gate_table[] = {
  2746. 07786         divide_error, DIVIDE_VECTOR, INTR_PRIVILEGE,
  2747. 07787         single_step_exception, DEBUG_VECTOR, INTR_PRIVILEGE,
  2748. 07788         nmi, NMI_VECTOR, INTR_PRIVILEGE,
  2749. 07789         breakpoint_exception, BREAKPOINT_VECTOR, USER_PRIVILEGE,
  2750. 07790         overflow, OVERFLOW_VECTOR, USER_PRIVILEGE,
  2751. 07791         bounds_check, BOUNDS_VECTOR, INTR_PRIVILEGE,
  2752. 07792         inval_opcode, INVAL_OP_VECTOR, INTR_PRIVILEGE,
  2753. 07793         copr_not_available, COPROC_NOT_VECTOR, INTR_PRIVILEGE,
  2754. 07794         double_fault, DOUBLE_FAULT_VECTOR, INTR_PRIVILEGE,
  2755. 07795         copr_seg_overrun, COPROC_SEG_VECTOR, INTR_PRIVILEGE,
  2756. 07796         inval_tss, INVAL_TSS_VECTOR, INTR_PRIVILEGE,
  2757. 07797         segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE,
  2758. 07798         stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE,
  2759. 07799         general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE,
  2760. 07800         page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE,
  2761. 07801         copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE,
  2762. 07802         { hwint00, VECTOR( 0), INTR_PRIVILEGE },
  2763. 07803         { hwint01, VECTOR( 1), INTR_PRIVILEGE },
  2764. 07804         { hwint02, VECTOR( 2), INTR_PRIVILEGE },
  2765. 07805         { hwint03, VECTOR( 3), INTR_PRIVILEGE },
  2766. 07806         { hwint04, VECTOR( 4), INTR_PRIVILEGE },
  2767. 07807         { hwint05, VECTOR( 5), INTR_PRIVILEGE },
  2768. 07808         { hwint06, VECTOR( 6), INTR_PRIVILEGE },
  2769. 07809         { hwint07, VECTOR( 7), INTR_PRIVILEGE },
  2770. 07810         { hwint08, VECTOR( 8), INTR_PRIVILEGE },
  2771. 07811         { hwint09, VECTOR( 9), INTR_PRIVILEGE },
  2772. 07812         { hwint10, VECTOR(10), INTR_PRIVILEGE },
  2773. 07813         { hwint11, VECTOR(11), INTR_PRIVILEGE },
  2774. 07814         { hwint12, VECTOR(12), INTR_PRIVILEGE },
  2775. .Ep 96 src/kernel/protect.c
  2776. 07815         { hwint13, VECTOR(13), INTR_PRIVILEGE },
  2777. 07816         { hwint14, VECTOR(14), INTR_PRIVILEGE },
  2778. 07817         { hwint15, VECTOR(15), INTR_PRIVILEGE },
  2779. 07818   };
  2780. 07819
  2781. 07820   /* This is called early and can't use tables set up by main(). */
  2782. 07821   data_bytes = (phys_bytes) sizes[1] << CLICK_SHIFT;
  2783. 07822   if (sizes[0] == 0)
  2784. 07823         code_bytes = data_bytes;        /* common I&D */
  2785. 07824   else
  2786. 07825         code_bytes = (phys_bytes) sizes[0] << CLICK_SHIFT;