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

操作系统开发

开发平台:

WINDOWS

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