COMPLETE.T
上传用户:jnzhq888
上传日期:2007-01-18
资源大小:51694k
文件大小:2535k
源码类别:

操作系统开发

开发平台:

WINDOWS

  1. 28263     /* Copy back to user */
  2. 28264     phys_copy(vir2phys(&input), user_phys, (phys_bytes) sizeof(input));
  3. 28265   }
  4. 28266         
  5. 28267   return OK;
  6. 28268 }
  7. 28271 /*=========================================================================*
  8. 28272  *                              get_set_output                             *
  9. 28273  *=========================================================================*/
  10. 28274 PRIVATE int get_set_output(m_ptr, flag)
  11. 28275 message *m_ptr;
  12. 28276 int flag;       /* 0 = get, 1 = set */
  13. 28277 {
  14. 28278   phys_bytes user_phys;
  15. 28279   struct inout_ctrl output;
  16. 28280   int output_mask, mask, del_mask, shift;
  17. 28281
  18. 28282   user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, 
  19. 28283                                          sizeof(struct inout_ctrl));
  20. 28284   if (user_phys == 0) return(EFAULT);
  21. 28285   phys_copy(user_phys, vir2phys(&output), (phys_bytes) sizeof(output));
  22. 28286
  23. 28287   mask = mixer_get(MIXER_OUTPUT_CTRL); 
  24. 28288
  25. 28289   switch (output.device)
  26. .Op 393 src/kernel/sb16_mixer.c
  27. 28290   {
  28. 28291     case Cd:   { shift = 1;
  29. 28292                  del_mask = 0x79;
  30. 28293                };break;
  31. 28294     case Line: { shift = 3;
  32. 28295                  del_mask = 0x67;
  33. 28296                };break;
  34. 28297     case Mic:  { shift = 0;
  35. 28298                  del_mask = 0x7E;
  36. 28299                };break;
  37. 28300     default:   return EINVAL;
  38. 28301   }
  39. 28302
  40. 28303   if (flag)  /* Set input */
  41. 28304   {
  42. 28305     output_mask = 
  43. 28306            ((output.left == ON ? 1 : 0) << 1) | (output.right == ON ? 1 : 0);
  44. 28307
  45. 28308     if (shift > 0)
  46. 28309      output_mask <<= shift;
  47. 28310     else
  48. 28311      output_mask >>= 1;
  49. 28312
  50. 28313     mask &= del_mask;   
  51. 28314     mask |= output_mask;
  52. 28315
  53. 28316     mixer_set(MIXER_OUTPUT_CTRL, mask);
  54. 28317   }
  55. 28318   else      /* Get input */
  56. 28319   {
  57. 28320     if (shift > 0)
  58. 28321     {
  59. 28322       output.left = ((mask >> (shift+1)) & 1 == 1 ? ON : OFF);
  60. 28323       output.right = ((mask >> shift) & 1 == 1 ? ON : OFF);
  61. 28324     }
  62. 28325     else
  63. 28326       output.left = ((mask & 1) == 1 ? ON : OFF);
  64. 28327
  65. 28328     /* Copy back to user */
  66. 28329     phys_copy(vir2phys(&output), user_phys, (phys_bytes) sizeof(output));
  67. 28330   }
  68. 28331         
  69. 28332   return OK;
  70. 28333 }
  71. 28334 #endif /* ENABLE_AUDIO */
  72. .Ep 394 src/kernel/start.c
  73. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  74. src/kernel/start.c    
  75. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  76. 28400 /* This file contains the C startup code for Minix on Intel processors.
  77. 28401  * It cooperates with mpx.s to set up a good environment for main().
  78. 28402  *
  79. 28403  * This code runs in real mode for a 16 bit kernel and may have to switch
  80. 28404  * to protected mode for a 286.
  81. 28405  *
  82. 28406  * For a 32 bit kernel this already runs in protected mode, but the selectors
  83. 28407  * are still those given by the BIOS with interrupts disabled, so the
  84. 28408  * descriptors need to be reloaded and interrupt descriptors made.
  85. 28409  */
  86. 28410
  87. 28411 #include "kernel.h"
  88. 28412 #include <stdlib.h>
  89. 28413 #include <minix/boot.h>
  90. 28414 #include "protect.h"
  91. 28415
  92. 28416 PRIVATE char k_environ[256];    /* environment strings passed by loader */
  93. 28417
  94. 28418 FORWARD _PROTOTYPE( int k_atoi, (char *s) );
  95. 28419
  96. 28420
  97. 28421 /*==========================================================================*
  98. 28422  *                              cstart                                      *
  99. 28423  *==========================================================================*/
  100. 28424 PUBLIC void cstart(cs, ds, mcs, mds, parmoff, parmsize)
  101. 28425 U16_t cs, ds;                   /* Kernel code and data segment */
  102. 28426 U16_t mcs, mds;                 /* Monitor code and data segment */
  103. 28427 U16_t parmoff, parmsize;        /* boot parameters offset and length */
  104. 28428 {
  105. 28429 /* Perform system initializations prior to calling main(). */
  106. 28430
  107. 28431   register char *envp;
  108. 28432   phys_bytes mcode_base, mdata_base;
  109. 28433   unsigned mon_start;
  110. 28434
  111. 28435   /* Record where the kernel and the monitor are. */
  112. 28436   code_base = seg2phys(cs);
  113. 28437   data_base = seg2phys(ds);
  114. 28438   mcode_base = seg2phys(mcs);
  115. 28439   mdata_base = seg2phys(mds);
  116. 28440
  117. 28441   /* Initialize protected mode descriptors. */
  118. 28442   prot_init();
  119. 28443
  120. 28444   /* Copy the boot parameters to kernel memory. */
  121. 28445   if (parmsize > sizeof k_environ - 2) parmsize = sizeof k_environ - 2;
  122. 28446   phys_copy(mdata_base + parmoff, vir2phys(k_environ), (phys_bytes) parmsize);
  123. 28447
  124. 28448   /* Convert important boot environment variables. */
  125. 28449   boot_parameters.bp_rootdev = k_atoi(k_getenv("rootdev"));
  126. 28450   boot_parameters.bp_ramimagedev = k_atoi(k_getenv("ramimagedev"));
  127. 28451   boot_parameters.bp_ramsize = k_atoi(k_getenv("ramsize"));
  128. 28452   boot_parameters.bp_processor = k_atoi(k_getenv("processor"));
  129. 28453
  130. 28454   /* Type of VDU: */
  131. .Op 395 src/kernel/start.c
  132. 28455   envp = k_getenv("video");
  133. 28456   if (strcmp(envp, "ega") == 0) ega = TRUE;
  134. 28457   if (strcmp(envp, "vga") == 0) vga = ega = TRUE;
  135. 28458
  136. 28459   /* Memory sizes: */
  137. 28460   low_memsize = k_atoi(k_getenv("memsize"));
  138. 28461   ext_memsize = k_atoi(k_getenv("emssize"));
  139. 28462
  140. 28463   /* Processor? */
  141. 28464   processor = boot_parameters.bp_processor;     /* 86, 186, 286, 386, ... */
  142. 28465
  143. 28466   /* XT, AT or MCA bus? */
  144. 28467   envp = k_getenv("bus");
  145. 28468   if (envp == NIL_PTR || strcmp(envp, "at") == 0) {
  146. 28469         pc_at = TRUE;
  147. 28470   } else
  148. 28471   if (strcmp(envp, "mca") == 0) {
  149. 28472         pc_at = ps_mca = TRUE;
  150. 28473   }
  151. 28474
  152. 28475   /* Decide if mode is protected. */
  153. 28476 #if _WORD_SIZE == 2
  154. 28477   protected_mode = processor >= 286;
  155. 28478 #endif
  156. 28479
  157. 28480   /* Is there a monitor to return to?  If so then keep it safe. */
  158. 28481   if (!protected_mode) mon_return = 0;
  159. 28482   mon_start = mcode_base / 1024;
  160. 28483   if (mon_return && low_memsize > mon_start) low_memsize = mon_start;
  161. 28484
  162. 28485   /* Return to assembler code to switch to protected mode (if 286), reload
  163. 28486    * selectors and call main().
  164. 28487    */
  165. 28488 }
  166. 28491 /*==========================================================================*
  167. 28492  *                              k_atoi                                      *
  168. 28493  *==========================================================================*/
  169. 28494 PRIVATE int k_atoi(s)
  170. 28495 register char *s;
  171. 28496 {
  172. 28497 /* Convert string to integer. */
  173. 28498
  174. 28499   return strtol(s, (char **) NULL, 10);
  175. 28500 }
  176. 28503 /*==========================================================================*
  177. 28504  *                              k_getenv                                    *
  178. 28505  *==========================================================================*/
  179. 28506 PUBLIC char *k_getenv(name)
  180. 28507 char *name;
  181. 28508 {
  182. 28509 /* Get environment value - kernel version of getenv to avoid setting up the
  183. 28510  * usual environment array.
  184. 28511  */
  185. 28512
  186. 28513   register char *namep;
  187. 28514   register char *envp;
  188. .Ep 396 src/kernel/start.c
  189. 28515
  190. 28516   for (envp = k_environ; *envp != 0;) {
  191. 28517         for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++)
  192. 28518                 ;
  193. 28519         if (*namep == '' && *envp == '=') return(envp + 1);
  194. 28520         while (*envp++ != 0)
  195. 28521                 ;
  196. 28522   }
  197. 28523   return(NIL_PTR);
  198. 28524 }
  199. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  200. src/kernel/system.c    
  201. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  202. 28600 /* This task handles the interface between file system and kernel as well as
  203. 28601  * between memory manager and kernel.  System services are obtained by sending
  204. 28602  * sys_task() a message specifying what is needed.  To make life easier for
  205. 28603  * MM and FS, a library is provided with routines whose names are of the
  206. 28604  * form sys_xxx, e.g. sys_xit sends the SYS_XIT message to sys_task.  The
  207. 28605  * message types and parameters are:
  208. 28606  *
  209. 28607  *   SYS_FORK    informs kernel that a process has forked
  210. 28608  *   SYS_NEWMAP  allows MM to set up a process memory map
  211. 28609  *   SYS_GETMAP  allows MM to get a process' memory map
  212. 28610  *   SYS_EXEC    sets program counter and stack pointer after EXEC
  213. 28611  *   SYS_XIT     informs kernel that a process has exited
  214. 28612  *   SYS_GETSP   caller wants to read out some process' stack pointer
  215. 28613  *   SYS_TIMES   caller wants to get accounting times for a process
  216. 28614  *   SYS_ABORT   MM or FS cannot go on; abort MINIX
  217. 28615  *   SYS_FRESH   start with a fresh process image during EXEC (68000 only)
  218. 28616  *   SYS_SENDSIG send a signal to a process (POSIX style)
  219. 28617  *   SYS_SIGRETURN complete POSIX-style signalling
  220. 28618  *   SYS_KILL    cause a signal to be sent via MM
  221. 28619  *   SYS_ENDSIG  finish up after SYS_KILL-type signal
  222. 28620  *   SYS_COPY    request a block of data to be copied between processes
  223. 28621  *   SYS_VCOPY   request a series of data blocks to be copied between procs
  224. 28622  *   SYS_GBOOT   copies the boot parameters to a process
  225. 28623  *   SYS_MEM     returns the next free chunk of physical memory
  226. 28624  *   SYS_UMAP    compute the physical address for a given virtual address
  227. 28625  *   SYS_TRACE   request a trace operation
  228. 28626  *
  229. 28627  * Message types and parameters:
  230. 28628  *
  231. 28629  *    m_type       PROC1     PROC2      PID     MEM_PTR
  232. 28630  * ------------------------------------------------------
  233. 28631  * | SYS_FORK   | parent  |  child  |   pid   |         |
  234. 28632  * |------------+---------+---------+---------+---------|
  235. 28633  * | SYS_NEWMAP | proc nr |         |         | map ptr |
  236. 28634  * |------------+---------+---------+---------+---------|
  237. 28635  * | SYS_EXEC   | proc nr | traced  | new sp  |         |
  238. 28636  * |------------+---------+---------+---------+---------|
  239. 28637  * | SYS_XIT    | parent  | exitee  |         |         |
  240. 28638  * |------------+---------+---------+---------+---------|
  241. 28639  * | SYS_GETSP  | proc nr |         |         |         |
  242. .Op 397 src/kernel/system.c
  243. 28640  * |------------+---------+---------+---------+---------|
  244. 28641  * | SYS_TIMES  | proc nr |         | buf ptr |         |
  245. 28642  * |------------+---------+---------+---------+---------|
  246. 28643  * | SYS_ABORT  |         |         |         |         |
  247. 28644  * |------------+---------+---------+---------+---------|
  248. 28645  * | SYS_FRESH  | proc nr | data_cl |         |         |
  249. 28646  * |------------+---------+---------+---------+---------|
  250. 28647  * | SYS_GBOOT  | proc nr |         |         | bootptr |
  251. 28648  * |------------+---------+---------+---------+---------|
  252. 28649  * | SYS_GETMAP | proc nr |         |         | map ptr |
  253. 28650  * ------------------------------------------------------
  254. 28651  *
  255. 28652  *    m_type          m1_i1     m1_i2     m1_i3       m1_p1
  256. 28653  * ----------------+---------+---------+---------+--------------
  257. 28654  * | SYS_VCOPY     |  src p  |  dst p  | vec siz | vc addr     |
  258. 28655  * |---------------+---------+---------+---------+-------------|
  259. 28656  * | SYS_SENDSIG   | proc nr |         |         | smp         |
  260. 28657  * |---------------+---------+---------+---------+-------------|
  261. 28658  * | SYS_SIGRETURN | proc nr |         |         | scp         |
  262. 28659  * |---------------+---------+---------+---------+-------------|
  263. 28660  * | SYS_ENDSIG    | proc nr |         |         |             |
  264. 28661  * -------------------------------------------------------------
  265. 28662  *
  266. 28663  *    m_type       m2_i1     m2_i2     m2_l1     m2_l2
  267. 28664  * ------------------------------------------------------
  268. 28665  * | SYS_TRACE  | proc_nr | request |  addr   |  data   |
  269. 28666  * ------------------------------------------------------
  270. 28667  *
  271. 28668  *
  272. 28669  *    m_type       m6_i1     m6_i2     m6_i3     m6_f1
  273. 28670  * ------------------------------------------------------
  274. 28671  * | SYS_KILL   | proc_nr  |  sig    |         |         |
  275. 28672  * ------------------------------------------------------
  276. 28673  *
  277. 28674  *
  278. 28675  *    m_type      m5_c1   m5_i1    m5_l1   m5_c2   m5_i2    m5_l2   m5_l3
  279. 28676  * --------------------------------------------------------------------------
  280. 28677  * | SYS_COPY   |src seg|src proc|src vir|dst seg|dst proc|dst vir| byte ct |
  281. 28678  * --------------------------------------------------------------------------
  282. 28679  * | SYS_UMAP   |  seg  |proc nr |vir adr|       |        |       | byte ct |
  283. 28680  * --------------------------------------------------------------------------
  284. 28681  *
  285. 28682  *
  286. 28683  *    m_type      m1_i1      m1_i2      m1_i3
  287. 28684  * |------------+----------+----------+----------
  288. 28685  * | SYS_MEM    | mem base | mem size | tot mem |
  289. 28686  * ----------------------------------------------
  290. 28687  *
  291. 28688  * In addition to the main sys_task() entry point, there are 5 other minor
  292. 28689  * entry points:
  293. 28690  *   cause_sig: take action to cause a signal to occur, sooner or later
  294. 28691  *   inform:    tell MM about pending signals
  295. 28692  *   numap:     umap D segment starting from process number instead of pointer
  296. 28693  *   umap:      compute the physical address for a given virtual address
  297. 28694  *   alloc_segments: allocate segments for 8088 or higher processor
  298. 28695  */
  299. 28696
  300. 28697 #include "kernel.h"
  301. 28698 #include <signal.h>
  302. 28699 #include <unistd.h>
  303. .Ep 398 src/kernel/system.c
  304. 28700 #include <sys/sigcontext.h>
  305. 28701 #include <sys/ptrace.h>
  306. 28702 #include <minix/boot.h>
  307. 28703 #include <minix/callnr.h>
  308. 28704 #include <minix/com.h>
  309. 28705 #include "proc.h"
  310. 28706 #if (CHIP == INTEL)
  311. 28707 #include "protect.h"
  312. 28708 #endif
  313. 28709
  314. 28710 /* PSW masks. */
  315. 28711 #define IF_MASK 0x00000200
  316. 28712 #define IOPL_MASK 0x003000
  317. 28713
  318. 28714 PRIVATE message m;
  319. 28715
  320. 28716 FORWARD _PROTOTYPE( int do_abort, (message *m_ptr) );
  321. 28717 FORWARD _PROTOTYPE( int do_copy, (message *m_ptr) );
  322. 28718 FORWARD _PROTOTYPE( int do_exec, (message *m_ptr) );
  323. 28719 FORWARD _PROTOTYPE( int do_fork, (message *m_ptr) );
  324. 28720 FORWARD _PROTOTYPE( int do_gboot, (message *m_ptr) );
  325. 28721 FORWARD _PROTOTYPE( int do_getsp, (message *m_ptr) );
  326. 28722 FORWARD _PROTOTYPE( int do_kill, (message *m_ptr) );
  327. 28723 FORWARD _PROTOTYPE( int do_mem, (message *m_ptr) );
  328. 28724 FORWARD _PROTOTYPE( int do_newmap, (message *m_ptr) );
  329. 28725 FORWARD _PROTOTYPE( int do_sendsig, (message *m_ptr) );
  330. 28726 FORWARD _PROTOTYPE( int do_sigreturn, (message *m_ptr) );
  331. 28727 FORWARD _PROTOTYPE( int do_endsig, (message *m_ptr) );
  332. 28728 FORWARD _PROTOTYPE( int do_times, (message *m_ptr) );
  333. 28729 FORWARD _PROTOTYPE( int do_trace, (message *m_ptr) );
  334. 28730 FORWARD _PROTOTYPE( int do_umap, (message *m_ptr) );
  335. 28731 FORWARD _PROTOTYPE( int do_xit, (message *m_ptr) );
  336. 28732 FORWARD _PROTOTYPE( int do_vcopy, (message *m_ptr) );
  337. 28733 FORWARD _PROTOTYPE( int do_getmap, (message *m_ptr) );
  338. 28734
  339. 28735 #if (SHADOWING == 1)
  340. 28736 FORWARD _PROTOTYPE( int do_fresh, (message *m_ptr) );
  341. 28737 #endif
  342. 28738
  343. 28739 /*===========================================================================*
  344. 28740  *                              sys_task                                     *
  345. 28741  *===========================================================================*/
  346. 28742 PUBLIC void sys_task()
  347. 28743 {
  348. 28744 /* Main entry point of sys_task.  Get the message and dispatch on type. */
  349. 28745
  350. 28746   register int r;
  351. 28747
  352. 28748   while (TRUE) {
  353. 28749         receive(ANY, &m);
  354. 28750
  355. 28751         switch (m.m_type) {     /* which system call */
  356. 28752             case SYS_FORK:      r = do_fork(&m);        break;
  357. 28753             case SYS_NEWMAP:    r = do_newmap(&m);      break;
  358. 28754             case SYS_GETMAP:    r = do_getmap(&m);      break;
  359. 28755             case SYS_EXEC:      r = do_exec(&m);        break;
  360. 28756             case SYS_XIT:       r = do_xit(&m);         break;
  361. 28757             case SYS_GETSP:     r = do_getsp(&m);       break;
  362. 28758             case SYS_TIMES:     r = do_times(&m);       break;
  363. 28759             case SYS_ABORT:     r = do_abort(&m);       break;
  364. .Op 399 src/kernel/system.c
  365. 28760 #if (SHADOWING == 1)
  366. 28761             case SYS_FRESH:     r = do_fresh(&m);       break;
  367. 28762 #endif
  368. 28763             case SYS_SENDSIG:   r = do_sendsig(&m);     break;
  369. 28764             case SYS_SIGRETURN: r = do_sigreturn(&m);   break;
  370. 28765             case SYS_KILL:      r = do_kill(&m);        break;
  371. 28766             case SYS_ENDSIG:    r = do_endsig(&m);      break;
  372. 28767             case SYS_COPY:      r = do_copy(&m);        break;
  373. 28768             case SYS_VCOPY:     r = do_vcopy(&m);       break;
  374. 28769             case SYS_GBOOT:     r = do_gboot(&m);       break;
  375. 28770             case SYS_MEM:       r = do_mem(&m);         break;
  376. 28771             case SYS_UMAP:      r = do_umap(&m);        break;
  377. 28772             case SYS_TRACE:     r = do_trace(&m);       break;
  378. 28773             default:            r = E_BAD_FCN;
  379. 28774         }
  380. 28775
  381. 28776         m.m_type = r;           /* 'r' reports status of call */
  382. 28777         send(m.m_source, &m);   /* send reply to caller */
  383. 28778   }
  384. 28779 }
  385. 28782 /*===========================================================================*
  386. 28783  *                              do_fork                                      *
  387. 28784  *===========================================================================*/
  388. 28785 PRIVATE int do_fork(m_ptr)
  389. 28786 register message *m_ptr;        /* pointer to request message */
  390. 28787 {
  391. 28788 /* Handle sys_fork().  m_ptr->PROC1 has forked.  The child is m_ptr->PROC2. */
  392. 28789
  393. 28790 #if (CHIP == INTEL)
  394. 28791   reg_t old_ldt_sel;
  395. 28792 #endif
  396. 28793   register struct proc *rpc;
  397. 28794   struct proc *rpp;
  398. 28795
  399. 28796   if (!isoksusern(m_ptr->PROC1) || !isoksusern(m_ptr->PROC2))
  400. 28797         return(E_BAD_PROC);
  401. 28798   rpp = proc_addr(m_ptr->PROC1);
  402. 28799   rpc = proc_addr(m_ptr->PROC2);
  403. 28800
  404. 28801   /* Copy parent 'proc' struct to child. */
  405. 28802 #if (CHIP == INTEL)
  406. 28803   old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */
  407. 28804 #endif
  408. 28805
  409. 28806   *rpc = *rpp;                  /* copy 'proc' struct */
  410. 28807
  411. 28808 #if (CHIP == INTEL)
  412. 28809   rpc->p_ldt_sel = old_ldt_sel;
  413. 28810 #endif
  414. 28811   rpc->p_nr = m_ptr->PROC2;     /* this was obliterated by copy */
  415. 28812
  416. 28813 #if (SHADOWING == 0)
  417. 28814   rpc->p_flags |= NO_MAP;       /* inhibit the process from running */
  418. 28815 #endif
  419. 28816
  420. 28817   rpc->p_flags &= ~(PENDING | SIG_PENDING | P_STOP);
  421. 28818
  422. 28819   /* Only 1 in group should have PENDING, child does not inherit trace status*/
  423. .Ep 400 src/kernel/system.c
  424. 28820   sigemptyset(&rpc->p_pending);
  425. 28821   rpc->p_pendcount = 0;
  426. 28822   rpc->p_pid = m_ptr->PID;      /* install child's pid */
  427. 28823   rpc->p_reg.retreg = 0;        /* child sees pid = 0 to know it is child */
  428. 28824
  429. 28825   rpc->user_time = 0;           /* set all the accounting times to 0 */
  430. 28826   rpc->sys_time = 0;
  431. 28827   rpc->child_utime = 0;
  432. 28828   rpc->child_stime = 0;
  433. 28829
  434. 28830 #if (SHADOWING == 1)
  435. 28831   rpc->p_nflips = 0;
  436. 28832   mkshadow(rpp, (phys_clicks)m_ptr->m1_p1);     /* run child first */
  437. 28833 #endif
  438. 28834
  439. 28835   return(OK);
  440. 28836 }
  441. 28839 /*===========================================================================*
  442. 28840  *                              do_newmap                                    *
  443. 28841  *===========================================================================*/
  444. 28842 PRIVATE int do_newmap(m_ptr)
  445. 28843 message *m_ptr;                 /* pointer to request message */
  446. 28844 {
  447. 28845 /* Handle sys_newmap().  Fetch the memory map from MM. */
  448. 28846
  449. 28847   register struct proc *rp;
  450. 28848   phys_bytes src_phys;
  451. 28849   int caller;                   /* whose space has the new map (usually MM) */
  452. 28850   int k;                        /* process whose map is to be loaded */
  453. 28851   int old_flags;                /* value of flags before modification */
  454. 28852   struct mem_map *map_ptr;      /* virtual address of map inside caller (MM) */
  455. 28853
  456. 28854   /* Extract message parameters and copy new memory map from MM. */
  457. 28855   caller = m_ptr->m_source;
  458. 28856   k = m_ptr->PROC1;
  459. 28857   map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
  460. 28858   if (!isokprocn(k)) return(E_BAD_PROC);
  461. 28859   rp = proc_addr(k);            /* ptr to entry of user getting new map */
  462. 28860
  463. 28861   /* Copy the map from MM. */
  464. 28862   src_phys = umap(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
  465. 28863   if (src_phys == 0) panic("bad call to sys_newmap", NO_NUM);
  466. 28864   phys_copy(src_phys, vir2phys(rp->p_map), (phys_bytes) sizeof(rp->p_map));
  467. 28865
  468. 28866 #if (SHADOWING == 0)
  469. 28867 #if (CHIP != M68000)
  470. 28868   alloc_segments(rp);
  471. 28869 #else
  472. 28870   pmmu_init_proc(rp);
  473. 28871 #endif
  474. 28872   old_flags = rp->p_flags;      /* save the previous value of the flags */
  475. 28873   rp->p_flags &= ~NO_MAP;
  476. 28874   if (old_flags != 0 && rp->p_flags == 0) lock_ready(rp);
  477. 28875 #endif
  478. 28876
  479. 28877   return(OK);
  480. 28878 }
  481. .Op 401 src/kernel/system.c
  482. 28881 /*===========================================================================*
  483. 28882  *                              do_getmap                                    *
  484. 28883  *===========================================================================*/
  485. 28884 PRIVATE int do_getmap(m_ptr)
  486. 28885 message *m_ptr;                 /* pointer to request message */
  487. 28886 {
  488. 28887 /* Handle sys_getmap().  Report the memory map to MM. */
  489. 28888
  490. 28889   register struct proc *rp;
  491. 28890   phys_bytes dst_phys;
  492. 28891   int caller;                   /* where the map has to be stored */
  493. 28892   int k;                        /* process whose map is to be loaded */
  494. 28893   struct mem_map *map_ptr;      /* virtual address of map inside caller (MM) */
  495. 28894
  496. 28895   /* Extract message parameters and copy new memory map to MM. */
  497. 28896   caller = m_ptr->m_source;
  498. 28897   k = m_ptr->PROC1;
  499. 28898   map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
  500. 28899
  501. 28900   if (!isokprocn(k))
  502. 28901         panic("do_getmap got bad proc: ", m_ptr->PROC1);
  503. 28902
  504. 28903   rp = proc_addr(k);            /* ptr to entry of the map */
  505. 28904
  506. 28905   /* Copy the map to MM. */
  507. 28906   dst_phys = umap(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
  508. 28907   if (dst_phys == 0) panic("bad call to sys_getmap", NO_NUM);
  509. 28908   phys_copy(vir2phys(rp->p_map), dst_phys, sizeof(rp->p_map));
  510. 28909
  511. 28910   return(OK);
  512. 28911 }
  513. 28914 /*===========================================================================*
  514. 28915  *                              do_exec                                      *
  515. 28916  *===========================================================================*/
  516. 28917 PRIVATE int do_exec(m_ptr)
  517. 28918 register message *m_ptr;        /* pointer to request message */
  518. 28919 {
  519. 28920 /* Handle sys_exec().  A process has done a successful EXEC. Patch it up. */
  520. 28921
  521. 28922   register struct proc *rp;
  522. 28923   reg_t sp;                     /* new sp */
  523. 28924   phys_bytes phys_name;
  524. 28925   char *np;
  525. 28926 #define NLEN (sizeof(rp->p_name)-1)
  526. 28927
  527. 28928   if (!isoksusern(m_ptr->PROC1)) return E_BAD_PROC;
  528. 28929   /* PROC2 field is used as flag to indicate process is being traced */
  529. 28930   if (m_ptr->PROC2) cause_sig(m_ptr->PROC1, SIGTRAP);
  530. 28931   sp = (reg_t) m_ptr->STACK_PTR;
  531. 28932   rp = proc_addr(m_ptr->PROC1);
  532. 28933   rp->p_reg.sp = sp;            /* set the stack pointer */
  533. 28934 #if (CHIP == M68000)
  534. 28935   rp->p_splow = sp;             /* set the stack pointer low water */
  535. 28936 #ifdef FPP
  536. 28937   /* Initialize fpp for this process */
  537. 28938   fpp_new_state(rp);
  538. 28939 #endif
  539. .Ep 402 src/kernel/system.c
  540. 28940 #endif
  541. 28941   rp->p_reg.pc = (reg_t) m_ptr->IP_PTR; /* set pc */
  542. 28942   rp->p_alarm = 0;              /* reset alarm timer */
  543. 28943   rp->p_flags &= ~RECEIVING;    /* MM does not reply to EXEC call */
  544. 28944   if (rp->p_flags == 0) lock_ready(rp);
  545. 28945
  546. 28946   /* Save command name for debugging, ps(1) output, etc. */
  547. 28947   phys_name = numap(m_ptr->m_source, (vir_bytes) m_ptr->NAME_PTR,
  548. 28948                                                         (vir_bytes) NLEN);
  549. 28949   if (phys_name != 0) {
  550. 28950         phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) NLEN);
  551. 28951         for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
  552. 28952         *np = 0;
  553. 28953   }
  554. 28954   return(OK);
  555. 28955 }
  556. 28958 /*===========================================================================*
  557. 28959  *                              do_xit                                       *
  558. 28960  *===========================================================================*/
  559. 28961 PRIVATE int do_xit(m_ptr)
  560. 28962 message *m_ptr;                 /* pointer to request message */
  561. 28963 {
  562. 28964 /* Handle sys_xit().  A process has exited. */
  563. 28965
  564. 28966   register struct proc *rp, *rc;
  565. 28967   struct proc *np, *xp;
  566. 28968   int parent;                   /* number of exiting proc's parent */
  567. 28969   int proc_nr;                  /* number of process doing the exit */
  568. 28970   phys_clicks base, size;
  569. 28971
  570. 28972   parent = m_ptr->PROC1;        /* slot number of parent process */
  571. 28973   proc_nr = m_ptr->PROC2;       /* slot number of exiting process */
  572. 28974   if (!isoksusern(parent) || !isoksusern(proc_nr)) return(E_BAD_PROC);
  573. 28975   rp = proc_addr(parent);
  574. 28976   rc = proc_addr(proc_nr);
  575. 28977   lock();
  576. 28978   rp->child_utime += rc->user_time + rc->child_utime;   /* accum child times */
  577. 28979   rp->child_stime += rc->sys_time + rc->child_stime;
  578. 28980   unlock();
  579. 28981   rc->p_alarm = 0;              /* turn off alarm timer */
  580. 28982   if (rc->p_flags == 0) lock_unready(rc);
  581. 28983
  582. 28984 #if (SHADOWING == 1)
  583. 28985   rmshadow(rc, &base, &size);
  584. 28986   m_ptr->m1_i1 = (int)base;
  585. 28987   m_ptr->m1_i2 = (int)size;
  586. 28988 #endif
  587. 28989
  588. 28990   strcpy(rc->p_name, "<noname>");       /* process no longer has a name */
  589. 28991
  590. 28992   /* If the process being terminated happens to be queued trying to send a
  591. 28993    * message (i.e., the process was killed by a signal, rather than it doing an
  592. 28994    * EXIT), then it must be removed from the message queues.
  593. 28995    */
  594. 28996   if (rc->p_flags & SENDING) {
  595. 28997         /* Check all proc slots to see if the exiting process is queued. */
  596. 28998         for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
  597. 28999                 if (rp->p_callerq == NIL_PROC) continue;
  598. .Op 403 src/kernel/system.c
  599. 29000                 if (rp->p_callerq == rc) {
  600. 29001                         /* Exiting process is on front of this queue. */
  601. 29002                         rp->p_callerq = rc->p_sendlink;
  602. 29003                         break;
  603. 29004                 } else {
  604. 29005                         /* See if exiting process is in middle of queue. */
  605. 29006                         np = rp->p_callerq;
  606. 29007                         while ( ( xp = np->p_sendlink) != NIL_PROC)
  607. 29008                                 if (xp == rc) {
  608. 29009                                         np->p_sendlink = xp->p_sendlink;
  609. 29010                                         break;
  610. 29011                                 } else {
  611. 29012                                         np = xp;
  612. 29013                                 }
  613. 29014                 }
  614. 29015         }
  615. 29016   }
  616. 29017 #if (CHIP == M68000) && (SHADOWING == 0)
  617. 29018   pmmu_delete(rc);      /* we're done remove tables */
  618. 29019 #endif
  619. 29020
  620. 29021   if (rc->p_flags & PENDING) --sig_procs;
  621. 29022   sigemptyset(&rc->p_pending);
  622. 29023   rc->p_pendcount = 0;
  623. 29024   rc->p_flags = P_SLOT_FREE;
  624. 29025   return(OK);
  625. 29026 }
  626. 29029 /*===========================================================================*
  627. 29030  *                              do_getsp                                     *
  628. 29031  *===========================================================================*/
  629. 29032 PRIVATE int do_getsp(m_ptr)
  630. 29033 register message *m_ptr;        /* pointer to request message */
  631. 29034 {
  632. 29035 /* Handle sys_getsp().  MM wants to know what sp is. */
  633. 29036
  634. 29037   register struct proc *rp;
  635. 29038
  636. 29039   if (!isoksusern(m_ptr->PROC1)) return(E_BAD_PROC);
  637. 29040   rp = proc_addr(m_ptr->PROC1);
  638. 29041   m_ptr->STACK_PTR = (char *) rp->p_reg.sp;     /* return sp here (bad type) */
  639. 29042   return(OK);
  640. 29043 }
  641. 29046 /*===========================================================================*
  642. 29047  *                              do_times                                     *
  643. 29048  *===========================================================================*/
  644. 29049 PRIVATE int do_times(m_ptr)
  645. 29050 register message *m_ptr;        /* pointer to request message */
  646. 29051 {
  647. 29052 /* Handle sys_times().  Retrieve the accounting information. */
  648. 29053
  649. 29054   register struct proc *rp;
  650. 29055
  651. 29056   if (!isoksusern(m_ptr->PROC1)) return E_BAD_PROC;
  652. 29057   rp = proc_addr(m_ptr->PROC1);
  653. 29058
  654. 29059   /* Insert the times needed by the TIMES system call in the message. */
  655. .Ep 404 src/kernel/system.c
  656. 29060   lock();                       /* halt the volatile time counters in rp */
  657. 29061   m_ptr->USER_TIME   = rp->user_time;
  658. 29062   m_ptr->SYSTEM_TIME = rp->sys_time;
  659. 29063   unlock();
  660. 29064   m_ptr->CHILD_UTIME = rp->child_utime;
  661. 29065   m_ptr->CHILD_STIME = rp->child_stime;
  662. 29066   m_ptr->BOOT_TICKS  = get_uptime();
  663. 29067   return(OK);
  664. 29068 }
  665. 29071 /*===========================================================================*
  666. 29072  *                              do_abort                                     *
  667. 29073  *===========================================================================*/
  668. 29074 PRIVATE int do_abort(m_ptr)
  669. 29075 message *m_ptr;                 /* pointer to request message */
  670. 29076 {
  671. 29077 /* Handle sys_abort.  MINIX is unable to continue.  Terminate operation. */
  672. 29078   char monitor_code[64];
  673. 29079   phys_bytes src_phys;
  674. 29080
  675. 29081   if (m_ptr->m1_i1 == RBT_MONITOR) {
  676. 29082         /* The monitor is to run user specified instructions. */
  677. 29083         src_phys = numap(m_ptr->m_source, (vir_bytes) m_ptr->m1_p1,
  678. 29084                                         (vir_bytes) sizeof(monitor_code));
  679. 29085         if (src_phys == 0) panic("bad monitor code from", m_ptr->m_source);
  680. 29086         phys_copy(src_phys, vir2phys(monitor_code),
  681. 29087                                         (phys_bytes) sizeof(monitor_code));
  682. 29088         reboot_code = vir2phys(monitor_code);
  683. 29089   }
  684. 29090   wreboot(m_ptr->m1_i1);
  685. 29091   return(OK);                   /* pro-forma (really EDISASTER) */
  686. 29092 }
  687. 29095 #if (SHADOWING == 1)
  688. 29096 /*===========================================================================*
  689. 29097  *                              do_fresh                                     *
  690. 29098  *===========================================================================*/
  691. 29099 PRIVATE int do_fresh(m_ptr)     /* for 68000 only */
  692. 29100 message *m_ptr;                 /* pointer to request message */
  693. 29101 {
  694. 29102 /* Handle sys_fresh.  Start with fresh process image during EXEC. */
  695. 29103
  696. 29104   register struct proc *p;
  697. 29105   int proc_nr;                  /* number of process doing the exec */
  698. 29106   phys_clicks base, size;
  699. 29107   phys_clicks c1, nc;
  700. 29108
  701. 29109   proc_nr = m_ptr->PROC1;       /* slot number of exec-ing process */
  702. 29110   if (!isokprocn(proc_nr)) return(E_BAD_PROC);
  703. 29111   p = proc_addr(proc_nr);
  704. 29112   rmshadow(p, &base, &size);
  705. 29113   do_newmap(m_ptr);
  706. 29114   c1 = p->p_map[D].mem_phys;
  707. 29115   nc = p->p_map[S].mem_phys - p->p_map[D].mem_phys + p->p_map[S].mem_len;
  708. 29116   c1 += m_ptr->m1_i2;
  709. 29117   nc -= m_ptr->m1_i2;
  710. 29118   zeroclicks(c1, nc);
  711. 29119   m_ptr->m1_i1 = (int)base;
  712. .Op 405 src/kernel/system.c
  713. 29120   m_ptr->m1_i2 = (int)size;
  714. 29121   return(OK);
  715. 29122 }
  716. 29123 #endif /* (SHADOWING == 1) */
  717. 29124
  718. 29125
  719. 29126 /*===========================================================================*
  720. 29127  *                            do_sendsig                                     *
  721. 29128  *===========================================================================*/
  722. 29129 PRIVATE int do_sendsig(m_ptr)
  723. 29130 message *m_ptr;                 /* pointer to request message */
  724. 29131 {
  725. 29132 /* Handle sys_sendsig, POSIX-style signal */
  726. 29133
  727. 29134   struct sigmsg smsg;
  728. 29135   register struct proc *rp;
  729. 29136   phys_bytes src_phys, dst_phys;
  730. 29137   struct sigcontext sc, *scp;
  731. 29138   struct sigframe fr, *frp;
  732. 29139
  733. 29140   if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
  734. 29141   rp = proc_addr(m_ptr->PROC1);
  735. 29142
  736. 29143   /* Get the sigmsg structure into our address space.  */
  737. 29144   src_phys = umap(proc_addr(MM_PROC_NR), D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
  738. 29145                   (vir_bytes) sizeof(struct sigmsg));
  739. 29146   if (src_phys == 0)
  740. 29147         panic("do_sendsig can't signal: bad sigmsg address from MM", NO_NUM);
  741. 29148   phys_copy(src_phys, vir2phys(&smsg), (phys_bytes) sizeof(struct sigmsg));
  742. 29149
  743. 29150   /* Compute the usr stack pointer value where sigcontext will be stored. */
  744. 29151   scp = (struct sigcontext *) smsg.sm_stkptr - 1;
  745. 29152
  746. 29153   /* Copy the registers to the sigcontext structure. */
  747. 29154   memcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs));
  748. 29155
  749. 29156   /* Finish the sigcontext initialization. */
  750. 29157   sc.sc_flags = SC_SIGCONTEXT;
  751. 29158
  752. 29159   sc.sc_mask = smsg.sm_mask;
  753. 29160
  754. 29161   /* Copy the sigcontext structure to the user's stack. */
  755. 29162   dst_phys = umap(rp, D, (vir_bytes) scp,
  756. 29163                   (vir_bytes) sizeof(struct sigcontext));
  757. 29164   if (dst_phys == 0) return(EFAULT);
  758. 29165   phys_copy(vir2phys(&sc), dst_phys, (phys_bytes) sizeof(struct sigcontext));
  759. 29166
  760. 29167   /* Initialize the sigframe structure. */
  761. 29168   frp = (struct sigframe *) scp - 1;
  762. 29169   fr.sf_scpcopy = scp;
  763. 29170   fr.sf_retadr2= (void (*)()) rp->p_reg.pc;
  764. 29171   fr.sf_fp = rp->p_reg.fp;
  765. 29172   rp->p_reg.fp = (reg_t) &frp->sf_fp;
  766. 29173   fr.sf_scp = scp;
  767. 29174   fr.sf_code = 0;       /* XXX - should be used for type of FP exception */
  768. 29175   fr.sf_signo = smsg.sm_signo;
  769. 29176   fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
  770. 29177
  771. 29178   /* Copy the sigframe structure to the user's stack. */
  772. 29179   dst_phys = umap(rp, D, (vir_bytes) frp, (vir_bytes) sizeof(struct sigframe));
  773. .Ep 406 src/kernel/system.c
  774. 29180   if (dst_phys == 0) return(EFAULT);
  775. 29181   phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
  776. 29182
  777. 29183   /* Reset user registers to execute the signal handler. */
  778. 29184   rp->p_reg.sp = (reg_t) frp;
  779. 29185   rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
  780. 29186
  781. 29187   return(OK);
  782. 29188 }
  783. 29190 /*===========================================================================*
  784. 29191  *                            do_sigreturn                                   *
  785. 29192  *===========================================================================*/
  786. 29193 PRIVATE int do_sigreturn(m_ptr)
  787. 29194 register message *m_ptr;
  788. 29195 {
  789. 29196 /* POSIX style signals require sys_sigreturn to put things in order before the
  790. 29197  * signalled process can resume execution
  791. 29198  */
  792. 29199
  793. 29200   struct sigcontext sc;
  794. 29201   register struct proc *rp;
  795. 29202   phys_bytes src_phys;
  796. 29203
  797. 29204   if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
  798. 29205   rp = proc_addr(m_ptr->PROC1);
  799. 29206
  800. 29207   /* Copy in the sigcontext structure. */
  801. 29208   src_phys = umap(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
  802. 29209                   (vir_bytes) sizeof(struct sigcontext));
  803. 29210   if (src_phys == 0) return(EFAULT);
  804. 29211   phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext));
  805. 29212
  806. 29213   /* Make sure that this is not just a jmp_buf. */
  807. 29214   if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL);
  808. 29215
  809. 29216   /* Fix up only certain key registers if the compiler doesn't use
  810. 29217    * register variables within functions containing setjmp.
  811. 29218    */
  812. 29219   if (sc.sc_flags & SC_NOREGLOCALS) {
  813. 29220         rp->p_reg.retreg = sc.sc_retreg;
  814. 29221         rp->p_reg.fp = sc.sc_fp;
  815. 29222         rp->p_reg.pc = sc.sc_pc;
  816. 29223         rp->p_reg.sp = sc.sc_sp;
  817. 29224         return (OK);
  818. 29225   }
  819. 29226   sc.sc_psw  = rp->p_reg.psw;
  820. 29227
  821. 29228 #if (CHIP == INTEL)
  822. 29229   /* Don't panic kernel if user gave bad selectors. */
  823. 29230   sc.sc_cs = rp->p_reg.cs;
  824. 29231   sc.sc_ds = rp->p_reg.ds;
  825. 29232   sc.sc_es = rp->p_reg.es;
  826. 29233 #if _WORD_SIZE == 4
  827. 29234   sc.sc_fs = rp->p_reg.fs;
  828. 29235   sc.sc_gs = rp->p_reg.gs;
  829. 29236 #endif
  830. 29237 #endif
  831. 29238
  832. 29239   /* Restore the registers. */
  833. .Op 407 src/kernel/system.c
  834. 29240   memcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
  835. 29241
  836. 29242   return(OK);
  837. 29243 }
  838. 29245 /*===========================================================================*
  839. 29246  *                              do_kill                                      *
  840. 29247  *===========================================================================*/
  841. 29248 PRIVATE int do_kill(m_ptr)
  842. 29249 register message *m_ptr;        /* pointer to request message */
  843. 29250 {
  844. 29251 /* Handle sys_kill(). Cause a signal to be sent to a process via MM.
  845. 29252  * Note that this has nothing to do with the kill (2) system call, this
  846. 29253  * is how the FS (and possibly other servers) get access to cause_sig to
  847. 29254  * send a KSIG message to MM
  848. 29255  */
  849. 29256
  850. 29257   if (!isokusern(m_ptr->PR)) return(E_BAD_PROC);
  851. 29258   cause_sig(m_ptr->PR, m_ptr->SIGNUM);
  852. 29259   return(OK);
  853. 29260 }
  854. 29263 /*===========================================================================*
  855. 29264  *                            do_endsig                                      *
  856. 29265  *===========================================================================*/
  857. 29266 PRIVATE int do_endsig(m_ptr)
  858. 29267 register message *m_ptr;        /* pointer to request message */
  859. 29268 {
  860. 29269 /* Finish up after a KSIG-type signal, caused by a SYS_KILL message or a call
  861. 29270  * to cause_sig by a task
  862. 29271  */
  863. 29272
  864. 29273   register struct proc *rp;
  865. 29274
  866. 29275   if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
  867. 29276   rp = proc_addr(m_ptr->PROC1);
  868. 29277
  869. 29278   /* MM has finished one KSIG. */
  870. 29279   if (rp->p_pendcount != 0 && --rp->p_pendcount == 0
  871. 29280       && (rp->p_flags &= ~SIG_PENDING) == 0)
  872. 29281         lock_ready(rp);
  873. 29282   return(OK);
  874. 29283 }
  875. 29285 /*===========================================================================*
  876. 29286  *                              do_copy                                      *
  877. 29287  *===========================================================================*/
  878. 29288 PRIVATE int do_copy(m_ptr)
  879. 29289 register message *m_ptr;        /* pointer to request message */
  880. 29290 {
  881. 29291 /* Handle sys_copy().  Copy data for MM or FS. */
  882. 29292
  883. 29293   int src_proc, dst_proc, src_space, dst_space;
  884. 29294   vir_bytes src_vir, dst_vir;
  885. 29295   phys_bytes src_phys, dst_phys, bytes;
  886. 29296
  887. 29297   /* Dismember the command message. */
  888. 29298   src_proc = m_ptr->SRC_PROC_NR;
  889. 29299   dst_proc = m_ptr->DST_PROC_NR;
  890. .Ep 408 src/kernel/system.c
  891. 29300   src_space = m_ptr->SRC_SPACE;
  892. 29301   dst_space = m_ptr->DST_SPACE;
  893. 29302   src_vir = (vir_bytes) m_ptr->SRC_BUFFER;
  894. 29303   dst_vir = (vir_bytes) m_ptr->DST_BUFFER;
  895. 29304   bytes = (phys_bytes) m_ptr->COPY_BYTES;
  896. 29305
  897. 29306   /* Compute the source and destination addresses and do the copy. */
  898. 29307 #if (SHADOWING == 0)
  899. 29308   if (src_proc == ABS)
  900. 29309         src_phys = (phys_bytes) m_ptr->SRC_BUFFER;
  901. 29310   else {
  902. 29311         if (bytes != (vir_bytes) bytes)
  903. 29312                 /* This would happen for 64K segments and 16-bit vir_bytes.
  904. 29313                  * It would happen a lot for do_fork except MM uses ABS
  905. 29314                  * copies for that case.
  906. 29315                  */
  907. 29316                 panic("overflow in count in do_copy", NO_NUM);
  908. 29317 #endif
  909. 29318
  910. 29319         src_phys = umap(proc_addr(src_proc), src_space, src_vir,
  911. 29320                         (vir_bytes) bytes);
  912. 29321 #if (SHADOWING == 0)
  913. 29322         }
  914. 29323 #endif
  915. 29324
  916. 29325 #if (SHADOWING == 0)
  917. 29326   if (dst_proc == ABS)
  918. 29327         dst_phys = (phys_bytes) m_ptr->DST_BUFFER;
  919. 29328   else
  920. 29329 #endif
  921. 29330         dst_phys = umap(proc_addr(dst_proc), dst_space, dst_vir,
  922. 29331                         (vir_bytes) bytes);
  923. 29332
  924. 29333   if (src_phys == 0 || dst_phys == 0) return(EFAULT);
  925. 29334   phys_copy(src_phys, dst_phys, bytes);
  926. 29335   return(OK);
  927. 29336 }
  928. 29339 /*===========================================================================*
  929. 29340  *                              do_vcopy                                     *
  930. 29341  *===========================================================================*/
  931. 29342 PRIVATE int do_vcopy(m_ptr)
  932. 29343 register message *m_ptr;        /* pointer to request message */
  933. 29344 {
  934. 29345 /* Handle sys_vcopy(). Copy multiple blocks of memory */
  935. 29346
  936. 29347   int src_proc, dst_proc, vect_s, i;
  937. 29348   vir_bytes src_vir, dst_vir, vect_addr;
  938. 29349   phys_bytes src_phys, dst_phys, bytes;
  939. 29350   cpvec_t cpvec_table[CPVEC_NR];
  940. 29351
  941. 29352   /* Dismember the command message. */
  942. 29353   src_proc = m_ptr->m1_i1;
  943. 29354   dst_proc = m_ptr->m1_i2;
  944. 29355   vect_s = m_ptr->m1_i3;
  945. 29356   vect_addr = (vir_bytes)m_ptr->m1_p1;
  946. 29357
  947. 29358   if (vect_s > CPVEC_NR) return EDOM;
  948. 29359
  949. .Op 409 src/kernel/system.c
  950. 29360   src_phys= numap (m_ptr->m_source, vect_addr, vect_s * sizeof(cpvec_t));
  951. 29361   if (!src_phys) return EFAULT;
  952. 29362   phys_copy(src_phys, vir2phys(cpvec_table),
  953. 29363                                 (phys_bytes) (vect_s * sizeof(cpvec_t)));
  954. 29364
  955. 29365   for (i = 0; i < vect_s; i++) {
  956. 29366         src_vir= cpvec_table[i].cpv_src;
  957. 29367         dst_vir= cpvec_table[i].cpv_dst;
  958. 29368         bytes= cpvec_table[i].cpv_size;
  959. 29369         src_phys = numap(src_proc,src_vir,(vir_bytes)bytes);
  960. 29370         dst_phys = numap(dst_proc,dst_vir,(vir_bytes)bytes);
  961. 29371         if (src_phys == 0 || dst_phys == 0) return(EFAULT);
  962. 29372         phys_copy(src_phys, dst_phys, bytes);
  963. 29373   }
  964. 29374   return(OK);
  965. 29375 }
  966. 29378 /*==========================================================================*
  967. 29379  *                              do_gboot                                    *
  968. 29380  *==========================================================================*/
  969. 29381 PUBLIC struct bparam_s boot_parameters;
  970. 29382
  971. 29383 PRIVATE int do_gboot(m_ptr)
  972. 29384 message *m_ptr;                 /* pointer to request message */
  973. 29385 {
  974. 29386 /* Copy the boot parameters.  Normally only called during fs init. */
  975. 29387
  976. 29388   phys_bytes dst_phys;
  977. 29389
  978. 29390   dst_phys = umap(proc_addr(m_ptr->PROC1), D, (vir_bytes) m_ptr->MEM_PTR,
  979. 29391                                 (vir_bytes) sizeof(boot_parameters));
  980. 29392   if (dst_phys == 0) panic("bad call to SYS_GBOOT", NO_NUM);
  981. 29393   phys_copy(vir2phys(&boot_parameters), dst_phys,
  982. 29394                                 (phys_bytes) sizeof(boot_parameters));
  983. 29395   return(OK);
  984. 29396 }
  985. 29399 /*===========================================================================*
  986. 29400  *                              do_mem                                       *
  987. 29401  *===========================================================================*/
  988. 29402 PRIVATE int do_mem(m_ptr)
  989. 29403 register message *m_ptr;        /* pointer to request message */
  990. 29404 {
  991. 29405 /* Return the base and size of the next chunk of memory. */
  992. 29406
  993. 29407   struct memory *memp;
  994. 29408
  995. 29409   for (memp = mem; memp < &mem[NR_MEMS]; ++memp) {
  996. 29410         m_ptr->m1_i1 = memp->base;
  997. 29411         m_ptr->m1_i2 = memp->size;
  998. 29412         m_ptr->m1_i3 = tot_mem_size;
  999. 29413         memp->size = 0;
  1000. 29414         if (m_ptr->m1_i2 != 0) break;           /* found a chunk */
  1001. 29415   }
  1002. 29416   return(OK);
  1003. 29417 }
  1004. .Ep 410 src/kernel/system.c
  1005. 29420 /*==========================================================================*
  1006. 29421  *                              do_umap                                     *
  1007. 29422  *==========================================================================*/
  1008. 29423 PRIVATE int do_umap(m_ptr)
  1009. 29424 register message *m_ptr;        /* pointer to request message */
  1010. 29425 {
  1011. 29426 /* Same as umap(), for non-kernel processes. */
  1012. 29427
  1013. 29428   m_ptr->SRC_BUFFER = umap(proc_addr((int) m_ptr->SRC_PROC_NR),
  1014. 29429                            (int) m_ptr->SRC_SPACE,
  1015. 29430                            (vir_bytes) m_ptr->SRC_BUFFER,
  1016. 29431                            (vir_bytes) m_ptr->COPY_BYTES);
  1017. 29432   return(OK);
  1018. 29433 }
  1019. 29436 /*==========================================================================*
  1020. 29437  *                              do_trace                                    *
  1021. 29438  *==========================================================================*/
  1022. 29439 #define TR_PROCNR       (m_ptr->m2_i1)
  1023. 29440 #define TR_REQUEST      (m_ptr->m2_i2)
  1024. 29441 #define TR_ADDR         ((vir_bytes) m_ptr->m2_l1)
  1025. 29442 #define TR_DATA         (m_ptr->m2_l2)
  1026. 29443 #define TR_VLSIZE       ((vir_bytes) sizeof(long))
  1027. 29444
  1028. 29445 PRIVATE int do_trace(m_ptr)
  1029. 29446 register message *m_ptr;
  1030. 29447 {
  1031. 29448 /* Handle the debugging commands supported by the ptrace system call
  1032. 29449  * The commands are:
  1033. 29450  * T_STOP       stop the process
  1034. 29451  * T_OK         enable tracing by parent for this process
  1035. 29452  * T_GETINS     return value from instruction space
  1036. 29453  * T_GETDATA    return value from data space
  1037. 29454  * T_GETUSER    return value from user process table
  1038. 29455  * T_SETINS     set value from instruction space
  1039. 29456  * T_SETDATA    set value from data space
  1040. 29457  * T_SETUSER    set value in user process table
  1041. 29458  * T_RESUME     resume execution
  1042. 29459  * T_EXIT       exit
  1043. 29460  * T_STEP       set trace bit
  1044. 29461  *
  1045. 29462  * The T_OK and T_EXIT commands are handled completely by the memory manager,
  1046. 29463  * all others come here.
  1047. 29464  */
  1048. 29465
  1049. 29466   register struct proc *rp;
  1050. 29467   phys_bytes src, dst;
  1051. 29468   int i;
  1052. 29469
  1053. 29470   rp = proc_addr(TR_PROCNR);
  1054. 29471   if (rp->p_flags & P_SLOT_FREE) return(EIO);
  1055. 29472   switch (TR_REQUEST) {
  1056. 29473   case T_STOP:                  /* stop process */
  1057. 29474         if (rp->p_flags == 0) lock_unready(rp);
  1058. 29475         rp->p_flags |= P_STOP;
  1059. 29476         rp->p_reg.psw &= ~TRACEBIT;     /* clear trace bit */
  1060. 29477         return(OK);
  1061. 29478
  1062. 29479   case T_GETINS:                /* return value from instruction space */
  1063. .Op 411 src/kernel/system.c
  1064. 29480         if (rp->p_map[T].mem_len != 0) {
  1065. 29481                 if ((src = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
  1066. 29482                 phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
  1067. 29483                 break;
  1068. 29484         }
  1069. 29485         /* Text space is actually data space - fall through. */
  1070. 29486
  1071. 29487   case T_GETDATA:               /* return value from data space */
  1072. 29488         if ((src = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
  1073. 29489         phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
  1074. 29490         break;
  1075. 29491
  1076. 29492   case T_GETUSER:               /* return value from process table */
  1077. 29493         if ((TR_ADDR & (sizeof(long) - 1)) != 0 ||
  1078. 29494             TR_ADDR > sizeof(struct proc) - sizeof(long))
  1079. 29495                 return(EIO);
  1080. 29496         TR_DATA = *(long *) ((char *) rp + (int) TR_ADDR);
  1081. 29497         break;
  1082. 29498
  1083. 29499   case T_SETINS:                /* set value in instruction space */
  1084. 29500         if (rp->p_map[T].mem_len != 0) {
  1085. 29501                 if ((dst = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
  1086. 29502                 phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
  1087. 29503                 TR_DATA = 0;
  1088. 29504                 break;
  1089. 29505         }
  1090. 29506         /* Text space is actually data space - fall through. */
  1091. 29507
  1092. 29508   case T_SETDATA:                       /* set value in data space */
  1093. 29509         if ((dst = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
  1094. 29510         phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
  1095. 29511         TR_DATA = 0;
  1096. 29512         break;
  1097. 29513
  1098. 29514   case T_SETUSER:                       /* set value in process table */
  1099. 29515         if ((TR_ADDR & (sizeof(reg_t) - 1)) != 0 ||
  1100. 29516              TR_ADDR > sizeof(struct stackframe_s) - sizeof(reg_t))
  1101. 29517                 return(EIO);
  1102. 29518         i = (int) TR_ADDR;
  1103. 29519 #if (CHIP == INTEL)
  1104. 29520         /* Altering segment registers might crash the kernel when it
  1105. 29521          * tries to load them prior to restarting a process, so do
  1106. 29522          * not allow it.
  1107. 29523          */
  1108. 29524         if (i == (int) &((struct proc *) 0)->p_reg.cs ||
  1109. 29525             i == (int) &((struct proc *) 0)->p_reg.ds ||
  1110. 29526             i == (int) &((struct proc *) 0)->p_reg.es ||
  1111. 29527 #if _WORD_SIZE == 4
  1112. 29528             i == (int) &((struct proc *) 0)->p_reg.gs ||
  1113. 29529             i == (int) &((struct proc *) 0)->p_reg.fs ||
  1114. 29530 #endif
  1115. 29531             i == (int) &((struct proc *) 0)->p_reg.ss)
  1116. 29532                 return(EIO);
  1117. 29533 #endif
  1118. 29534         if (i == (int) &((struct proc *) 0)->p_reg.psw)
  1119. 29535                 /* only selected bits are changeable */
  1120. 29536                 SETPSW(rp, TR_DATA);
  1121. 29537         else
  1122. 29538                 *(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) TR_DATA;
  1123. 29539         TR_DATA = 0;
  1124. .Ep 412 src/kernel/system.c
  1125. 29540         break;
  1126. 29541
  1127. 29542   case T_RESUME:                /* resume execution */
  1128. 29543         rp->p_flags &= ~P_STOP;
  1129. 29544         if (rp->p_flags == 0) lock_ready(rp);
  1130. 29545         TR_DATA = 0;
  1131. 29546         break;
  1132. 29547
  1133. 29548   case T_STEP:                  /* set trace bit */
  1134. 29549         rp->p_reg.psw |= TRACEBIT;
  1135. 29550         rp->p_flags &= ~P_STOP;
  1136. 29551         if (rp->p_flags == 0) lock_ready(rp);
  1137. 29552         TR_DATA = 0;
  1138. 29553         break;
  1139. 29554
  1140. 29555   default:
  1141. 29556         return(EIO);
  1142. 29557   }
  1143. 29558   return(OK);
  1144. 29559 }
  1145. 29561 /*===========================================================================*
  1146. 29562  *                              cause_sig                                    *
  1147. 29563  *===========================================================================*/
  1148. 29564 PUBLIC void cause_sig(proc_nr, sig_nr)
  1149. 29565 int proc_nr;                    /* process to be signalled */
  1150. 29566 int sig_nr;                     /* signal to be sent, 1 to _NSIG */
  1151. 29567 {
  1152. 29568 /* A task wants to send a signal to a process.   Examples of such tasks are:
  1153. 29569  *   TTY wanting to cause SIGINT upon getting a DEL
  1154. 29570  *   CLOCK wanting to cause SIGALRM when timer expires
  1155. 29571  * FS also uses this to send a signal, via the SYS_KILL message.
  1156. 29572  * Signals are handled by sending a message to MM.  The tasks don't dare do
  1157. 29573  * that directly, for fear of what would happen if MM were busy.  Instead they
  1158. 29574  * call cause_sig, which sets bits in p_pending, and then carefully checks to
  1159. 29575  * see if MM is free.  If so, a message is sent to it.  If not, when it becomes
  1160. 29576  * free, a message is sent.  The process being signaled is blocked while MM
  1161. 29577  * has not seen or finished with all signals for it.  These signals are
  1162. 29578  * counted in p_pendcount, and the SIG_PENDING flag is kept nonzero while
  1163. 29579  * there are some.  It is not sufficient to ready the process when MM is
  1164. 29580  * informed, because MM can block waiting for FS to do a core dump.
  1165. 29581  */
  1166. 29582
  1167. 29583   register struct proc *rp, *mmp;
  1168. 29584
  1169. 29585   rp = proc_addr(proc_nr);
  1170. 29586   if (sigismember(&rp->p_pending, sig_nr))
  1171. 29587         return;                 /* this signal already pending */
  1172. 29588   sigaddset(&rp->p_pending, sig_nr);
  1173. 29589   ++rp->p_pendcount;            /* count new signal pending */
  1174. 29590   if (rp->p_flags & PENDING)
  1175. 29591         return;                 /* another signal already pending */
  1176. 29592   if (rp->p_flags == 0) lock_unready(rp);
  1177. 29593   rp->p_flags |= PENDING | SIG_PENDING;
  1178. 29594   ++sig_procs;                  /* count new process pending */
  1179. 29595
  1180. 29596   mmp = proc_addr(MM_PROC_NR);
  1181. 29597   if ( ((mmp->p_flags & RECEIVING) == 0) || mmp->p_getfrom != ANY) return;
  1182. 29598   inform();
  1183. 29599 }
  1184. .Op 413 src/kernel/system.c
  1185. 29602 /*===========================================================================*
  1186. 29603  *                              inform                                       *
  1187. 29604  *===========================================================================*/
  1188. 29605 PUBLIC void inform()
  1189. 29606 {
  1190. 29607 /* When a signal is detected by the kernel (e.g., DEL), or generated by a task
  1191. 29608  * (e.g. clock task for SIGALRM), cause_sig() is called to set a bit in the
  1192. 29609  * p_pending field of the process to signal.  Then inform() is called to see
  1193. 29610  * if MM is idle and can be told about it.  Whenever MM blocks, a check is
  1194. 29611  * made to see if 'sig_procs' is nonzero; if so, inform() is called.
  1195. 29612  */
  1196. 29613
  1197. 29614   register struct proc *rp;
  1198. 29615
  1199. 29616   /* MM is waiting for new input.  Find a process with pending signals. */
  1200. 29617   for (rp = BEG_SERV_ADDR; rp < END_PROC_ADDR; rp++)
  1201. 29618         if (rp->p_flags & PENDING) {
  1202. 29619                 m.m_type = KSIG;
  1203. 29620                 m.SIG_PROC = proc_number(rp);
  1204. 29621                 m.SIG_MAP = rp->p_pending;
  1205. 29622                 sig_procs--;
  1206. 29623                 if (lock_mini_send(proc_addr(HARDWARE), MM_PROC_NR, &m) != OK)
  1207. 29624                         panic("can't inform MM", NO_NUM);
  1208. 29625                 sigemptyset(&rp->p_pending); /* the ball is now in MM's court */
  1209. 29626                 rp->p_flags &= ~PENDING;/* remains inhibited by SIG_PENDING */
  1210. 29627                 lock_pick_proc();       /* avoid delay in scheduling MM */
  1211. 29628                 return;
  1212. 29629         }
  1213. 29630 }
  1214. 29633 /*===========================================================================*
  1215. 29634  *                              umap                                         *
  1216. 29635  *===========================================================================*/
  1217. 29636 PUBLIC phys_bytes umap(rp, seg, vir_addr, bytes)
  1218. 29637 register struct proc *rp;       /* pointer to proc table entry for process */
  1219. 29638 int seg;                        /* T, D, or S segment */
  1220. 29639 vir_bytes vir_addr;             /* virtual address in bytes within the seg */
  1221. 29640 vir_bytes bytes;                /* # of bytes to be copied */
  1222. 29641 {
  1223. 29642 /* Calculate the physical memory address for a given virtual address. */
  1224. 29643
  1225. 29644   vir_clicks vc;                /* the virtual address in clicks */
  1226. 29645   phys_bytes pa;                /* intermediate variables as phys_bytes */
  1227. 29646 #if (CHIP == INTEL)
  1228. 29647   phys_bytes seg_base;
  1229. 29648 #endif
  1230. 29649
  1231. 29650   /* If 'seg' is D it could really be S and vice versa.  T really means T.
  1232. 29651    * If the virtual address falls in the gap,  it causes a problem. On the
  1233. 29652    * 8088 it is probably a legal stack reference, since "stackfaults" are
  1234. 29653    * not detected by the hardware.  On 8088s, the gap is called S and
  1235. 29654    * accepted, but on other machines it is called D and rejected.
  1236. 29655    * The Atari ST behaves like the 8088 in this respect.
  1237. 29656    */
  1238. 29657
  1239. 29658   if (bytes <= 0) return( (phys_bytes) 0);
  1240. 29659   vc = (vir_addr + bytes - 1) >> CLICK_SHIFT;   /* last click of data */
  1241. .Ep 414 src/kernel/system.c
  1242. 29660
  1243. 29661 #if (CHIP == INTEL) || (CHIP == M68000)
  1244. 29662   if (seg != T)
  1245. 29663         seg = (vc < rp->p_map[D].mem_vir + rp->p_map[D].mem_len ? D : S);
  1246. 29664 #else
  1247. 29665   if (seg != T)
  1248. 29666         seg = (vc < rp->p_map[S].mem_vir ? D : S);
  1249. 29667 #endif
  1250. 29668
  1251. 29669   if((vir_addr>>CLICK_SHIFT) >= rp->p_map[seg].mem_vir+ rp->p_map[seg].mem_len)
  1252. 29670         return( (phys_bytes) 0 );
  1253. 29671 #if (CHIP == INTEL)
  1254. 29672   seg_base = (phys_bytes) rp->p_map[seg].mem_phys;
  1255. 29673   seg_base = seg_base << CLICK_SHIFT;   /* segment origin in bytes */
  1256. 29674 #endif
  1257. 29675   pa = (phys_bytes) vir_addr;
  1258. 29676 #if (CHIP != M68000)
  1259. 29677   pa -= rp->p_map[seg].mem_vir << CLICK_SHIFT;
  1260. 29678   return(seg_base + pa);
  1261. 29679 #endif
  1262. 29680 #if (CHIP == M68000)
  1263. 29681 #if (SHADOWING == 0)
  1264. 29682   pa -= (phys_bytes)rp->p_map[seg].mem_vir << CLICK_SHIFT;
  1265. 29683   pa += (phys_bytes)rp->p_map[seg].mem_phys << CLICK_SHIFT;
  1266. 29684 #else
  1267. 29685   if (rp->p_shadow && seg != T) {
  1268. 29686         pa -= (phys_bytes)rp->p_map[D].mem_phys << CLICK_SHIFT;
  1269. 29687         pa += (phys_bytes)rp->p_shadow << CLICK_SHIFT;
  1270. 29688   }
  1271. 29689 #endif
  1272. 29690   return(pa);
  1273. 29691 #endif
  1274. 29692 }
  1275. 29695 /*==========================================================================*
  1276. 29696  *                              numap                                       *
  1277. 29697  *==========================================================================*/
  1278. 29698 PUBLIC phys_bytes numap(proc_nr, vir_addr, bytes)
  1279. 29699 int proc_nr;                    /* process number to be mapped */
  1280. 29700 vir_bytes vir_addr;             /* virtual address in bytes within D seg */
  1281. 29701 vir_bytes bytes;                /* # of bytes required in segment  */
  1282. 29702 {
  1283. 29703 /* Do umap() starting from a process number instead of a pointer.  This
  1284. 29704  * function is used by device drivers, so they need not know about the
  1285. 29705  * process table.  To save time, there is no 'seg' parameter. The segment
  1286. 29706  * is always D.
  1287. 29707  */
  1288. 29708
  1289. 29709   return(umap(proc_addr(proc_nr), D, vir_addr, bytes));
  1290. 29710 }
  1291. 29713 #if (CHIP == INTEL)
  1292. 29714 /*==========================================================================*
  1293. 29715  *                              alloc_segments                              *
  1294. 29716  *==========================================================================*/
  1295. 29717 PUBLIC void alloc_segments(rp)
  1296. 29718 register struct proc *rp;
  1297. 29719 {
  1298. .Op 415 src/kernel/system.c
  1299. 29720 /* This is called only by do_newmap, but is broken out as a separate function
  1300. 29721  * because so much is hardware-dependent.
  1301. 29722  */
  1302. 29723
  1303. 29724   phys_bytes code_bytes;
  1304. 29725   phys_bytes data_bytes;
  1305. 29726   int privilege;
  1306. 29727
  1307. 29728   if (protected_mode) {
  1308. 29729         data_bytes = (phys_bytes) (rp->p_map[S].mem_vir + rp->p_map[S].mem_len)
  1309. 29730                      << CLICK_SHIFT;
  1310. 29731         if (rp->p_map[T].mem_len == 0)
  1311. 29732                 code_bytes = data_bytes;        /* common I&D, poor protect */
  1312. 29733         else
  1313. 29734                 code_bytes = (phys_bytes) rp->p_map[T].mem_len << CLICK_SHIFT;
  1314. 29735         privilege = istaskp(rp) ? TASK_PRIVILEGE : USER_PRIVILEGE;
  1315. 29736         init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
  1316. 29737                      (phys_bytes) rp->p_map[T].mem_phys << CLICK_SHIFT,
  1317. 29738                      code_bytes, privilege);
  1318. 29739         init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
  1319. 29740                      (phys_bytes) rp->p_map[D].mem_phys << CLICK_SHIFT,
  1320. 29741                      data_bytes, privilege);
  1321. 29742         rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
  1322. 29743 #if _WORD_SIZE == 4
  1323. 29744         rp->p_reg.gs =
  1324. 29745         rp->p_reg.fs =
  1325. 29746 #endif
  1326. 29747         rp->p_reg.ss =
  1327. 29748         rp->p_reg.es =
  1328. 29749         rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
  1329. 29750   } else {
  1330. 29751         rp->p_reg.cs = click_to_hclick(rp->p_map[T].mem_phys);
  1331. 29752         rp->p_reg.ss =
  1332. 29753         rp->p_reg.es =
  1333. 29754         rp->p_reg.ds = click_to_hclick(rp->p_map[D].mem_phys);
  1334. 29755   }
  1335. 29756 }
  1336. 29757 #endif /* (CHIP == INTEL) */
  1337. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1338. src/kernel/table.c    
  1339. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1340. 29800 /* The object file of "table.c" contains all the data.  In the *.h files, 
  1341. 29801  * declared variables appear with EXTERN in front of them, as in
  1342. 29802  *
  1343. 29803  *    EXTERN int x;
  1344. 29804  *
  1345. 29805  * Normally EXTERN is defined as extern, so when they are included in another
  1346. 29806  * file, no storage is allocated.  If the EXTERN were not present, but just
  1347. 29807  * say,
  1348. 29808  *
  1349. 29809  *    int x;
  1350. 29810  *
  1351. 29811  * then including this file in several source files would cause 'x' to be
  1352. 29812  * declared several times.  While some linkers accept this, others do not,
  1353. 29813  * so they are declared extern when included normally.  However, it must
  1354. 29814  * be declared for real somewhere.  That is done here, by redefining
  1355. .Ep 416 src/kernel/table.c
  1356. 29815  * EXTERN as the null string, so the inclusion of all the *.h files in
  1357. 29816  * table.c actually generates storage for them.  All the initialized
  1358. 29817  * variables are also declared here, since
  1359. 29818  *
  1360. 29819  * extern int x = 4;
  1361. 29820  *
  1362. 29821  * is not allowed.  If such variables are shared, they must also be declared
  1363. 29822  * in one of the *.h files without the initialization.
  1364. 29823  */
  1365. 29824
  1366. 29825 #define _TABLE
  1367. 29826
  1368. 29827 #include "kernel.h"
  1369. 29828 #include <termios.h>
  1370. 29829 #include <minix/com.h>
  1371. 29830 #include "proc.h"
  1372. 29831 #include "tty.h"
  1373. 29832
  1374. 29833 /* The startup routine of each task is given below, from -NR_TASKS upwards.
  1375. 29834  * The order of the names here MUST agree with the numerical values assigned to
  1376. 29835  * the tasks in <minix/com.h>.
  1377. 29836  */
  1378. 29837 #define SMALL_STACK     (128 * sizeof(char *))
  1379. 29838
  1380. 29839 #define TTY_STACK       (3 * SMALL_STACK)
  1381. 29840 #define SYN_ALRM_STACK  SMALL_STACK
  1382. 29841
  1383. 29842 #define DP8390_STACK    (SMALL_STACK * ENABLE_NETWORKING)
  1384. 29843
  1385. 29844 #if (CHIP == INTEL)
  1386. 29845 #define IDLE_STACK      ((3+3+4) * sizeof(char *))  /* 3 intr, 3 temps, 4 db */
  1387. 29846 #else
  1388. 29847 #define IDLE_STACK      SMALL_STACK
  1389. 29848 #endif
  1390. 29849
  1391. 29850 #define PRINTER_STACK   SMALL_STACK
  1392. 29851
  1393. 29852 #if (CHIP == INTEL)
  1394. 29853 #define WINCH_STACK     (2 * SMALL_STACK * ENABLE_WINI)
  1395. 29854 #else
  1396. 29855 #define WINCH_STACK     (3 * SMALL_STACK * ENABLE_WINI)
  1397. 29856 #endif
  1398. 29857
  1399. 29858 #if (MACHINE == ATARI)
  1400. 29859 #define SCSI_STACK      (3 * SMALL_STACK)
  1401. 29860 #endif
  1402. 29861
  1403. 29862 #if (MACHINE == IBM_PC)
  1404. 29863 #define SCSI_STACK      (2 * SMALL_STACK * ENABLE_SCSI)
  1405. 29864 #endif
  1406. 29865
  1407. 29866 #define CDROM_STACK     (4 * SMALL_STACK * ENABLE_CDROM)
  1408. 29867 #define AUDIO_STACK     (4 * SMALL_STACK * ENABLE_AUDIO)
  1409. 29868 #define MIXER_STACK     (4 * SMALL_STACK * ENABLE_AUDIO)
  1410. 29869
  1411. 29870 #define FLOP_STACK      (3 * SMALL_STACK)
  1412. 29871 #define MEM_STACK       SMALL_STACK
  1413. 29872 #define CLOCK_STACK     SMALL_STACK
  1414. 29873 #define SYS_STACK       SMALL_STACK
  1415. 29874 #define HARDWARE_STACK  0               /* dummy task, uses kernel stack */
  1416. .Op 417 src/kernel/table.c
  1417. 29875
  1418. 29876
  1419. 29877 #define TOT_STACK_SPACE         (TTY_STACK + DP8390_STACK + SCSI_STACK + 
  1420. 29878         SYN_ALRM_STACK + IDLE_STACK + HARDWARE_STACK + PRINTER_STACK + 
  1421. 29879         WINCH_STACK + FLOP_STACK + MEM_STACK + CLOCK_STACK + SYS_STACK + 
  1422. 29880         CDROM_STACK + AUDIO_STACK + MIXER_STACK)
  1423. 29881
  1424. 29882
  1425. 29883 /* SCSI, CDROM and AUDIO may in the future have different choices like
  1426. 29884  * WINCHESTER, but for now the choice is fixed.
  1427. 29885  */
  1428. 29886 #define scsi_task       aha_scsi_task
  1429. 29887 #define cdrom_task      mcd_task
  1430. 29888 #define audio_task      dsp_task
  1431. 29889
  1432. 29890
  1433. 29891 /*
  1434. 29892  * Some notes about the following table:
  1435. 29893  *  1) The tty_task should always be first so that other tasks can use printf
  1436. 29894  *     if their initialisation has problems.
  1437. 29895  *  2) If you add a new kernel task, add it before the printer task.
  1438. 29896  *  3) The task name is used for the process name (p_name).
  1439. 29897  */
  1440. 29898
  1441. 29899 PUBLIC struct tasktab tasktab[] = {
  1442. 29900         { tty_task,             TTY_STACK,      "TTY"           },
  1443. 29901 #if ENABLE_NETWORKING
  1444. 29902         { dp8390_task,          DP8390_STACK,   "DP8390"        },
  1445. 29903 #endif
  1446. 29904 #if ENABLE_CDROM
  1447. 29905         { cdrom_task,           CDROM_STACK,    "CDROM"         },
  1448. 29906 #endif
  1449. 29907 #if ENABLE_AUDIO
  1450. 29908         { audio_task,           AUDIO_STACK,    "AUDIO"         },
  1451. 29909         { mixer_task,           MIXER_STACK,    "MIXER"         },
  1452. 29910 #endif
  1453. 29911 #if ENABLE_SCSI
  1454. 29912         { scsi_task,            SCSI_STACK,     "SCSI"          },
  1455. 29913 #endif
  1456. 29914 #if ENABLE_WINI
  1457. 29915         { winchester_task,      WINCH_STACK,    "WINCH"         },
  1458. 29916 #endif
  1459. 29917         { syn_alrm_task,        SYN_ALRM_STACK, "SYN_AL"        },
  1460. 29918         { idle_task,            IDLE_STACK,     "IDLE"          },
  1461. 29919         { printer_task,         PRINTER_STACK,  "PRINTER"       },
  1462. 29920         { floppy_task,          FLOP_STACK,     "FLOPPY"        },
  1463. 29921         { mem_task,             MEM_STACK,      "MEMORY"        },
  1464. 29922         { clock_task,           CLOCK_STACK,    "CLOCK"         },
  1465. 29923         { sys_task,             SYS_STACK,      "SYS"           },
  1466. 29924         { 0,                    HARDWARE_STACK, "HARDWAR"       },
  1467. 29925         { 0,                    0,              "MM"            },
  1468. 29926         { 0,                    0,              "FS"            },
  1469. 29927 #if ENABLE_NETWORKING
  1470. 29928         { 0,                    0,              "INET"          },
  1471. 29929 #endif
  1472. 29930         { 0,                    0,              "INIT"          },
  1473. 29931 };
  1474. 29932
  1475. 29933 /* Stack space for all the task stacks.  (Declared as (char *) to align it.) */
  1476. 29934 PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
  1477. .Ep 418 src/kernel/table.c
  1478. 29935
  1479. 29936 /*
  1480. 29937  * The number of kernel tasks must be the same as NR_TASKS.
  1481. 29938  * If NR_TASKS is not correct then you will get the compile error:
  1482. 29939  *   "array size is negative"
  1483. 29940  */
  1484. 29941
  1485. 29942 #define NKT (sizeof tasktab / sizeof (struct tasktab) - (INIT_PROC_NR + 1))
  1486. 29943
  1487. 29944 extern int dummy_tasktab_check[NR_TASKS == NKT ? 1 : -1];
  1488. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1489. src/kernel/tty.c    
  1490. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1491. 30000 /* This file contains the terminal driver, both for the IBM console and regular
  1492. 30001  * ASCII terminals.  It handles only the device-independent part of a TTY, the
  1493. 30002  * device dependent parts are in console.c, rs232.c, etc.  This file contains
  1494. 30003  * two main entry points, tty_task() and tty_wakeup(), and several minor entry
  1495. 30004  * points for use by the device-dependent code.
  1496. 30005  *
  1497. 30006  * The device-independent part accepts "keyboard" input from the device-
  1498. 30007  * dependent part, performs input processing (special key interpretation),
  1499. 30008  * and sends the input to a process reading from the TTY.  Output to a TTY
  1500. 30009  * is sent to the device-dependent code for output processing and "screen"
  1501. 30010  * display.  Input processing is done by the device by calling 'in_process'
  1502. 30011  * on the input characters, output processing may be done by the device itself
  1503. 30012  * or by calling 'out_process'.  The TTY takes care of input queuing, the
  1504. 30013  * device does the output queuing.  If a device receives an external signal,
  1505. 30014  * like an interrupt, then it causes tty_wakeup() to be run by the CLOCK task
  1506. 30015  * to, you guessed it, wake up the TTY to check if input or output can
  1507. 30016  * continue.
  1508. 30017  *
  1509. 30018  * The valid messages and their parameters are:
  1510. 30019  *
  1511. 30020  *   HARD_INT:     output has been completed or input has arrived
  1512. 30021  *   DEV_READ:     a process wants to read from a terminal
  1513. 30022  *   DEV_WRITE:    a process wants to write on a terminal
  1514. 30023  *   DEV_IOCTL:    a process wants to change a terminal's parameters
  1515. 30024  *   DEV_OPEN:     a tty line has been opened
  1516. 30025  *   DEV_CLOSE:    a tty line has been closed
  1517. 30026  *   CANCEL:       terminate a previous incomplete system call immediately
  1518. 30027  *
  1519. 30028  *    m_type      TTY_LINE   PROC_NR    COUNT   TTY_SPEK  TTY_FLAGS  ADDRESS
  1520. 30029  * ---------------------------------------------------------------------------
  1521. 30030  * | HARD_INT    |         |         |         |         |         |         |
  1522. 30031  * |-------------+---------+---------+---------+---------+---------+---------|
  1523. 30032  * | DEV_READ    |minor dev| proc nr |  count  |         O_NONBLOCK| buf ptr |
  1524. 30033  * |-------------+---------+---------+---------+---------+---------+---------|
  1525. 30034  * | DEV_WRITE   |minor dev| proc nr |  count  |         |         | buf ptr |
  1526. 30035  * |-------------+---------+---------+---------+---------+---------+---------|
  1527. 30036  * | DEV_IOCTL   |minor dev| proc nr |func code|erase etc|  flags  |         |
  1528. 30037  * |-------------+---------+---------+---------+---------+---------+---------|
  1529. 30038  * | DEV_OPEN    |minor dev| proc nr | O_NOCTTY|         |         |         |
  1530. 30039  * |-------------+---------+---------+---------+---------+---------+---------|
  1531. .Op 419 src/kernel/tty.c
  1532. 30040  * | DEV_CLOSE   |minor dev| proc nr |         |         |         |         |
  1533. 30041  * |-------------+---------+---------+---------+---------+---------+---------|
  1534. 30042  * | CANCEL      |minor dev| proc nr |         |         |         |         |
  1535. 30043  * ---------------------------------------------------------------------------
  1536. 30044  */
  1537. 30045
  1538. 30046 #include "kernel.h"
  1539. 30047 #include <termios.h>
  1540. 30048 #if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
  1541. 30049 #include <sgtty.h>
  1542. 30050 #endif
  1543. 30051 #include <sys/ioctl.h>
  1544. 30052 #include <signal.h>
  1545. 30053 #include <minix/callnr.h>
  1546. 30054 #include <minix/com.h>
  1547. 30055 #if (CHIP == INTEL)
  1548. 30056 #include <minix/keymap.h>
  1549. 30057 #endif
  1550. 30058 #include "tty.h"
  1551. 30059 #include "proc.h"
  1552. 30060
  1553. 30061 /* Address of a tty structure. */
  1554. 30062 #define tty_addr(line)  (&tty_table[line])
  1555. 30063
  1556. 30064 /* First minor numbers for the various classes of TTY devices. */
  1557. 30065 #define CONS_MINOR        0
  1558. 30066 #define LOG_MINOR        15
  1559. 30067 #define RS232_MINOR      16
  1560. 30068 #define TTYPX_MINOR     128
  1561. 30069 #define PTYPX_MINOR     192
  1562. 30070
  1563. 30071 /* Macros for magic tty types. */
  1564. 30072 #define isconsole(tp)   ((tp) < tty_addr(NR_CONS))
  1565. 30073
  1566. 30074 /* Macros for magic tty structure pointers. */
  1567. 30075 #define FIRST_TTY       tty_addr(0)
  1568. 30076 #define END_TTY         tty_addr(sizeof(tty_table) / sizeof(tty_table[0]))
  1569. 30077
  1570. 30078 /* A device exists if at least its 'devread' function is defined. */
  1571. 30079 #define tty_active(tp)  ((tp)->tty_devread != NULL)
  1572. 30080
  1573. 30081 /* RS232 lines or pseudo terminals can be completely configured out. */
  1574. 30082 #if NR_RS_LINES == 0
  1575. 30083 #define rs_init(tp)     ((void) 0)
  1576. 30084 #endif
  1577. 30085 #if NR_PTYS == 0
  1578. 30086 #define pty_init(tp)    ((void) 0)
  1579. 30087 #define do_pty(tp, mp)  ((void) 0)
  1580. 30088 #endif
  1581. 30089
  1582. 30090 FORWARD _PROTOTYPE( void do_cancel, (tty_t *tp, message *m_ptr)         );
  1583. 30091 FORWARD _PROTOTYPE( void do_ioctl, (tty_t *tp, message *m_ptr)          );
  1584. 30092 FORWARD _PROTOTYPE( void do_open, (tty_t *tp, message *m_ptr)           );
  1585. 30093 FORWARD _PROTOTYPE( void do_close, (tty_t *tp, message *m_ptr)          );
  1586. 30094 FORWARD _PROTOTYPE( void do_read, (tty_t *tp, message *m_ptr)           );
  1587. 30095 FORWARD _PROTOTYPE( void do_write, (tty_t *tp, message *m_ptr)          );
  1588. 30096 FORWARD _PROTOTYPE( void in_transfer, (tty_t *tp)                       );
  1589. 30097 FORWARD _PROTOTYPE( int echo, (tty_t *tp, int ch)                       );
  1590. 30098 FORWARD _PROTOTYPE( void rawecho, (tty_t *tp, int ch)                   );
  1591. 30099 FORWARD _PROTOTYPE( int back_over, (tty_t *tp)                          );
  1592. .Ep 420 src/kernel/tty.c
  1593. 30100 FORWARD _PROTOTYPE( void reprint, (tty_t *tp)                           );
  1594. 30101 FORWARD _PROTOTYPE( void dev_ioctl, (tty_t *tp)                         );
  1595. 30102 FORWARD _PROTOTYPE( void setattr, (tty_t *tp)                           );
  1596. 30103 FORWARD _PROTOTYPE( void tty_icancel, (tty_t *tp)                       );
  1597. 30104 FORWARD _PROTOTYPE( void tty_init, (tty_t *tp)                          );
  1598. 30105 FORWARD _PROTOTYPE( void settimer, (tty_t *tp, int on)                  );
  1599. 30106 #if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
  1600. 30107 FORWARD _PROTOTYPE( int compat_getp, (tty_t *tp, struct sgttyb *sg)     );
  1601. 30108 FORWARD _PROTOTYPE( int compat_getc, (tty_t *tp, struct tchars *sg)     );
  1602. 30109 FORWARD _PROTOTYPE( int compat_setp, (tty_t *tp, struct sgttyb *sg)     );
  1603. 30110 FORWARD _PROTOTYPE( int compat_setc, (tty_t *tp, struct tchars *sg)     );
  1604. 30111 FORWARD _PROTOTYPE( int tspd2sgspd, (speed_t tspd)                      );
  1605. 30112 FORWARD _PROTOTYPE( speed_t sgspd2tspd, (int sgspd)                     );
  1606. 30113 #if ENABLE_BINCOMPAT
  1607. 30114 FORWARD _PROTOTYPE( void do_ioctl_compat, (tty_t *tp, message *m_ptr)   );
  1608. 30115 #endif
  1609. 30116 #endif
  1610. 30117
  1611. 30118 /* Default attributes. */
  1612. 30119 PRIVATE struct termios termios_defaults = {
  1613. 30120   TINPUT_DEF, TOUTPUT_DEF, TCTRL_DEF, TLOCAL_DEF, TSPEED_DEF, TSPEED_DEF,
  1614. 30121   {
  1615. 30122         TEOF_DEF, TEOL_DEF, TERASE_DEF, TINTR_DEF, TKILL_DEF, TMIN_DEF,
  1616. 30123         TQUIT_DEF, TTIME_DEF, TSUSP_DEF, TSTART_DEF, TSTOP_DEF,
  1617. 30124         TREPRINT_DEF, TLNEXT_DEF, TDISCARD_DEF,
  1618. 30125   },
  1619. 30126 };
  1620. 30127 PRIVATE struct winsize winsize_defaults;        /* = all zeroes */
  1621. 30128
  1622. 30129
  1623. 30130 /*===========================================================================*
  1624. 30131  *                              tty_task                                     *
  1625. 30132  *===========================================================================*/
  1626. 30133 PUBLIC void tty_task()
  1627. 30134 {
  1628. 30135 /* Main routine of the terminal task. */
  1629. 30136
  1630. 30137   message tty_mess;             /* buffer for all incoming messages */
  1631. 30138   register tty_t *tp;
  1632. 30139   unsigned line;
  1633. 30140
  1634. 30141   /* Initialize the terminal lines. */
  1635. 30142   for (tp = FIRST_TTY; tp < END_TTY; tp++) tty_init(tp);
  1636. 30143
  1637. 30144   /* Display the Minix startup banner. */
  1638. 30145   printf("Minix %s.%s  Copyright 1997 Prentice-Hall, Inc.nn",
  1639. 30146                                                 OS_RELEASE, OS_VERSION);
  1640. 30147
  1641. 30148 #if (CHIP == INTEL)
  1642. 30149   /* Real mode, or 16/32-bit protected mode? */
  1643. 30150 #if _WORD_SIZE == 4
  1644. 30151   printf("Executing in 32-bit protected modenn");
  1645. 30152 #else
  1646. 30153   printf("Executing in %s modenn",
  1647. 30154         protected_mode ? "16-bit protected" : "real");
  1648. 30155 #endif
  1649. 30156 #endif
  1650. 30157
  1651. 30158   while (TRUE) {
  1652. 30159         /* Handle any events on any of the ttys. */
  1653. .Op 421 src/kernel/tty.c
  1654. 30160         for (tp = FIRST_TTY; tp < END_TTY; tp++) {
  1655. 30161                 if (tp->tty_events) handle_events(tp);
  1656. 30162         }
  1657. 30163
  1658. 30164         receive(ANY, &tty_mess);
  1659. 30165
  1660. 30166         /* A hardware interrupt is an invitation to check for events. */
  1661. 30167         if (tty_mess.m_type == HARD_INT) continue;
  1662. 30168
  1663. 30169         /* Check the minor device number. */
  1664. 30170         line = tty_mess.TTY_LINE;
  1665. 30171         if ((line - CONS_MINOR) < NR_CONS) {
  1666. 30172                 tp = tty_addr(line - CONS_MINOR);
  1667. 30173         } else
  1668. 30174         if (line == LOG_MINOR) {
  1669. 30175                 tp = tty_addr(0);
  1670. 30176         } else
  1671. 30177         if ((line - RS232_MINOR) < NR_RS_LINES) {
  1672. 30178                 tp = tty_addr(line - RS232_MINOR + NR_CONS);
  1673. 30179         } else
  1674. 30180         if ((line - TTYPX_MINOR) < NR_PTYS) {
  1675. 30181                 tp = tty_addr(line - TTYPX_MINOR + NR_CONS + NR_RS_LINES);
  1676. 30182         } else
  1677. 30183         if ((line - PTYPX_MINOR) < NR_PTYS) {
  1678. 30184                 tp = tty_addr(line - PTYPX_MINOR + NR_CONS + NR_RS_LINES);
  1679. 30185                 do_pty(tp, &tty_mess);
  1680. 30186                 continue;                       /* this is a pty, not a tty */
  1681. 30187         } else {
  1682. 30188                 tp = NULL;
  1683. 30189         }
  1684. 30190
  1685. 30191         /* If the device doesn't exist or is not configured return ENXIO. */
  1686. 30192         if (tp == NULL || !tty_active(tp)) {
  1687. 30193                 tty_reply(TASK_REPLY, tty_mess.m_source,
  1688. 30194                                                 tty_mess.PROC_NR, ENXIO);
  1689. 30195                 continue;
  1690. 30196         }
  1691. 30197
  1692. 30198         /* Execute the requested function. */
  1693. 30199         switch (tty_mess.m_type) {
  1694. 30200             case DEV_READ:      do_read(tp, &tty_mess);         break;
  1695. 30201             case DEV_WRITE:     do_write(tp, &tty_mess);        break;
  1696. 30202             case DEV_IOCTL:     do_ioctl(tp, &tty_mess);        break;
  1697. 30203             case DEV_OPEN:      do_open(tp, &tty_mess);         break;
  1698. 30204             case DEV_CLOSE:     do_close(tp, &tty_mess);        break;
  1699. 30205             case CANCEL:        do_cancel(tp, &tty_mess);       break;
  1700. 30206             default:            tty_reply(TASK_REPLY, tty_mess.m_source,
  1701. 30207                                                 tty_mess.PROC_NR, EINVAL);
  1702. 30208         }
  1703. 30209   }
  1704. 30210 }
  1705. 30213 /*===========================================================================*
  1706. 30214  *                              do_read                                      *
  1707. 30215  *===========================================================================*/
  1708. 30216 PRIVATE void do_read(tp, m_ptr)
  1709. 30217 register tty_t *tp;             /* pointer to tty struct */
  1710. 30218 message *m_ptr;                 /* pointer to message sent to the task */
  1711. 30219 {
  1712. .Ep 422 src/kernel/tty.c
  1713. 30220 /* A process wants to read from a terminal. */
  1714. 30221   int r;
  1715. 30222
  1716. 30223   /* Check if there is already a process hanging in a read, check if the
  1717. 30224    * parameters are correct, do I/O.
  1718. 30225    */
  1719. 30226   if (tp->tty_inleft > 0) {
  1720. 30227         r = EIO;
  1721. 30228   } else
  1722. 30229   if (m_ptr->COUNT <= 0) {
  1723. 30230         r = EINVAL;
  1724. 30231   } else
  1725. 30232   if (numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT) == 0) {
  1726. 30233         r = EFAULT;
  1727. 30234   } else {
  1728. 30235         /* Copy information from the message to the tty struct. */
  1729. 30236         tp->tty_inrepcode = TASK_REPLY;
  1730. 30237         tp->tty_incaller = m_ptr->m_source;
  1731. 30238         tp->tty_inproc = m_ptr->PROC_NR;
  1732. 30239         tp->tty_in_vir = (vir_bytes) m_ptr->ADDRESS;
  1733. 30240         tp->tty_inleft = m_ptr->COUNT;
  1734. 30241
  1735. 30242         if (!(tp->tty_termios.c_lflag & ICANON)
  1736. 30243                                         && tp->tty_termios.c_cc[VTIME] > 0) {
  1737. 30244                 if (tp->tty_termios.c_cc[VMIN] == 0) {
  1738. 30245                         /* MIN & TIME specify a read timer that finishes the
  1739. 30246                          * read in TIME/10 seconds if no bytes are available.
  1740. 30247                          */
  1741. 30248                         lock();
  1742. 30249                         settimer(tp, TRUE);
  1743. 30250                         tp->tty_min = 1;
  1744. 30251                         unlock();
  1745. 30252                 } else {
  1746. 30253                         /* MIN & TIME specify an inter-byte timer that may
  1747. 30254                          * have to be cancelled if there are no bytes yet.
  1748. 30255                          */
  1749. 30256                         if (tp->tty_eotct == 0) {
  1750. 30257                                 lock();
  1751. 30258                                 settimer(tp, FALSE);
  1752. 30259                                 unlock();
  1753. 30260                                 tp->tty_min = tp->tty_termios.c_cc[VMIN];
  1754. 30261                         }
  1755. 30262                 }
  1756. 30263         }
  1757. 30264
  1758. 30265         /* Anything waiting in the input buffer? Clear it out... */
  1759. 30266         in_transfer(tp);
  1760. 30267         /* ...then go back for more */
  1761. 30268         handle_events(tp);
  1762. 30269         if (tp->tty_inleft == 0) return;                /* already done */
  1763. 30270
  1764. 30271         /* There were no bytes in the input queue available, so either suspend
  1765. 30272          * the caller or break off the read if nonblocking.
  1766. 30273          */
  1767. 30274         if (m_ptr->TTY_FLAGS & O_NONBLOCK) {
  1768. 30275                 r = EAGAIN;                             /* cancel the read */
  1769. 30276                 tp->tty_inleft = tp->tty_incum = 0;
  1770. 30277         } else {
  1771. 30278                 r = SUSPEND;                            /* suspend the caller */
  1772. 30279                 tp->tty_inrepcode = REVIVE;
  1773. .Op 423 src/kernel/tty.c
  1774. 30280         }
  1775. 30281   }
  1776. 30282   tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
  1777. 30283 }
  1778. 30286 /*===========================================================================*
  1779. 30287  *                              do_write                                     *
  1780. 30288  *===========================================================================*/
  1781. 30289 PRIVATE void do_write(tp, m_ptr)
  1782. 30290 register tty_t *tp;
  1783. 30291 register message *m_ptr;        /* pointer to message sent to the task */
  1784. 30292 {
  1785. 30293 /* A process wants to write on a terminal. */
  1786. 30294   int r;
  1787. 30295
  1788. 30296   /* Check if there is already a process hanging in a write, check if the
  1789. 30297    * parameters are correct, do I/O.
  1790. 30298    */
  1791. 30299   if (tp->tty_outleft > 0) {
  1792. 30300         r = EIO;
  1793. 30301   } else
  1794. 30302   if (m_ptr->COUNT <= 0) {
  1795. 30303         r = EINVAL;
  1796. 30304   } else
  1797. 30305   if (numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT) == 0) {
  1798. 30306         r = EFAULT;
  1799. 30307   } else {
  1800. 30308         /* Copy message parameters to the tty structure. */
  1801. 30309         tp->tty_outrepcode = TASK_REPLY;
  1802. 30310         tp->tty_outcaller = m_ptr->m_source;
  1803. 30311         tp->tty_outproc = m_ptr->PROC_NR;
  1804. 30312         tp->tty_out_vir = (vir_bytes) m_ptr->ADDRESS;
  1805. 30313         tp->tty_outleft = m_ptr->COUNT;
  1806. 30314
  1807. 30315         /* Try to write. */
  1808. 30316         handle_events(tp);
  1809. 30317         if (tp->tty_outleft == 0) return;               /* already done */
  1810. 30318
  1811. 30319         /* None or not all the bytes could be written, so either suspend the
  1812. 30320          * caller or break off the write if nonblocking.
  1813. 30321          */
  1814. 30322         if (m_ptr->TTY_FLAGS & O_NONBLOCK) {            /* cancel the write */
  1815. 30323                 r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN;
  1816. 30324                 tp->tty_outleft = tp->tty_outcum = 0;
  1817. 30325         } else {
  1818. 30326                 r = SUSPEND;                            /* suspend the caller */
  1819. 30327                 tp->tty_outrepcode = REVIVE;
  1820. 30328         }
  1821. 30329   }
  1822. 30330   tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
  1823. 30331 }
  1824. 30334 /*===========================================================================*
  1825. 30335  *                              do_ioctl                                     *
  1826. 30336  *===========================================================================*/
  1827. 30337 PRIVATE void do_ioctl(tp, m_ptr)
  1828. 30338 register tty_t *tp;
  1829. 30339 message *m_ptr;                 /* pointer to message sent to task */
  1830. .Ep 424 src/kernel/tty.c
  1831. 30340 {
  1832. 30341 /* Perform an IOCTL on this terminal. Posix termios calls are handled
  1833. 30342  * by the IOCTL system call
  1834. 30343  */
  1835. 30344
  1836. 30345   int r;
  1837. 30346   union {
  1838. 30347         int i;
  1839. 30348 #if ENABLE_SRCCOMPAT
  1840. 30349         struct sgttyb sg;
  1841. 30350         struct tchars tc;
  1842. 30351 #endif
  1843. 30352   } param;
  1844. 30353   phys_bytes user_phys;
  1845. 30354   size_t size;
  1846. 30355
  1847. 30356   /* Size of the ioctl parameter. */
  1848. 30357   switch (m_ptr->TTY_REQUEST) {
  1849. 30358     case TCGETS:        /* Posix tcgetattr function */
  1850. 30359     case TCSETS:        /* Posix tcsetattr function, TCSANOW option */ 
  1851. 30360     case TCSETSW:       /* Posix tcsetattr function, TCSADRAIN option */
  1852. 30361     case TCSETSF:       /* Posix tcsetattr function, TCSAFLUSH option */
  1853. 30362         size = sizeof(struct termios);
  1854. 30363         break;
  1855. 30364
  1856. 30365     case TCSBRK:        /* Posix tcsendbreak function */
  1857. 30366     case TCFLOW:        /* Posix tcflow function */
  1858. 30367     case TCFLSH:        /* Posix tcflush function */
  1859. 30368     case TIOCGPGRP:     /* Posix tcgetpgrp function */
  1860. 30369     case TIOCSPGRP:     /* Posix tcsetpgrp function */
  1861. 30370         size = sizeof(int);
  1862. 30371         break;
  1863. 30372
  1864. 30373     case TIOCGWINSZ:    /* get window size (not Posix) */
  1865. 30374     case TIOCSWINSZ:    /* set window size (not Posix) */
  1866. 30375         size = sizeof(struct winsize);
  1867. 30376         break;
  1868. 30377
  1869. 30378 #if ENABLE_SRCCOMPAT
  1870. 30379     case TIOCGETP:      /* BSD-style get terminal properties */
  1871. 30380     case TIOCSETP:      /* BSD-style set terminal properties */
  1872. 30381         size = sizeof(struct sgttyb);
  1873. 30382         break;
  1874. 30383
  1875. 30384     case TIOCGETC:      /* BSD-style get terminal special characters */ 
  1876. 30385     case TIOCSETC:      /* BSD-style get terminal special characters */ 
  1877. 30386         size = sizeof(struct tchars);
  1878. 30387         break;
  1879. 30388 #endif
  1880. 30389 #if (MACHINE == IBM_PC)
  1881. 30390     case KIOCSMAP:      /* load keymap (Minix extension) */
  1882. 30391         size = sizeof(keymap_t);
  1883. 30392         break;
  1884. 30393
  1885. 30394     case TIOCSFON:      /* load font (Minix extension) */
  1886. 30395         size = sizeof(u8_t [8192]);
  1887. 30396         break;
  1888. 30397
  1889. 30398 #endif
  1890. 30399     case TCDRAIN:       /* Posix tcdrain function -- no parameter */
  1891. .Op 425 src/kernel/tty.c
  1892. 30400     default:            size = 0;
  1893. 30401   }
  1894. 30402
  1895. 30403   if (size != 0) {
  1896. 30404         user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, size);
  1897. 30405         if (user_phys == 0) {
  1898. 30406                 tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EFAULT);
  1899. 30407                 return;
  1900. 30408         }
  1901. 30409   }
  1902. 30410
  1903. 30411   r = OK;
  1904. 30412   switch (m_ptr->TTY_REQUEST) {
  1905. 30413     case TCGETS:
  1906. 30414         /* Get the termios attributes. */
  1907. 30415         phys_copy(vir2phys(&tp->tty_termios), user_phys, (phys_bytes) size);
  1908. 30416         break;
  1909. 30417
  1910. 30418     case TCSETSW:
  1911. 30419     case TCSETSF:
  1912. 30420     case TCDRAIN:
  1913. 30421         if (tp->tty_outleft > 0) {
  1914. 30422                 /* Wait for all ongoing output processing to finish. */
  1915. 30423                 tp->tty_iocaller = m_ptr->m_source;
  1916. 30424                 tp->tty_ioproc = m_ptr->PROC_NR;
  1917. 30425                 tp->tty_ioreq = m_ptr->REQUEST;
  1918. 30426                 tp->tty_iovir = (vir_bytes) m_ptr->ADDRESS;
  1919. 30427                 r = SUSPEND;
  1920. 30428                 break;
  1921. 30429         }
  1922. 30430         if (m_ptr->TTY_REQUEST == TCDRAIN) break;
  1923. 30431         if (m_ptr->TTY_REQUEST == TCSETSF) tty_icancel(tp);
  1924. 30432         /*FALL THROUGH*/
  1925. 30433     case TCSETS:
  1926. 30434         /* Set the termios attributes. */
  1927. 30435         phys_copy(user_phys, vir2phys(&tp->tty_termios), (phys_bytes) size);
  1928. 30436         setattr(tp);
  1929. 30437         break;
  1930. 30438
  1931. 30439     case TCFLSH:
  1932. 30440         phys_copy(user_phys, vir2phys(&param.i), (phys_bytes) size);
  1933. 30441         switch (param.i) {
  1934. 30442             case TCIFLUSH:      tty_icancel(tp);                        break;
  1935. 30443             case TCOFLUSH:      (*tp->tty_ocancel)(tp);                 break;
  1936. 30444             case TCIOFLUSH:     tty_icancel(tp); (*tp->tty_ocancel)(tp);break;
  1937. 30445             default:            r = EINVAL;
  1938. 30446         }
  1939. 30447         break;
  1940. 30448
  1941. 30449     case TCFLOW:
  1942. 30450         phys_copy(user_phys, vir2phys(&param.i), (phys_bytes) size);
  1943. 30451         switch (param.i) {
  1944. 30452             case TCOOFF:
  1945. 30453             case TCOON:
  1946. 30454                 tp->tty_inhibited = (param.i == TCOOFF);
  1947. 30455                 tp->tty_events = 1;
  1948. 30456                 break;
  1949. 30457             case TCIOFF:
  1950. 30458                 (*tp->tty_echo)(tp, tp->tty_termios.c_cc[VSTOP]);
  1951. 30459                 break;
  1952. .Ep 426 src/kernel/tty.c
  1953. 30460             case TCION:
  1954. 30461                 (*tp->tty_echo)(tp, tp->tty_termios.c_cc[VSTART]);
  1955. 30462                 break;
  1956. 30463             default:
  1957. 30464                 r = EINVAL;
  1958. 30465         }
  1959. 30466         break;
  1960. 30467
  1961. 30468     case TCSBRK:
  1962. 30469         if (tp->tty_break != NULL) (*tp->tty_break)(tp);
  1963. 30470         break;
  1964. 30471
  1965. 30472     case TIOCGWINSZ:
  1966. 30473         phys_copy(vir2phys(&tp->tty_winsize), user_phys, (phys_bytes) size);
  1967. 30474         break;
  1968. 30475
  1969. 30476     case TIOCSWINSZ:
  1970. 30477         phys_copy(user_phys, vir2phys(&tp->tty_winsize), (phys_bytes) size);
  1971. 30478         /* SIGWINCH... */
  1972. 30479         break;
  1973. 30480
  1974. 30481 #if ENABLE_SRCCOMPAT
  1975. 30482     case TIOCGETP:
  1976. 30483         compat_getp(tp, &param.sg);
  1977. 30484         phys_copy(vir2phys(&param.sg), user_phys, (phys_bytes) size);
  1978. 30485         break;
  1979. 30486
  1980. 30487     case TIOCSETP:
  1981. 30488         phys_copy(user_phys, vir2phys(&param.sg), (phys_bytes) size);
  1982. 30489         compat_setp(tp, &param.sg);
  1983. 30490         break;
  1984. 30491
  1985. 30492     case TIOCGETC:
  1986. 30493         compat_getc(tp, &param.tc);
  1987. 30494         phys_copy(vir2phys(&param.tc), user_phys, (phys_bytes) size);
  1988. 30495         break;
  1989. 30496
  1990. 30497     case TIOCSETC:
  1991. 30498         phys_copy(user_phys, vir2phys(&param.tc), (phys_bytes) size);
  1992. 30499         compat_setc(tp, &param.tc);
  1993. 30500         break;
  1994. 30501 #endif
  1995. 30502
  1996. 30503 #if (MACHINE == IBM_PC)
  1997. 30504     case KIOCSMAP:
  1998. 30505         /* Load a new keymap (only /dev/console). */
  1999. 30506         if (isconsole(tp)) r = kbd_loadmap(user_phys);
  2000. 30507         break;
  2001. 30508
  2002. 30509     case TIOCSFON:
  2003. 30510         /* Load a font into an EGA or VGA card (hs@hck.hr) */
  2004. 30511         if (isconsole(tp)) r = con_loadfont(user_phys);
  2005. 30512         break;
  2006. 30513 #endif
  2007. 30514
  2008. 30515 #if (MACHINE == ATARI)
  2009. 30516     case VDU_LOADFONT:
  2010. 30517         r = vdu_loadfont(m_ptr);
  2011. 30518         break;
  2012. 30519 #endif
  2013. .Op 427 src/kernel/tty.c
  2014. 30520
  2015. 30521 /* These Posix functions are allowed to fail if _POSIX_JOB_CONTROL is 
  2016. 30522  * not defined.
  2017. 30523  */
  2018. 30524     case TIOCGPGRP:     
  2019. 30525     case TIOCSPGRP:     
  2020. 30526     default:
  2021. 30527 #if ENABLE_BINCOMPAT
  2022. 30528         do_ioctl_compat(tp, m_ptr);
  2023. 30529         return;
  2024. 30530 #else
  2025. 30531         r = ENOTTY;
  2026. 30532 #endif
  2027. 30533   }
  2028. 30534
  2029. 30535   /* Send the reply. */
  2030. 30536   tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
  2031. 30537 }
  2032. 30540 /*===========================================================================*
  2033. 30541  *                              do_open                                      *
  2034. 30542  *===========================================================================*/
  2035. 30543 PRIVATE void do_open(tp, m_ptr)
  2036. 30544 register tty_t *tp;
  2037. 30545 message *m_ptr;                 /* pointer to message sent to task */
  2038. 30546 {
  2039. 30547 /* A tty line has been opened.  Make it the callers controlling tty if
  2040. 30548  * O_NOCTTY is *not* set and it is not the log device.  1 is returned if
  2041. 30549  * the tty is made the controlling tty, otherwise OK or an error code.
  2042. 30550  */
  2043. 30551   int r = OK;
  2044. 30552
  2045. 30553   if (m_ptr->TTY_LINE == LOG_MINOR) {
  2046. 30554         /* The log device is a write-only diagnostics device. */
  2047. 30555         if (m_ptr->COUNT & R_BIT) r = EACCES;
  2048. 30556   } else {
  2049. 30557         if (!(m_ptr->COUNT & O_NOCTTY)) {
  2050. 30558                 tp->tty_pgrp = m_ptr->PROC_NR;
  2051. 30559                 r = 1;
  2052. 30560         }
  2053. 30561         tp->tty_openct++;
  2054. 30562   }
  2055. 30563   tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
  2056. 30564 }
  2057. 30567 /*===========================================================================*
  2058. 30568  *                              do_close                                     *
  2059. 30569  *===========================================================================*/
  2060. 30570 PRIVATE void do_close(tp, m_ptr)
  2061. 30571 register tty_t *tp;
  2062. 30572 message *m_ptr;                 /* pointer to message sent to task */
  2063. 30573 {
  2064. 30574 /* A tty line has been closed.  Clean up the line if it is the last close. */
  2065. 30575
  2066. 30576   if (m_ptr->TTY_LINE != LOG_MINOR && --tp->tty_openct == 0) {
  2067. 30577         tp->tty_pgrp = 0;
  2068. 30578         tty_icancel(tp);
  2069. 30579         (*tp->tty_ocancel)(tp);
  2070. .Ep 428 src/kernel/tty.c
  2071. 30580         (*tp->tty_close)(tp);
  2072. 30581         tp->tty_termios = termios_defaults;
  2073. 30582         tp->tty_winsize = winsize_defaults;
  2074. 30583         setattr(tp);
  2075. 30584   }
  2076. 30585   tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, OK);
  2077. 30586 }
  2078. 30589 /*===========================================================================*
  2079. 30590  *                              do_cancel                                    *
  2080. 30591  *===========================================================================*/
  2081. 30592 PRIVATE void do_cancel(tp, m_ptr)
  2082. 30593 register tty_t *tp;
  2083. 30594 message *m_ptr;                 /* pointer to message sent to task */
  2084. 30595 {
  2085. 30596 /* A signal has been sent to a process that is hanging trying to read or write.
  2086. 30597  * The pending read or write must be finished off immediately.
  2087. 30598  */
  2088. 30599
  2089. 30600   int proc_nr;
  2090. 30601   int mode;
  2091. 30602
  2092. 30603   /* Check the parameters carefully, to avoid cancelling twice. */
  2093. 30604   proc_nr = m_ptr->PROC_NR;
  2094. 30605   mode = m_ptr->COUNT;
  2095. 30606   if ((mode & R_BIT) && tp->tty_inleft != 0 && proc_nr == tp->tty_inproc) {
  2096. 30607         /* Process was reading when killed.  Clean up input. */
  2097. 30608         tty_icancel(tp);
  2098. 30609         tp->tty_inleft = tp->tty_incum = 0;
  2099. 30610   }
  2100. 30611   if ((mode & W_BIT) && tp->tty_outleft != 0 && proc_nr == tp->tty_outproc) {
  2101. 30612         /* Process was writing when killed.  Clean up output. */
  2102. 30613         (*tp->tty_ocancel)(tp);
  2103. 30614         tp->tty_outleft = tp->tty_outcum = 0;
  2104. 30615   }
  2105. 30616   if (tp->tty_ioreq != 0 && proc_nr == tp->tty_ioproc) {
  2106. 30617         /* Process was waiting for output to drain. */
  2107. 30618         tp->tty_ioreq = 0;
  2108. 30619   }
  2109. 30620   tp->tty_events = 1;
  2110. 30621   tty_reply(TASK_REPLY, m_ptr->m_source, proc_nr, EINTR);
  2111. 30622 }
  2112. 30625 /*===========================================================================*
  2113. 30626  *                              handle_events                                *
  2114. 30627  *===========================================================================*/
  2115. 30628 PUBLIC void handle_events(tp)
  2116. 30629 tty_t *tp;                      /* TTY to check for events. */
  2117. 30630 {
  2118. 30631 /* Handle any events pending on a TTY.  These events are usually device
  2119. 30632  * interrupts.
  2120. 30633  *
  2121. 30634  * Two kinds of events are prominent:
  2122. 30635  *      - a character has been received from the console or an RS232 line.
  2123. 30636  *      - an RS232 line has completed a write request (on behalf of a user).
  2124. 30637  * The interrupt handler may delay the interrupt message at its discretion
  2125. 30638  * to avoid swamping the TTY task.  Messages may be overwritten when the
  2126. 30639  * lines are fast or when there are races between different lines, input
  2127. .Op 429 src/kernel/tty.c
  2128. 30640  * and output, because MINIX only provides single buffering for interrupt
  2129. 30641  * messages (in proc.c).  This is handled by explicitly checking each line
  2130. 30642  * for fresh input and completed output on each interrupt.
  2131. 30643  */
  2132. 30644   char *buf;
  2133. 30645   unsigned count;
  2134. 30646
  2135. 30647   do {
  2136. 30648         tp->tty_events = 0;
  2137. 30649
  2138. 30650         /* Read input and perform input processing. */
  2139. 30651         (*tp->tty_devread)(tp);
  2140. 30652
  2141. 30653         /* Perform output processing and write output. */
  2142. 30654         (*tp->tty_devwrite)(tp);
  2143. 30655
  2144. 30656         /* Ioctl waiting for some event? */
  2145. 30657         if (tp->tty_ioreq != 0) dev_ioctl(tp);
  2146. 30658   } while (tp->tty_events);
  2147. 30659
  2148. 30660   /* Transfer characters from the input queue to a waiting process. */
  2149. 30661   in_transfer(tp);
  2150. 30662
  2151. 30663   /* Reply if enough bytes are available. */
  2152. 30664   if (tp->tty_incum >= tp->tty_min && tp->tty_inleft > 0) {
  2153. 30665         tty_reply(tp->tty_inrepcode, tp->tty_incaller, tp->tty_inproc,
  2154. 30666                                                                 tp->tty_incum);
  2155. 30667         tp->tty_inleft = tp->tty_incum = 0;
  2156. 30668   }
  2157. 30669 }
  2158. 30672 /*===========================================================================*
  2159. 30673  *                              in_transfer                                  *
  2160. 30674  *===========================================================================*/
  2161. 30675 PRIVATE void in_transfer(tp)
  2162. 30676 register tty_t *tp;             /* pointer to terminal to read from */
  2163. 30677 {
  2164. 30678 /* Transfer bytes from the input queue to a process reading from a terminal. */
  2165. 30679
  2166. 30680   int ch;
  2167. 30681   int count;
  2168. 30682   phys_bytes buf_phys, user_base;
  2169. 30683   char buf[64], *bp;
  2170. 30684
  2171. 30685   /* Anything to do? */
  2172. 30686   if (tp->tty_inleft == 0 || tp->tty_eotct < tp->tty_min) return;
  2173. 30687
  2174. 30688   buf_phys = vir2phys(buf);
  2175. 30689   user_base = proc_vir2phys(proc_addr(tp->tty_inproc), 0);
  2176. 30690   bp = buf;
  2177. 30691   while (tp->tty_inleft > 0 && tp->tty_eotct > 0) {
  2178. 30692         ch = *tp->tty_intail;
  2179. 30693
  2180. 30694         if (!(ch & IN_EOF)) {
  2181. 30695                 /* One character to be delivered to the user. */
  2182. 30696                 *bp = ch & IN_CHAR;
  2183. 30697                 tp->tty_inleft--;
  2184. 30698                 if (++bp == bufend(buf)) {
  2185. 30699                         /* Temp buffer full, copy to user space. */
  2186. .Ep 430 src/kernel/tty.c
  2187. 30700                         phys_copy(buf_phys, user_base + tp->tty_in_vir,
  2188. 30701                                                 (phys_bytes) buflen(buf));
  2189. 30702                         tp->tty_in_vir += buflen(buf);
  2190. 30703                         tp->tty_incum += buflen(buf);
  2191. 30704                         bp = buf;
  2192. 30705                 }
  2193. 30706         }
  2194. 30707
  2195. 30708         /* Remove the character from the input queue. */
  2196. 30709         if (++tp->tty_intail == bufend(tp->tty_inbuf))
  2197. 30710                 tp->tty_intail = tp->tty_inbuf;
  2198. 30711         tp->tty_incount--;
  2199. 30712         if (ch & IN_EOT) {
  2200. 30713                 tp->tty_eotct--;
  2201. 30714                 /* Don't read past a line break in canonical mode. */
  2202. 30715                 if (tp->tty_termios.c_lflag & ICANON) tp->tty_inleft = 0;
  2203. 30716         }
  2204. 30717   }
  2205. 30718
  2206. 30719   if (bp > buf) {
  2207. 30720         /* Leftover characters in the buffer. */
  2208. 30721         count = bp - buf;
  2209. 30722         phys_copy(buf_phys, user_base + tp->tty_in_vir, (phys_bytes) count);
  2210. 30723         tp->tty_in_vir += count;
  2211. 30724         tp->tty_incum += count;
  2212. 30725   }
  2213. 30726
  2214. 30727   /* Usually reply to the reader, possibly even if incum == 0 (EOF). */
  2215. 30728   if (tp->tty_inleft == 0) {
  2216. 30729         tty_reply(tp->tty_inrepcode, tp->tty_incaller, tp->tty_inproc,
  2217. 30730                                                                 tp->tty_incum);
  2218. 30731         tp->tty_inleft = tp->tty_incum = 0;
  2219. 30732   }
  2220. 30733 }
  2221. 30736 /*===========================================================================*
  2222. 30737  *                              in_process                                   *
  2223. 30738  *===========================================================================*/
  2224. 30739 PUBLIC int in_process(tp, buf, count)
  2225. 30740 register tty_t *tp;             /* terminal on which character has arrived */
  2226. 30741 char *buf;                      /* buffer with input characters */
  2227. 30742 int count;                      /* number of input characters */
  2228. 30743 {
  2229. 30744 /* Characters have just been typed in.  Process, save, and echo them.  Return
  2230. 30745  * the number of characters processed.
  2231. 30746  */
  2232. 30747
  2233. 30748   int ch, sig, ct;
  2234. 30749   int timeset = FALSE;
  2235. 30750   static unsigned char csize_mask[] = { 0x1F, 0x3F, 0x7F, 0xFF };
  2236. 30751
  2237. 30752   for (ct = 0; ct < count; ct++) {
  2238. 30753         /* Take one character. */
  2239. 30754         ch = *buf++ & BYTE;
  2240. 30755
  2241. 30756         /* Strip to seven bits? */
  2242. 30757         if (tp->tty_termios.c_iflag & ISTRIP) ch &= 0x7F;
  2243. 30758
  2244. 30759         /* Input extensions? */
  2245. .Op 431 src/kernel/tty.c
  2246. 30760         if (tp->tty_termios.c_lflag & IEXTEN) {
  2247. 30761
  2248. 30762                 /* Previous character was a character escape? */
  2249. 30763                 if (tp->tty_escaped) {
  2250. 30764                         tp->tty_escaped = NOT_ESCAPED;
  2251. 30765                         ch |= IN_ESC;   /* protect character */
  2252. 30766                 }
  2253. 30767
  2254. 30768                 /* LNEXT (^V) to escape the next character? */
  2255. 30769                 if (ch == tp->tty_termios.c_cc[VLNEXT]) {
  2256. 30770                         tp->tty_escaped = ESCAPED;
  2257. 30771                         rawecho(tp, '^');
  2258. 30772                         rawecho(tp, 'b');
  2259. 30773                         continue;       /* do not store the escape */
  2260. 30774                 }
  2261. 30775
  2262. 30776                 /* REPRINT (^R) to reprint echoed characters? */
  2263. 30777                 if (ch == tp->tty_termios.c_cc[VREPRINT]) {
  2264. 30778                         reprint(tp);
  2265. 30779                         continue;
  2266. 30780                 }
  2267. 30781         }
  2268. 30782
  2269. 30783         /* _POSIX_VDISABLE is a normal character value, so better escape it. */
  2270. 30784         if (ch == _POSIX_VDISABLE) ch |= IN_ESC;
  2271. 30785
  2272. 30786         /* Map CR to LF, ignore CR, or map LF to CR. */
  2273. 30787         if (ch == 'r') {
  2274. 30788                 if (tp->tty_termios.c_iflag & IGNCR) continue;
  2275. 30789                 if (tp->tty_termios.c_iflag & ICRNL) ch = 'n';
  2276. 30790         } else
  2277. 30791         if (ch == 'n') {
  2278. 30792                 if (tp->tty_termios.c_iflag & INLCR) ch = 'r';
  2279. 30793         }
  2280. 30794
  2281. 30795         /* Canonical mode? */
  2282. 30796         if (tp->tty_termios.c_lflag & ICANON) {
  2283. 30797
  2284. 30798                 /* Erase processing (rub out of last character). */
  2285. 30799                 if (ch == tp->tty_termios.c_cc[VERASE]) {
  2286. 30800                         (void) back_over(tp);
  2287. 30801                         if (!(tp->tty_termios.c_lflag & ECHOE)) {
  2288. 30802                                 (void) echo(tp, ch);
  2289. 30803                         }
  2290. 30804                         continue;
  2291. 30805                 }
  2292. 30806
  2293. 30807                 /* Kill processing (remove current line). */
  2294. 30808                 if (ch == tp->tty_termios.c_cc[VKILL]) {
  2295. 30809                         while (back_over(tp)) {}
  2296. 30810                         if (!(tp->tty_termios.c_lflag & ECHOE)) {
  2297. 30811                                 (void) echo(tp, ch);
  2298. 30812                                 if (tp->tty_termios.c_lflag & ECHOK)
  2299. 30813                                         rawecho(tp, 'n');
  2300. 30814                         }
  2301. 30815                         continue;
  2302. 30816                 }
  2303. 30817
  2304. 30818                 /* EOF (^D) means end-of-file, an invisible "line break". */
  2305. 30819                 if (ch == tp->tty_termios.c_cc[VEOF]) ch |= IN_EOT | IN_EOF;
  2306. .Ep 432 src/kernel/tty.c
  2307. 30820
  2308. 30821                 /* The line may be returned to the user after an LF. */
  2309. 30822                 if (ch == 'n') ch |= IN_EOT;
  2310. 30823
  2311. 30824                 /* Same thing with EOL, whatever it may be. */
  2312. 30825                 if (ch == tp->tty_termios.c_cc[VEOL]) ch |= IN_EOT;
  2313. 30826         }
  2314. 30827
  2315. 30828         /* Start/stop input control? */
  2316. 30829         if (tp->tty_termios.c_iflag & IXON) {
  2317. 30830
  2318. 30831                 /* Output stops on STOP (^S). */
  2319. 30832                 if (ch == tp->tty_termios.c_cc[VSTOP]) {
  2320. 30833                         tp->tty_inhibited = STOPPED;
  2321. 30834                         tp->tty_events = 1;
  2322. 30835                         continue;
  2323. 30836                 }
  2324. 30837
  2325. 30838                 /* Output restarts on START (^Q) or any character if IXANY. */
  2326. 30839                 if (tp->tty_inhibited) {
  2327. 30840                         if (ch == tp->tty_termios.c_cc[VSTART]
  2328. 30841                                         || (tp->tty_termios.c_iflag & IXANY)) {
  2329. 30842                                 tp->tty_inhibited = RUNNING;
  2330. 30843                                 tp->tty_events = 1;
  2331. 30844                                 if (ch == tp->tty_termios.c_cc[VSTART])
  2332. 30845                                         continue;
  2333. 30846                         }
  2334. 30847                 }
  2335. 30848         }
  2336. 30849
  2337. 30850         if (tp->tty_termios.c_lflag & ISIG) {
  2338. 30851                 /* Check for INTR (^?) and QUIT (^) characters. */
  2339. 30852                 if (ch == tp->tty_termios.c_cc[VINTR]
  2340. 30853                                         || ch == tp->tty_termios.c_cc[VQUIT]) {
  2341. 30854                         sig = SIGINT;
  2342. 30855                         if (ch == tp->tty_termios.c_cc[VQUIT]) sig = SIGQUIT;
  2343. 30856                         sigchar(tp, sig);
  2344. 30857                         (void) echo(tp, ch);
  2345. 30858                         continue;
  2346. 30859                 }
  2347. 30860         }
  2348. 30861
  2349. 30862         /* Is there space in the input buffer? */
  2350. 30863         if (tp->tty_incount == buflen(tp->tty_inbuf)) {
  2351. 30864                 /* No space; discard in canonical mode, keep in raw mode. */
  2352. 30865                 if (tp->tty_termios.c_lflag & ICANON) continue;
  2353. 30866                 break;
  2354. 30867         }
  2355. 30868
  2356. 30869         if (!(tp->tty_termios.c_lflag & ICANON)) {
  2357. 30870                 /* In raw mode all characters are "line breaks". */
  2358. 30871                 ch |= IN_EOT;
  2359. 30872
  2360. 30873                 /* Start an inter-byte timer? */
  2361. 30874                 if (!timeset && tp->tty_termios.c_cc[VMIN] > 0
  2362. 30875                                 && tp->tty_termios.c_cc[VTIME] > 0) {
  2363. 30876                         lock();
  2364. 30877                         settimer(tp, TRUE);
  2365. 30878                         unlock();
  2366. 30879                         timeset = TRUE;
  2367. .Op 433 src/kernel/tty.c
  2368. 30880                 }
  2369. 30881         }
  2370. 30882
  2371. 30883         /* Perform the intricate function of echoing. */
  2372. 30884         if (tp->tty_termios.c_lflag & (ECHO|ECHONL)) ch = echo(tp, ch);
  2373. 30885
  2374. 30886         /* Save the character in the input queue. */
  2375. 30887         *tp->tty_inhead++ = ch;
  2376. 30888         if (tp->tty_inhead == bufend(tp->tty_inbuf))
  2377. 30889                 tp->tty_inhead = tp->tty_inbuf;
  2378. 30890         tp->tty_incount++;
  2379. 30891         if (ch & IN_EOT) tp->tty_eotct++;
  2380. 30892
  2381. 30893         /* Try to finish input if the queue threatens to overflow. */
  2382. 30894         if (tp->tty_incount == buflen(tp->tty_inbuf)) in_transfer(tp);
  2383. 30895   }
  2384. 30896   return ct;
  2385. 30897 }
  2386. 30900 /*===========================================================================*
  2387. 30901  *                              echo                                         *
  2388. 30902  *===========================================================================*/
  2389. 30903 PRIVATE int echo(tp, ch)
  2390. 30904 register tty_t *tp;             /* terminal on which to echo */
  2391. 30905 register int ch;                /* pointer to character to echo */
  2392. 30906 {
  2393. 30907 /* Echo the character if echoing is on.  Some control characters are echoed
  2394. 30908  * with their normal effect, other control characters are echoed as "^X",
  2395. 30909  * normal characters are echoed normally.  EOF (^D) is echoed, but immediately
  2396. 30910  * backspaced over.  Return the character with the echoed length added to its
  2397. 30911  * attributes.
  2398. 30912  */
  2399. 30913   int len, rp;
  2400. 30914
  2401. 30915   ch &= ~IN_LEN;
  2402. 30916   if (!(tp->tty_termios.c_lflag & ECHO)) {
  2403. 30917         if (ch == ('n' | IN_EOT) && (tp->tty_termios.c_lflag
  2404. 30918                                         & (ICANON|ECHONL)) == (ICANON|ECHONL))
  2405. 30919                 (*tp->tty_echo)(tp, 'n');
  2406. 30920         return(ch);
  2407. 30921   }
  2408. 30922
  2409. 30923   /* "Reprint" tells if the echo output has been messed up by other output. */
  2410. 30924   rp = tp->tty_incount == 0 ? FALSE : tp->tty_reprint;
  2411. 30925
  2412. 30926   if ((ch & IN_CHAR) < ' ') {
  2413. 30927         switch (ch & (IN_ESC|IN_EOF|IN_EOT|IN_CHAR)) {
  2414. 30928             case 't':
  2415. 30929                 len = 0;
  2416. 30930                 do {
  2417. 30931                         (*tp->tty_echo)(tp, ' ');
  2418. 30932                         len++;
  2419. 30933                 } while (len < TAB_SIZE && (tp->tty_position & TAB_MASK) != 0);
  2420. 30934                 break;
  2421. 30935             case 'r' | IN_EOT:
  2422. 30936             case 'n' | IN_EOT:
  2423. 30937                 (*tp->tty_echo)(tp, ch & IN_CHAR);
  2424. 30938                 len = 0;
  2425. 30939                 break;
  2426. .Ep 434 src/kernel/tty.c
  2427. 30940             default:
  2428. 30941                 (*tp->tty_echo)(tp, '^');
  2429. 30942                 (*tp->tty_echo)(tp, '@' + (ch & IN_CHAR));
  2430. 30943                 len = 2;
  2431. 30944         }
  2432. 30945   } else
  2433. 30946   if ((ch & IN_CHAR) == '177') {
  2434. 30947         /* A DEL prints as "^?". */
  2435. 30948         (*tp->tty_echo)(tp, '^');
  2436. 30949         (*tp->tty_echo)(tp, '?');
  2437. 30950         len = 2;
  2438. 30951   } else {
  2439. 30952         (*tp->tty_echo)(tp, ch & IN_CHAR);
  2440. 30953         len = 1;
  2441. 30954   }
  2442. 30955   if (ch & IN_EOF) while (len > 0) { (*tp->tty_echo)(tp, 'b'); len--; }
  2443. 30956
  2444. 30957   tp->tty_reprint = rp;
  2445. 30958   return(ch | (len << IN_LSHIFT));
  2446. 30959 }
  2447. 30962 /*==========================================================================*
  2448. 30963  *                              rawecho                                     *
  2449. 30964  *==========================================================================*/
  2450. 30965 PRIVATE void rawecho(tp, ch)
  2451. 30966 register tty_t *tp;
  2452. 30967 int ch;
  2453. 30968 {
  2454. 30969 /* Echo without interpretation if ECHO is set. */
  2455. 30970   int rp = tp->tty_reprint;
  2456. 30971   if (tp->tty_termios.c_lflag & ECHO) (*tp->tty_echo)(tp, ch);
  2457. 30972   tp->tty_reprint = rp;
  2458. 30973 }
  2459. 30976 /*==========================================================================*
  2460. 30977  *                              back_over                                   *
  2461. 30978  *==========================================================================*/
  2462. 30979 PRIVATE int back_over(tp)
  2463. 30980 register tty_t *tp;
  2464. 30981 {
  2465. 30982 /* Backspace to previous character on screen and erase it. */
  2466. 30983   u16_t *head;
  2467. 30984   int len;
  2468. 30985
  2469. 30986   if (tp->tty_incount == 0) return(0);  /* queue empty */
  2470. 30987   head = tp->tty_inhead;
  2471. 30988   if (head == tp->tty_inbuf) head = bufend(tp->tty_inbuf);
  2472. 30989   if (*--head & IN_EOT) return(0);              /* can't erase "line breaks" */
  2473. 30990   if (tp->tty_reprint) reprint(tp);             /* reprint if messed up */
  2474. 30991   tp->tty_inhead = head;
  2475. 30992   tp->tty_incount--;
  2476. 30993   if (tp->tty_termios.c_lflag & ECHOE) {
  2477. 30994         len = (*head & IN_LEN) >> IN_LSHIFT;
  2478. 30995         while (len > 0) {
  2479. 30996                 rawecho(tp, 'b');
  2480. 30997                 rawecho(tp, ' ');
  2481. 30998                 rawecho(tp, 'b');
  2482. 30999                 len--;
  2483. .Op 435 src/kernel/tty.c
  2484. 31000         }
  2485. 31001   }
  2486. 31002   return(1);                            /* one character erased */
  2487. 31003 }
  2488. 31006 /*==========================================================================*
  2489. 31007  *                              reprint                                     *
  2490. 31008  *==========================================================================*/
  2491. 31009 PRIVATE void reprint(tp)
  2492. 31010 register tty_t *tp;             /* pointer to tty struct */
  2493. 31011 {
  2494. 31012 /* Restore what has been echoed to screen before if the user input has been
  2495. 31013  * messed up by output, or if REPRINT (^R) is typed.
  2496. 31014  */
  2497. 31015   int count;
  2498. 31016   u16_t *head;
  2499. 31017
  2500. 31018   tp->tty_reprint = FALSE;
  2501. 31019
  2502. 31020   /* Find the last line break in the input. */
  2503. 31021   head = tp->tty_inhead;
  2504. 31022   count = tp->tty_incount;
  2505. 31023   while (count > 0) {
  2506. 31024         if (head == tp->tty_inbuf) head = bufend(tp->tty_inbuf);
  2507. 31025         if (head[-1] & IN_EOT) break;
  2508. 31026         head--;
  2509. 31027         count--;
  2510. 31028   }
  2511. 31029   if (count == tp->tty_incount) return;         /* no reason to reprint */
  2512. 31030
  2513. 31031   /* Show REPRINT (^R) and move to a new line. */
  2514. 31032   (void) echo(tp, tp->tty_termios.c_cc[VREPRINT] | IN_ESC);
  2515. 31033   rawecho(tp, 'r');
  2516. 31034   rawecho(tp, 'n');
  2517. 31035
  2518. 31036   /* Reprint from the last break onwards. */
  2519. 31037   do {
  2520. 31038         if (head == bufend(tp->tty_inbuf)) head = tp->tty_inbuf;
  2521. 31039         *head = echo(tp, *head);
  2522. 31040         head++;
  2523. 31041         count++;
  2524. 31042   } while (count < tp->tty_incount);
  2525. 31043 }
  2526. 31046 /*==========================================================================*
  2527. 31047  *                              out_process                                 *
  2528. 31048  *==========================================================================*/
  2529. 31049 PUBLIC void out_process(tp, bstart, bpos, bend, icount, ocount)
  2530. 31050 tty_t *tp;
  2531. 31051 char *bstart, *bpos, *bend;     /* start/pos/end of circular buffer */
  2532. 31052 int *icount;                    /* # input chars / input chars used */
  2533. 31053 int *ocount;                    /* max output chars / output chars used */
  2534. 31054 {
  2535. 31055 /* Perform output processing on a circular buffer.  *icount is the number of
  2536. 31056  * bytes to process, and the number of bytes actually processed on return.
  2537. 31057  * *ocount is the space available on input and the space used on output.
  2538. 31058  * (Naturally *icount < *ocount.)  The column position is updated modulo
  2539. 31059  * the TAB size, because we really only need it for tabs.
  2540. .Ep 436 src/kernel/tty.c
  2541. 31060  */
  2542. 31061
  2543. 31062   int tablen;
  2544. 31063   int ict = *icount;
  2545. 31064   int oct = *ocount;
  2546. 31065   int pos = tp->tty_position;
  2547. 31066
  2548. 31067   while (ict > 0) {
  2549. 31068         switch (*bpos) {
  2550. 31069         case '7':
  2551. 31070                 break;
  2552. 31071         case 'b':
  2553. 31072                 pos--;
  2554. 31073                 break;
  2555. 31074         case 'r':
  2556. 31075                 pos = 0;
  2557. 31076                 break;
  2558. 31077         case 'n':
  2559. 31078                 if ((tp->tty_termios.c_oflag & (OPOST|ONLCR))
  2560. 31079                                                         == (OPOST|ONLCR)) {
  2561. 31080                         /* Map LF to CR+LF if there is space.  Note that the
  2562. 31081                          * next character in the buffer is overwritten, so
  2563. 31082                          * we stop at this point.
  2564. 31083                          */
  2565. 31084                         if (oct >= 2) {
  2566. 31085                                 *bpos = 'r';
  2567. 31086                                 if (++bpos == bend) bpos = bstart;
  2568. 31087                                 *bpos = 'n';
  2569. 31088                                 pos = 0;
  2570. 31089                                 ict--;
  2571. 31090                                 oct -= 2;
  2572. 31091                         }
  2573. 31092                         goto out_done;  /* no space or buffer got changed */
  2574. 31093                 }
  2575. 31094                 break;
  2576. 31095         case 't':
  2577. 31096                 /* Best guess for the tab length. */
  2578. 31097                 tablen = TAB_SIZE - (pos & TAB_MASK);
  2579. 31098
  2580. 31099                 if ((tp->tty_termios.c_oflag & (OPOST|XTABS))
  2581. 31100                                                         == (OPOST|XTABS)) {
  2582. 31101                         /* Tabs must be expanded. */
  2583. 31102                         if (oct >= tablen) {
  2584. 31103                                 pos += tablen;
  2585. 31104                                 ict--;
  2586. 31105                                 oct -= tablen;
  2587. 31106                                 do {
  2588. 31107                                         *bpos = ' ';
  2589. 31108                                         if (++bpos == bend) bpos = bstart;
  2590. 31109                                 } while (--tablen != 0);
  2591. 31110                         }
  2592. 31111                         goto out_done;
  2593. 31112                 }
  2594. 31113                 /* Tabs are output directly. */
  2595. 31114                 pos += tablen;
  2596. 31115                 break;
  2597. 31116         default:
  2598. 31117                 /* Assume any other character prints as one character. */
  2599. 31118                 pos++;
  2600. 31119         }
  2601. .Op 437 src/kernel/tty.c
  2602. 31120         if (++bpos == bend) bpos = bstart;
  2603. 31121         ict--;
  2604. 31122         oct--;
  2605. 31123   }
  2606. 31124 out_done:
  2607. 31125   tp->tty_position = pos & TAB_MASK;
  2608. 31126
  2609. 31127   *icount -= ict;       /* [io]ct are the number of chars not used */
  2610. 31128   *ocount -= oct;       /* *[io]count are the number of chars that are used */
  2611. 31129 }
  2612. 31132 /*===========================================================================*
  2613. 31133  *                              dev_ioctl                                    *
  2614. 31134  *===========================================================================*/
  2615. 31135 PRIVATE void dev_ioctl(tp)
  2616. 31136 tty_t *tp;
  2617. 31137 {
  2618. 31138 /* The ioctl's TCSETSW, TCSETSF and TCDRAIN wait for output to finish to make
  2619. 31139  * sure that an attribute change doesn't affect the processing of current
  2620. 31140  * output.  Once output finishes the ioctl is executed as in do_ioctl().
  2621. 31141  */
  2622. 31142   phys_bytes user_phys;
  2623. 31143
  2624. 31144   if (tp->tty_outleft > 0) return;              /* output not finished */
  2625. 31145
  2626. 31146   if (tp->tty_ioreq != TCDRAIN) {
  2627. 31147         if (tp->tty_ioreq == TCSETSF) tty_icancel(tp);
  2628. 31148         user_phys = proc_vir2phys(proc_addr(tp->tty_ioproc), tp->tty_iovir);
  2629. 31149         phys_copy(user_phys, vir2phys(&tp->tty_termios),
  2630. 31150                                         (phys_bytes) sizeof(tp->tty_termios));
  2631. 31151         setattr(tp);
  2632. 31152   }
  2633. 31153   tp->tty_ioreq = 0;
  2634. 31154   tty_reply(REVIVE, tp->tty_iocaller, tp->tty_ioproc, OK);
  2635. 31155 }
  2636. 31158 /*===========================================================================*
  2637. 31159  *                              setattr                                      *
  2638. 31160  *===========================================================================*/
  2639. 31161 PRIVATE void setattr(tp)
  2640. 31162 tty_t *tp;
  2641. 31163 {
  2642. 31164 /* Apply the new line attributes (raw/canonical, line speed, etc.) */
  2643. 31165   u16_t *inp;
  2644. 31166   int count;
  2645. 31167
  2646. 31168   if (!(tp->tty_termios.c_lflag & ICANON)) {
  2647. 31169         /* Raw mode; put a "line break" on all characters in the input queue.
  2648. 31170          * It is undefined what happens to the input queue when ICANON is
  2649. 31171          * switched off, a process should use TCSAFLUSH to flush the queue.
  2650. 31172          * Keeping the queue to preserve typeahead is the Right Thing, however
  2651. 31173          * when a process does use TCSANOW to switch to raw mode.
  2652. 31174          */
  2653. 31175         count = tp->tty_eotct = tp->tty_incount;
  2654. 31176         inp = tp->tty_intail;
  2655. 31177         while (count > 0) {
  2656. 31178                 *inp |= IN_EOT;
  2657. 31179                 if (++inp == bufend(tp->tty_inbuf)) inp = tp->tty_inbuf;
  2658. .Ep 438 src/kernel/tty.c
  2659. 31180                 --count;
  2660. 31181         }
  2661. 31182   }
  2662. 31183
  2663. 31184   /* Inspect MIN and TIME. */
  2664. 31185   lock();
  2665. 31186   settimer(tp, FALSE);
  2666. 31187   unlock();
  2667. 31188   if (tp->tty_termios.c_lflag & ICANON) {
  2668. 31189         /* No MIN & TIME in canonical mode. */
  2669. 31190         tp->tty_min = 1;
  2670. 31191   } else {
  2671. 31192         /* In raw mode MIN is the number of chars wanted, and TIME how long
  2672. 31193          * to wait for them.  With interesting exceptions if either is zero.
  2673. 31194          */
  2674. 31195         tp->tty_min = tp->tty_termios.c_cc[VMIN];
  2675. 31196         if (tp->tty_min == 0 && tp->tty_termios.c_cc[VTIME] > 0)
  2676. 31197                 tp->tty_min = 1;
  2677. 31198   }
  2678. 31199
  2679. 31200   if (!(tp->tty_termios.c_iflag & IXON)) {
  2680. 31201         /* No start/stop output control, so don't leave output inhibited. */
  2681. 31202         tp->tty_inhibited = RUNNING;
  2682. 31203         tp->tty_events = 1;
  2683. 31204   }
  2684. 31205
  2685. 31206   /* Setting the output speed to zero hangs up the phone. */
  2686. 31207   if (tp->tty_termios.c_ospeed == B0) sigchar(tp, SIGHUP);
  2687. 31208
  2688. 31209   /* Set new line speed, character size, etc at the device level. */
  2689. 31210   (*tp->tty_ioctl)(tp);
  2690. 31211 }
  2691. 31214 /*===========================================================================*
  2692. 31215  *                              tty_reply                                    *
  2693. 31216  *===========================================================================*/
  2694. 31217 PUBLIC void tty_reply(code, replyee, proc_nr, status)
  2695. 31218 int code;                       /* TASK_REPLY or REVIVE */
  2696. 31219 int replyee;                    /* destination address for the reply */
  2697. 31220 int proc_nr;                    /* to whom should the reply go? */
  2698. 31221 int status;                     /* reply code */
  2699. 31222 {
  2700. 31223 /* Send a reply to a process that wanted to read or write data. */
  2701. 31224
  2702. 31225   message tty_mess;
  2703. 31226
  2704. 31227   tty_mess.m_type = code;
  2705. 31228   tty_mess.REP_PROC_NR = proc_nr;
  2706. 31229   tty_mess.REP_STATUS = status;
  2707. 31230   if ((status = send(replyee, &tty_mess)) != OK)
  2708. 31231         panic("tty_reply failed, statusn", status);
  2709. 31232 }
  2710. 31235 /*===========================================================================*
  2711. 31236  *                              sigchar                                      *
  2712. 31237  *===========================================================================*/
  2713. 31238 PUBLIC void sigchar(tp, sig)
  2714. 31239 register tty_t *tp;
  2715. .Op 439 src/kernel/tty.c
  2716. 31240 int sig;                        /* SIGINT, SIGQUIT, SIGKILL or SIGHUP */
  2717. 31241 {
  2718. 31242 /* Process a SIGINT, SIGQUIT or SIGKILL char from the keyboard or SIGHUP from
  2719. 31243  * a tty close, "stty 0", or a real RS-232 hangup.  MM will send the signal to
  2720. 31244  * the process group (INT, QUIT), all processes (KILL), or the session leader
  2721. 31245  * (HUP).
  2722. 31246  */
  2723. 31247
  2724. 31248   if (tp->tty_pgrp != 0) cause_sig(tp->tty_pgrp, sig);
  2725. 31249
  2726. 31250   if (!(tp->tty_termios.c_lflag & NOFLSH)) {
  2727. 31251         tp->tty_incount = tp->tty_eotct = 0;    /* kill earlier input */
  2728. 31252         tp->tty_intail = tp->tty_inhead;
  2729. 31253         (*tp->tty_ocancel)(tp);                 /* kill all output */
  2730. 31254         tp->tty_inhibited = RUNNING;
  2731. 31255         tp->tty_events = 1;
  2732. 31256   }
  2733. 31257 }
  2734. 31260 /*==========================================================================*
  2735. 31261  *                              tty_icancel                                 *
  2736. 31262  *==========================================================================*/
  2737. 31263 PRIVATE void tty_icancel(tp)
  2738. 31264 register tty_t *tp;
  2739. 31265 {
  2740. 31266 /* Discard all pending input, tty buffer or device. */
  2741. 31267
  2742. 31268   tp->tty_incount = tp->tty_eotct = 0;
  2743. 31269   tp->tty_intail = tp->tty_inhead;
  2744. 31270   (*tp->tty_icancel)(tp);
  2745. 31271 }
  2746. 31274 /*==========================================================================*
  2747. 31275  *                              tty_init                                    *
  2748. 31276  *==========================================================================*/
  2749. 31277 PRIVATE void tty_init(tp)
  2750. 31278 tty_t *tp;                      /* TTY line to initialize. */
  2751. 31279 {
  2752. 31280 /* Initialize tty structure and call device initialization routines. */
  2753. 31281
  2754. 31282   tp->tty_intail = tp->tty_inhead = tp->tty_inbuf;
  2755. 31283   tp->tty_min = 1;
  2756. 31284   tp->tty_termios = termios_defaults;
  2757. 31285   tp->tty_icancel = tp->tty_ocancel = tp->tty_ioctl = tp->tty_close =
  2758. 31286                                                                 tty_devnop;
  2759. 31287   if (tp < tty_addr(NR_CONS)) {
  2760. 31288         scr_init(tp);
  2761. 31289   } else
  2762. 31290   if (tp < tty_addr(NR_CONS+NR_RS_LINES)) {
  2763. 31291         rs_init(tp);
  2764. 31292   } else {
  2765. 31293         pty_init(tp);
  2766. 31294   }
  2767. 31295 }
  2768. 31298 /*==========================================================================*
  2769. 31299  *                              tty_wakeup                                  *
  2770. .Ep 440 src/kernel/tty.c
  2771. 31300  *==========================================================================*/
  2772. 31301 PUBLIC void tty_wakeup(now)
  2773. 31302 clock_t now;                            /* current time */
  2774. 31303 {
  2775. 31304 /* Wake up TTY when something interesting is happening on one of the terminal
  2776. 31305  * lines, like a character arriving on an RS232 line, a key being typed, or
  2777. 31306  * a timer on a line expiring by TIME.
  2778. 31307  */
  2779. 31308   tty_t *tp;
  2780. 31309
  2781. 31310   /* Scan the timerlist for expired timers and compute the next timeout time. */
  2782. 31311   tty_timeout = TIME_NEVER;
  2783. 31312   while ((tp = tty_timelist) != NULL) {
  2784. 31313         if (tp->tty_time > now) {
  2785. 31314                 tty_timeout = tp->tty_time;     /* this timer is next */
  2786. 31315                 break;
  2787. 31316         }
  2788. 31317         tp->tty_min = 0;                        /* force read to succeed */
  2789. 31318         tp->tty_events = 1;
  2790. 31319         tty_timelist = tp->tty_timenext;
  2791. 31320   }
  2792. 31321
  2793. 31322   /* Let TTY know there is something afoot. */
  2794. 31323   interrupt(TTY);
  2795. 31324 }
  2796. 31327 /*===========================================================================*
  2797. 31328  *                              settimer                                     *
  2798. 31329  *===========================================================================*/
  2799. 31330 PRIVATE void settimer(tp, on)
  2800. 31331 tty_t *tp;                      /* line to set or unset a timer on */
  2801. 31332 int on;                         /* set timer if true, otherwise unset */
  2802. 31333 {
  2803. 31334 /* Set or unset a TIME inspired timer.  This function is interrupt sensitive
  2804. 31335  * due to tty_wakeup(), so it must be called from within lock()/unlock().
  2805. 31336  */
  2806. 31337   tty_t **ptp;
  2807. 31338
  2808. 31339   /* Take tp out of the timerlist if present. */
  2809. 31340   for (ptp = &tty_timelist; *ptp != NULL; ptp = &(*ptp)->tty_timenext) {
  2810. 31341         if (tp == *ptp) {
  2811. 31342                 *ptp = tp->tty_timenext;        /* take tp out of the list */
  2812. 31343                 break;
  2813. 31344         }
  2814. 31345   }
  2815. 31346   if (!on) return;                              /* unsetting it is enough */
  2816. 31347
  2817. 31348   /* Timeout occurs TIME deciseconds from now. */
  2818. 31349   tp->tty_time = get_uptime() + tp->tty_termios.c_cc[VTIME] * (HZ/10);
  2819. 31350
  2820. 31351   /* Find a new place in the list. */
  2821. 31352   for (ptp = &tty_timelist; *ptp != NULL; ptp = &(*ptp)->tty_timenext) {
  2822. 31353         if (tp->tty_time <= (*ptp)->tty_time) break;
  2823. 31354   }
  2824. 31355   tp->tty_timenext = *ptp;
  2825. 31356   *ptp = tp;
  2826. 31357   if (tp->tty_time < tty_timeout) tty_timeout = tp->tty_time;
  2827. 31358 }
  2828. .Op 441 src/kernel/tty.c
  2829. 31361 /*==========================================================================*
  2830. 31362  *                              tty_devnop                                  *
  2831. 31363  *==========================================================================*/
  2832. 31364 PUBLIC void tty_devnop(tp)
  2833. 31365 tty_t *tp;
  2834. 31366 {
  2835. 31367   /* Some functions need not be implemented at the device level. */
  2836. 31368 }
  2837. 31371 #if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
  2838. 31372 /*===========================================================================*
  2839. 31373  *                              compat_getp                                  *
  2840. 31374  *===========================================================================*/
  2841. 31375 PRIVATE int compat_getp(tp, sg)
  2842. 31376 tty_t *tp;
  2843. 31377 struct sgttyb *sg;
  2844. 31378 {
  2845. 31379 /* Translate an old TIOCGETP to the termios equivalent. */
  2846. 31380   int flgs;
  2847. 31381
  2848. 31382   sg->sg_erase = tp->tty_termios.c_cc[VERASE];
  2849. 31383   sg->sg_kill = tp->tty_termios.c_cc[VKILL];
  2850. 31384   sg->sg_ospeed = tspd2sgspd(cfgetospeed(&tp->tty_termios));
  2851. 31385   sg->sg_ispeed = tspd2sgspd(cfgetispeed(&tp->tty_termios));