COMPLETE.TXT
资源名称:os_source.zip [点击查看]
上传用户:datang2001
上传日期:2007-02-01
资源大小:53269k
文件大小:2565k
源码类别:
操作系统开发
开发平台:
C/C++
- 28297 case Mic: { shift = 0;
- 28298 del_mask = 0x7E;
- 28299 };break;
- 28300 default: return EINVAL;
- 28301 }
- 28302
- 28303 if (flag) /* Set input */
- 28304 {
- 28305 output_mask =
- 28306 ((output.left == ON ? 1 : 0) << 1) | (output.right == ON ? 1 : 0);
- 28307
- 28308 if (shift > 0)
- 28309 output_mask <<= shift;
- 28310 else
- 28311 output_mask >>= 1;
- 28312
- 28313 mask &= del_mask;
- 28314 mask |= output_mask;
- 28315
- 28316 mixer_set(MIXER_OUTPUT_CTRL, mask);
- 28317 }
- 28318 else /* Get input */
- 28319 {
- 28320 if (shift > 0)
- 28321 {
- 28322 output.left = ((mask >> (shift+1)) & 1 == 1 ? ON : OFF);
- 28323 output.right = ((mask >> shift) & 1 == 1 ? ON : OFF);
- 28324 }
- 28325 else
- 28326 output.left = ((mask & 1) == 1 ? ON : OFF);
- 28327
- 28328 /* Copy back to user */
- 28329 phys_copy(vir2phys(&output), user_phys, (phys_bytes) sizeof(output));
- 28330 }
- 28331
- 28332 return OK;
- 28333 }
- 28334 #endif /* ENABLE_AUDIO */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/start.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 28400 /* This file contains the C startup code for Minix on Intel processors.
- 28401 * It cooperates with mpx.s to set up a good environment for main().
- 28402 *
- 28403 * This code runs in real mode for a 16 bit kernel and may have to switch
- 28404 * to protected mode for a 286.
- 28405 *
- 28406 * For a 32 bit kernel this already runs in protected mode, but the selectors
- 28407 * are still those given by the BIOS with interrupts disabled, so the
- 28408 * descriptors need to be reloaded and interrupt descriptors made.
- 28409 */
- 28410
- 28411 #include "kernel.h"
- 28412 #include <stdlib.h>
- 28413 #include <minix/boot.h>
- 28414 #include "protect.h"
- 28415
- 28416 PRIVATE char k_environ[256]; /* environment strings passed by loader */
- 28417
- 28418 FORWARD _PROTOTYPE( int k_atoi, (char *s) );
- 28419
- 28420
- 28421 /*==========================================================================*
- 28422 * cstart *
- 28423 *==========================================================================*/
- 28424 PUBLIC void cstart(cs, ds, mcs, mds, parmoff, parmsize)
- 28425 U16_t cs, ds; /* Kernel code and data segment */
- 28426 U16_t mcs, mds; /* Monitor code and data segment */
- 28427 U16_t parmoff, parmsize; /* boot parameters offset and length */
- 28428 {
- 28429 /* Perform system initializations prior to calling main(). */
- 28430
- 28431 register char *envp;
- 28432 phys_bytes mcode_base, mdata_base;
- 28433 unsigned mon_start;
- 28434
- 28435 /* Record where the kernel and the monitor are. */
- 28436 code_base = seg2phys(cs);
- 28437 data_base = seg2phys(ds);
- 28438 mcode_base = seg2phys(mcs);
- 28439 mdata_base = seg2phys(mds);
- 28440
- 28441 /* Initialize protected mode descriptors. */
- 28442 prot_init();
- 28443
- 28444 /* Copy the boot parameters to kernel memory. */
- 28445 if (parmsize > sizeof k_environ - 2) parmsize = sizeof k_environ - 2;
- 28446 phys_copy(mdata_base + parmoff, vir2phys(k_environ), (phys_bytes) parmsize);
- 28447
- 28448 /* Convert important boot environment variables. */
- 28449 boot_parameters.bp_rootdev = k_atoi(k_getenv("rootdev"));
- 28450 boot_parameters.bp_ramimagedev = k_atoi(k_getenv("ramimagedev"));
- 28451 boot_parameters.bp_ramsize = k_atoi(k_getenv("ramsize"));
- 28452 boot_parameters.bp_processor = k_atoi(k_getenv("processor"));
- 28453
- 28454 /* Type of VDU: */
- 28455 envp = k_getenv("video");
- 28456 if (strcmp(envp, "ega") == 0) ega = TRUE;
- 28457 if (strcmp(envp, "vga") == 0) vga = ega = TRUE;
- 28458
- 28459 /* Memory sizes: */
- 28460 low_memsize = k_atoi(k_getenv("memsize"));
- 28461 ext_memsize = k_atoi(k_getenv("emssize"));
- 28462
- 28463 /* Processor? */
- 28464 processor = boot_parameters.bp_processor; /* 86, 186, 286, 386, ... */
- 28465
- 28466 /* XT, AT or MCA bus? */
- 28467 envp = k_getenv("bus");
- 28468 if (envp == NIL_PTR || strcmp(envp, "at") == 0) {
- 28469 pc_at = TRUE;
- 28470 } else
- 28471 if (strcmp(envp, "mca") == 0) {
- 28472 pc_at = ps_mca = TRUE;
- 28473 }
- 28474
- 28475 /* Decide if mode is protected. */
- 28476 #if _WORD_SIZE == 2
- 28477 protected_mode = processor >= 286;
- 28478 #endif
- 28479
- 28480 /* Is there a monitor to return to? If so then keep it safe. */
- 28481 if (!protected_mode) mon_return = 0;
- 28482 mon_start = mcode_base / 1024;
- 28483 if (mon_return && low_memsize > mon_start) low_memsize = mon_start;
- 28484
- 28485 /* Return to assembler code to switch to protected mode (if 286), reload
- 28486 * selectors and call main().
- 28487 */
- 28488 }
- 28491 /*==========================================================================*
- 28492 * k_atoi *
- 28493 *==========================================================================*/
- 28494 PRIVATE int k_atoi(s)
- 28495 register char *s;
- 28496 {
- 28497 /* Convert string to integer. */
- 28498
- 28499 return strtol(s, (char **) NULL, 10);
- 28500 }
- 28503 /*==========================================================================*
- 28504 * k_getenv *
- 28505 *==========================================================================*/
- 28506 PUBLIC char *k_getenv(name)
- 28507 char *name;
- 28508 {
- 28509 /* Get environment value - kernel version of getenv to avoid setting up the
- 28510 * usual environment array.
- 28511 */
- 28512
- 28513 register char *namep;
- 28514 register char *envp;
- 28515
- 28516 for (envp = k_environ; *envp != 0;) {
- 28517 for (namep = name; *namep != 0 && *namep == *envp; namep++, envp++)
- 28518 ;
- 28519 if (*namep == ' ' && *envp == '=') return(envp + 1);
- 28520 while (*envp++ != 0)
- 28521 ;
- 28522 }
- 28523 return(NIL_PTR);
- 28524 }
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/system.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 28600 /* This task handles the interface between file system and kernel as well as
- 28601 * between memory manager and kernel. System services are obtained by sending
- 28602 * sys_task() a message specifying what is needed. To make life easier for
- 28603 * MM and FS, a library is provided with routines whose names are of the
- 28604 * form sys_xxx, e.g. sys_xit sends the SYS_XIT message to sys_task. The
- 28605 * message types and parameters are:
- 28606 *
- 28607 * SYS_FORK informs kernel that a process has forked
- 28608 * SYS_NEWMAP allows MM to set up a process memory map
- 28609 * SYS_GETMAP allows MM to get a process' memory map
- 28610 * SYS_EXEC sets program counter and stack pointer after EXEC
- 28611 * SYS_XIT informs kernel that a process has exited
- 28612 * SYS_GETSP caller wants to read out some process' stack pointer
- 28613 * SYS_TIMES caller wants to get accounting times for a process
- 28614 * SYS_ABORT MM or FS cannot go on; abort MINIX
- 28615 * SYS_FRESH start with a fresh process image during EXEC (68000 only)
- 28616 * SYS_SENDSIG send a signal to a process (POSIX style)
- 28617 * SYS_SIGRETURN complete POSIX-style signalling
- 28618 * SYS_KILL cause a signal to be sent via MM
- 28619 * SYS_ENDSIG finish up after SYS_KILL-type signal
- 28620 * SYS_COPY request a block of data to be copied between processes
- 28621 * SYS_VCOPY request a series of data blocks to be copied between procs
- 28622 * SYS_GBOOT copies the boot parameters to a process
- 28623 * SYS_MEM returns the next free chunk of physical memory
- 28624 * SYS_UMAP compute the physical address for a given virtual address
- 28625 * SYS_TRACE request a trace operation
- 28626 *
- 28627 * Message types and parameters:
- 28628 *
- 28629 * m_type PROC1 PROC2 PID MEM_PTR
- 28630 * ------------------------------------------------------
- 28631 * | SYS_FORK | parent | child | pid | |
- 28632 * |------------+---------+---------+---------+---------|
- 28633 * | SYS_NEWMAP | proc nr | | | map ptr |
- 28634 * |------------+---------+---------+---------+---------|
- 28635 * | SYS_EXEC | proc nr | traced | new sp | |
- 28636 * |------------+---------+---------+---------+---------|
- 28637 * | SYS_XIT | parent | exitee | | |
- 28638 * |------------+---------+---------+---------+---------|
- 28639 * | SYS_GETSP | proc nr | | | |
- 28640 * |------------+---------+---------+---------+---------|
- 28641 * | SYS_TIMES | proc nr | | buf ptr | |
- 28642 * |------------+---------+---------+---------+---------|
- 28643 * | SYS_ABORT | | | | |
- 28644 * |------------+---------+---------+---------+---------|
- 28645 * | SYS_FRESH | proc nr | data_cl | | |
- 28646 * |------------+---------+---------+---------+---------|
- 28647 * | SYS_GBOOT | proc nr | | | bootptr |
- 28648 * |------------+---------+---------+---------+---------|
- 28649 * | SYS_GETMAP | proc nr | | | map ptr |
- 28650 * ------------------------------------------------------
- 28651 *
- 28652 * m_type m1_i1 m1_i2 m1_i3 m1_p1
- 28653 * ----------------+---------+---------+---------+--------------
- 28654 * | SYS_VCOPY | src p | dst p | vec siz | vc addr |
- 28655 * |---------------+---------+---------+---------+-------------|
- 28656 * | SYS_SENDSIG | proc nr | | | smp |
- 28657 * |---------------+---------+---------+---------+-------------|
- 28658 * | SYS_SIGRETURN | proc nr | | | scp |
- 28659 * |---------------+---------+---------+---------+-------------|
- 28660 * | SYS_ENDSIG | proc nr | | | |
- 28661 * -------------------------------------------------------------
- 28662 *
- 28663 * m_type m2_i1 m2_i2 m2_l1 m2_l2
- 28664 * ------------------------------------------------------
- 28665 * | SYS_TRACE | proc_nr | request | addr | data |
- 28666 * ------------------------------------------------------
- 28667 *
- 28668 *
- 28669 * m_type m6_i1 m6_i2 m6_i3 m6_f1
- 28670 * ------------------------------------------------------
- 28671 * | SYS_KILL | proc_nr | sig | | |
- 28672 * ------------------------------------------------------
- 28673 *
- 28674 *
- 28675 * m_type m5_c1 m5_i1 m5_l1 m5_c2 m5_i2 m5_l2 m5_l3
- 28676 * --------------------------------------------------------------------------
- 28677 * | SYS_COPY |src seg|src proc|src vir|dst seg|dst proc|dst vir| byte ct |
- 28678 * --------------------------------------------------------------------------
- 28679 * | SYS_UMAP | seg |proc nr |vir adr| | | | byte ct |
- 28680 * --------------------------------------------------------------------------
- 28681 *
- 28682 *
- 28683 * m_type m1_i1 m1_i2 m1_i3
- 28684 * |------------+----------+----------+----------
- 28685 * | SYS_MEM | mem base | mem size | tot mem |
- 28686 * ----------------------------------------------
- 28687 *
- 28688 * In addition to the main sys_task() entry point, there are 5 other minor
- 28689 * entry points:
- 28690 * cause_sig: take action to cause a signal to occur, sooner or later
- 28691 * inform: tell MM about pending signals
- 28692 * numap: umap D segment starting from process number instead of pointer
- 28693 * umap: compute the physical address for a given virtual address
- 28694 * alloc_segments: allocate segments for 8088 or higher processor
- 28695 */
- 28696
- 28697 #include "kernel.h"
- 28698 #include <signal.h>
- 28699 #include <unistd.h>
- 28700 #include <sys/sigcontext.h>
- 28701 #include <sys/ptrace.h>
- 28702 #include <minix/boot.h>
- 28703 #include <minix/callnr.h>
- 28704 #include <minix/com.h>
- 28705 #include "proc.h"
- 28706 #if (CHIP == INTEL)
- 28707 #include "protect.h"
- 28708 #endif
- 28709
- 28710 /* PSW masks. */
- 28711 #define IF_MASK 0x00000200
- 28712 #define IOPL_MASK 0x003000
- 28713
- 28714 PRIVATE message m;
- 28715
- 28716 FORWARD _PROTOTYPE( int do_abort, (message *m_ptr) );
- 28717 FORWARD _PROTOTYPE( int do_copy, (message *m_ptr) );
- 28718 FORWARD _PROTOTYPE( int do_exec, (message *m_ptr) );
- 28719 FORWARD _PROTOTYPE( int do_fork, (message *m_ptr) );
- 28720 FORWARD _PROTOTYPE( int do_gboot, (message *m_ptr) );
- 28721 FORWARD _PROTOTYPE( int do_getsp, (message *m_ptr) );
- 28722 FORWARD _PROTOTYPE( int do_kill, (message *m_ptr) );
- 28723 FORWARD _PROTOTYPE( int do_mem, (message *m_ptr) );
- 28724 FORWARD _PROTOTYPE( int do_newmap, (message *m_ptr) );
- 28725 FORWARD _PROTOTYPE( int do_sendsig, (message *m_ptr) );
- 28726 FORWARD _PROTOTYPE( int do_sigreturn, (message *m_ptr) );
- 28727 FORWARD _PROTOTYPE( int do_endsig, (message *m_ptr) );
- 28728 FORWARD _PROTOTYPE( int do_times, (message *m_ptr) );
- 28729 FORWARD _PROTOTYPE( int do_trace, (message *m_ptr) );
- 28730 FORWARD _PROTOTYPE( int do_umap, (message *m_ptr) );
- 28731 FORWARD _PROTOTYPE( int do_xit, (message *m_ptr) );
- 28732 FORWARD _PROTOTYPE( int do_vcopy, (message *m_ptr) );
- 28733 FORWARD _PROTOTYPE( int do_getmap, (message *m_ptr) );
- 28734
- 28735 #if (SHADOWING == 1)
- 28736 FORWARD _PROTOTYPE( int do_fresh, (message *m_ptr) );
- 28737 #endif
- 28738
- 28739 /*===========================================================================*
- 28740 * sys_task *
- 28741 *===========================================================================*/
- 28742 PUBLIC void sys_task()
- 28743 {
- 28744 /* Main entry point of sys_task. Get the message and dispatch on type. */
- 28745
- 28746 register int r;
- 28747
- 28748 while (TRUE) {
- 28749 receive(ANY, &m);
- 28750
- 28751 switch (m.m_type) { /* which system call */
- 28752 case SYS_FORK: r = do_fork(&m); break;
- 28753 case SYS_NEWMAP: r = do_newmap(&m); break;
- 28754 case SYS_GETMAP: r = do_getmap(&m); break;
- 28755 case SYS_EXEC: r = do_exec(&m); break;
- 28756 case SYS_XIT: r = do_xit(&m); break;
- 28757 case SYS_GETSP: r = do_getsp(&m); break;
- 28758 case SYS_TIMES: r = do_times(&m); break;
- 28759 case SYS_ABORT: r = do_abort(&m); break;
- 28760 #if (SHADOWING == 1)
- 28761 case SYS_FRESH: r = do_fresh(&m); break;
- 28762 #endif
- 28763 case SYS_SENDSIG: r = do_sendsig(&m); break;
- 28764 case SYS_SIGRETURN: r = do_sigreturn(&m); break;
- 28765 case SYS_KILL: r = do_kill(&m); break;
- 28766 case SYS_ENDSIG: r = do_endsig(&m); break;
- 28767 case SYS_COPY: r = do_copy(&m); break;
- 28768 case SYS_VCOPY: r = do_vcopy(&m); break;
- 28769 case SYS_GBOOT: r = do_gboot(&m); break;
- 28770 case SYS_MEM: r = do_mem(&m); break;
- 28771 case SYS_UMAP: r = do_umap(&m); break;
- 28772 case SYS_TRACE: r = do_trace(&m); break;
- 28773 default: r = E_BAD_FCN;
- 28774 }
- 28775
- 28776 m.m_type = r; /* 'r' reports status of call */
- 28777 send(m.m_source, &m); /* send reply to caller */
- 28778 }
- 28779 }
- 28782 /*===========================================================================*
- 28783 * do_fork *
- 28784 *===========================================================================*/
- 28785 PRIVATE int do_fork(m_ptr)
- 28786 register message *m_ptr; /* pointer to request message */
- 28787 {
- 28788 /* Handle sys_fork(). m_ptr->PROC1 has forked. The child is m_ptr->PROC2. */
- 28789
- 28790 #if (CHIP == INTEL)
- 28791 reg_t old_ldt_sel;
- 28792 #endif
- 28793 register struct proc *rpc;
- 28794 struct proc *rpp;
- 28795
- 28796 if (!isoksusern(m_ptr->PROC1) || !isoksusern(m_ptr->PROC2))
- 28797 return(E_BAD_PROC);
- 28798 rpp = proc_addr(m_ptr->PROC1);
- 28799 rpc = proc_addr(m_ptr->PROC2);
- 28800
- 28801 /* Copy parent 'proc' struct to child. */
- 28802 #if (CHIP == INTEL)
- 28803 old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */
- 28804 #endif
- 28805
- 28806 *rpc = *rpp; /* copy 'proc' struct */
- 28807
- 28808 #if (CHIP == INTEL)
- 28809 rpc->p_ldt_sel = old_ldt_sel;
- 28810 #endif
- 28811 rpc->p_nr = m_ptr->PROC2; /* this was obliterated by copy */
- 28812
- 28813 #if (SHADOWING == 0)
- 28814 rpc->p_flags |= NO_MAP; /* inhibit the process from running */
- 28815 #endif
- 28816
- 28817 rpc->p_flags &= ~(PENDING | SIG_PENDING | P_STOP);
- 28818
- 28819 /* Only 1 in group should have PENDING, child does not inherit trace status*/
- 28820 sigemptyset(&rpc->p_pending);
- 28821 rpc->p_pendcount = 0;
- 28822 rpc->p_pid = m_ptr->PID; /* install child's pid */
- 28823 rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */
- 28824
- 28825 rpc->user_time = 0; /* set all the accounting times to 0 */
- 28826 rpc->sys_time = 0;
- 28827 rpc->child_utime = 0;
- 28828 rpc->child_stime = 0;
- 28829
- 28830 #if (SHADOWING == 1)
- 28831 rpc->p_nflips = 0;
- 28832 mkshadow(rpp, (phys_clicks)m_ptr->m1_p1); /* run child first */
- 28833 #endif
- 28834
- 28835 return(OK);
- 28836 }
- 28839 /*===========================================================================*
- 28840 * do_newmap *
- 28841 *===========================================================================*/
- 28842 PRIVATE int do_newmap(m_ptr)
- 28843 message *m_ptr; /* pointer to request message */
- 28844 {
- 28845 /* Handle sys_newmap(). Fetch the memory map from MM. */
- 28846
- 28847 register struct proc *rp;
- 28848 phys_bytes src_phys;
- 28849 int caller; /* whose space has the new map (usually MM) */
- 28850 int k; /* process whose map is to be loaded */
- 28851 int old_flags; /* value of flags before modification */
- 28852 struct mem_map *map_ptr; /* virtual address of map inside caller (MM) */
- 28853
- 28854 /* Extract message parameters and copy new memory map from MM. */
- 28855 caller = m_ptr->m_source;
- 28856 k = m_ptr->PROC1;
- 28857 map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
- 28858 if (!isokprocn(k)) return(E_BAD_PROC);
- 28859 rp = proc_addr(k); /* ptr to entry of user getting new map */
- 28860
- 28861 /* Copy the map from MM. */
- 28862 src_phys = umap(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
- 28863 if (src_phys == 0) panic("bad call to sys_newmap", NO_NUM);
- 28864 phys_copy(src_phys, vir2phys(rp->p_map), (phys_bytes) sizeof(rp->p_map));
- 28865
- 28866 #if (SHADOWING == 0)
- 28867 #if (CHIP != M68000)
- 28868 alloc_segments(rp);
- 28869 #else
- 28870 pmmu_init_proc(rp);
- 28871 #endif
- 28872 old_flags = rp->p_flags; /* save the previous value of the flags */
- 28873 rp->p_flags &= ~NO_MAP;
- 28874 if (old_flags != 0 && rp->p_flags == 0) lock_ready(rp);
- 28875 #endif
- 28876
- 28877 return(OK);
- 28878 }
- 28881 /*===========================================================================*
- 28882 * do_getmap *
- 28883 *===========================================================================*/
- 28884 PRIVATE int do_getmap(m_ptr)
- 28885 message *m_ptr; /* pointer to request message */
- 28886 {
- 28887 /* Handle sys_getmap(). Report the memory map to MM. */
- 28888
- 28889 register struct proc *rp;
- 28890 phys_bytes dst_phys;
- 28891 int caller; /* where the map has to be stored */
- 28892 int k; /* process whose map is to be loaded */
- 28893 struct mem_map *map_ptr; /* virtual address of map inside caller (MM) */
- 28894
- 28895 /* Extract message parameters and copy new memory map to MM. */
- 28896 caller = m_ptr->m_source;
- 28897 k = m_ptr->PROC1;
- 28898 map_ptr = (struct mem_map *) m_ptr->MEM_PTR;
- 28899
- 28900 if (!isokprocn(k))
- 28901 panic("do_getmap got bad proc: ", m_ptr->PROC1);
- 28902
- 28903 rp = proc_addr(k); /* ptr to entry of the map */
- 28904
- 28905 /* Copy the map to MM. */
- 28906 dst_phys = umap(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_map));
- 28907 if (dst_phys == 0) panic("bad call to sys_getmap", NO_NUM);
- 28908 phys_copy(vir2phys(rp->p_map), dst_phys, sizeof(rp->p_map));
- 28909
- 28910 return(OK);
- 28911 }
- 28914 /*===========================================================================*
- 28915 * do_exec *
- 28916 *===========================================================================*/
- 28917 PRIVATE int do_exec(m_ptr)
- 28918 register message *m_ptr; /* pointer to request message */
- 28919 {
- 28920 /* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */
- 28921
- 28922 register struct proc *rp;
- 28923 reg_t sp; /* new sp */
- 28924 phys_bytes phys_name;
- 28925 char *np;
- 28926 #define NLEN (sizeof(rp->p_name)-1)
- 28927
- 28928 if (!isoksusern(m_ptr->PROC1)) return E_BAD_PROC;
- 28929 /* PROC2 field is used as flag to indicate process is being traced */
- 28930 if (m_ptr->PROC2) cause_sig(m_ptr->PROC1, SIGTRAP);
- 28931 sp = (reg_t) m_ptr->STACK_PTR;
- 28932 rp = proc_addr(m_ptr->PROC1);
- 28933 rp->p_reg.sp = sp; /* set the stack pointer */
- 28934 #if (CHIP == M68000)
- 28935 rp->p_splow = sp; /* set the stack pointer low water */
- 28936 #ifdef FPP
- 28937 /* Initialize fpp for this process */
- 28938 fpp_new_state(rp);
- 28939 #endif
- 28940 #endif
- 28941 rp->p_reg.pc = (reg_t) m_ptr->IP_PTR; /* set pc */
- 28942 rp->p_alarm = 0; /* reset alarm timer */
- 28943 rp->p_flags &= ~RECEIVING; /* MM does not reply to EXEC call */
- 28944 if (rp->p_flags == 0) lock_ready(rp);
- 28945
- 28946 /* Save command name for debugging, ps(1) output, etc. */
- 28947 phys_name = numap(m_ptr->m_source, (vir_bytes) m_ptr->NAME_PTR,
- 28948 (vir_bytes) NLEN);
- 28949 if (phys_name != 0) {
- 28950 phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) NLEN);
- 28951 for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {}
- 28952 *np = 0;
- 28953 }
- 28954 return(OK);
- 28955 }
- 28958 /*===========================================================================*
- 28959 * do_xit *
- 28960 *===========================================================================*/
- 28961 PRIVATE int do_xit(m_ptr)
- 28962 message *m_ptr; /* pointer to request message */
- 28963 {
- 28964 /* Handle sys_xit(). A process has exited. */
- 28965
- 28966 register struct proc *rp, *rc;
- 28967 struct proc *np, *xp;
- 28968 int parent; /* number of exiting proc's parent */
- 28969 int proc_nr; /* number of process doing the exit */
- 28970 phys_clicks base, size;
- 28971
- 28972 parent = m_ptr->PROC1; /* slot number of parent process */
- 28973 proc_nr = m_ptr->PROC2; /* slot number of exiting process */
- 28974 if (!isoksusern(parent) || !isoksusern(proc_nr)) return(E_BAD_PROC);
- 28975 rp = proc_addr(parent);
- 28976 rc = proc_addr(proc_nr);
- 28977 lock();
- 28978 rp->child_utime += rc->user_time + rc->child_utime; /* accum child times */
- 28979 rp->child_stime += rc->sys_time + rc->child_stime;
- 28980 unlock();
- 28981 rc->p_alarm = 0; /* turn off alarm timer */
- 28982 if (rc->p_flags == 0) lock_unready(rc);
- 28983
- 28984 #if (SHADOWING == 1)
- 28985 rmshadow(rc, &base, &size);
- 28986 m_ptr->m1_i1 = (int)base;
- 28987 m_ptr->m1_i2 = (int)size;
- 28988 #endif
- 28989
- 28990 strcpy(rc->p_name, "<noname>"); /* process no longer has a name */
- 28991
- 28992 /* If the process being terminated happens to be queued trying to send a
- 28993 * message (i.e., the process was killed by a signal, rather than it doing an
- 28994 * EXIT), then it must be removed from the message queues.
- 28995 */
- 28996 if (rc->p_flags & SENDING) {
- 28997 /* Check all proc slots to see if the exiting process is queued. */
- 28998 for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
- 28999 if (rp->p_callerq == NIL_PROC) continue;
- 29000 if (rp->p_callerq == rc) {
- 29001 /* Exiting process is on front of this queue. */
- 29002 rp->p_callerq = rc->p_sendlink;
- 29003 break;
- 29004 } else {
- 29005 /* See if exiting process is in middle of queue. */
- 29006 np = rp->p_callerq;
- 29007 while ( ( xp = np->p_sendlink) != NIL_PROC)
- 29008 if (xp == rc) {
- 29009 np->p_sendlink = xp->p_sendlink;
- 29010 break;
- 29011 } else {
- 29012 np = xp;
- 29013 }
- 29014 }
- 29015 }
- 29016 }
- 29017 #if (CHIP == M68000) && (SHADOWING == 0)
- 29018 pmmu_delete(rc); /* we're done remove tables */
- 29019 #endif
- 29020
- 29021 if (rc->p_flags & PENDING) --sig_procs;
- 29022 sigemptyset(&rc->p_pending);
- 29023 rc->p_pendcount = 0;
- 29024 rc->p_flags = P_SLOT_FREE;
- 29025 return(OK);
- 29026 }
- 29029 /*===========================================================================*
- 29030 * do_getsp *
- 29031 *===========================================================================*/
- 29032 PRIVATE int do_getsp(m_ptr)
- 29033 register message *m_ptr; /* pointer to request message */
- 29034 {
- 29035 /* Handle sys_getsp(). MM wants to know what sp is. */
- 29036
- 29037 register struct proc *rp;
- 29038
- 29039 if (!isoksusern(m_ptr->PROC1)) return(E_BAD_PROC);
- 29040 rp = proc_addr(m_ptr->PROC1);
- 29041 m_ptr->STACK_PTR = (char *) rp->p_reg.sp; /* return sp here (bad type) */
- 29042 return(OK);
- 29043 }
- 29046 /*===========================================================================*
- 29047 * do_times *
- 29048 *===========================================================================*/
- 29049 PRIVATE int do_times(m_ptr)
- 29050 register message *m_ptr; /* pointer to request message */
- 29051 {
- 29052 /* Handle sys_times(). Retrieve the accounting information. */
- 29053
- 29054 register struct proc *rp;
- 29055
- 29056 if (!isoksusern(m_ptr->PROC1)) return E_BAD_PROC;
- 29057 rp = proc_addr(m_ptr->PROC1);
- 29058
- 29059 /* Insert the times needed by the TIMES system call in the message. */
- 29060 lock(); /* halt the volatile time counters in rp */
- 29061 m_ptr->USER_TIME = rp->user_time;
- 29062 m_ptr->SYSTEM_TIME = rp->sys_time;
- 29063 unlock();
- 29064 m_ptr->CHILD_UTIME = rp->child_utime;
- 29065 m_ptr->CHILD_STIME = rp->child_stime;
- 29066 m_ptr->BOOT_TICKS = get_uptime();
- 29067 return(OK);
- 29068 }
- 29071 /*===========================================================================*
- 29072 * do_abort *
- 29073 *===========================================================================*/
- 29074 PRIVATE int do_abort(m_ptr)
- 29075 message *m_ptr; /* pointer to request message */
- 29076 {
- 29077 /* Handle sys_abort. MINIX is unable to continue. Terminate operation. */
- 29078 char monitor_code[64];
- 29079 phys_bytes src_phys;
- 29080
- 29081 if (m_ptr->m1_i1 == RBT_MONITOR) {
- 29082 /* The monitor is to run user specified instructions. */
- 29083 src_phys = numap(m_ptr->m_source, (vir_bytes) m_ptr->m1_p1,
- 29084 (vir_bytes) sizeof(monitor_code));
- 29085 if (src_phys == 0) panic("bad monitor code from", m_ptr->m_source);
- 29086 phys_copy(src_phys, vir2phys(monitor_code),
- 29087 (phys_bytes) sizeof(monitor_code));
- 29088 reboot_code = vir2phys(monitor_code);
- 29089 }
- 29090 wreboot(m_ptr->m1_i1);
- 29091 return(OK); /* pro-forma (really EDISASTER) */
- 29092 }
- 29095 #if (SHADOWING == 1)
- 29096 /*===========================================================================*
- 29097 * do_fresh *
- 29098 *===========================================================================*/
- 29099 PRIVATE int do_fresh(m_ptr) /* for 68000 only */
- 29100 message *m_ptr; /* pointer to request message */
- 29101 {
- 29102 /* Handle sys_fresh. Start with fresh process image during EXEC. */
- 29103
- 29104 register struct proc *p;
- 29105 int proc_nr; /* number of process doing the exec */
- 29106 phys_clicks base, size;
- 29107 phys_clicks c1, nc;
- 29108
- 29109 proc_nr = m_ptr->PROC1; /* slot number of exec-ing process */
- 29110 if (!isokprocn(proc_nr)) return(E_BAD_PROC);
- 29111 p = proc_addr(proc_nr);
- 29112 rmshadow(p, &base, &size);
- 29113 do_newmap(m_ptr);
- 29114 c1 = p->p_map[D].mem_phys;
- 29115 nc = p->p_map[S].mem_phys - p->p_map[D].mem_phys + p->p_map[S].mem_len;
- 29116 c1 += m_ptr->m1_i2;
- 29117 nc -= m_ptr->m1_i2;
- 29118 zeroclicks(c1, nc);
- 29119 m_ptr->m1_i1 = (int)base;
- 29120 m_ptr->m1_i2 = (int)size;
- 29121 return(OK);
- 29122 }
- 29123 #endif /* (SHADOWING == 1) */
- 29124
- 29125
- 29126 /*===========================================================================*
- 29127 * do_sendsig *
- 29128 *===========================================================================*/
- 29129 PRIVATE int do_sendsig(m_ptr)
- 29130 message *m_ptr; /* pointer to request message */
- 29131 {
- 29132 /* Handle sys_sendsig, POSIX-style signal */
- 29133
- 29134 struct sigmsg smsg;
- 29135 register struct proc *rp;
- 29136 phys_bytes src_phys, dst_phys;
- 29137 struct sigcontext sc, *scp;
- 29138 struct sigframe fr, *frp;
- 29139
- 29140 if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
- 29141 rp = proc_addr(m_ptr->PROC1);
- 29142
- 29143 /* Get the sigmsg structure into our address space. */
- 29144 src_phys = umap(proc_addr(MM_PROC_NR), D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
- 29145 (vir_bytes) sizeof(struct sigmsg));
- 29146 if (src_phys == 0)
- 29147 panic("do_sendsig can't signal: bad sigmsg address from MM", NO_NUM);
- 29148 phys_copy(src_phys, vir2phys(&smsg), (phys_bytes) sizeof(struct sigmsg));
- 29149
- 29150 /* Compute the usr stack pointer value where sigcontext will be stored. */
- 29151 scp = (struct sigcontext *) smsg.sm_stkptr - 1;
- 29152
- 29153 /* Copy the registers to the sigcontext structure. */
- 29154 memcpy(&sc.sc_regs, &rp->p_reg, sizeof(struct sigregs));
- 29155
- 29156 /* Finish the sigcontext initialization. */
- 29157 sc.sc_flags = SC_SIGCONTEXT;
- 29158
- 29159 sc.sc_mask = smsg.sm_mask;
- 29160
- 29161 /* Copy the sigcontext structure to the user's stack. */
- 29162 dst_phys = umap(rp, D, (vir_bytes) scp,
- 29163 (vir_bytes) sizeof(struct sigcontext));
- 29164 if (dst_phys == 0) return(EFAULT);
- 29165 phys_copy(vir2phys(&sc), dst_phys, (phys_bytes) sizeof(struct sigcontext));
- 29166
- 29167 /* Initialize the sigframe structure. */
- 29168 frp = (struct sigframe *) scp - 1;
- 29169 fr.sf_scpcopy = scp;
- 29170 fr.sf_retadr2= (void (*)()) rp->p_reg.pc;
- 29171 fr.sf_fp = rp->p_reg.fp;
- 29172 rp->p_reg.fp = (reg_t) &frp->sf_fp;
- 29173 fr.sf_scp = scp;
- 29174 fr.sf_code = 0; /* XXX - should be used for type of FP exception */
- 29175 fr.sf_signo = smsg.sm_signo;
- 29176 fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;
- 29177
- 29178 /* Copy the sigframe structure to the user's stack. */
- 29179 dst_phys = umap(rp, D, (vir_bytes) frp, (vir_bytes) sizeof(struct sigframe));
- 29180 if (dst_phys == 0) return(EFAULT);
- 29181 phys_copy(vir2phys(&fr), dst_phys, (phys_bytes) sizeof(struct sigframe));
- 29182
- 29183 /* Reset user registers to execute the signal handler. */
- 29184 rp->p_reg.sp = (reg_t) frp;
- 29185 rp->p_reg.pc = (reg_t) smsg.sm_sighandler;
- 29186
- 29187 return(OK);
- 29188 }
- 29190 /*===========================================================================*
- 29191 * do_sigreturn *
- 29192 *===========================================================================*/
- 29193 PRIVATE int do_sigreturn(m_ptr)
- 29194 register message *m_ptr;
- 29195 {
- 29196 /* POSIX style signals require sys_sigreturn to put things in order before the
- 29197 * signalled process can resume execution
- 29198 */
- 29199
- 29200 struct sigcontext sc;
- 29201 register struct proc *rp;
- 29202 phys_bytes src_phys;
- 29203
- 29204 if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
- 29205 rp = proc_addr(m_ptr->PROC1);
- 29206
- 29207 /* Copy in the sigcontext structure. */
- 29208 src_phys = umap(rp, D, (vir_bytes) m_ptr->SIG_CTXT_PTR,
- 29209 (vir_bytes) sizeof(struct sigcontext));
- 29210 if (src_phys == 0) return(EFAULT);
- 29211 phys_copy(src_phys, vir2phys(&sc), (phys_bytes) sizeof(struct sigcontext));
- 29212
- 29213 /* Make sure that this is not just a jmp_buf. */
- 29214 if ((sc.sc_flags & SC_SIGCONTEXT) == 0) return(EINVAL);
- 29215
- 29216 /* Fix up only certain key registers if the compiler doesn't use
- 29217 * register variables within functions containing setjmp.
- 29218 */
- 29219 if (sc.sc_flags & SC_NOREGLOCALS) {
- 29220 rp->p_reg.retreg = sc.sc_retreg;
- 29221 rp->p_reg.fp = sc.sc_fp;
- 29222 rp->p_reg.pc = sc.sc_pc;
- 29223 rp->p_reg.sp = sc.sc_sp;
- 29224 return (OK);
- 29225 }
- 29226 sc.sc_psw = rp->p_reg.psw;
- 29227
- 29228 #if (CHIP == INTEL)
- 29229 /* Don't panic kernel if user gave bad selectors. */
- 29230 sc.sc_cs = rp->p_reg.cs;
- 29231 sc.sc_ds = rp->p_reg.ds;
- 29232 sc.sc_es = rp->p_reg.es;
- 29233 #if _WORD_SIZE == 4
- 29234 sc.sc_fs = rp->p_reg.fs;
- 29235 sc.sc_gs = rp->p_reg.gs;
- 29236 #endif
- 29237 #endif
- 29238
- 29239 /* Restore the registers. */
- 29240 memcpy(&rp->p_reg, (char *)&sc.sc_regs, sizeof(struct sigregs));
- 29241
- 29242 return(OK);
- 29243 }
- 29245 /*===========================================================================*
- 29246 * do_kill *
- 29247 *===========================================================================*/
- 29248 PRIVATE int do_kill(m_ptr)
- 29249 register message *m_ptr; /* pointer to request message */
- 29250 {
- 29251 /* Handle sys_kill(). Cause a signal to be sent to a process via MM.
- 29252 * Note that this has nothing to do with the kill (2) system call, this
- 29253 * is how the FS (and possibly other servers) get access to cause_sig to
- 29254 * send a KSIG message to MM
- 29255 */
- 29256
- 29257 if (!isokusern(m_ptr->PR)) return(E_BAD_PROC);
- 29258 cause_sig(m_ptr->PR, m_ptr->SIGNUM);
- 29259 return(OK);
- 29260 }
- 29263 /*===========================================================================*
- 29264 * do_endsig *
- 29265 *===========================================================================*/
- 29266 PRIVATE int do_endsig(m_ptr)
- 29267 register message *m_ptr; /* pointer to request message */
- 29268 {
- 29269 /* Finish up after a KSIG-type signal, caused by a SYS_KILL message or a call
- 29270 * to cause_sig by a task
- 29271 */
- 29272
- 29273 register struct proc *rp;
- 29274
- 29275 if (!isokusern(m_ptr->PROC1)) return(E_BAD_PROC);
- 29276 rp = proc_addr(m_ptr->PROC1);
- 29277
- 29278 /* MM has finished one KSIG. */
- 29279 if (rp->p_pendcount != 0 && --rp->p_pendcount == 0
- 29280 && (rp->p_flags &= ~SIG_PENDING) == 0)
- 29281 lock_ready(rp);
- 29282 return(OK);
- 29283 }
- 29285 /*===========================================================================*
- 29286 * do_copy *
- 29287 *===========================================================================*/
- 29288 PRIVATE int do_copy(m_ptr)
- 29289 register message *m_ptr; /* pointer to request message */
- 29290 {
- 29291 /* Handle sys_copy(). Copy data for MM or FS. */
- 29292
- 29293 int src_proc, dst_proc, src_space, dst_space;
- 29294 vir_bytes src_vir, dst_vir;
- 29295 phys_bytes src_phys, dst_phys, bytes;
- 29296
- 29297 /* Dismember the command message. */
- 29298 src_proc = m_ptr->SRC_PROC_NR;
- 29299 dst_proc = m_ptr->DST_PROC_NR;
- 29300 src_space = m_ptr->SRC_SPACE;
- 29301 dst_space = m_ptr->DST_SPACE;
- 29302 src_vir = (vir_bytes) m_ptr->SRC_BUFFER;
- 29303 dst_vir = (vir_bytes) m_ptr->DST_BUFFER;
- 29304 bytes = (phys_bytes) m_ptr->COPY_BYTES;
- 29305
- 29306 /* Compute the source and destination addresses and do the copy. */
- 29307 #if (SHADOWING == 0)
- 29308 if (src_proc == ABS)
- 29309 src_phys = (phys_bytes) m_ptr->SRC_BUFFER;
- 29310 else {
- 29311 if (bytes != (vir_bytes) bytes)
- 29312 /* This would happen for 64K segments and 16-bit vir_bytes.
- 29313 * It would happen a lot for do_fork except MM uses ABS
- 29314 * copies for that case.
- 29315 */
- 29316 panic("overflow in count in do_copy", NO_NUM);
- 29317 #endif
- 29318
- 29319 src_phys = umap(proc_addr(src_proc), src_space, src_vir,
- 29320 (vir_bytes) bytes);
- 29321 #if (SHADOWING == 0)
- 29322 }
- 29323 #endif
- 29324
- 29325 #if (SHADOWING == 0)
- 29326 if (dst_proc == ABS)
- 29327 dst_phys = (phys_bytes) m_ptr->DST_BUFFER;
- 29328 else
- 29329 #endif
- 29330 dst_phys = umap(proc_addr(dst_proc), dst_space, dst_vir,
- 29331 (vir_bytes) bytes);
- 29332
- 29333 if (src_phys == 0 || dst_phys == 0) return(EFAULT);
- 29334 phys_copy(src_phys, dst_phys, bytes);
- 29335 return(OK);
- 29336 }
- 29339 /*===========================================================================*
- 29340 * do_vcopy *
- 29341 *===========================================================================*/
- 29342 PRIVATE int do_vcopy(m_ptr)
- 29343 register message *m_ptr; /* pointer to request message */
- 29344 {
- 29345 /* Handle sys_vcopy(). Copy multiple blocks of memory */
- 29346
- 29347 int src_proc, dst_proc, vect_s, i;
- 29348 vir_bytes src_vir, dst_vir, vect_addr;
- 29349 phys_bytes src_phys, dst_phys, bytes;
- 29350 cpvec_t cpvec_table[CPVEC_NR];
- 29351
- 29352 /* Dismember the command message. */
- 29353 src_proc = m_ptr->m1_i1;
- 29354 dst_proc = m_ptr->m1_i2;
- 29355 vect_s = m_ptr->m1_i3;
- 29356 vect_addr = (vir_bytes)m_ptr->m1_p1;
- 29357
- 29358 if (vect_s > CPVEC_NR) return EDOM;
- 29359
- 29360 src_phys= numap (m_ptr->m_source, vect_addr, vect_s * sizeof(cpvec_t));
- 29361 if (!src_phys) return EFAULT;
- 29362 phys_copy(src_phys, vir2phys(cpvec_table),
- 29363 (phys_bytes) (vect_s * sizeof(cpvec_t)));
- 29364
- 29365 for (i = 0; i < vect_s; i++) {
- 29366 src_vir= cpvec_table[i].cpv_src;
- 29367 dst_vir= cpvec_table[i].cpv_dst;
- 29368 bytes= cpvec_table[i].cpv_size;
- 29369 src_phys = numap(src_proc,src_vir,(vir_bytes)bytes);
- 29370 dst_phys = numap(dst_proc,dst_vir,(vir_bytes)bytes);
- 29371 if (src_phys == 0 || dst_phys == 0) return(EFAULT);
- 29372 phys_copy(src_phys, dst_phys, bytes);
- 29373 }
- 29374 return(OK);
- 29375 }
- 29378 /*==========================================================================*
- 29379 * do_gboot *
- 29380 *==========================================================================*/
- 29381 PUBLIC struct bparam_s boot_parameters;
- 29382
- 29383 PRIVATE int do_gboot(m_ptr)
- 29384 message *m_ptr; /* pointer to request message */
- 29385 {
- 29386 /* Copy the boot parameters. Normally only called during fs init. */
- 29387
- 29388 phys_bytes dst_phys;
- 29389
- 29390 dst_phys = umap(proc_addr(m_ptr->PROC1), D, (vir_bytes) m_ptr->MEM_PTR,
- 29391 (vir_bytes) sizeof(boot_parameters));
- 29392 if (dst_phys == 0) panic("bad call to SYS_GBOOT", NO_NUM);
- 29393 phys_copy(vir2phys(&boot_parameters), dst_phys,
- 29394 (phys_bytes) sizeof(boot_parameters));
- 29395 return(OK);
- 29396 }
- 29399 /*===========================================================================*
- 29400 * do_mem *
- 29401 *===========================================================================*/
- 29402 PRIVATE int do_mem(m_ptr)
- 29403 register message *m_ptr; /* pointer to request message */
- 29404 {
- 29405 /* Return the base and size of the next chunk of memory. */
- 29406
- 29407 struct memory *memp;
- 29408
- 29409 for (memp = mem; memp < &mem[NR_MEMS]; ++memp) {
- 29410 m_ptr->m1_i1 = memp->base;
- 29411 m_ptr->m1_i2 = memp->size;
- 29412 m_ptr->m1_i3 = tot_mem_size;
- 29413 memp->size = 0;
- 29414 if (m_ptr->m1_i2 != 0) break; /* found a chunk */
- 29415 }
- 29416 return(OK);
- 29417 }
- 29420 /*==========================================================================*
- 29421 * do_umap *
- 29422 *==========================================================================*/
- 29423 PRIVATE int do_umap(m_ptr)
- 29424 register message *m_ptr; /* pointer to request message */
- 29425 {
- 29426 /* Same as umap(), for non-kernel processes. */
- 29427
- 29428 m_ptr->SRC_BUFFER = umap(proc_addr((int) m_ptr->SRC_PROC_NR),
- 29429 (int) m_ptr->SRC_SPACE,
- 29430 (vir_bytes) m_ptr->SRC_BUFFER,
- 29431 (vir_bytes) m_ptr->COPY_BYTES);
- 29432 return(OK);
- 29433 }
- 29436 /*==========================================================================*
- 29437 * do_trace *
- 29438 *==========================================================================*/
- 29439 #define TR_PROCNR (m_ptr->m2_i1)
- 29440 #define TR_REQUEST (m_ptr->m2_i2)
- 29441 #define TR_ADDR ((vir_bytes) m_ptr->m2_l1)
- 29442 #define TR_DATA (m_ptr->m2_l2)
- 29443 #define TR_VLSIZE ((vir_bytes) sizeof(long))
- 29444
- 29445 PRIVATE int do_trace(m_ptr)
- 29446 register message *m_ptr;
- 29447 {
- 29448 /* Handle the debugging commands supported by the ptrace system call
- 29449 * The commands are:
- 29450 * T_STOP stop the process
- 29451 * T_OK enable tracing by parent for this process
- 29452 * T_GETINS return value from instruction space
- 29453 * T_GETDATA return value from data space
- 29454 * T_GETUSER return value from user process table
- 29455 * T_SETINS set value from instruction space
- 29456 * T_SETDATA set value from data space
- 29457 * T_SETUSER set value in user process table
- 29458 * T_RESUME resume execution
- 29459 * T_EXIT exit
- 29460 * T_STEP set trace bit
- 29461 *
- 29462 * The T_OK and T_EXIT commands are handled completely by the memory manager,
- 29463 * all others come here.
- 29464 */
- 29465
- 29466 register struct proc *rp;
- 29467 phys_bytes src, dst;
- 29468 int i;
- 29469
- 29470 rp = proc_addr(TR_PROCNR);
- 29471 if (rp->p_flags & P_SLOT_FREE) return(EIO);
- 29472 switch (TR_REQUEST) {
- 29473 case T_STOP: /* stop process */
- 29474 if (rp->p_flags == 0) lock_unready(rp);
- 29475 rp->p_flags |= P_STOP;
- 29476 rp->p_reg.psw &= ~TRACEBIT; /* clear trace bit */
- 29477 return(OK);
- 29478
- 29479 case T_GETINS: /* return value from instruction space */
- 29480 if (rp->p_map[T].mem_len != 0) {
- 29481 if ((src = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
- 29482 phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
- 29483 break;
- 29484 }
- 29485 /* Text space is actually data space - fall through. */
- 29486
- 29487 case T_GETDATA: /* return value from data space */
- 29488 if ((src = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
- 29489 phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
- 29490 break;
- 29491
- 29492 case T_GETUSER: /* return value from process table */
- 29493 if ((TR_ADDR & (sizeof(long) - 1)) != 0 ||
- 29494 TR_ADDR > sizeof(struct proc) - sizeof(long))
- 29495 return(EIO);
- 29496 TR_DATA = *(long *) ((char *) rp + (int) TR_ADDR);
- 29497 break;
- 29498
- 29499 case T_SETINS: /* set value in instruction space */
- 29500 if (rp->p_map[T].mem_len != 0) {
- 29501 if ((dst = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
- 29502 phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
- 29503 TR_DATA = 0;
- 29504 break;
- 29505 }
- 29506 /* Text space is actually data space - fall through. */
- 29507
- 29508 case T_SETDATA: /* set value in data space */
- 29509 if ((dst = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
- 29510 phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
- 29511 TR_DATA = 0;
- 29512 break;
- 29513
- 29514 case T_SETUSER: /* set value in process table */
- 29515 if ((TR_ADDR & (sizeof(reg_t) - 1)) != 0 ||
- 29516 TR_ADDR > sizeof(struct stackframe_s) - sizeof(reg_t))
- 29517 return(EIO);
- 29518 i = (int) TR_ADDR;
- 29519 #if (CHIP == INTEL)
- 29520 /* Altering segment registers might crash the kernel when it
- 29521 * tries to load them prior to restarting a process, so do
- 29522 * not allow it.
- 29523 */
- 29524 if (i == (int) &((struct proc *) 0)->p_reg.cs ||
- 29525 i == (int) &((struct proc *) 0)->p_reg.ds ||
- 29526 i == (int) &((struct proc *) 0)->p_reg.es ||
- 29527 #if _WORD_SIZE == 4
- 29528 i == (int) &((struct proc *) 0)->p_reg.gs ||
- 29529 i == (int) &((struct proc *) 0)->p_reg.fs ||
- 29530 #endif
- 29531 i == (int) &((struct proc *) 0)->p_reg.ss)
- 29532 return(EIO);
- 29533 #endif
- 29534 if (i == (int) &((struct proc *) 0)->p_reg.psw)
- 29535 /* only selected bits are changeable */
- 29536 SETPSW(rp, TR_DATA);
- 29537 else
- 29538 *(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) TR_DATA;
- 29539 TR_DATA = 0;
- 29540 break;
- 29541
- 29542 case T_RESUME: /* resume execution */
- 29543 rp->p_flags &= ~P_STOP;
- 29544 if (rp->p_flags == 0) lock_ready(rp);
- 29545 TR_DATA = 0;
- 29546 break;
- 29547
- 29548 case T_STEP: /* set trace bit */
- 29549 rp->p_reg.psw |= TRACEBIT;
- 29550 rp->p_flags &= ~P_STOP;
- 29551 if (rp->p_flags == 0) lock_ready(rp);
- 29552 TR_DATA = 0;
- 29553 break;
- 29554
- 29555 default:
- 29556 return(EIO);
- 29557 }
- 29558 return(OK);
- 29559 }
- 29561 /*===========================================================================*
- 29562 * cause_sig *
- 29563 *===========================================================================*/
- 29564 PUBLIC void cause_sig(proc_nr, sig_nr)
- 29565 int proc_nr; /* process to be signalled */
- 29566 int sig_nr; /* signal to be sent, 1 to _NSIG */
- 29567 {
- 29568 /* A task wants to send a signal to a process. Examples of such tasks are:
- 29569 * TTY wanting to cause SIGINT upon getting a DEL
- 29570 * CLOCK wanting to cause SIGALRM when timer expires
- 29571 * FS also uses this to send a signal, via the SYS_KILL message.
- 29572 * Signals are handled by sending a message to MM. The tasks don't dare do
- 29573 * that directly, for fear of what would happen if MM were busy. Instead they
- 29574 * call cause_sig, which sets bits in p_pending, and then carefully checks to
- 29575 * see if MM is free. If so, a message is sent to it. If not, when it becomes
- 29576 * free, a message is sent. The process being signaled is blocked while MM
- 29577 * has not seen or finished with all signals for it. These signals are
- 29578 * counted in p_pendcount, and the SIG_PENDING flag is kept nonzero while
- 29579 * there are some. It is not sufficient to ready the process when MM is
- 29580 * informed, because MM can block waiting for FS to do a core dump.
- 29581 */
- 29582
- 29583 register struct proc *rp, *mmp;
- 29584
- 29585 rp = proc_addr(proc_nr);
- 29586 if (sigismember(&rp->p_pending, sig_nr))
- 29587 return; /* this signal already pending */
- 29588 sigaddset(&rp->p_pending, sig_nr);
- 29589 ++rp->p_pendcount; /* count new signal pending */
- 29590 if (rp->p_flags & PENDING)
- 29591 return; /* another signal already pending */
- 29592 if (rp->p_flags == 0) lock_unready(rp);
- 29593 rp->p_flags |= PENDING | SIG_PENDING;
- 29594 ++sig_procs; /* count new process pending */
- 29595
- 29596 mmp = proc_addr(MM_PROC_NR);
- 29597 if ( ((mmp->p_flags & RECEIVING) == 0) || mmp->p_getfrom != ANY) return;
- 29598 inform();
- 29599 }
- 29602 /*===========================================================================*
- 29603 * inform *
- 29604 *===========================================================================*/
- 29605 PUBLIC void inform()
- 29606 {
- 29607 /* When a signal is detected by the kernel (e.g., DEL), or generated by a task
- 29608 * (e.g. clock task for SIGALRM), cause_sig() is called to set a bit in the
- 29609 * p_pending field of the process to signal. Then inform() is called to see
- 29610 * if MM is idle and can be told about it. Whenever MM blocks, a check is
- 29611 * made to see if 'sig_procs' is nonzero; if so, inform() is called.
- 29612 */
- 29613
- 29614 register struct proc *rp;
- 29615
- 29616 /* MM is waiting for new input. Find a process with pending signals. */
- 29617 for (rp = BEG_SERV_ADDR; rp < END_PROC_ADDR; rp++)
- 29618 if (rp->p_flags & PENDING) {
- 29619 m.m_type = KSIG;
- 29620 m.SIG_PROC = proc_number(rp);
- 29621 m.SIG_MAP = rp->p_pending;
- 29622 sig_procs--;
- 29623 if (lock_mini_send(proc_addr(HARDWARE), MM_PROC_NR, &m) != OK)
- 29624 panic("can't inform MM", NO_NUM);
- 29625 sigemptyset(&rp->p_pending); /* the ball is now in MM's court */
- 29626 rp->p_flags &= ~PENDING;/* remains inhibited by SIG_PENDING */
- 29627 lock_pick_proc(); /* avoid delay in scheduling MM */
- 29628 return;
- 29629 }
- 29630 }
- 29633 /*===========================================================================*
- 29634 * umap *
- 29635 *===========================================================================*/
- 29636 PUBLIC phys_bytes umap(rp, seg, vir_addr, bytes)
- 29637 register struct proc *rp; /* pointer to proc table entry for process */
- 29638 int seg; /* T, D, or S segment */
- 29639 vir_bytes vir_addr; /* virtual address in bytes within the seg */
- 29640 vir_bytes bytes; /* # of bytes to be copied */
- 29641 {
- 29642 /* Calculate the physical memory address for a given virtual address. */
- 29643
- 29644 vir_clicks vc; /* the virtual address in clicks */
- 29645 phys_bytes pa; /* intermediate variables as phys_bytes */
- 29646 #if (CHIP == INTEL)
- 29647 phys_bytes seg_base;
- 29648 #endif
- 29649
- 29650 /* If 'seg' is D it could really be S and vice versa. T really means T.
- 29651 * If the virtual address falls in the gap, it causes a problem. On the
- 29652 * 8088 it is probably a legal stack reference, since "stackfaults" are
- 29653 * not detected by the hardware. On 8088s, the gap is called S and
- 29654 * accepted, but on other machines it is called D and rejected.
- 29655 * The Atari ST behaves like the 8088 in this respect.
- 29656 */
- 29657
- 29658 if (bytes <= 0) return( (phys_bytes) 0);
- 29659 vc = (vir_addr + bytes - 1) >> CLICK_SHIFT; /* last click of data */
- 29660
- 29661 #if (CHIP == INTEL) || (CHIP == M68000)
- 29662 if (seg != T)
- 29663 seg = (vc < rp->p_map[D].mem_vir + rp->p_map[D].mem_len ? D : S);
- 29664 #else
- 29665 if (seg != T)
- 29666 seg = (vc < rp->p_map[S].mem_vir ? D : S);
- 29667 #endif
- 29668
- 29669 if((vir_addr>>CLICK_SHIFT) >= rp->p_map[seg].mem_vir+ rp->p_map[seg].mem_len)
- 29670 return( (phys_bytes) 0 );
- 29671 #if (CHIP == INTEL)
- 29672 seg_base = (phys_bytes) rp->p_map[seg].mem_phys;
- 29673 seg_base = seg_base << CLICK_SHIFT; /* segment origin in bytes */
- 29674 #endif
- 29675 pa = (phys_bytes) vir_addr;
- 29676 #if (CHIP != M68000)
- 29677 pa -= rp->p_map[seg].mem_vir << CLICK_SHIFT;
- 29678 return(seg_base + pa);
- 29679 #endif
- 29680 #if (CHIP == M68000)
- 29681 #if (SHADOWING == 0)
- 29682 pa -= (phys_bytes)rp->p_map[seg].mem_vir << CLICK_SHIFT;
- 29683 pa += (phys_bytes)rp->p_map[seg].mem_phys << CLICK_SHIFT;
- 29684 #else
- 29685 if (rp->p_shadow && seg != T) {
- 29686 pa -= (phys_bytes)rp->p_map[D].mem_phys << CLICK_SHIFT;
- 29687 pa += (phys_bytes)rp->p_shadow << CLICK_SHIFT;
- 29688 }
- 29689 #endif
- 29690 return(pa);
- 29691 #endif
- 29692 }
- 29695 /*==========================================================================*
- 29696 * numap *
- 29697 *==========================================================================*/
- 29698 PUBLIC phys_bytes numap(proc_nr, vir_addr, bytes)
- 29699 int proc_nr; /* process number to be mapped */
- 29700 vir_bytes vir_addr; /* virtual address in bytes within D seg */
- 29701 vir_bytes bytes; /* # of bytes required in segment */
- 29702 {
- 29703 /* Do umap() starting from a process number instead of a pointer. This
- 29704 * function is used by device drivers, so they need not know about the
- 29705 * process table. To save time, there is no 'seg' parameter. The segment
- 29706 * is always D.
- 29707 */
- 29708
- 29709 return(umap(proc_addr(proc_nr), D, vir_addr, bytes));
- 29710 }
- 29713 #if (CHIP == INTEL)
- 29714 /*==========================================================================*
- 29715 * alloc_segments *
- 29716 *==========================================================================*/
- 29717 PUBLIC void alloc_segments(rp)
- 29718 register struct proc *rp;
- 29719 {
- 29720 /* This is called only by do_newmap, but is broken out as a separate function
- 29721 * because so much is hardware-dependent.
- 29722 */
- 29723
- 29724 phys_bytes code_bytes;
- 29725 phys_bytes data_bytes;
- 29726 int privilege;
- 29727
- 29728 if (protected_mode) {
- 29729 data_bytes = (phys_bytes) (rp->p_map[S].mem_vir + rp->p_map[S].mem_len)
- 29730 << CLICK_SHIFT;
- 29731 if (rp->p_map[T].mem_len == 0)
- 29732 code_bytes = data_bytes; /* common I&D, poor protect */
- 29733 else
- 29734 code_bytes = (phys_bytes) rp->p_map[T].mem_len << CLICK_SHIFT;
- 29735 privilege = istaskp(rp) ? TASK_PRIVILEGE : USER_PRIVILEGE;
- 29736 init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
- 29737 (phys_bytes) rp->p_map[T].mem_phys << CLICK_SHIFT,
- 29738 code_bytes, privilege);
- 29739 init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
- 29740 (phys_bytes) rp->p_map[D].mem_phys << CLICK_SHIFT,
- 29741 data_bytes, privilege);
- 29742 rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
- 29743 #if _WORD_SIZE == 4
- 29744 rp->p_reg.gs =
- 29745 rp->p_reg.fs =
- 29746 #endif
- 29747 rp->p_reg.ss =
- 29748 rp->p_reg.es =
- 29749 rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
- 29750 } else {
- 29751 rp->p_reg.cs = click_to_hclick(rp->p_map[T].mem_phys);
- 29752 rp->p_reg.ss =
- 29753 rp->p_reg.es =
- 29754 rp->p_reg.ds = click_to_hclick(rp->p_map[D].mem_phys);
- 29755 }
- 29756 }
- 29757 #endif /* (CHIP == INTEL) */
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/table.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 29800 /* The object file of "table.c" contains all the data. In the *.h files,
- 29801 * declared variables appear with EXTERN in front of them, as in
- 29802 *
- 29803 * EXTERN int x;
- 29804 *
- 29805 * Normally EXTERN is defined as extern, so when they are included in another
- 29806 * file, no storage is allocated. If the EXTERN were not present, but just
- 29807 * say,
- 29808 *
- 29809 * int x;
- 29810 *
- 29811 * then including this file in several source files would cause 'x' to be
- 29812 * declared several times. While some linkers accept this, others do not,
- 29813 * so they are declared extern when included normally. However, it must
- 29814 * be declared for real somewhere. That is done here, by redefining
- 29815 * EXTERN as the null string, so the inclusion of all the *.h files in
- 29816 * table.c actually generates storage for them. All the initialized
- 29817 * variables are also declared here, since
- 29818 *
- 29819 * extern int x = 4;
- 29820 *
- 29821 * is not allowed. If such variables are shared, they must also be declared
- 29822 * in one of the *.h files without the initialization.
- 29823 */
- 29824
- 29825 #define _TABLE
- 29826
- 29827 #include "kernel.h"
- 29828 #include <termios.h>
- 29829 #include <minix/com.h>
- 29830 #include "proc.h"
- 29831 #include "tty.h"
- 29832
- 29833 /* The startup routine of each task is given below, from -NR_TASKS upwards.
- 29834 * The order of the names here MUST agree with the numerical values assigned to
- 29835 * the tasks in <minix/com.h>.
- 29836 */
- 29837 #define SMALL_STACK (128 * sizeof(char *))
- 29838
- 29839 #define TTY_STACK (3 * SMALL_STACK)
- 29840 #define SYN_ALRM_STACK SMALL_STACK
- 29841
- 29842 #define DP8390_STACK (SMALL_STACK * ENABLE_NETWORKING)
- 29843
- 29844 #if (CHIP == INTEL)
- 29845 #define IDLE_STACK ((3+3+4) * sizeof(char *)) /* 3 intr, 3 temps, 4 db */
- 29846 #else
- 29847 #define IDLE_STACK SMALL_STACK
- 29848 #endif
- 29849
- 29850 #define PRINTER_STACK SMALL_STACK
- 29851
- 29852 #if (CHIP == INTEL)
- 29853 #define WINCH_STACK (2 * SMALL_STACK * ENABLE_WINI)
- 29854 #else
- 29855 #define WINCH_STACK (3 * SMALL_STACK * ENABLE_WINI)
- 29856 #endif
- 29857
- 29858 #if (MACHINE == ATARI)
- 29859 #define SCSI_STACK (3 * SMALL_STACK)
- 29860 #endif
- 29861
- 29862 #if (MACHINE == IBM_PC)
- 29863 #define SCSI_STACK (2 * SMALL_STACK * ENABLE_SCSI)
- 29864 #endif
- 29865
- 29866 #define CDROM_STACK (4 * SMALL_STACK * ENABLE_CDROM)
- 29867 #define AUDIO_STACK (4 * SMALL_STACK * ENABLE_AUDIO)
- 29868 #define MIXER_STACK (4 * SMALL_STACK * ENABLE_AUDIO)
- 29869
- 29870 #define FLOP_STACK (3 * SMALL_STACK)
- 29871 #define MEM_STACK SMALL_STACK
- 29872 #define CLOCK_STACK SMALL_STACK
- 29873 #define SYS_STACK SMALL_STACK
- 29874 #define HARDWARE_STACK 0 /* dummy task, uses kernel stack */
- 29875
- 29876
- 29877 #define TOT_STACK_SPACE (TTY_STACK + DP8390_STACK + SCSI_STACK +
- 29878 SYN_ALRM_STACK + IDLE_STACK + HARDWARE_STACK + PRINTER_STACK +
- 29879 WINCH_STACK + FLOP_STACK + MEM_STACK + CLOCK_STACK + SYS_STACK +
- 29880 CDROM_STACK + AUDIO_STACK + MIXER_STACK)
- 29881
- 29882
- 29883 /* SCSI, CDROM and AUDIO may in the future have different choices like
- 29884 * WINCHESTER, but for now the choice is fixed.
- 29885 */
- 29886 #define scsi_task aha_scsi_task
- 29887 #define cdrom_task mcd_task
- 29888 #define audio_task dsp_task
- 29889
- 29890
- 29891 /*
- 29892 * Some notes about the following table:
- 29893 * 1) The tty_task should always be first so that other tasks can use printf
- 29894 * if their initialisation has problems.
- 29895 * 2) If you add a new kernel task, add it before the printer task.
- 29896 * 3) The task name is used for the process name (p_name).
- 29897 */
- 29898
- 29899 PUBLIC struct tasktab tasktab[] = {
- 29900 { tty_task, TTY_STACK, "TTY" },
- 29901 #if ENABLE_NETWORKING
- 29902 { dp8390_task, DP8390_STACK, "DP8390" },
- 29903 #endif
- 29904 #if ENABLE_CDROM
- 29905 { cdrom_task, CDROM_STACK, "CDROM" },
- 29906 #endif
- 29907 #if ENABLE_AUDIO
- 29908 { audio_task, AUDIO_STACK, "AUDIO" },
- 29909 { mixer_task, MIXER_STACK, "MIXER" },
- 29910 #endif
- 29911 #if ENABLE_SCSI
- 29912 { scsi_task, SCSI_STACK, "SCSI" },
- 29913 #endif
- 29914 #if ENABLE_WINI
- 29915 { winchester_task, WINCH_STACK, "WINCH" },
- 29916 #endif
- 29917 { syn_alrm_task, SYN_ALRM_STACK, "SYN_AL" },
- 29918 { idle_task, IDLE_STACK, "IDLE" },
- 29919 { printer_task, PRINTER_STACK, "PRINTER" },
- 29920 { floppy_task, FLOP_STACK, "FLOPPY" },
- 29921 { mem_task, MEM_STACK, "MEMORY" },
- 29922 { clock_task, CLOCK_STACK, "CLOCK" },
- 29923 { sys_task, SYS_STACK, "SYS" },
- 29924 { 0, HARDWARE_STACK, "HARDWAR" },
- 29925 { 0, 0, "MM" },
- 29926 { 0, 0, "FS" },
- 29927 #if ENABLE_NETWORKING
- 29928 { 0, 0, "INET" },
- 29929 #endif
- 29930 { 0, 0, "INIT" },
- 29931 };
- 29932
- 29933 /* Stack space for all the task stacks. (Declared as (char *) to align it.) */
- 29934 PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
- 29935
- 29936 /*
- 29937 * The number of kernel tasks must be the same as NR_TASKS.
- 29938 * If NR_TASKS is not correct then you will get the compile error:
- 29939 * "array size is negative"
- 29940 */
- 29941
- 29942 #define NKT (sizeof tasktab / sizeof (struct tasktab) - (INIT_PROC_NR + 1))
- 29943
- 29944 extern int dummy_tasktab_check[NR_TASKS == NKT ? 1 : -1];
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/kernel/tty.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 30000 /* This file contains the terminal driver, both for the IBM console and regular
- 30001 * ASCII terminals. It handles only the device-independent part of a TTY, the
- 30002 * device dependent parts are in console.c, rs232.c, etc. This file contains
- 30003 * two main entry points, tty_task() and tty_wakeup(), and several minor entry
- 30004 * points for use by the device-dependent code.
- 30005 *
- 30006 * The device-independent part accepts "keyboard" input from the device-
- 30007 * dependent part, performs input processing (special key interpretation),
- 30008 * and sends the input to a process reading from the TTY. Output to a TTY
- 30009 * is sent to the device-dependent code for output processing and "screen"
- 30010 * display. Input processing is done by the device by calling 'in_process'
- 30011 * on the input characters, output processing may be done by the device itself
- 30012 * or by calling 'out_process'. The TTY takes care of input queuing, the
- 30013 * device does the output queuing. If a device receives an external signal,
- 30014 * like an interrupt, then it causes tty_wakeup() to be run by the CLOCK task
- 30015 * to, you guessed it, wake up the TTY to check if input or output can
- 30016 * continue.
- 30017 *
- 30018 * The valid messages and their parameters are:
- 30019 *
- 30020 * HARD_INT: output has been completed or input has arrived
- 30021 * DEV_READ: a process wants to read from a terminal
- 30022 * DEV_WRITE: a process wants to write on a terminal
- 30023 * DEV_IOCTL: a process wants to change a terminal's parameters
- 30024 * DEV_OPEN: a tty line has been opened
- 30025 * DEV_CLOSE: a tty line has been closed
- 30026 * CANCEL: terminate a previous incomplete system call immediately
- 30027 *
- 30028 * m_type TTY_LINE PROC_NR COUNT TTY_SPEK TTY_FLAGS ADDRESS
- 30029 * ---------------------------------------------------------------------------
- 30030 * | HARD_INT | | | | | | |
- 30031 * |-------------+---------+---------+---------+---------+---------+---------|
- 30032 * | DEV_READ |minor dev| proc nr | count | O_NONBLOCK| buf ptr |
- 30033 * |-------------+---------+---------+---------+---------+---------+---------|
- 30034 * | DEV_WRITE |minor dev| proc nr | count | | | buf ptr |
- 30035 * |-------------+---------+---------+---------+---------+---------+---------|
- 30036 * | DEV_IOCTL |minor dev| proc nr |func code|erase etc| flags | |
- 30037 * |-------------+---------+---------+---------+---------+---------+---------|
- 30038 * | DEV_OPEN |minor dev| proc nr | O_NOCTTY| | | |
- 30039 * |-------------+---------+---------+---------+---------+---------+---------|
- 30040 * | DEV_CLOSE |minor dev| proc nr | | | | |
- 30041 * |-------------+---------+---------+---------+---------+---------+---------|
- 30042 * | CANCEL |minor dev| proc nr | | | | |
- 30043 * ---------------------------------------------------------------------------
- 30044 */
- 30045
- 30046 #include "kernel.h"
- 30047 #include <termios.h>
- 30048 #if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
- 30049 #include <sgtty.h>
- 30050 #endif
- 30051 #include <sys/ioctl.h>
- 30052 #include <signal.h>
- 30053 #include <minix/callnr.h>
- 30054 #include <minix/com.h>
- 30055 #if (CHIP == INTEL)
- 30056 #include <minix/keymap.h>
- 30057 #endif
- 30058 #include "tty.h"
- 30059 #include "proc.h"
- 30060
- 30061 /* Address of a tty structure. */
- 30062 #define tty_addr(line) (&tty_table[line])
- 30063
- 30064 /* First minor numbers for the various classes of TTY devices. */
- 30065 #define CONS_MINOR 0
- 30066 #define LOG_MINOR 15
- 30067 #define RS232_MINOR 16
- 30068 #define TTYPX_MINOR 128
- 30069 #define PTYPX_MINOR 192
- 30070
- 30071 /* Macros for magic tty types. */
- 30072 #define isconsole(tp) ((tp) < tty_addr(NR_CONS))
- 30073
- 30074 /* Macros for magic tty structure pointers. */
- 30075 #define FIRST_TTY tty_addr(0)
- 30076 #define END_TTY tty_addr(sizeof(tty_table) / sizeof(tty_table[0]))
- 30077
- 30078 /* A device exists if at least its 'devread' function is defined. */
- 30079 #define tty_active(tp) ((tp)->tty_devread != NULL)
- 30080
- 30081 /* RS232 lines or pseudo terminals can be completely configured out. */
- 30082 #if NR_RS_LINES == 0
- 30083 #define rs_init(tp) ((void) 0)
- 30084 #endif
- 30085 #if NR_PTYS == 0
- 30086 #define pty_init(tp) ((void) 0)
- 30087 #define do_pty(tp, mp) ((void) 0)
- 30088 #endif
- 30089
- 30090 FORWARD _PROTOTYPE( void do_cancel, (tty_t *tp, message *m_ptr) );
- 30091 FORWARD _PROTOTYPE( void do_ioctl, (tty_t *tp, message *m_ptr) );
- 30092 FORWARD _PROTOTYPE( void do_open, (tty_t *tp, message *m_ptr) );
- 30093 FORWARD _PROTOTYPE( void do_close, (tty_t *tp, message *m_ptr) );
- 30094 FORWARD _PROTOTYPE( void do_read, (tty_t *tp, message *m_ptr) );
- 30095 FORWARD _PROTOTYPE( void do_write, (tty_t *tp, message *m_ptr) );
- 30096 FORWARD _PROTOTYPE( void in_transfer, (tty_t *tp) );
- 30097 FORWARD _PROTOTYPE( int echo, (tty_t *tp, int ch) );
- 30098 FORWARD _PROTOTYPE( void rawecho, (tty_t *tp, int ch) );
- 30099 FORWARD _PROTOTYPE( int back_over, (tty_t *tp) );
- 30100 FORWARD _PROTOTYPE( void reprint, (tty_t *tp) );
- 30101 FORWARD _PROTOTYPE( void dev_ioctl, (tty_t *tp) );
- 30102 FORWARD _PROTOTYPE( void setattr, (tty_t *tp) );
- 30103 FORWARD _PROTOTYPE( void tty_icancel, (tty_t *tp) );
- 30104 FORWARD _PROTOTYPE( void tty_init, (tty_t *tp) );
- 30105 FORWARD _PROTOTYPE( void settimer, (tty_t *tp, int on) );
- 30106 #if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
- 30107 FORWARD _PROTOTYPE( int compat_getp, (tty_t *tp, struct sgttyb *sg) );
- 30108 FORWARD _PROTOTYPE( int compat_getc, (tty_t *tp, struct tchars *sg) );
- 30109 FORWARD _PROTOTYPE( int compat_setp, (tty_t *tp, struct sgttyb *sg) );
- 30110 FORWARD _PROTOTYPE( int compat_setc, (tty_t *tp, struct tchars *sg) );
- 30111 FORWARD _PROTOTYPE( int tspd2sgspd, (speed_t tspd) );
- 30112 FORWARD _PROTOTYPE( speed_t sgspd2tspd, (int sgspd) );
- 30113 #if ENABLE_BINCOMPAT
- 30114 FORWARD _PROTOTYPE( void do_ioctl_compat, (tty_t *tp, message *m_ptr) );
- 30115 #endif
- 30116 #endif
- 30117
- 30118 /* Default attributes. */
- 30119 PRIVATE struct termios termios_defaults = {
- 30120 TINPUT_DEF, TOUTPUT_DEF, TCTRL_DEF, TLOCAL_DEF, TSPEED_DEF, TSPEED_DEF,
- 30121 {
- 30122 TEOF_DEF, TEOL_DEF, TERASE_DEF, TINTR_DEF, TKILL_DEF, TMIN_DEF,
- 30123 TQUIT_DEF, TTIME_DEF, TSUSP_DEF, TSTART_DEF, TSTOP_DEF,
- 30124 TREPRINT_DEF, TLNEXT_DEF, TDISCARD_DEF,
- 30125 },
- 30126 };
- 30127 PRIVATE struct winsize winsize_defaults; /* = all zeroes */
- 30128
- 30129
- 30130 /*===========================================================================*
- 30131 * tty_task *
- 30132 *===========================================================================*/
- 30133 PUBLIC void tty_task()
- 30134 {
- 30135 /* Main routine of the terminal task. */
- 30136
- 30137 message tty_mess; /* buffer for all incoming messages */
- 30138 register tty_t *tp;
- 30139 unsigned line;
- 30140
- 30141 /* Initialize the terminal lines. */
- 30142 for (tp = FIRST_TTY; tp < END_TTY; tp++) tty_init(tp);
- 30143
- 30144 /* Display the Minix startup banner. */
- 30145 printf("Minix %s.%s Copyright 1997 Prentice-Hall, Inc.nn",
- 30146 OS_RELEASE, OS_VERSION);
- 30147
- 30148 #if (CHIP == INTEL)
- 30149 /* Real mode, or 16/32-bit protected mode? */
- 30150 #if _WORD_SIZE == 4
- 30151 printf("Executing in 32-bit protected modenn");
- 30152 #else
- 30153 printf("Executing in %s modenn",
- 30154 protected_mode ? "16-bit protected" : "real");
- 30155 #endif
- 30156 #endif
- 30157
- 30158 while (TRUE) {
- 30159 /* Handle any events on any of the ttys. */
- 30160 for (tp = FIRST_TTY; tp < END_TTY; tp++) {
- 30161 if (tp->tty_events) handle_events(tp);
- 30162 }
- 30163
- 30164 receive(ANY, &tty_mess);
- 30165
- 30166 /* A hardware interrupt is an invitation to check for events. */
- 30167 if (tty_mess.m_type == HARD_INT) continue;
- 30168
- 30169 /* Check the minor device number. */
- 30170 line = tty_mess.TTY_LINE;
- 30171 if ((line - CONS_MINOR) < NR_CONS) {
- 30172 tp = tty_addr(line - CONS_MINOR);
- 30173 } else
- 30174 if (line == LOG_MINOR) {
- 30175 tp = tty_addr(0);
- 30176 } else
- 30177 if ((line - RS232_MINOR) < NR_RS_LINES) {
- 30178 tp = tty_addr(line - RS232_MINOR + NR_CONS);
- 30179 } else
- 30180 if ((line - TTYPX_MINOR) < NR_PTYS) {
- 30181 tp = tty_addr(line - TTYPX_MINOR + NR_CONS + NR_RS_LINES);
- 30182 } else
- 30183 if ((line - PTYPX_MINOR) < NR_PTYS) {
- 30184 tp = tty_addr(line - PTYPX_MINOR + NR_CONS + NR_RS_LINES);
- 30185 do_pty(tp, &tty_mess);
- 30186 continue; /* this is a pty, not a tty */
- 30187 } else {
- 30188 tp = NULL;
- 30189 }
- 30190
- 30191 /* If the device doesn't exist or is not configured return ENXIO. */
- 30192 if (tp == NULL || !tty_active(tp)) {
- 30193 tty_reply(TASK_REPLY, tty_mess.m_source,
- 30194 tty_mess.PROC_NR, ENXIO);
- 30195 continue;
- 30196 }
- 30197
- 30198 /* Execute the requested function. */
- 30199 switch (tty_mess.m_type) {
- 30200 case DEV_READ: do_read(tp, &tty_mess); break;
- 30201 case DEV_WRITE: do_write(tp, &tty_mess); break;
- 30202 case DEV_IOCTL: do_ioctl(tp, &tty_mess); break;
- 30203 case DEV_OPEN: do_open(tp, &tty_mess); break;
- 30204 case DEV_CLOSE: do_close(tp, &tty_mess); break;
- 30205 case CANCEL: do_cancel(tp, &tty_mess); break;
- 30206 default: tty_reply(TASK_REPLY, tty_mess.m_source,
- 30207 tty_mess.PROC_NR, EINVAL);
- 30208 }
- 30209 }
- 30210 }
- 30213 /*===========================================================================*
- 30214 * do_read *
- 30215 *===========================================================================*/
- 30216 PRIVATE void do_read(tp, m_ptr)
- 30217 register tty_t *tp; /* pointer to tty struct */
- 30218 message *m_ptr; /* pointer to message sent to the task */
- 30219 {
- 30220 /* A process wants to read from a terminal. */
- 30221 int r;
- 30222
- 30223 /* Check if there is already a process hanging in a read, check if the
- 30224 * parameters are correct, do I/O.
- 30225 */
- 30226 if (tp->tty_inleft > 0) {
- 30227 r = EIO;
- 30228 } else
- 30229 if (m_ptr->COUNT <= 0) {
- 30230 r = EINVAL;
- 30231 } else
- 30232 if (numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT) == 0) {
- 30233 r = EFAULT;
- 30234 } else {
- 30235 /* Copy information from the message to the tty struct. */
- 30236 tp->tty_inrepcode = TASK_REPLY;
- 30237 tp->tty_incaller = m_ptr->m_source;
- 30238 tp->tty_inproc = m_ptr->PROC_NR;
- 30239 tp->tty_in_vir = (vir_bytes) m_ptr->ADDRESS;
- 30240 tp->tty_inleft = m_ptr->COUNT;
- 30241
- 30242 if (!(tp->tty_termios.c_lflag & ICANON)
- 30243 && tp->tty_termios.c_cc[VTIME] > 0) {
- 30244 if (tp->tty_termios.c_cc[VMIN] == 0) {
- 30245 /* MIN & TIME specify a read timer that finishes the
- 30246 * read in TIME/10 seconds if no bytes are available.
- 30247 */
- 30248 lock();
- 30249 settimer(tp, TRUE);
- 30250 tp->tty_min = 1;
- 30251 unlock();
- 30252 } else {
- 30253 /* MIN & TIME specify an inter-byte timer that may
- 30254 * have to be cancelled if there are no bytes yet.
- 30255 */
- 30256 if (tp->tty_eotct == 0) {
- 30257 lock();
- 30258 settimer(tp, FALSE);
- 30259 unlock();
- 30260 tp->tty_min = tp->tty_termios.c_cc[VMIN];
- 30261 }
- 30262 }
- 30263 }
- 30264
- 30265 /* Anything waiting in the input buffer? Clear it out... */
- 30266 in_transfer(tp);
- 30267 /* ...then go back for more */
- 30268 handle_events(tp);
- 30269 if (tp->tty_inleft == 0) return; /* already done */
- 30270
- 30271 /* There were no bytes in the input queue available, so either suspend
- 30272 * the caller or break off the read if nonblocking.
- 30273 */
- 30274 if (m_ptr->TTY_FLAGS & O_NONBLOCK) {
- 30275 r = EAGAIN; /* cancel the read */
- 30276 tp->tty_inleft = tp->tty_incum = 0;
- 30277 } else {
- 30278 r = SUSPEND; /* suspend the caller */
- 30279 tp->tty_inrepcode = REVIVE;
- 30280 }
- 30281 }
- 30282 tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
- 30283 }
- 30286 /*===========================================================================*
- 30287 * do_write *
- 30288 *===========================================================================*/
- 30289 PRIVATE void do_write(tp, m_ptr)
- 30290 register tty_t *tp;
- 30291 register message *m_ptr; /* pointer to message sent to the task */
- 30292 {
- 30293 /* A process wants to write on a terminal. */
- 30294 int r;
- 30295
- 30296 /* Check if there is already a process hanging in a write, check if the
- 30297 * parameters are correct, do I/O.
- 30298 */
- 30299 if (tp->tty_outleft > 0) {
- 30300 r = EIO;
- 30301 } else
- 30302 if (m_ptr->COUNT <= 0) {
- 30303 r = EINVAL;
- 30304 } else
- 30305 if (numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, m_ptr->COUNT) == 0) {
- 30306 r = EFAULT;
- 30307 } else {
- 30308 /* Copy message parameters to the tty structure. */
- 30309 tp->tty_outrepcode = TASK_REPLY;
- 30310 tp->tty_outcaller = m_ptr->m_source;
- 30311 tp->tty_outproc = m_ptr->PROC_NR;
- 30312 tp->tty_out_vir = (vir_bytes) m_ptr->ADDRESS;
- 30313 tp->tty_outleft = m_ptr->COUNT;
- 30314
- 30315 /* Try to write. */
- 30316 handle_events(tp);
- 30317 if (tp->tty_outleft == 0) return; /* already done */
- 30318
- 30319 /* None or not all the bytes could be written, so either suspend the
- 30320 * caller or break off the write if nonblocking.
- 30321 */
- 30322 if (m_ptr->TTY_FLAGS & O_NONBLOCK) { /* cancel the write */
- 30323 r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN;
- 30324 tp->tty_outleft = tp->tty_outcum = 0;
- 30325 } else {
- 30326 r = SUSPEND; /* suspend the caller */
- 30327 tp->tty_outrepcode = REVIVE;
- 30328 }
- 30329 }
- 30330 tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
- 30331 }
- 30334 /*===========================================================================*
- 30335 * do_ioctl *
- 30336 *===========================================================================*/
- 30337 PRIVATE void do_ioctl(tp, m_ptr)
- 30338 register tty_t *tp;
- 30339 message *m_ptr; /* pointer to message sent to task */
- 30340 {
- 30341 /* Perform an IOCTL on this terminal. Posix termios calls are handled
- 30342 * by the IOCTL system call
- 30343 */
- 30344
- 30345 int r;
- 30346 union {
- 30347 int i;
- 30348 #if ENABLE_SRCCOMPAT
- 30349 struct sgttyb sg;
- 30350 struct tchars tc;
- 30351 #endif
- 30352 } param;
- 30353 phys_bytes user_phys;
- 30354 size_t size;
- 30355
- 30356 /* Size of the ioctl parameter. */
- 30357 switch (m_ptr->TTY_REQUEST) {
- 30358 case TCGETS: /* Posix tcgetattr function */
- 30359 case TCSETS: /* Posix tcsetattr function, TCSANOW option */
- 30360 case TCSETSW: /* Posix tcsetattr function, TCSADRAIN option */
- 30361 case TCSETSF: /* Posix tcsetattr function, TCSAFLUSH option */
- 30362 size = sizeof(struct termios);
- 30363 break;
- 30364
- 30365 case TCSBRK: /* Posix tcsendbreak function */
- 30366 case TCFLOW: /* Posix tcflow function */
- 30367 case TCFLSH: /* Posix tcflush function */
- 30368 case TIOCGPGRP: /* Posix tcgetpgrp function */
- 30369 case TIOCSPGRP: /* Posix tcsetpgrp function */
- 30370 size = sizeof(int);
- 30371 break;
- 30372
- 30373 case TIOCGWINSZ: /* get window size (not Posix) */
- 30374 case TIOCSWINSZ: /* set window size (not Posix) */
- 30375 size = sizeof(struct winsize);
- 30376 break;
- 30377
- 30378 #if ENABLE_SRCCOMPAT
- 30379 case TIOCGETP: /* BSD-style get terminal properties */
- 30380 case TIOCSETP: /* BSD-style set terminal properties */
- 30381 size = sizeof(struct sgttyb);
- 30382 break;
- 30383
- 30384 case TIOCGETC: /* BSD-style get terminal special characters */
- 30385 case TIOCSETC: /* BSD-style get terminal special characters */
- 30386 size = sizeof(struct tchars);
- 30387 break;
- 30388 #endif
- 30389 #if (MACHINE == IBM_PC)
- 30390 case KIOCSMAP: /* load keymap (Minix extension) */
- 30391 size = sizeof(keymap_t);
- 30392 break;
- 30393
- 30394 case TIOCSFON: /* load font (Minix extension) */
- 30395 size = sizeof(u8_t [8192]);
- 30396 break;
- 30397
- 30398 #endif
- 30399 case TCDRAIN: /* Posix tcdrain function -- no parameter */
- 30400 default: size = 0;
- 30401 }
- 30402
- 30403 if (size != 0) {
- 30404 user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, size);
- 30405 if (user_phys == 0) {
- 30406 tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, EFAULT);
- 30407 return;
- 30408 }
- 30409 }
- 30410
- 30411 r = OK;
- 30412 switch (m_ptr->TTY_REQUEST) {
- 30413 case TCGETS:
- 30414 /* Get the termios attributes. */
- 30415 phys_copy(vir2phys(&tp->tty_termios), user_phys, (phys_bytes) size);
- 30416 break;
- 30417
- 30418 case TCSETSW:
- 30419 case TCSETSF:
- 30420 case TCDRAIN:
- 30421 if (tp->tty_outleft > 0) {
- 30422 /* Wait for all ongoing output processing to finish. */
- 30423 tp->tty_iocaller = m_ptr->m_source;
- 30424 tp->tty_ioproc = m_ptr->PROC_NR;
- 30425 tp->tty_ioreq = m_ptr->REQUEST;
- 30426 tp->tty_iovir = (vir_bytes) m_ptr->ADDRESS;
- 30427 r = SUSPEND;
- 30428 break;
- 30429 }
- 30430 if (m_ptr->TTY_REQUEST == TCDRAIN) break;
- 30431 if (m_ptr->TTY_REQUEST == TCSETSF) tty_icancel(tp);
- 30432 /*FALL THROUGH*/
- 30433 case TCSETS:
- 30434 /* Set the termios attributes. */
- 30435 phys_copy(user_phys, vir2phys(&tp->tty_termios), (phys_bytes) size);
- 30436 setattr(tp);
- 30437 break;
- 30438
- 30439 case TCFLSH:
- 30440 phys_copy(user_phys, vir2phys(¶m.i), (phys_bytes) size);
- 30441 switch (param.i) {
- 30442 case TCIFLUSH: tty_icancel(tp); break;
- 30443 case TCOFLUSH: (*tp->tty_ocancel)(tp); break;
- 30444 case TCIOFLUSH: tty_icancel(tp); (*tp->tty_ocancel)(tp);break;
- 30445 default: r = EINVAL;
- 30446 }
- 30447 break;
- 30448
- 30449 case TCFLOW:
- 30450 phys_copy(user_phys, vir2phys(¶m.i), (phys_bytes) size);
- 30451 switch (param.i) {
- 30452 case TCOOFF:
- 30453 case TCOON:
- 30454 tp->tty_inhibited = (param.i == TCOOFF);
- 30455 tp->tty_events = 1;
- 30456 break;
- 30457 case TCIOFF:
- 30458 (*tp->tty_echo)(tp, tp->tty_termios.c_cc[VSTOP]);
- 30459 break;
- 30460 case TCION:
- 30461 (*tp->tty_echo)(tp, tp->tty_termios.c_cc[VSTART]);
- 30462 break;
- 30463 default:
- 30464 r = EINVAL;
- 30465 }
- 30466 break;
- 30467
- 30468 case TCSBRK:
- 30469 if (tp->tty_break != NULL) (*tp->tty_break)(tp);
- 30470 break;
- 30471
- 30472 case TIOCGWINSZ:
- 30473 phys_copy(vir2phys(&tp->tty_winsize), user_phys, (phys_bytes) size);
- 30474 break;
- 30475
- 30476 case TIOCSWINSZ:
- 30477 phys_copy(user_phys, vir2phys(&tp->tty_winsize), (phys_bytes) size);
- 30478 /* SIGWINCH... */
- 30479 break;
- 30480
- 30481 #if ENABLE_SRCCOMPAT
- 30482 case TIOCGETP:
- 30483 compat_getp(tp, ¶m.sg);
- 30484 phys_copy(vir2phys(¶m.sg), user_phys, (phys_bytes) size);
- 30485 break;
- 30486
- 30487 case TIOCSETP:
- 30488 phys_copy(user_phys, vir2phys(¶m.sg), (phys_bytes) size);
- 30489 compat_setp(tp, ¶m.sg);
- 30490 break;
- 30491
- 30492 case TIOCGETC:
- 30493 compat_getc(tp, ¶m.tc);
- 30494 phys_copy(vir2phys(¶m.tc), user_phys, (phys_bytes) size);
- 30495 break;
- 30496
- 30497 case TIOCSETC:
- 30498 phys_copy(user_phys, vir2phys(¶m.tc), (phys_bytes) size);
- 30499 compat_setc(tp, ¶m.tc);
- 30500 break;
- 30501 #endif
- 30502
- 30503 #if (MACHINE == IBM_PC)
- 30504 case KIOCSMAP:
- 30505 /* Load a new keymap (only /dev/console). */
- 30506 if (isconsole(tp)) r = kbd_loadmap(user_phys);
- 30507 break;
- 30508
- 30509 case TIOCSFON:
- 30510 /* Load a font into an EGA or VGA card (hs@hck.hr) */
- 30511 if (isconsole(tp)) r = con_loadfont(user_phys);
- 30512 break;
- 30513 #endif
- 30514
- 30515 #if (MACHINE == ATARI)
- 30516 case VDU_LOADFONT:
- 30517 r = vdu_loadfont(m_ptr);
- 30518 break;
- 30519 #endif
- 30520
- 30521 /* These Posix functions are allowed to fail if _POSIX_JOB_CONTROL is
- 30522 * not defined.
- 30523 */
- 30524 case TIOCGPGRP:
- 30525 case TIOCSPGRP:
- 30526 default:
- 30527 #if ENABLE_BINCOMPAT
- 30528 do_ioctl_compat(tp, m_ptr);
- 30529 return;
- 30530 #else
- 30531 r = ENOTTY;
- 30532 #endif
- 30533 }
- 30534
- 30535 /* Send the reply. */
- 30536 tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
- 30537 }
- 30540 /*===========================================================================*
- 30541 * do_open *
- 30542 *===========================================================================*/
- 30543 PRIVATE void do_open(tp, m_ptr)
- 30544 register tty_t *tp;
- 30545 message *m_ptr; /* pointer to message sent to task */
- 30546 {
- 30547 /* A tty line has been opened. Make it the callers controlling tty if
- 30548 * O_NOCTTY is *not* set and it is not the log device. 1 is returned if
- 30549 * the tty is made the controlling tty, otherwise OK or an error code.
- 30550 */
- 30551 int r = OK;
- 30552
- 30553 if (m_ptr->TTY_LINE == LOG_MINOR) {
- 30554 /* The log device is a write-only diagnostics device. */
- 30555 if (m_ptr->COUNT & R_BIT) r = EACCES;
- 30556 } else {
- 30557 if (!(m_ptr->COUNT & O_NOCTTY)) {
- 30558 tp->tty_pgrp = m_ptr->PROC_NR;
- 30559 r = 1;
- 30560 }
- 30561 tp->tty_openct++;
- 30562 }
- 30563 tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, r);
- 30564 }
- 30567 /*===========================================================================*
- 30568 * do_close *
- 30569 *===========================================================================*/
- 30570 PRIVATE void do_close(tp, m_ptr)
- 30571 register tty_t *tp;
- 30572 message *m_ptr; /* pointer to message sent to task */
- 30573 {
- 30574 /* A tty line has been closed. Clean up the line if it is the last close. */
- 30575
- 30576 if (m_ptr->TTY_LINE != LOG_MINOR && --tp->tty_openct == 0) {
- 30577 tp->tty_pgrp = 0;
- 30578 tty_icancel(tp);
- 30579 (*tp->tty_ocancel)(tp);
- 30580 (*tp->tty_close)(tp);
- 30581 tp->tty_termios = termios_defaults;
- 30582 tp->tty_winsize = winsize_defaults;
- 30583 setattr(tp);
- 30584 }
- 30585 tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->PROC_NR, OK);
- 30586 }
- 30589 /*===========================================================================*
- 30590 * do_cancel *
- 30591 *===========================================================================*/
- 30592 PRIVATE void do_cancel(tp, m_ptr)
- 30593 register tty_t *tp;
- 30594 message *m_ptr; /* pointer to message sent to task */
- 30595 {
- 30596 /* A signal has been sent to a process that is hanging trying to read or write.
- 30597 * The pending read or write must be finished off immediately.
- 30598 */
- 30599
- 30600 int proc_nr;
- 30601 int mode;
- 30602
- 30603 /* Check the parameters carefully, to avoid cancelling twice. */
- 30604 proc_nr = m_ptr->PROC_NR;
- 30605 mode = m_ptr->COUNT;
- 30606 if ((mode & R_BIT) && tp->tty_inleft != 0 && proc_nr == tp->tty_inproc) {
- 30607 /* Process was reading when killed. Clean up input. */
- 30608 tty_icancel(tp);
- 30609 tp->tty_inleft = tp->tty_incum = 0;
- 30610 }
- 30611 if ((mode & W_BIT) && tp->tty_outleft != 0 && proc_nr == tp->tty_outproc) {
- 30612 /* Process was writing when killed. Clean up output. */
- 30613 (*tp->tty_ocancel)(tp);
- 30614 tp->tty_outleft = tp->tty_outcum = 0;
- 30615 }
- 30616 if (tp->tty_ioreq != 0 && proc_nr == tp->tty_ioproc) {
- 30617 /* Process was waiting for output to drain. */
- 30618 tp->tty_ioreq = 0;
- 30619 }
- 30620 tp->tty_events = 1;
- 30621 tty_reply(TASK_REPLY, m_ptr->m_source, proc_nr, EINTR);
- 30622 }
- 30625 /*===========================================================================*
- 30626 * handle_events *
- 30627 *===========================================================================*/
- 30628 PUBLIC void handle_events(tp)
- 30629 tty_t *tp; /* TTY to check for events. */
- 30630 {
- 30631 /* Handle any events pending on a TTY. These events are usually device
- 30632 * interrupts.
- 30633 *
- 30634 * Two kinds of events are prominent:
- 30635 * - a character has been received from the console or an RS232 line.
- 30636 * - an RS232 line has completed a write request (on behalf of a user).
- 30637 * The interrupt handler may delay the interrupt message at its discretion
- 30638 * to avoid swamping the TTY task. Messages may be overwritten when the
- 30639 * lines are fast or when there are races between different lines, input
- 30640 * and output, because MINIX only provides single buffering for interrupt
- 30641 * messages (in proc.c). This is handled by explicitly checking each line
- 30642 * for fresh input and completed output on each interrupt.
- 30643 */
- 30644 char *buf;
- 30645 unsigned count;
- 30646
- 30647 do {
- 30648 tp->tty_events = 0;
- 30649
- 30650 /* Read input and perform input processing. */
- 30651 (*tp->tty_devread)(tp);
- 30652
- 30653 /* Perform output processing and write output. */
- 30654 (*tp->tty_devwrite)(tp);
- 30655
- 30656 /* Ioctl waiting for some event? */
- 30657 if (tp->tty_ioreq != 0) dev_ioctl(tp);
- 30658 } while (tp->tty_events);
- 30659
- 30660 /* Transfer characters from the input queue to a waiting process. */
- 30661 in_transfer(tp);
- 30662
- 30663 /* Reply if enough bytes are available. */
- 30664 if (tp->tty_incum >= tp->tty_min && tp->tty_inleft > 0) {
- 30665 tty_reply(tp->tty_inrepcode, tp->tty_incaller, tp->tty_inproc,
- 30666 tp->tty_incum);
- 30667 tp->tty_inleft = tp->tty_incum = 0;
- 30668 }
- 30669 }
- 30672 /*===========================================================================*
- 30673 * in_transfer *
- 30674 *===========================================================================*/
- 30675 PRIVATE void in_transfer(tp)
- 30676 register tty_t *tp; /* pointer to terminal to read from */
- 30677 {
- 30678 /* Transfer bytes from the input queue to a process reading from a terminal. */
- 30679
- 30680 int ch;
- 30681 int count;
- 30682 phys_bytes buf_phys, user_base;
- 30683 char buf[64], *bp;
- 30684
- 30685 /* Anything to do? */
- 30686 if (tp->tty_inleft == 0 || tp->tty_eotct < tp->tty_min) return;
- 30687
- 30688 buf_phys = vir2phys(buf);
- 30689 user_base = proc_vir2phys(proc_addr(tp->tty_inproc), 0);
- 30690 bp = buf;
- 30691 while (tp->tty_inleft > 0 && tp->tty_eotct > 0) {
- 30692 ch = *tp->tty_intail;
- 30693
- 30694 if (!(ch & IN_EOF)) {
- 30695 /* One character to be delivered to the user. */
- 30696 *bp = ch & IN_CHAR;
- 30697 tp->tty_inleft--;
- 30698 if (++bp == bufend(buf)) {
- 30699 /* Temp buffer full, copy to user space. */
- 30700 phys_copy(buf_phys, user_base + tp->tty_in_vir,
- 30701 (phys_bytes) buflen(buf));
- 30702 tp->tty_in_vir += buflen(buf);
- 30703 tp->tty_incum += buflen(buf);
- 30704 bp = buf;
- 30705 }
- 30706 }
- 30707
- 30708 /* Remove the character from the input queue. */
- 30709 if (++tp->tty_intail == bufend(tp->tty_inbuf))
- 30710 tp->tty_intail = tp->tty_inbuf;
- 30711 tp->tty_incount--;
- 30712 if (ch & IN_EOT) {
- 30713 tp->tty_eotct--;
- 30714 /* Don't read past a line break in canonical mode. */
- 30715 if (tp->tty_termios.c_lflag & ICANON) tp->tty_inleft = 0;
- 30716 }
- 30717 }
- 30718
- 30719 if (bp > buf) {
- 30720 /* Leftover characters in the buffer. */
- 30721 count = bp - buf;
- 30722 phys_copy(buf_phys, user_base + tp->tty_in_vir, (phys_bytes) count);
- 30723 tp->tty_in_vir += count;
- 30724 tp->tty_incum += count;
- 30725 }
- 30726
- 30727 /* Usually reply to the reader, possibly even if incum == 0 (EOF). */
- 30728 if (tp->tty_inleft == 0) {
- 30729 tty_reply(tp->tty_inrepcode, tp->tty_incaller, tp->tty_inproc,
- 30730 tp->tty_incum);
- 30731 tp->tty_inleft = tp->tty_incum = 0;
- 30732 }
- 30733 }
- 30736 /*===========================================================================*
- 30737 * in_process *
- 30738 *===========================================================================*/
- 30739 PUBLIC int in_process(tp, buf, count)
- 30740 register tty_t *tp; /* terminal on which character has arrived */
- 30741 char *buf; /* buffer with input characters */
- 30742 int count; /* number of input characters */
- 30743 {
- 30744 /* Characters have just been typed in. Process, save, and echo them. Return
- 30745 * the number of characters processed.
- 30746 */
- 30747
- 30748 int ch, sig, ct;
- 30749 int timeset = FALSE;
- 30750 static unsigned char csize_mask[] = { 0x1F, 0x3F, 0x7F, 0xFF };
- 30751
- 30752 for (ct = 0; ct < count; ct++) {
- 30753 /* Take one character. */
- 30754 ch = *buf++ & BYTE;
- 30755
- 30756 /* Strip to seven bits? */
- 30757 if (tp->tty_termios.c_iflag & ISTRIP) ch &= 0x7F;
- 30758
- 30759 /* Input extensions? */
- 30760 if (tp->tty_termios.c_lflag & IEXTEN) {
- 30761
- 30762 /* Previous character was a character escape? */
- 30763 if (tp->tty_escaped) {
- 30764 tp->tty_escaped = NOT_ESCAPED;
- 30765 ch |= IN_ESC; /* protect character */
- 30766 }
- 30767
- 30768 /* LNEXT (^V) to escape the next character? */
- 30769 if (ch == tp->tty_termios.c_cc[VLNEXT]) {
- 30770 tp->tty_escaped = ESCAPED;
- 30771 rawecho(tp, '^');
- 30772 rawecho(tp, 'b');
- 30773 continue; /* do not store the escape */
- 30774 }
- 30775
- 30776 /* REPRINT (^R) to reprint echoed characters? */
- 30777 if (ch == tp->tty_termios.c_cc[VREPRINT]) {
- 30778 reprint(tp);
- 30779 continue;
- 30780 }
- 30781 }
- 30782
- 30783 /* _POSIX_VDISABLE is a normal character value, so better escape it. */
- 30784 if (ch == _POSIX_VDISABLE) ch |= IN_ESC;
- 30785
- 30786 /* Map CR to LF, ignore CR, or map LF to CR. */
- 30787 if (ch == 'r') {
- 30788 if (tp->tty_termios.c_iflag & IGNCR) continue;
- 30789 if (tp->tty_termios.c_iflag & ICRNL) ch = 'n';
- 30790 } else
- 30791 if (ch == 'n') {
- 30792 if (tp->tty_termios.c_iflag & INLCR) ch = 'r';
- 30793 }
- 30794
- 30795 /* Canonical mode? */
- 30796 if (tp->tty_termios.c_lflag & ICANON) {
- 30797
- 30798 /* Erase processing (rub out of last character). */
- 30799 if (ch == tp->tty_termios.c_cc[VERASE]) {
- 30800 (void) back_over(tp);
- 30801 if (!(tp->tty_termios.c_lflag & ECHOE)) {
- 30802 (void) echo(tp, ch);
- 30803 }
- 30804 continue;
- 30805 }
- 30806
- 30807 /* Kill processing (remove current line). */
- 30808 if (ch == tp->tty_termios.c_cc[VKILL]) {
- 30809 while (back_over(tp)) {}
- 30810 if (!(tp->tty_termios.c_lflag & ECHOE)) {
- 30811 (void) echo(tp, ch);
- 30812 if (tp->tty_termios.c_lflag & ECHOK)
- 30813 rawecho(tp, 'n');
- 30814 }
- 30815 continue;
- 30816 }
- 30817
- 30818 /* EOF (^D) means end-of-file, an invisible "line break". */
- 30819 if (ch == tp->tty_termios.c_cc[VEOF]) ch |= IN_EOT | IN_EOF;
- 30820
- 30821 /* The line may be returned to the user after an LF. */
- 30822 if (ch == 'n') ch |= IN_EOT;
- 30823
- 30824 /* Same thing with EOL, whatever it may be. */
- 30825 if (ch == tp->tty_termios.c_cc[VEOL]) ch |= IN_EOT;
- 30826 }
- 30827
- 30828 /* Start/stop input control? */
- 30829 if (tp->tty_termios.c_iflag & IXON) {
- 30830
- 30831 /* Output stops on STOP (^S). */
- 30832 if (ch == tp->tty_termios.c_cc[VSTOP]) {
- 30833 tp->tty_inhibited = STOPPED;
- 30834 tp->tty_events = 1;
- 30835 continue;
- 30836 }
- 30837
- 30838 /* Output restarts on START (^Q) or any character if IXANY. */
- 30839 if (tp->tty_inhibited) {
- 30840 if (ch == tp->tty_termios.c_cc[VSTART]
- 30841 || (tp->tty_termios.c_iflag & IXANY)) {
- 30842 tp->tty_inhibited = RUNNING;
- 30843 tp->tty_events = 1;
- 30844 if (ch == tp->tty_termios.c_cc[VSTART])
- 30845 continue;
- 30846 }
- 30847 }
- 30848 }
- 30849
- 30850 if (tp->tty_termios.c_lflag & ISIG) {
- 30851 /* Check for INTR (^?) and QUIT (^) characters. */
- 30852 if (ch == tp->tty_termios.c_cc[VINTR]
- 30853 || ch == tp->tty_termios.c_cc[VQUIT]) {
- 30854 sig = SIGINT;
- 30855 if (ch == tp->tty_termios.c_cc[VQUIT]) sig = SIGQUIT;
- 30856 sigchar(tp, sig);
- 30857 (void) echo(tp, ch);
- 30858 continue;
- 30859 }
- 30860 }
- 30861
- 30862 /* Is there space in the input buffer? */
- 30863 if (tp->tty_incount == buflen(tp->tty_inbuf)) {
- 30864 /* No space; discard in canonical mode, keep in raw mode. */
- 30865 if (tp->tty_termios.c_lflag & ICANON) continue;
- 30866 break;
- 30867 }
- 30868
- 30869 if (!(tp->tty_termios.c_lflag & ICANON)) {
- 30870 /* In raw mode all characters are "line breaks". */
- 30871 ch |= IN_EOT;
- 30872
- 30873 /* Start an inter-byte timer? */
- 30874 if (!timeset && tp->tty_termios.c_cc[VMIN] > 0
- 30875 && tp->tty_termios.c_cc[VTIME] > 0) {
- 30876 lock();
- 30877 settimer(tp, TRUE);
- 30878 unlock();
- 30879 timeset = TRUE;
- 30880 }
- 30881 }
- 30882
- 30883 /* Perform the intricate function of echoing. */
- 30884 if (tp->tty_termios.c_lflag & (ECHO|ECHONL)) ch = echo(tp, ch);
- 30885
- 30886 /* Save the character in the input queue. */
- 30887 *tp->tty_inhead++ = ch;
- 30888 if (tp->tty_inhead == bufend(tp->tty_inbuf))
- 30889 tp->tty_inhead = tp->tty_inbuf;
- 30890 tp->tty_incount++;
- 30891 if (ch & IN_EOT) tp->tty_eotct++;
- 30892
- 30893 /* Try to finish input if the queue threatens to overflow. */
- 30894 if (tp->tty_incount == buflen(tp->tty_inbuf)) in_transfer(tp);
- 30895 }
- 30896 return ct;
- 30897 }
- 30900 /*===========================================================================*
- 30901 * echo *
- 30902 *===========================================================================*/
- 30903 PRIVATE int echo(tp, ch)
- 30904 register tty_t *tp; /* terminal on which to echo */
- 30905 register int ch; /* pointer to character to echo */
- 30906 {
- 30907 /* Echo the character if echoing is on. Some control characters are echoed
- 30908 * with their normal effect, other control characters are echoed as "^X",
- 30909 * normal characters are echoed normally. EOF (^D) is echoed, but immediately
- 30910 * backspaced over. Return the character with the echoed length added to its
- 30911 * attributes.
- 30912 */
- 30913 int len, rp;
- 30914
- 30915 ch &= ~IN_LEN;
- 30916 if (!(tp->tty_termios.c_lflag & ECHO)) {
- 30917 if (ch == ('n' | IN_EOT) && (tp->tty_termios.c_lflag
- 30918 & (ICANON|ECHONL)) == (ICANON|ECHONL))
- 30919 (*tp->tty_echo)(tp, 'n');
- 30920 return(ch);
- 30921 }
- 30922
- 30923 /* "Reprint" tells if the echo output has been messed up by other output. */
- 30924 rp = tp->tty_incount == 0 ? FALSE : tp->tty_reprint;
- 30925
- 30926 if ((ch & IN_CHAR) < ' ') {
- 30927 switch (ch & (IN_ESC|IN_EOF|IN_EOT|IN_CHAR)) {
- 30928 case 't':
- 30929 len = 0;
- 30930 do {
- 30931 (*tp->tty_echo)(tp, ' ');
- 30932 len++;
- 30933 } while (len < TAB_SIZE && (tp->tty_position & TAB_MASK) != 0);
- 30934 break;
- 30935 case 'r' | IN_EOT:
- 30936 case 'n' | IN_EOT:
- 30937 (*tp->tty_echo)(tp, ch & IN_CHAR);
- 30938 len = 0;
- 30939 break;
- 30940 default:
- 30941 (*tp->tty_echo)(tp, '^');
- 30942 (*tp->tty_echo)(tp, '@' + (ch & IN_CHAR));
- 30943 len = 2;
- 30944 }
- 30945 } else
- 30946 if ((ch & IN_CHAR) == '177') {
- 30947 /* A DEL prints as "^?". */
- 30948 (*tp->tty_echo)(tp, '^');
- 30949 (*tp->tty_echo)(tp, '?');
- 30950 len = 2;
- 30951 } else {
- 30952 (*tp->tty_echo)(tp, ch & IN_CHAR);
- 30953 len = 1;
- 30954 }
- 30955 if (ch & IN_EOF) while (len > 0) { (*tp->tty_echo)(tp, 'b'); len--; }
- 30956
- 30957 tp->tty_reprint = rp;
- 30958 return(ch | (len << IN_LSHIFT));
- 30959 }
- 30962 /*==========================================================================*
- 30963 * rawecho *
- 30964 *==========================================================================*/
- 30965 PRIVATE void rawecho(tp, ch)
- 30966 register tty_t *tp;
- 30967 int ch;
- 30968 {
- 30969 /* Echo without interpretation if ECHO is set. */
- 30970 int rp = tp->tty_reprint;
- 30971 if (tp->tty_termios.c_lflag & ECHO) (*tp->tty_echo)(tp, ch);
- 30972 tp->tty_reprint = rp;
- 30973 }
- 30976 /*==========================================================================*
- 30977 * back_over *
- 30978 *==========================================================================*/
- 30979 PRIVATE int back_over(tp)
- 30980 register tty_t *tp;
- 30981 {
- 30982 /* Backspace to previous character on screen and erase it. */
- 30983 u16_t *head;
- 30984 int len;
- 30985
- 30986 if (tp->tty_incount == 0) return(0); /* queue empty */
- 30987 head = tp->tty_inhead;
- 30988 if (head == tp->tty_inbuf) head = bufend(tp->tty_inbuf);
- 30989 if (*--head & IN_EOT) return(0); /* can't erase "line breaks" */
- 30990 if (tp->tty_reprint) reprint(tp); /* reprint if messed up */
- 30991 tp->tty_inhead = head;
- 30992 tp->tty_incount--;
- 30993 if (tp->tty_termios.c_lflag & ECHOE) {
- 30994 len = (*head & IN_LEN) >> IN_LSHIFT;
- 30995 while (len > 0) {
- 30996 rawecho(tp, 'b');
- 30997 rawecho(tp, ' ');
- 30998 rawecho(tp, 'b');
- 30999 len--;
- 31000 }
- 31001 }
- 31002 return(1); /* one character erased */
- 31003 }
- 31006 /*==========================================================================*
- 31007 * reprint *
- 31008 *==========================================================================*/
- 31009 PRIVATE void reprint(tp)
- 31010 register tty_t *tp; /* pointer to tty struct */
- 31011 {
- 31012 /* Restore what has been echoed to screen before if the user input has been
- 31013 * messed up by output, or if REPRINT (^R) is typed.
- 31014 */
- 31015 int count;
- 31016 u16_t *head;
- 31017
- 31018 tp->tty_reprint = FALSE;
- 31019
- 31020 /* Find the last line break in the input. */
- 31021 head = tp->tty_inhead;
- 31022 count = tp->tty_incount;
- 31023 while (count > 0) {
- 31024 if (head == tp->tty_inbuf) head = bufend(tp->tty_inbuf);
- 31025 if (head[-1] & IN_EOT) break;
- 31026 head--;
- 31027 count--;
- 31028 }
- 31029 if (count == tp->tty_incount) return; /* no reason to reprint */
- 31030
- 31031 /* Show REPRINT (^R) and move to a new line. */
- 31032 (void) echo(tp, tp->tty_termios.c_cc[VREPRINT] | IN_ESC);
- 31033 rawecho(tp, 'r');
- 31034 rawecho(tp, 'n');
- 31035
- 31036 /* Reprint from the last break onwards. */
- 31037 do {
- 31038 if (head == bufend(tp->tty_inbuf)) head = tp->tty_inbuf;
- 31039 *head = echo(tp, *head);
- 31040 head++;
- 31041 count++;
- 31042 } while (count < tp->tty_incount);
- 31043 }
- 31046 /*==========================================================================*
- 31047 * out_process *
- 31048 *==========================================================================*/
- 31049 PUBLIC void out_process(tp, bstart, bpos, bend, icount, ocount)
- 31050 tty_t *tp;
- 31051 char *bstart, *bpos, *bend; /* start/pos/end of circular buffer */
- 31052 int *icount; /* # input chars / input chars used */
- 31053 int *ocount; /* max output chars / output chars used */
- 31054 {
- 31055 /* Perform output processing on a circular buffer. *icount is the number of
- 31056 * bytes to process, and the number of bytes actually processed on return.
- 31057 * *ocount is the space available on input and the space used on output.
- 31058 * (Naturally *icount < *ocount.) The column position is updated modulo
- 31059 * the TAB size, because we really only need it for tabs.
- 31060 */
- 31061
- 31062 int tablen;
- 31063 int ict = *icount;
- 31064 int oct = *ocount;
- 31065 int pos = tp->tty_position;
- 31066
- 31067 while (ict > 0) {
- 31068 switch (*bpos) {
- 31069 case '7':
- 31070 break;
- 31071 case 'b':
- 31072 pos--;
- 31073 break;
- 31074 case 'r':
- 31075 pos = 0;
- 31076 break;
- 31077 case 'n':
- 31078 if ((tp->tty_termios.c_oflag & (OPOST|ONLCR))
- 31079 == (OPOST|ONLCR)) {
- 31080 /* Map LF to CR+LF if there is space. Note that the
- 31081 * next character in the buffer is overwritten, so
- 31082 * we stop at this point.
- 31083 */
- 31084 if (oct >= 2) {
- 31085 *bpos = 'r';
- 31086 if (++bpos == bend) bpos = bstart;
- 31087 *bpos = 'n';
- 31088 pos = 0;
- 31089 ict--;
- 31090 oct -= 2;
- 31091 }
- 31092 goto out_done; /* no space or buffer got changed */
- 31093 }
- 31094 break;
- 31095 case 't':
- 31096 /* Best guess for the tab length. */
- 31097 tablen = TAB_SIZE - (pos & TAB_MASK);
- 31098
- 31099 if ((tp->tty_termios.c_oflag & (OPOST|XTABS))
- 31100 == (OPOST|XTABS)) {
- 31101 /* Tabs must be expanded. */
- 31102 if (oct >= tablen) {
- 31103 pos += tablen;
- 31104 ict--;
- 31105 oct -= tablen;
- 31106 do {
- 31107 *bpos = ' ';
- 31108 if (++bpos == bend) bpos = bstart;
- 31109 } while (--tablen != 0);
- 31110 }
- 31111 goto out_done;
- 31112 }
- 31113 /* Tabs are output directly. */
- 31114 pos += tablen;
- 31115 break;
- 31116 default:
- 31117 /* Assume any other character prints as one character. */
- 31118 pos++;
- 31119 }
- 31120 if (++bpos == bend) bpos = bstart;
- 31121 ict--;
- 31122 oct--;
- 31123 }
- 31124 out_done:
- 31125 tp->tty_position = pos & TAB_MASK;
- 31126
- 31127 *icount -= ict; /* [io]ct are the number of chars not used */
- 31128 *ocount -= oct; /* *[io]count are the number of chars that are used */
- 31129 }
- 31132 /*===========================================================================*
- 31133 * dev_ioctl *
- 31134 *===========================================================================*/
- 31135 PRIVATE void dev_ioctl(tp)
- 31136 tty_t *tp;
- 31137 {
- 31138 /* The ioctl's TCSETSW, TCSETSF and TCDRAIN wait for output to finish to make
- 31139 * sure that an attribute change doesn't affect the processing of current
- 31140 * output. Once output finishes the ioctl is executed as in do_ioctl().
- 31141 */
- 31142 phys_bytes user_phys;
- 31143
- 31144 if (tp->tty_outleft > 0) return; /* output not finished */
- 31145
- 31146 if (tp->tty_ioreq != TCDRAIN) {
- 31147 if (tp->tty_ioreq == TCSETSF) tty_icancel(tp);
- 31148 user_phys = proc_vir2phys(proc_addr(tp->tty_ioproc), tp->tty_iovir);
- 31149 phys_copy(user_phys, vir2phys(&tp->tty_termios),
- 31150 (phys_bytes) sizeof(tp->tty_termios));
- 31151 setattr(tp);
- 31152 }
- 31153 tp->tty_ioreq = 0;
- 31154 tty_reply(REVIVE, tp->tty_iocaller, tp->tty_ioproc, OK);
- 31155 }
- 31158 /*===========================================================================*
- 31159 * setattr *
- 31160 *===========================================================================*/
- 31161 PRIVATE void setattr(tp)
- 31162 tty_t *tp;
- 31163 {
- 31164 /* Apply the new line attributes (raw/canonical, line speed, etc.) */
- 31165 u16_t *inp;
- 31166 int count;
- 31167
- 31168 if (!(tp->tty_termios.c_lflag & ICANON)) {
- 31169 /* Raw mode; put a "line break" on all characters in the input queue.
- 31170 * It is undefined what happens to the input queue when ICANON is
- 31171 * switched off, a process should use TCSAFLUSH to flush the queue.
- 31172 * Keeping the queue to preserve typeahead is the Right Thing, however
- 31173 * when a process does use TCSANOW to switch to raw mode.
- 31174 */
- 31175 count = tp->tty_eotct = tp->tty_incount;
- 31176 inp = tp->tty_intail;
- 31177 while (count > 0) {
- 31178 *inp |= IN_EOT;
- 31179 if (++inp == bufend(tp->tty_inbuf)) inp = tp->tty_inbuf;
- 31180 --count;
- 31181 }
- 31182 }
- 31183
- 31184 /* Inspect MIN and TIME. */
- 31185 lock();
- 31186 settimer(tp, FALSE);
- 31187 unlock();
- 31188 if (tp->tty_termios.c_lflag & ICANON) {
- 31189 /* No MIN & TIME in canonical mode. */
- 31190 tp->tty_min = 1;
- 31191 } else {
- 31192 /* In raw mode MIN is the number of chars wanted, and TIME how long
- 31193 * to wait for them. With interesting exceptions if either is zero.
- 31194 */
- 31195 tp->tty_min = tp->tty_termios.c_cc[VMIN];
- 31196 if (tp->tty_min == 0 && tp->tty_termios.c_cc[VTIME] > 0)
- 31197 tp->tty_min = 1;
- 31198 }
- 31199
- 31200 if (!(tp->tty_termios.c_iflag & IXON)) {
- 31201 /* No start/stop output control, so don't leave output inhibited. */
- 31202 tp->tty_inhibited = RUNNING;
- 31203 tp->tty_events = 1;
- 31204 }
- 31205
- 31206 /* Setting the output speed to zero hangs up the phone. */
- 31207 if (tp->tty_termios.c_ospeed == B0) sigchar(tp, SIGHUP);
- 31208
- 31209 /* Set new line speed, character size, etc at the device level. */
- 31210 (*tp->tty_ioctl)(tp);
- 31211 }
- 31214 /*===========================================================================*
- 31215 * tty_reply *
- 31216 *===========================================================================*/
- 31217 PUBLIC void tty_reply(code, replyee, proc_nr, status)
- 31218 int code; /* TASK_REPLY or REVIVE */
- 31219 int replyee; /* destination address for the reply */
- 31220 int proc_nr; /* to whom should the reply go? */
- 31221 int status; /* reply code */
- 31222 {
- 31223 /* Send a reply to a process that wanted to read or write data. */
- 31224
- 31225 message tty_mess;
- 31226
- 31227 tty_mess.m_type = code;
- 31228 tty_mess.REP_PROC_NR = proc_nr;
- 31229 tty_mess.REP_STATUS = status;
- 31230 if ((status = send(replyee, &tty_mess)) != OK)
- 31231 panic("tty_reply failed, statusn", status);
- 31232 }
- 31235 /*===========================================================================*
- 31236 * sigchar *
- 31237 *===========================================================================*/
- 31238 PUBLIC void sigchar(tp, sig)
- 31239 register tty_t *tp;
- 31240 int sig; /* SIGINT, SIGQUIT, SIGKILL or SIGHUP */
- 31241 {
- 31242 /* Process a SIGINT, SIGQUIT or SIGKILL char from the keyboard or SIGHUP from
- 31243 * a tty close, "stty 0", or a real RS-232 hangup. MM will send the signal to
- 31244 * the process group (INT, QUIT), all processes (KILL), or the session leader
- 31245 * (HUP).
- 31246 */
- 31247
- 31248 if (tp->tty_pgrp != 0) cause_sig(tp->tty_pgrp, sig);
- 31249
- 31250 if (!(tp->tty_termios.c_lflag & NOFLSH)) {
- 31251 tp->tty_incount = tp->tty_eotct = 0; /* kill earlier input */
- 31252 tp->tty_intail = tp->tty_inhead;
- 31253 (*tp->tty_ocancel)(tp); /* kill all output */
- 31254 tp->tty_inhibited = RUNNING;
- 31255 tp->tty_events = 1;
- 31256 }
- 31257 }
- 31260 /*==========================================================================*
- 31261 * tty_icancel *
- 31262 *==========================================================================*/
- 31263 PRIVATE void tty_icancel(tp)
- 31264 register tty_t *tp;
- 31265 {
- 31266 /* Discard all pending input, tty buffer or device. */
- 31267
- 31268 tp->tty_incount = tp->tty_eotct = 0;
- 31269 tp->tty_intail = tp->tty_inhead;
- 31270 (*tp->tty_icancel)(tp);
- 31271 }
- 31274 /*==========================================================================*
- 31275 * tty_init *
- 31276 *==========================================================================*/
- 31277 PRIVATE void tty_init(tp)
- 31278 tty_t *tp; /* TTY line to initialize. */
- 31279 {
- 31280 /* Initialize tty structure and call device initialization routines. */
- 31281
- 31282 tp->tty_intail = tp->tty_inhead = tp->tty_inbuf;
- 31283 tp->tty_min = 1;
- 31284 tp->tty_termios = termios_defaults;
- 31285 tp->tty_icancel = tp->tty_ocancel = tp->tty_ioctl = tp->tty_close =
- 31286 tty_devnop;
- 31287 if (tp < tty_addr(NR_CONS)) {
- 31288 scr_init(tp);
- 31289 } else
- 31290 if (tp < tty_addr(NR_CONS+NR_RS_LINES)) {
- 31291 rs_init(tp);
- 31292 } else {
- 31293 pty_init(tp);
- 31294 }
- 31295 }
- 31298 /*==========================================================================*
- 31299 * tty_wakeup *
- 31300 *==========================================================================*/
- 31301 PUBLIC void tty_wakeup(now)
- 31302 clock_t now; /* current time */
- 31303 {
- 31304 /* Wake up TTY when something interesting is happening on one of the terminal
- 31305 * lines, like a character arriving on an RS232 line, a key being typed, or
- 31306 * a timer on a line expiring by TIME.
- 31307 */
- 31308 tty_t *tp;
- 31309
- 31310 /* Scan the timerlist for expired timers and compute the next timeout time. */
- 31311 tty_timeout = TIME_NEVER;
- 31312 while ((tp = tty_timelist) != NULL) {
- 31313 if (tp->tty_time > now) {
- 31314 tty_timeout = tp->tty_time; /* this timer is next */
- 31315 break;
- 31316 }
- 31317 tp->tty_min = 0; /* force read to succeed */
- 31318 tp->tty_events = 1;
- 31319 tty_timelist = tp->tty_timenext;
- 31320 }
- 31321
- 31322 /* Let TTY know there is something afoot. */
- 31323 interrupt(TTY);
- 31324 }
- 31327 /*===========================================================================*
- 31328 * settimer *
- 31329 *===========================================================================*/
- 31330 PRIVATE void settimer(tp, on)
- 31331 tty_t *tp; /* line to set or unset a timer on */
- 31332 int on; /* set timer if true, otherwise unset */
- 31333 {
- 31334 /* Set or unset a TIME inspired timer. This function is interrupt sensitive
- 31335 * due to tty_wakeup(), so it must be called from within lock()/unlock().
- 31336 */
- 31337 tty_t **ptp;
- 31338
- 31339 /* Take tp out of the timerlist if present. */
- 31340 for (ptp = &tty_timelist; *ptp != NULL; ptp = &(*ptp)->tty_timenext) {
- 31341 if (tp == *ptp) {
- 31342 *ptp = tp->tty_timenext; /* take tp out of the list */
- 31343 break;
- 31344 }
- 31345 }
- 31346 if (!on) return; /* unsetting it is enough */
- 31347
- 31348 /* Timeout occurs TIME deciseconds from now. */
- 31349 tp->tty_time = get_uptime() + tp->tty_termios.c_cc[VTIME] * (HZ/10);
- 31350
- 31351 /* Find a new place in the list. */
- 31352 for (ptp = &tty_timelist; *ptp != NULL; ptp = &(*ptp)->tty_timenext) {
- 31353 if (tp->tty_time <= (*ptp)->tty_time) break;
- 31354 }
- 31355 tp->tty_timenext = *ptp;
- 31356 *ptp = tp;
- 31357 if (tp->tty_time < tty_timeout) tty_timeout = tp->tty_time;
- 31358 }
- 31361 /*==========================================================================*
- 31362 * tty_devnop *
- 31363 *==========================================================================*/
- 31364 PUBLIC void tty_devnop(tp)
- 31365 tty_t *tp;
- 31366 {
- 31367 /* Some functions need not be implemented at the device level. */
- 31368 }
- 31371 #if ENABLE_SRCCOMPAT || ENABLE_BINCOMPAT
- 31372 /*===========================================================================*
- 31373 * compat_getp *
- 31374 *===========================================================================*/
- 31375 PRIVATE int compat_getp(tp, sg)
- 31376 tty_t *tp;
- 31377 struct sgttyb *sg;
- 31378 {
- 31379 /* Translate an old TIOCGETP to the termios equivalent. */
- 31380 int flgs;
- 31381
- 31382 sg->sg_erase = tp->tty_termios.c_cc[VERASE];
- 31383 sg->sg_kill = tp->tty_termios.c_cc[VKILL];
- 31384 sg->sg_ospeed = tspd2sgspd(cfgetospeed(&tp->tty_termios));
- 31385 sg->sg_ispeed = tspd2sgspd(cfgetispeed(&tp->tty_termios));
- 31386
- 31387 flgs = 0;
- 31388
- 31389 /* XTABS - if OPOST and XTABS */
- 31390 if ((tp->tty_termios.c_oflag & (OPOST|XTABS)) == (OPOST|XTABS))
- 31391 flgs |= 0006000;
- 31392
- 31393 /* BITS5..BITS8 - map directly to CS5..CS8 */
- 31394 flgs |= (tp->tty_termios.c_cflag & CSIZE) << (8-2);
- 31395
- 31396 /* EVENP - if PARENB and not PARODD */
- 31397 if ((tp->tty_termios.c_cflag & (PARENB|PARODD)) == PARENB)
- 31398 flgs |= 0000200;
- 31399
- 31400 /* ODDP - if PARENB and PARODD */
- 31401 if ((tp->tty_termios.c_cflag & (PARENB|PARODD)) == (PARENB|PARODD))