Skip to content

Instantly share code, notes, and snippets.

@sondnm
Created March 2, 2020 15:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sondnm/3515259a534227b5b5b4d25115260234 to your computer and use it in GitHub Desktop.
Save sondnm/3515259a534227b5b5b4d25115260234 to your computer and use it in GitHub Desktop.
Lions' Commentary on UNIX source code
0100: /* fundamental constants: cannot be changed */
0100: /* fundamental constants: cannot be changed */
0101:
0102:
0103: #define USIZE 16 /* size of user block (*64) */
0104: #define NULL 0
0105: #define NODEV (-1)
0106: #define ROOTINO 1 /* i number of all roots */
0107: #define DIRSIZ 14 /* max characters per directory */
0108:
0109:
0110: /* signals: dont change */
0111:
0112:
0113: #define NSIG 20
0114: #define SIGHUP 1 /* hangup */
0115: #define SIGINT 2 /* interrupt (rubout) */
0116: #define SIGQIT 3 /* quit (FS) */
0117: #define SIGINS 4 /* illegal instruction */
0118: #define SIGTRC 5 /* trace or breakpoint */
0119: #define SIGIOT 6 /* iot */
0120: #define SIGEMT 7 /* emt */
0121: #define SIGFPT 8 /* floating exception */
0122: #define SIGKIL 9 /* kill */
0123: #define SIGBUS 10 /* bus error */
0124: #define SIGSEG 11 /* segmentation violation */
0125: #define SIGSYS 12 /* sys */
0126: #define SIGPIPE 13 /* end of pipe */
0127:
0128: /* tunable variables */
0129:
0130: #define NBUF 15 /* size of buffer cache */
0131: #define NINODE 100 /* number of in core inodes */
0132: #define NFILE 100 /* number of in core file structures */
0133: #define NMOUNT 5 /* number of mountable file systems */
0134: #define NEXEC 3 /* number of simultaneous exec's */
0135: #define MAXMEM (64*32) /* max core per process
0136: - first # is Kw */
0137: #define SSIZE 20 /* initial stack size (*64 bytes) */
0138: #define SINCR 20 /* increment of stack (*64 bytes) */
0139: #define NOFILE 15 /* max open files per process */
0140: #define CANBSIZ 256 /* max size of typewriter line */
0141: #define CMAPSIZ 100 /* size of core allocation area */
0142: #define SMAPSIZ 100 /* size of swap allocation area */
0143: #define NCALL 20 /* max simultaneous time callouts */
0144: #define NPROC 50 /* max number of processes */
0145: #define NTEXT 40 /* max number of pure texts */
0146: #define NCLIST 100 /* max total clist size */
0147: #define HZ 60 /* Ticks/second of the clock */
0148:
0149:
0150:
0151: /* priorities: probably should not be altered too much */
0152:
0153:
0154: #define PSWP -100
0155: #define PINOD -90
0156: #define PRIBIO -50
0157: #define PPIPE 1
0158: #define PWAIT 40
0159: #define PSLEP 90
0160: #define PUSER 100
0161:
0162: /* Certain processor registers */
0163:
0164: #define PS 0177776
0165: #define KL 0177560
0166: #define SW 0177570
0167:
0168: /* --------------------------- */
0169:
0170: /* structure to access : */
0171:
0172:
0173: /* an integer */
0174:
0175: struct { int integ; };
0176:
0177:
0178: /* an integer in bytes */
0179:
0180: struct { char lobyte; char hibyte; };
0181:
0182:
0183: /* a sequence of integers */
0184:
0185: struct { int r[]; };
0186:
0187:
0188: /* --------------------------- */
0200: /* Random set of variables used by more than one routine. */
0201:
0202: char canonb[CANBSIZ]; /* buffer for erase and kill (#@) */
0203: int coremap[CMAPSIZ]; /* space for core allocation */
0204: int swapmap[SMAPSIZ]; /* space for swap allocation */
0205:
0206: int *rootdir; /* pointer to inode of root directory */
0207:
0208: int cputype; /* type of cpu =40, 45, or 70 */
0209:
0210: int execnt; /* number of processes in exec */
0211:
0212: int lbolt; /* time of day in 60th not in time */
0213: int time[2]; /* time in sec from 1970 */
0214: int tout[2]; /* time of day of next sleep */
0215:
0216: int mpid; /* generic for unique process id's */
0217:
0218: char runin; /* scheduling flag */
0219: char runout; /* scheduling flag */
0220: char runrun; /* scheduling flag */
0221:
0222: char curpri; /* more scheduling */
0223:
0224: int maxmem; /* actual max memory per process */
0225:
0226: int *lks; /* pointer to clock device */
0227:
0228: int rootdev; /* dev of root see conf.c */
0229: int swapdev; /* dev of swap see conf.c */
0230:
0231: int swplo; /* block number of swap space */
0232: int nswap; /* size of swap space */
0233:
0234: int updlock; /* lock for sync */
0235: int rablock; /* block to be read ahead */
0236:
0237: char regloc[]; /* locs. of saved user registers (trap.c) */
0238:
0239:
0240:
0241: /* --------------------------- */
0242:
0243:
0244:
0245:
0246:
0247:
0248:
0249:
0250:
0251: /* --------------------------- */
0252:
0253: /* The callout structure is for a routine
0254: * arranging to be called by the clock interrupt
0255: * (clock.c) with a specified argument,
0256: * within a specified amount of time.
0257: * It is used, for example, to time tab delays
0258: * on teletypes. */
0259:
0260: struct callo
0261: {
0262: int c_time; /* incremental time */
0263: int c_arg; /* argument to routine */
0264: int (*c_func)(); /* routine */
0265: } callout[NCALL];
0266: /* --------------------------- */
0267:
0268: /* Mount structure.
0269: * One allocated on every mount. Used to find the super block.
0270: */
0271:
0272: struct mount
0273: {
0274: int m_dev; /* device mounted */
0275: int *m_bufp; /* pointer to superblock */
0276: int *m_inodp; /* pointer to mounted on inode */
0277: } mount[NMOUNT];
0278: /* --------------------------- */
0300:
0301: /* KT-11 addresses and bits */
0302:
0303: #define UISD 0177600 /* first user I-space descriptor register */
0304:
0305: #define UISA 0177640 /* first user I-space address register */
0306:
0307: #define UDSA 0177660 /* first user D-space address register */
0308:
0309:
0310: #define UBMAP 0170200 /* address to access 11/70 UNIBUS map */
0311:
0312: #define RO 02 /* access abilities */
0313: #define WO 04
0314: #define RW 06
0315: #define ED 010 /* extend direction */
0316:
0317: /* --------------------------- */
0318:
0319: int *ka6; /* 11/40 KISA6; 11/45 KDSA6 */
0350: /*
0351: * One structure allocated per active
0352: * process. It contains all data needed
0353: * about the process while the
0354: * process may be swapped out.
0355: * Other per process data (user.h)
0356: * is swapped with the process.
0357: */
0358: struct proc
0359: {
0360: char p_stat;
0361: char p_flag;
0362: char p_pri; /* priority, negative is high */
0363: char p_sig; /* signal number sent to this process */
0364: char p_uid; /* user id, used to direct tty signals */
0365: char p_time; /* resident time for scheduling */
0366: char p_cpu; /* cpu usage for scheduling */
0367: char p_nice; /* nice for scheduling */
0368: int p_ttyp; /* controlling tty */
0369: int p_pid; /* unique process id */
0370: int p_ppid; /* process id of parent */
0371: int p_addr; /* address of swappable image */
0372: int p_size; /* size of swappable image (*64 bytes) */
0373: int p_wchan; /* event process is awaiting */
0374: int *p_textp; /* pointer to text structure */
0375:
0376: } proc[NPROC];
0377: /* --------------------------- */
0378:
0379: /* stat codes */
0380:
0381:
0382: #define SSLEEP 1 /* sleeping on high priority */
0383: #define SWAIT 2 /* sleeping on low priority */
0384: #define SRUN 3 /* running */
0385: #define SIDL 4 /* intermediate state in process creation */
0386: #define SZOMB 5 /* intermediate state in process termination */
0387: #define SSTOP 6 /* process being traced */
0388:
0389: /* flag codes */
0390:
0391: #define SLOAD 01 /* in core */
0392: #define SSYS 02 /* scheduling process */
0393: #define SLOCK 04 /* process cannot be swapped */
0394: #define SSWAP 010 /* process is being swapped out */
0395: #define STRC 020 /* process is being traced */
0396: #define SWTED 040 /* another tracing flag */
0400: /*
0401: * The user structure.
0402: * One allocated per process.
0403: * Contains all per process data
0404: * that doesn't need to be referenced
0405: * while the process is swapped.
0406: * The user block is USIZE*64 bytes
0407: * long; resides at virtual kernel
0408: * loc 140000; contains the system
0409: * stack per user; is cross referenced
0410: * with the proc structure for the
0411: * same process.
0412: */
0413: struct user
0414: {
0415: int u_rsav[2]; /* save r5,r6 when exchanging stacks */
0416: int u_fsav[25]; /* save fp registers */
0417: /* rsav and fsav must be first in structure */
0418: char u_segflg; /* flag for IO; user or kernel space */
0419: char u_error; /* return error code */
0420: char u_uid; /* effective user id */
0421: char u_gid; /* effective group id */
0422: char u_ruid; /* real user id */
0423: char u_rgid; /* real group id */
0424: int u_procp; /* pointer to proc structure */
0425: char *u_base; /* base address for IO */
0426: char *u_count; /* bytes remaining for IO */
0427: char *u_offset[2]; /* offset in file for IO */
0428: int *u_cdir; /* pointer to inode of current directory */
0429: char u_dbuf[DIRSIZ]; /* current pathname component */
0430: char *u_dirp; /* current pointer to inode */
0431: struct { /* current directory entry */
0432: int u_ino;
0433: char u_name[DIRSIZ];
0434: } u_dent;
0435: int *u_pdir; /* inode of parent directory of dirp */
0436: int u_uisa[16]; /* prototype of segmentation addresses */
0437: int u_uisd[16]; /* prototype of segmentation descriptors */
0438: int u_ofile[NOFILE]; /* pointers to file structures of open files */
0439: int u_arg[5]; /* arguments to current system call */
0440: int u_tsize; /* text size (*64) */
0441: int u_dsize; /* data size (*64) */
0442: int u_ssize; /* stack size (*64) */
0443: int u_sep; /* flag for I and D separation */
0444: int u_qsav[2]; /* label variable for quits and interrupts */
0445: int u_ssav[2]; /* label variable for swapping */
0446: int u_signal[NSIG]; /* disposition of signals */
0447: int u_utime; /* this process user time */
0448: int u_stime; /* this process system time */
0449: int u_cutime[2]; /* sum of childs' utimes */
0450: int u_cstime[2]; /* sum of childs' stimes */
0451: int *u_ar0; /* address of users saved R0 */
0452: int u_prof[4]; /* profile arguments */
0453: char u_intflg; /* catch intr from sys */
0454: /* kernel stack per user
0455: * extends from u + USIZE*64
0456: * backward not to reach here
0457: */
0458: } u;
0459: /* --------------------------- */
0460:
0461: /* u_error codes */
0462:
0463:
0464:
0465: #define EFAULT 106
0466: #define EPERM 1
0467: #define ENOENT 2
0468: #define ESRCH 3
0469: #define EINTR 4
0470: #define EIO 5
0471: #define ENXIO 6
0472: #define E2BIG 7
0473: #define ENOEXEC 8
0474: #define EBADF 9
0475: #define ECHILD 10
0476: #define EAGAIN 11
0477: #define ENOMEM 12
0478: #define EACCES 13
0479: #define ENOTBLK 15
0480: #define EBUSY 16
0481: #define EEXIST 17
0482: #define EXDEV 18
0483: #define ENODEV 19
0484: #define ENOTDIR 20
0485: #define EISDIR 21
0486: #define EINVAL 22
0487: #define ENFILE 23
0488: #define EMFILE 24
0489: #define ENOTTY 25
0490: #define ETXTBSY 26
0491: #define EFBIG 27
0492: #define ENOSPC 28
0493: #define ESPIPE 29
0494: #define EROFS 30
0495: #define EMLINK 31
0496: #define EPIPE 32
0500: / low core
0501:
0502: br4 = 200
0503: br5 = 240
0504: br6 = 300
0505: br7 = 340
0506:
0507: . = 0^.
0508: br 1f
0509: 4
0510:
0511: / trap vectors
0512: trap; br7+0. / bus error
0513: trap; br7+1. / illegal instruction
0514: trap; br7+2. / bpt-trace trap
0515: trap; br7+3. / iot trap
0516: trap; br7+4. / power fail
0517: trap; br7+5. / emulator trap
0518: trap; br7+6. / system entry
0519:
0520: . = 40^.
0521: .globl start, dump
0522: 1: jmp start
0523: jmp dump
0524:
0525: . = 60^.
0526: klin; br4
0527: klou; br4
0528:
0529: . = 70^.
0530: pcin; br4
0531: pcou; br4
0532:
0533: . = 100^.
0534: kwlp; br6
0535: kwlp; br6
0536:
0537: . = 114^.
0538: trap; br7+7. / 11/70 parity
0539:
0540: . = 200^.
0541: lpou; br4
0542:
0543: . = 220^.
0544: rkio; br5
0545:
0546: . = 240^.
0547: trap; br7+7. / programmed interrupt
0548: trap; br7+8. / floating point
0549: trap; br7+9. / segmentation violation
0550:
0551: //////////////////////////////////////////////////////
0552: / interface code to C
0553: //////////////////////////////////////////////////////
0554:
0555: .globl call, trap
0556:
0557: .globl _klrint
0558: klin: jsr r0,call; _klrint
0559:
0560: .globl _klxint
0561: klou: jsr r0,call; _klxint
0562:
0563: .globl _pcrint
0564: pcin: jsr r0,call; _pcrint
0565:
0566: .globl _pcpint
0567: pcou: jsr r0,call; _pcpint
0568:
0569: .globl _clock
0570: kwlp: jsr r0,call; _clock
0571:
0572:
0573: .globl _lpintr
0574: lpou: jsr r0,call; _lpintr
0575:
0576: .globl _rkintr
0577: rkio: jsr r0,call; _rkintr
0600: / machine language assist
0601: / for 11/40
0602:
0603: / non-UNIX instructions
0604: mfpi = 6500^tst
0605: mtpi = 6600^tst
0606: wait = 1
0607: rtt = 6
0608: reset = 5
0609:
0610: /* --------------------------- */
0611: .globl start, _end, _edata, _main
0612: start:
0613: bit $1,SSR0
0614: bne start / loop if restart
0615: reset
0616:
0617: / initialize systems segments
0618:
0619: mov $KISA0,r0
0620: mov $KISD0,r1
0621: mov $200,r4
0622: clr r2
0623: mov $6,r3
0624: 1:
0625: mov r2,(r0)+
0626: mov $77406,(r1)+ / 4k rw
0627: add r4,r2
0628: sob r3,1b
0629:
0630: / initialize user segment
0631:
0632: mov $_end+63.,r2
0633: ash $-6,r2
0634: bic $!1777,r2
0635: mov r2,(r0)+ / ksr6 = sysu
0636: mov $usize-1\<8|6,(r1)+
0637:
0638: / initialize io segment
0639: / set up counts on supervisor segments
0640:
0641: mov $IO,(r0)+
0642: mov $77406,(r1)+ / rw 4k
0643:
0644: / get a sp and start segmentation
0645:
0646: mov $_u+[usize*64.],sp
0647: inc SSR0
0648:
0649: / clear bss
0650:
0651: mov $_edata,r0
0652: 1:
0653: clr (r0)+
0654: cmp r0,$_end
0655: blo 1b
0656:
0657: / clear user block
0658:
0659: mov $_u,r0
0660: 1:
0661: clr (r0)+
0662: cmp r0,$_u+[usize*64.]
0663: blo 1b
0664:
0665: / set up previous mode and call main
0666: / on return, enter user mode at 0R
0667:
0668: mov $30000,PS
0669: jsr pc,_main
0670: mov $170000,-(sp)
0671: clr -(sp)
0672: rtt
0673:
0674: /* --------------------------- */
0675: .globl _clearseg
0676: _clearseg:
0677: mov PS,-(sp)
0678: mov UISA0,-(sp)
0679: mov $30340,PS
0680: mov 6(sp),UISA0
0681: mov UISD0,-(sp)
0682: mov $6,UISD0
0683: clr r0
0684: mov $32.,r1
0685: 1:
0686: clr -(sp)
0687: mtpi (r0)+
0688: sob r1,1b
0689: mov (sp)+,UISD0
0690: mov (sp)+,UISA0
0691: mov (sp)+,PS
0692: rts pc
0693:
0694: /* --------------------------- */
0695: .globl _copyseg
0696: _copyseg:
0697: mov PS,-(sp)
0698: mov UISA0,-(sp)
0699: mov UISA1,-(sp)
0700: mov $30340,PS
0701: mov 10(sp),UISA0
0702: mov 12(sp),UISA1
0703: mov UISD0,-(sp)
0704: mov UISD1,-(sp)
0705: mov $6,UISD0
0706: mov $6,UISD1
0707: mov r2,-(sp)
0708: clr r0
0709: mov $8192.,r1
0710: mov $32.,r2
0711: 1:
0712: mfpi (r0)+
0713: mtpi (r1)+
0714: sob r2,1b
0715: mov (sp)+,r2
0716: mov (sp)+,UISD1
0717: mov (sp)+,UISD0
0718: mov (sp)+,UISA1
0719: mov (sp)+,UISA0
0720: mov (sp)+,PS
0721: rts pc
0722:
0723: /* --------------------------- */
0724: .globl _savu, _retu, _aretu
0725: _savu:
0726: bis $340,PS
0727: mov (sp)+,r1
0728: mov (sp),r0
0729: mov sp,(r0)+
0730: mov r5,(r0)+
0731: bic $340,PS
0732: jmp (r1)
0733:
0734: _aretu:
0735: bis $340,PS
0736: mov (sp)+,r1
0737: mov (sp),r0
0738: br 1f
0739:
0740: _retu:
0741: bis $340,PS
0742: mov (sp)+,r1
0743: mov (sp),KISA6
0744: mov $_u,r0
0745: 1:
0746: mov (r0)+,sp
0747: mov (r0)+,r5
0748: bic $340,PS
0749: jmp (r1)
0750:
0751: /* --------------------------- */
0752: .globl trap, call
0753: /* --------------------------- */
0754: .globl _trap
0755: trap:
0756: mov PS,-4(sp)
0757: tst nofault
0758: bne 1f
0759: mov SSR0,ssr
0760: mov SSR2,ssr+4
0761: mov $1,SSR0
0762: jsr r0,call1; _trap
0763: / no return
0764: 1:
0765: mov $1,SSR0
0766: mov nofault,(sp)
0767: rtt
0768:
0769: /* --------------------------- */
0770: .globl _runrun, _swtch
0771: call1:
0772: tst -(sp)
0773: bic $340,PS
0774: br 1f
0775:
0776: call:
0777: mov PS,-(sp)
0778: 1:
0779: mov r1,-(sp)
0780: mfpi sp
0781: mov 4(sp),-(sp)
0782: bic $!37,(sp)
0783: bit $30000,PS
0784: beq 1f
0785: jsr pc,*(r0)+
0786: 2:
0787: bis $340,PS
0788: tstb _runrun
0789: beq 2f
0790: bic $340,PS
0791: jsr pc,_swtch
0792: br 2b
0793: 2:
0794: tst (sp)+
0795: mtpi sp
0796: br 2f
0797: 1:
0798: bis $30000,PS
0799: jsr pc,*(r0)+
0800: cmp (sp)+,(sp)+
0801: 2:
0802: mov (sp)+,r1
0803: tst (sp)+
0804: mov (sp)+,r0
0805: rtt
0806: /* --------------------------- */
0807: .globl _fubyte, _subyte
0808: /* --------------------------- */
0809: .globl _fuibyte, _suibyte
0810: /* --------------------------- */
0811: .globl _fuword, _suword
0812: /* --------------------------- */
0813: .globl _fuiword, _suiword
0814: _fuibyte:
0815: _fubyte:
0816: mov 2(sp),r1
0817: bic $1,r1
0818: jsr pc,gword
0819: cmp r1,2(sp)
0820: beq 1f
0821: swab r0
0822: 1:
0823: bic $!377,r0
0824: rts pc
0825:
0826: _suibyte:
0827: _subyte:
0828: mov 2(sp),r1
0829: bic $1,r1
0830: jsr pc,gword
0831: mov r0,-(sp)
0832: cmp r1,4(sp)
0833: beq 1f
0834: movb 6(sp),1(sp)
0835: br 2f
0836: 1:
0837: movb 6(sp),(sp)
0838: 2:
0839: mov (sp)+,r0
0840: jsr pc,pword
0841: clr r0
0842: rts pc
0843:
0844: _fuiword:
0845: _fuword:
0846: mov 2(sp),r1
0847: fuword:
0848: jsr pc,gword
0849: rts pc
0850:
0851: gword:
0852: mov PS,-(sp)
0853: bis $340,PS
0854: mov nofault,-(sp)
0855: mov $err,nofault
0856: mfpi (r1)
0857: mov (sp)+,r0
0858: br 1f
0859:
0860: _suiword:
0861: _suword:
0862: mov 2(sp),r1
0863: mov 4(sp),r0
0864: suword:
0865: jsr pc,pword
0866: rts pc
0867:
0868: pword:
0869: mov PS,-(sp)
0870: bis $340,PS
0871: mov nofault,-(sp)
0872: mov $err,nofault
0873: mov r0,-(sp)
0874: mtpi (r1)
0875: 1:
0876: mov (sp)+,nofault
0877: mov (sp)+,PS
0878: rts pc
0879:
0880: err:
0881: mov (sp)+,nofault
0882: mov (sp)+,PS
0883: tst (sp)+
0884: mov $-1,r0
0885: rts pc
0886:
0887: /* --------------------------- */
0888: .globl _savfp, _display
0889: _savfp:
0890: _display:
0891: rts pc
0892:
0893: /* --------------------------- */
0894: .globl _incupc
0895: _incupc:
0896: mov r2,-(sp)
0897: mov 6(sp),r2 / base of prof with base,leng,off,scale
0898: mov 4(sp),r0 / pc
0899: sub 4(r2),r0 / offset
0900: clc
0901: ror r0
0902: mul 6(r2),r0 / scale
0903: ashc $-14.,r0
0904: inc r1
0905: bic $1,r1
0906: cmp r1,2(r2) / length
0907: bhis 1f
0908: add (r2),r1 / base
0909: mov nofault,-(sp)
0910: mov $2f,nofault
0911: mfpi (r1)
0912: inc (sp)
0913: mtpi (r1)
0914: br 3f
0915: 2:
0916: clr 6(r2)
0917: 3:
0918: mov (sp)+,nofault
0919: 1:
0920: mov (sp)+,r2
0921: rts pc
0922:
0923: / Character list get/put
0924:
0925: /* --------------------------- */
0926: .globl _getc, _putc
0927: /* --------------------------- */
0928: .globl _cfreelist
0929:
0930: _getc:
0931: mov 2(sp),r1
0932: mov PS,-(sp)
0933: mov r2,-(sp)
0934: bis $340,PS
0935: bic $100,PS / spl 5
0936: mov 2(r1),r2 / first ptr
0937: beq 9f / empty
0938: movb (r2)+,r0 / character
0939: bic $!377,r0
0940: mov r2,2(r1)
0941: dec (r1)+ / count
0942: bne 1f
0943: clr (r1)+
0944: clr (r1)+ / last block
0945: br 2f
0946: 1:
0947: bit $7,r2
0948: bne 3f
0949: mov -10(r2),(r1) / next block
0950: add $2,(r1)
0951: 2:
0952: dec r2
0953: bic $7,r2
0954: mov _cfreelist,(r2)
0955: mov r2,_cfreelist
0956: 3:
0957: mov (sp)+,r2
0958: mov (sp)+,PS
0959: rts pc
0960: 9:
0961: clr 4(r1)
0962: mov $-1,r0
0963: mov (sp)+,r2
0964: mov (sp)+,PS
0965: rts pc
0966:
0967: _putc:
0968: mov 2(sp),r0
0969: mov 4(sp),r1
0970: mov PS,-(sp)
0971: mov r2,-(sp)
0972: mov r3,-(sp)
0973: bis $340,PS
0974: bic $100,PS / spl 5
0975: mov 4(r1),r2 / last ptr
0976: bne 1f
0977: mov _cfreelist,r2
0978: beq 9f
0979: mov (r2),_cfreelist
0980: clr (r2)+
0981: mov r2,2(r1) / first ptr
0982: br 2f
0983: 1:
0984: bit $7,r2
0985: bne 2f
0986: mov _cfreelist,r3
0987: beq 9f
0988: mov (r3),_cfreelist
0989: mov r3,-10(r2)
0990: mov r3,r2
0991: clr (r2)+
0992: 2:
0993: movb r0,(r2)+
0994: mov r2,4(r1)
0995: inc (r1) / count
0996: clr r0
0997: mov (sp)+,r3
0998: mov (sp)+,r2
0999: mov (sp)+,PS
1000: rts pc
1001: 9:
1002: mov pc,r0
1003: mov (sp)+,r3
1004: mov (sp)+,r2
1005: mov (sp)+,PS
1006: rts pc
1007:
1008: /* --------------------------- */
1009: .globl _backup
1010: /* --------------------------- */
1011: .globl _regloc
1012: _backup:
1013: mov 2(sp),ssr+2
1014: mov r2,-(sp)
1015: jsr pc,backup
1016: mov r2,ssr+2
1017: mov (sp)+,r2
1018: movb jflg,r0
1019: bne 2f
1020: mov 2(sp),r0
1021: movb ssr+2,r1
1022: jsr pc,1f
1023: movb ssr+3,r1
1024: jsr pc,1f
1025: movb _regloc+7,r1
1026: asl r1
1027: add r0,r1
1028: mov ssr+4,(r1)
1029: clr r0
1030: 2:
1031: rts pc
1032: 1:
1033: mov r1,-(sp)
1034: asr (sp)
1035: asr (sp)
1036: asr (sp)
1037: bic $!7,r1
1038: movb _regloc(r1),r1
1039: asl r1
1040: add r0,r1
1041: sub (sp)+,(r1)
1042: rts pc
1043:
1044: / hard part
1045: / simulate the ssr2 register missing on 11/40
1046:
1047: backup:
1048: clr r2 / backup register ssr1
1049: mov $1,bflg / clrs jflg
1050: mov ssr+4,r0
1051: jsr pc,fetch
1052: mov r0,r1
1053: ash $-11.,r0
1054: bic $!36,r0
1055: jmp *0f(r0)
1056: 0: t00; t01; t02; t03; t04; t05; t06; t07
1057: t10; t11; t12; t13; t14; t15; t16; t17
1058:
1059: t00:
1060: clrb bflg
1061:
1062: t10:
1063: mov r1,r0
1064: swab r0
1065: bic $!16,r0
1066: jmp *0f(r0)
1067: 0: u0; u1; u2; u3; u4; u5; u6; u7
1068:
1069: u6: / single op, m[tf]pi, sxt, illegal
1070: bit $400,r1
1071: beq u5 / all but m[tf], sxt
1072: bit $200,r1
1073: beq 1f / mfpi
1074: bit $100,r1
1075: bne u5 / sxt
1076:
1077: / simulate mtpi with double (sp)+,dd
1078: bic $4000,r1 / turn instr into (sp)+
1079: br t01
1080:
1081: / simulate mfpi with double ss,-(sp)
1082: 1:
1083: ash $6,r1
1084: bis $46,r1 / -(sp)
1085: br t01
1086:
1087: u4: / jsr
1088: mov r1,r0
1089: jsr pc,setreg / assume no fault
1090: bis $173000,r2 / -2 from sp
1091: rts pc
1092:
1093: t07: / EIS
1094: clrb bflg
1095:
1096: u0: / jmp, swab
1097: u5: / single op
1098: mov r1,r0
1099: br setreg
1100:
1101: t01: / mov
1102: t02: / cmp
1103: t03: / bit
1104: t04: / bic
1105: t05: / bis
1106: t06: / add
1107: t16: / sub
1108: clrb bflg
1109:
1110: t11: / movb
1111: t12: / cmpb
1112: t13: / bitb
1113: t14: / bicb
1114: t15: / bisb
1115: mov r1,r0
1116: ash $-6,r0
1117: jsr pc,setreg
1118: swab r2
1119: mov r1,r0
1120: jsr pc,setreg
1121:
1122: / if delta(dest) is zero,
1123: / no need to fetch source
1124:
1125: bit $370,r2
1126: beq 1f
1127:
1128: / if mode(source) is R,
1129: / no fault is possible
1130:
1131: bit $7000,r1
1132: beq 1f
1133:
1134: / if reg(source) is reg(dest),
1135: / too bad.
1136:
1137: mov r2,-(sp)
1138: bic $174370,(sp)
1139: cmpb 1(sp),(sp)+
1140: beq t17
1141:
1142: / start source cycle
1143: / pick up value of reg
1144:
1145: mov r1,r0
1146: ash $-6,r0
1147: bic $!7,r0
1148: movb _regloc(r0),r0
1149: asl r0
1150: add ssr+2,r0
1151: mov (r0),r0
1152:
1153: / if reg has been incremented,
1154: / must decrement it before fetch
1155:
1156: bit $174000,r2
1157: ble 2f
1158: dec r0
1159: bit $10000,r2
1160: beq 2f
1161: dec r0
1162: 2:
1163:
1164: / if mode is 6,7 fetch and add X(R) to R
1165:
1166: bit $4000,r1
1167: beq 2f
1168: bit $2000,r1
1169: beq 2f
1170: mov r0,-(sp)
1171: mov ssr+4,r0
1172: add $2,r0
1173: jsr pc,fetch
1174: add (sp)+,r0
1175: 2:
1176:
1177: / fetch operand
1178: / if mode is 3,5,7 fetch *
1179:
1180: jsr pc,fetch
1181: bit $1000,r1
1182: beq 1f
1183: bit $6000,r1
1184: bne fetch
1185: 1:
1186: rts pc
1187:
1188: t17: / illegal
1189: u1: / br
1190: u2: / br
1191: u3: / br
1192: u7: / illegal
1193: incb jflg
1194: rts pc
1195:
1196: setreg:
1197: mov r0,-(sp)
1198: bic $!7,r0
1199: bis r0,r2
1200: mov (sp)+,r0
1201: ash $-3,r0
1202: bic $!7,r0
1203: movb 0f(r0),r0
1204: tstb bflg
1205: beq 1f
1206: bit $2,r2
1207: beq 2f
1208: bit $4,r2
1209: beq 2f
1210: 1:
1211: cmp r0,$20
1212: beq 2f
1213: cmp r0,$-20
1214: beq 2f
1215: asl r0
1216: 2:
1217: bisb r0,r2
1218: rts pc
1219:
1220: 0: .byte 0,0,10,20,-10,-20,0,0
1221:
1222: fetch:
1223: bic $1,r0
1224: mov nofault,-(sp)
1225: mov $1f,nofault
1226: mfpi (r0)
1227: mov (sp)+,r0
1228: mov (sp)+,nofault
1229: rts pc
1230:
1231: 1:
1232: mov (sp)+,nofault
1233: clrb r2 / clear out dest on fault
1234: mov $-1,r0
1235: rts pc
1236:
1237: .bss
1238: bflg: .=.+1
1239: jflg: .=.+1
1240: .text
1241:
1242: /* --------------------------- */
1243: .globl _copyin, _copyout
1244: _copyin:
1245: jsr pc,copsu
1246: 1:
1247: mfpi (r0)+
1248: mov (sp)+,(r1)+
1249: sob r2,1b
1250: br 2f
1251:
1252: _copyout:
1253: jsr pc,copsu
1254: 1:
1255: mov (r0)+,-(sp)
1256: mtpi (r1)+
1257: sob r2,1b
1258: 2:
1259: mov (sp)+,nofault
1260: mov (sp)+,r2
1261: clr r0
1262: rts pc
1263:
1264: copsu:
1265: mov (sp)+,r0
1266: mov r2,-(sp)
1267: mov nofault,-(sp)
1268: mov r0,-(sp)
1269: mov 10(sp),r0
1270: mov 12(sp),r1
1271: mov 14(sp),r2
1272: asr r2
1273: mov $1f,nofault
1274: rts pc
1275:
1276: 1:
1277: mov (sp)+,nofault
1278: mov (sp)+,r2
1279: mov $-1,r0
1280: rts pc
1281:
1282: /* --------------------------- */
1283: .globl _idle
1284: _idle:
1285: mov PS,-(sp)
1286: bic $340,PS
1287: wait
1288: mov (sp)+,PS
1289: rts pc
1290:
1291: /* --------------------------- */
1292: .globl _spl0, _spl1, _spl4, _spl5, _spl6, _spl7
1293: _spl0:
1294: bic $340,PS
1295: rts pc
1296:
1297: _spl1:
1298: bis $40,PS
1299: bic $300,PS
1300: rts pc
1301:
1302: _spl4:
1303: _spl5:
1304: bis $340,PS
1305: bic $100,PS
1306: rts pc
1307:
1308: _spl6:
1309: bis $340,PS
1310: bic $40,PS
1311: rts pc
1312:
1313: _spl7:
1314: bis $340,PS
1315: rts pc
1316:
1317: /* --------------------------- */
1318: .globl _dpadd
1319: _dpadd:
1320: mov 2(sp),r0
1321: add 4(sp),2(r0)
1322: adc (r0)
1323: rts pc
1324:
1325: /* --------------------------- */
1326: .globl _dpcmp
1327: _dpcmp:
1328: mov 2(sp),r0
1329: mov 4(sp),r1
1330: sub 6(sp),r0
1331: sub 8(sp),r1
1332: sbc r0
1333: bge 1f
1334: cmp r0,$-1
1335: bne 2f
1336: cmp r1,$-512.
1337: bhi 3f
1338: 2:
1339: mov $-512.,r0
1340: rts pc
1341: 1:
1342: bne 2f
1343: cmp r1,$512.
1344: blo 3f
1345: 2:
1346: mov $512.,r1
1347: 3:
1348: mov r1,r0
1349: rts pc
1350:
1351: /* --------------------------- */
1352: .globl dump
1353: dump:
1354: bit $1,SSR0
1355: bne dump
1356:
1357: / save regs r0,r1,r2,r3,r4,r5,r6,KIA6
1358: / starting at abs location 4
1359:
1360: mov r0,4
1361: mov $6,r0
1362: mov r1,(r0)+
1363: mov r2,(r0)+
1364: mov r3,(r0)+
1365: mov r4,(r0)+
1366: mov r5,(r0)+
1367: mov sp,(r0)+
1368: mov KISA6,(r0)+
1369:
1370: / dump all of core (ie to first mt error)
1371: / onto mag tape. (9 track or 7 track 'binary')
1372:
1373: mov $MTC,r0
1374: mov $60004,(r0)+
1375: clr 2(r0)
1376: 1:
1377: mov $-512.,(r0)
1378: inc -(r0)
1379: 2:
1380: tstb (r0)
1381: bge 2b
1382: tst (r0)+
1383: bge 1b
1384: reset
1385:
1386: / end of file and loop
1387:
1388: mov $60007,-(r0)
1389: br .
1390:
1391: /* --------------------------- */
1392: .globl _ldiv
1393: _ldiv:
1394: clr r0
1395: mov 2(sp),r1
1396: div 4(sp),r0
1397: rts pc
1398:
1399: /* --------------------------- */
1400: .globl _lrem
1401: _lrem:
1402: clr r0
1403: mov 2(sp),r1
1404: div 4(sp),r0
1405: mov r1,r0
1406: rts pc
1407:
1408: /* --------------------------- */
1409: .globl _lshift
1410: _lshift:
1411: mov 2(sp),r1
1412: mov (r1)+,r0
1413: mov (r1),r1
1414: ashc 4(sp),r0
1415: mov r1,r0
1416: rts pc
1417:
1418: /* --------------------------- */
1419: .globl csv
1420: csv:
1421: mov r5,r0
1422: mov sp,r5
1423: mov r4,-(sp)
1424: mov r3,-(sp)
1425: mov r2,-(sp)
1426: jsr pc,(r0)
1427:
1428: /* --------------------------- */
1429: .globl cret
1430: cret:
1431: mov r5,r1
1432: mov -(r1),r4
1433: mov -(r1),r3
1434: mov -(r1),r2
1435: mov r5,sp
1436: mov (sp)+,r5
1437: rts pc
1438:
1439: /* --------------------------- */
1440: .globl _u
1441: _u = 140000
1442: usize = 16.
1443:
1444: PS = 177776
1445: SSR0 = 177572
1446: SSR2 = 177576
1447: KISA0 = 172340
1448: KISA6 = 172354
1449: KISD0 = 172300
1450: MTC = 172522
1451: UISA0 = 177640
1452: UISA1 = 177642
1453: UISD0 = 177600
1454: UISD1 = 177602
1455: IO = 7600
1456:
1457: .data
1458: /* --------------------------- */
1459: .globl _ka6, _cputype
1460: _ka6: KISA6
1461: _cputype:40.
1462:
1463: .bss
1464: /* --------------------------- */
1465: .globl nofault, ssr, badtrap
1466: nofault:.=.+2
1467: ssr: .=.+6
1468: badtrap:.=.+2
1500: #
1501: #include "../param.h"
1502: #include "../user.h"
1503: #include "../systm.h"
1504: #include "../proc.h"
1505: #include "../text.h"
1506: #include "../inode.h"
1507: #include "../seg.h"
1508:
1509: #define CLOCK1 0177546
1510: #define CLOCK2 0172540
1511: /*
1512: * Icode is the octal bootstrap
1513: * program executed in user mode
1514: * to bring up the system.
1515: */
1516: int icode[]
1517: {
1518: 0104413, /* sys exec; init; initp */
1519: 0000014,
1520: 0000010,
1521: 0000777, /* br . */
1522: 0000014, /* initp: init; 0 */
1523: 0000000,
1524: 0062457, /* init: </etc/init\0> */
1525: 0061564,
1526: 0064457,
1527: 0064556,
1528: 0000164,
1529: };
1530: /* --------------------------- */
1531:
1532: /*
1533: * Initialization code.
1534: * Called from m40.s or m45.s as
1535: * soon as a stack and segmentation
1536: * have been established.
1537: * Functions:
1538: * clear and free user core
1539: * find which clock is configured
1540: * hand craft 0th process
1541: * call all initialization routines
1542: * fork - process 0 to schedule
1543: * - process 1 execute bootstrap
1544: *
1545: * panic: no clock -- neither clock responds
1546: * loop at loc 6 in user mode -- /etc/init
1547: * cannot be executed.
1548: */
1549:
1550: main()
1551: {
1552: extern schar;
1553: register i, *p;
1554:
1555: /*
1556: * zero and free all of core
1557: */
1558:
1559: updlock = 0;
1560: i = *ka6 + USIZE;
1561: UISD->r[0] = 077406;
1562: for(;;) {
1563: UISA->r[0] = i;
1564: if(fuibyte(0) < 0)
1565: break;
1566: clearseg(i);
1567: maxmem++;
1568: mfree(coremap, 1, i);
1569: i++;
1570: }
1571: if(cputype == 70)
1572: for(i=0; i<62; i=+2) {
1573: UBMAP->r[i] = i<<12;
1574: UBMAP->r[i+1] = 0;
1575: }
1576: printf("mem = %l\n", maxmem*5/16);
1577:
1578:
1579:
1580:
1581:
1582: maxmem = min(maxmem, MAXMEM);
1583: mfree(swapmap, nswap, swplo);
1584:
1585: /*
1586: * set up system process
1587: */
1588:
1589: proc[0].p_addr = *ka6;
1590: proc[0].p_size = USIZE;
1591: proc[0].p_stat = SRUN;
1592: proc[0].p_flag =| SLOAD|SSYS;
1593: u.u_procp = &proc[0];
1594:
1595: /*
1596: * determine clock
1597: */
1598:
1599: UISA->r[7] = ka6[1]; /* io segment */
1600: UISD->r[7] = 077406;
1601: lks = CLOCK1;
1602: if(fuiword(lks) == -1) {
1603: lks = CLOCK2;
1604: if(fuiword(lks) == -1)
1605: panic("no clock");
1606: }
1607:
1608: /*
1609: * set up 'known' i-nodes
1610: */
1611:
1612: *lks = 0115;
1613: cinit();
1614: binit();
1615: iinit();
1616: rootdir = iget(rootdev, ROOTINO);
1617: rootdir->i_flag =& ~ILOCK;
1618: u.u_cdir = iget(rootdev, ROOTINO);
1619: u.u_cdir->i_flag =& ~ILOCK;
1620:
1621: /*
1622: * make init process
1623: * enter scheduling loop
1624: * with system process
1625: */
1626:
1627: if(newproc()) {
1628: expand(USIZE+1);
1629: estabur(0, 1, 0, 0);
1630: copyout(icode, 0, sizeof icode);
1631: /*
1632: * Return goes to loc. 0 of user init
1633: * code just copied out.
1634: */
1635: return;
1636: }
1637: sched();
1638: }
1639: /* --------------------------- */
1640:
1641: /*
1642: * Set up software prototype segmentation
1643: * registers to implement the 3 pseudo
1644: * text,data,stack segment sizes passed
1645: * as arguments.
1646: * The argument sep specifies if the
1647: * text and data+stack segments are to
1648: * be separated.
1649: */
1650: estabur(nt, nd, ns, sep)
1651: {
1652: register a, *ap, *dp;
1653:
1654: if(sep) {
1655: if(cputype == 40)
1656: goto err;
1657: if(nseg(nt) > 8 || nseg(nd)+nseg(ns) > 8)
1658: goto err;
1659: } else
1660: if(nseg(nt)+nseg(nd)+nseg(ns) > 8)
1661: goto err;
1662: if(nt+nd+ns+USIZE > maxmem)
1663: goto err;
1664: a = 0;
1665: ap = &u.u_uisa[0];
1666: dp = &u.u_uisd[0];
1667: while(nt >= 128) {
1668: *dp++ = (127<<8) | RO;
1669: *ap++ = a;
1670: a =+ 128;
1671: nt =- 128;
1672: }
1673: if(nt) {
1674: *dp++ = ((nt-1)<<8) | RO;
1675: *ap++ = a;
1676: }
1677: if(sep)
1678: while(ap < &u.u_uisa[8]) {
1679: *ap++ = 0;
1680: *dp++ = 0;
1681: }
1682: a = USIZE;
1683: while(nd >= 128) {
1684: *dp++ = (127<<8) | RW;
1685: *ap++ = a;
1686: a =+ 128;
1687: nd =- 128;
1688: }
1689: if(nd) {
1690: *dp++ = ((nd-1)<<8) | RW;
1691: *ap++ = a;
1692: a =+ nd;
1693: }
1694: while(ap < &u.u_uisa[8]) {
1695: *dp++ = 0;
1696: *ap++ = 0;
1697: }
1698: if(sep)
1699: while(ap < &u.u_uisa[16]) {
1700: *dp++ = 0;
1701: *ap++ = 0;
1702: }
1703: a =+ ns;
1704: while(ns >= 128) {
1705: a =- 128;
1706: ns =- 128;
1707: *--dp = (127<<8) | RW;
1708: *--ap = a;
1709: }
1710: if(ns) {
1711: *--dp = ((128-ns)<<8) | RW | ED;
1712: *--ap = a-128;
1713: }
1714: if(!sep) {
1715: ap = &u.u_uisa[0];
1716: dp = &u.u_uisa[8];
1717: while(ap < &u.u_uisa[8])
1718: *dp++ = *ap++;
1719: ap = &u.u_uisd[0];
1720: dp = &u.u_uisd[8];
1721: while(ap < &u.u_uisd[8])
1722: *dp++ = *ap++;
1723: }
1724: sureg();
1725: return(0);
1726:
1727: err:
1728: u.u_error = ENOMEM;
1729: return(-1);
1730: }
1731: /* --------------------------- */
1732:
1733: /*
1734: * Load the user hardware segmentation
1735: * registers from the software prototype.
1736: * The software registers must have
1737: * been setup prior by estabur.
1738: */
1739: sureg()
1740: {
1741: register *up, *rp, a;
1742:
1743: a = u.u_procp->p_addr;
1744: up = &u.u_uisa[16];
1745: rp = &UISA->r[16];
1746: if(cputype == 40) {
1747: up =- 8;
1748: rp =- 8;
1749: }
1750: while(rp > &UISA->r[0])
1751: *--rp = *--up + a;
1752: if((up=u.u_procp->p_textp) != NULL)
1753: a =- up->x_caddr;
1754: up = &u.u_uisd[16];
1755: rp = &UISD->r[16];
1756: if(cputype == 40) {
1757: up =- 8;
1758: rp =- 8;
1759: }
1760: while(rp > &UISD->r[0]) {
1761: *--rp = *--up;
1762: if((*rp & WO) == 0)
1763: rp[(UISA-UISD)/2] =- a;
1764: }
1765: }
1766: /* --------------------------- */
1767:
1768: /*
1769: * Return the arg/128 rounded up.
1770: */
1771: nseg(n)
1772: {
1773:
1774: return((n+127)>>7);
1775: }
1776: /* --------------------------- */
1800: #
1801: /*
1802: */
1803:
1804: #include "../param.h"
1805: #include "../user.h"
1806: #include "../proc.h"
1807: #include "../text.h"
1808: #include "../systm.h"
1809: #include "../file.h"
1810: #include "../inode.h"
1811: #include "../buf.h"
1812: /* --------------------------- */
1813: /*
1814: * Create a new process-- the internal version of
1815: * sys fork.
1816: * It returns 1 in the new process.
1817: * How this happens is rather hard to understand.
1818: * The essential fact is that the new process is created
1819: * in such a way that appears to have started executing
1820: * in the same call to newproc as the parent;
1821: * but in fact the code that runs is that of swtch.
1822: * The subtle implication of the returned value of swtch
1823: * (see above) is that this is the value that newproc's
1824: * caller in the new process sees.
1825: */
1826: newproc()
1827: {
1828: int a1, a2;
1829: struct proc *p, *up;
1830: register struct proc *rpp;
1831: register *rip, n;
1832:
1833: p = NULL;
1834: /*
1835: * First, just locate a slot for a process
1836: * and copy the useful info from this process into it.
1837: * The panic "cannot happen" because fork has already
1838: * checked for the existence of a slot.
1839: */
1840: retry:
1841: mpid++;
1842: if(mpid < 0) {
1843: mpid = 0;
1844: goto retry;
1845: }
1846: for(rpp = &proc[0]; rpp < &proc[NPROC]; rpp++) {
1847: if(rpp->p_stat == NULL && p==NULL)
1848: p = rpp;
1849: if (rpp->p_pid==mpid)
1850: goto retry;
1851: }
1852: if ((rpp = p)==NULL)
1853: panic("no procs");
1854:
1855: /*
1856: * make proc entry for new proc
1857: */
1858:
1859: rip = u.u_procp;
1860: up = rip;
1861: rpp->p_stat = SRUN;
1862: rpp->p_flag = SLOAD;
1863: rpp->p_uid = rip->p_uid;
1864: rpp->p_ttyp = rip->p_ttyp;
1865: rpp->p_nice = rip->p_nice;
1866: rpp->p_textp = rip->p_textp;
1867: rpp->p_pid = mpid;
1868: rpp->p_ppid = rip->p_pid;
1869: rpp->p_time = 0;
1870:
1871: /*
1872: * make duplicate entries
1873: * where needed
1874: */
1875:
1876: for(rip = &u.u_ofile[0]; rip < &u.u_ofile[NOFILE];)
1877: if((rpp = *rip++) != NULL)
1878: rpp->f_count++;
1879: if((rpp=up->p_textp) != NULL) {
1880: rpp->x_count++;
1881: rpp->x_ccount++;
1882: }
1883: u.u_cdir->i_count++;
1884: /*
1885: * Partially simulate the environment
1886: * of the new process so that when it is actually
1887: * created (by copying) it will look right.
1888: */
1889: savu(u.u_rsav);
1890: rpp = p;
1891: u.u_procp = rpp;
1892: rip = up;
1893: n = rip->p_size;
1894: a1 = rip->p_addr;
1895: rpp->p_size = n;
1896: a2 = malloc(coremap, n);
1897: /*
1898: * If there is not enough core for the
1899: * new process, swap out the current process to generate the
1900: * copy.
1901: */
1902: if(a2 == NULL) {
1903: rip->p_stat = SIDL;
1904: rpp->p_addr = a1;
1905: savu(u.u_ssav);
1906: xswap(rpp, 0, 0);
1907: rpp->p_flag =| SSWAP;
1908: rip->p_stat = SRUN;
1909: } else {
1910: /*
1911: * There is core, so just copy.
1912: */
1913: rpp->p_addr = a2;
1914: while(n--)
1915: copyseg(a1++, a2++);
1916: }
1917: u.u_procp = rip;
1918: return(0);
1919: }
1920: /* --------------------------- */
1921:
1922: /*
1923: * The main loop of the scheduling (swapping)
1924: * process.
1925: * The basic idea is:
1926: * see if anyone wants to be swapped in;
1927: * swap out processes until there is room;
1928: * swap him in;
1929: * repeat.
1930: * Although it is not remarkably evident, the basic
1931: * synchronization here is on the runin flag, which is
1932: * slept on and is set once per second by the clock routine.
1933: * Core shuffling therefore takes place once per second.
1934: *
1935: * panic: swap error -- IO error while swapping.
1936: * this is the one panic that should be
1937: * handled in a less drastic way. Its
1938: * very hard.
1939: */
1940: sched()
1941: {
1942: struct proc *p1;
1943: register struct proc *rp;
1944: register a, n;
1945:
1946: /*
1947: * find user to swap in
1948: * of users ready, select one out longest
1949: */
1950:
1951: goto loop;
1952:
1953: sloop:
1954: runin++;
1955: sleep(&runin, PSWP);
1956:
1957: loop:
1958: spl6();
1959: n = -1;
1960: for(rp = &proc[0]; rp < &proc[NPROC]; rp++)
1961: if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)==0 &&
1962: rp->p_time > n) {
1963: p1 = rp;
1964: n = rp->p_time;
1965: }
1966: if(n == -1) {
1967: runout++;
1968: sleep(&runout, PSWP);
1969: goto loop;
1970: }
1971:
1972: /*
1973: * see if there is core for that process
1974: */
1975:
1976: spl0();
1977: rp = p1;
1978: a = rp->p_size;
1979: if((rp=rp->p_textp) != NULL)
1980: if(rp->x_ccount == 0)
1981: a =+ rp->x_size;
1982: if((a=malloc(coremap, a)) != NULL)
1983: goto found2;
1984:
1985: /*
1986: * none found,
1987: * look around for easy core
1988: */
1989:
1990: spl6();
1991: for(rp = &proc[0]; rp < &proc[NPROC]; rp++)
1992: if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD &&
1993: (rp->p_stat == SWAIT || rp->p_stat==SSTOP))
1994: goto found1;
1995:
1996: /*
1997: * no easy core,
1998: * if this process is deserving,
1999: * look around for
2000: * oldest process in core
2001: */
2002:
2003: if(n < 3)
2004: goto sloop;
2005: n = -1;
2006: for(rp = &proc[0]; rp < &proc[NPROC]; rp++)
2007: if((rp->p_flag&(SSYS|SLOCK|SLOAD))==SLOAD &&
2008: (rp->p_stat==SRUN || rp->p_stat==SSLEEP) &&
2009: rp->p_time > n) {
2010: p1 = rp;
2011: n = rp->p_time;
2012: }
2013: if(n < 2)
2014: goto sloop;
2015: rp = p1;
2016:
2017: /*
2018: * swap user out
2019: */
2020:
2021: found1:
2022: spl0();
2023: rp->p_flag =& ~SLOAD;
2024: xswap(rp, 1, 0);
2025: goto loop;
2026:
2027: /*
2028: * swap user in
2029: */
2030:
2031: found2:
2032: if((rp=p1->p_textp) != NULL) {
2033: if(rp->x_ccount == 0) {
2034: if(swap(rp->x_daddr, a, rp->x_size, B_READ))
2035: goto swaper;
2036: rp->x_caddr = a;
2037: a =+ rp->x_size;
2038: }
2039: rp->x_ccount++;
2040: }
2041: rp = p1;
2042: if(swap(rp->p_addr, a, rp->p_size, B_READ))
2043: goto swaper;
2044: mfree(swapmap, (rp->p_size+7)/8, rp->p_addr);
2045: rp->p_addr = a;
2046: rp->p_flag =| SLOAD;
2047: rp->p_time = 0;
2048: goto loop;
2049:
2050: swaper:
2051: panic("swap error");
2052: }
2053: /* --------------------------- */
2054:
2055: /*
2056: * Give up the processor till a wakeup occurs
2057: * on chan, at which time the process
2058: * enters the scheduling queue at priority pri.
2059: * The most important effect of pri is that when
2060: * pri<0 a signal cannot disturb the sleep;
2061: * if pri>=0 signals will be processed.
2062: * Callers of this routine must be prepared for
2063: * premature return, and check that the reason for
2064: * sleeping has gone away.
2065: */
2066: sleep(chan, pri)
2067: {
2068: register *rp, s;
2069:
2070: s = PS->integ;
2071: rp = u.u_procp;
2072: if(pri >= 0) {
2073: if(issig())
2074: goto psig;
2075: spl6();
2076: rp->p_wchan = chan;
2077: rp->p_stat = SWAIT;
2078: rp->p_pri = pri;
2079: spl0();
2080: if(runin != 0) {
2081: runin = 0;
2082: wakeup(&runin);
2083: }
2084: swtch();
2085: if(issig())
2086: goto psig;
2087: } else {
2088: spl6();
2089: rp->p_wchan = chan;
2090: rp->p_stat = SSLEEP;
2091: rp->p_pri = pri;
2092: spl0();
2093: swtch();
2094: }
2095: PS->integ = s;
2096: return;
2097:
2098: /*
2099: * If priority was low (>=0) and
2100: * there has been a signal,
2101: * execute non-local goto to
2102: * the qsav location.
2103: * (see trap1/trap.c)
2104: */
2105: psig:
2106: aretu(u.u_qsav);
2107: }
2108: /* --------------------------- */
2109:
2110: /*
2111: * Wake up all processes sleeping on chan.
2112: */
2113: wakeup(chan)
2114: {
2115: register struct proc *p;
2116: register c, i;
2117:
2118: c = chan;
2119: p = &proc[0];
2120: i = NPROC;
2121: do {
2122: if(p->p_wchan == c) {
2123: setrun(p);
2124: }
2125: p++;
2126: } while(--i);
2127: }
2128: /* --------------------------- */
2129:
2130: /*
2131: * Set the process running;
2132: * arrange for it to be swapped in if necessary.
2133: */
2134: setrun(p)
2135: {
2136: register struct proc *rp;
2137:
2138: rp = p;
2139: rp->p_wchan = 0;
2140: rp->p_stat = SRUN;
2141: if(rp->p_pri < curpri)
2142: runrun++;
2143: if(runout != 0 && (rp->p_flag&SLOAD) == 0) {
2144: runout = 0;
2145: wakeup(&runout);
2146: }
2147: }
2148: /* --------------------------- */
2149:
2150: /*
2151: * Set user priority.
2152: * The rescheduling flag (runrun)
2153: * is set if the priority is higher
2154: * than the currently running process.
2155: */
2156: setpri(up)
2157: {
2158: register *pp, p;
2159:
2160: pp = up;
2161: p = (pp->p_cpu & 0377)/16;
2162: p =+ PUSER + pp->p_nice;
2163: if(p > 127)
2164: p = 127;
2165: if(p > curpri)
2166: runrun++;
2167: pp->p_pri = p;
2168: }
2169: /* --------------------------- */
2170:
2171:
2172: /*
2173: * This routine is called to reschedule the CPU.
2174: * if the calling process is not in RUN state,
2175: * arrangements for it to restart must have
2176: * been made elsewhere, usually by calling via sleep.
2177: */
2178: swtch()
2179: {
2180: static struct proc *p;
2181: register i, n;
2182: register struct proc *rp;
2183:
2184: if(p == NULL)
2185: p = &proc[0];
2186: /*
2187: * Remember stack of caller
2188: */
2189: savu(u.u_rsav);
2190: /*
2191: * Switch to scheduler's stack
2192: */
2193: retu(proc[0].p_addr);
2194:
2195: loop:
2196: runrun = 0;
2197: rp = p;
2198: p = NULL;
2199: n = 128;
2200: /*
2201: * Search for highest-priority runnable process
2202: */
2203: i = NPROC;
2204: do {
2205: rp++;
2206: if(rp >= &proc[NPROC])
2207: rp = &proc[0];
2208: if(rp->p_stat==SRUN && (rp->p_flag&SLOAD)!=0) {
2209: if(rp->p_pri < n) {
2210: p = rp;
2211: n = rp->p_pri;
2212: }
2213: }
2214: } while(--i);
2215: /*
2216: * If no process is runnable, idle.
2217: */
2218: if(p == NULL) {
2219: p = rp;
2220: idle();
2221: goto loop;
2222: }
2223: rp = p;
2224: curpri = n;
2225: /* Switch to stack of the new process and set up
2226: * his segmentation registers.
2227: */
2228: retu(rp->p_addr);
2229: sureg();
2230: /*
2231: * If the new process paused because it was
2232: * swapped out, set the stack level to the last call
2233: * to savu(u_ssav). This means that the return
2234: * which is executed immediately after the call to aretu
2235: * actually returns from the last routine which did
2236: * the savu.
2237: *
2238: * You are not expected to understand this.
2239: */
2240: if(rp->p_flag&SSWAP) {
2241: rp->p_flag =& ~SSWAP;
2242: aretu(u.u_ssav);
2243: }
2244: /* The value returned here has many subtle implications.
2245: * See the newproc comments.
2246: */
2247: return(1);
2248: }
2249: /* --------------------------- */
2250:
2251: /*
2252: * Change the size of the data+stack regions of the process.
2253: * If the size is shrinking, it's easy-- just release the extra core.
2254: * If it's growing, and there is core, just allocate it
2255: * and copy the image, taking care to reset registers to account
2256: * for the fact that the system's stack has moved.
2257: *
2258: * If there is no core, arrange for the process to be swapped
2259: * out after adjusting the size requirement-- when it comes
2260: * in, enough core will be allocated.
2261: * Because of the ssave and SSWAP flags, control will
2262: * resume after the swap in swtch, which executes the return
2263: * from this stack level.
2264: *
2265: * After the expansion, the caller will take care of copying
2266: * the user's stack towards or away from the data area.
2267: */
2268: expand(newsize)
2269: {
2270: int i, n;
2271: register *p, a1, a2;
2272:
2273: p = u.u_procp;
2274: n = p->p_size;
2275: p->p_size = newsize;
2276: a1 = p->p_addr;
2277: if(n >= newsize) {
2278: mfree(coremap, n-newsize, a1+newsize);
2279: return;
2280: }
2281: savu(u.u_rsav);
2282: a2 = malloc(coremap, newsize);
2283: if(a2 == NULL) {
2284: savu(u.u_ssav);
2285: xswap(p, 1, n);
2286: p->p_flag =| SSWAP;
2287: swtch();
2288: /* no return */
2289: }
2290: p->p_addr = a2;
2291: for(i=0; i<n; i++)
2292: copyseg(a1+i, a2++);
2293: mfree(coremap, n, a1);
2294: retu(p->p_addr);
2295: sureg();
2296: }
2297: /* --------------------------- */
2300: #
2301: /*
2302: */
2303:
2304: #include "../param.h"
2305: #include "../seg.h"
2306: #include "../buf.h"
2307: #include "../conf.h"
2308:
2309: /*
2310: * Address and structure of the
2311: * KL-11 console device registers.
2312: */
2313: struct
2314: {
2315: int rsr;
2316: int rbr;
2317: int xsr;
2318: int xbr;
2319: };
2320: /* --------------------------- */
2321:
2322: /*
2323: * In case console is off,
2324: * panicstr contains argument to last
2325: * call to panic.
2326: */
2327:
2328: char *panicstr;
2329:
2330: /*
2331: * Scaled down version of C Library printf.
2332: * Only %s %l %d (==%l) %o are recognized.
2333: * Used to print diagnostic information
2334: * directly on console tty.
2335: * Since it is not interrupt driven,
2336: * all system activities are pretty much
2337: * suspended.
2338: * Printf should not be used for chit-chat.
2339: */
2340: printf(fmt,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc)
2341: char fmt[];
2342: {
2343: register char *s;
2344: register *adx, c;
2345:
2346: adx = &x1;
2347: loop:
2348: while((c = *fmt++) != '%') {
2349: if(c == '\0')
2350: return;
2351: putchar(c);
2352: }
2353: c = *fmt++;
2354: if(c == 'd' || c == 'l' || c == 'o')
2355: printn(*adx, c=='o'? 8: 10);
2356: if(c == 's') {
2357: s = *adx;
2358: while(c = *s++)
2359: putchar(c);
2360: }
2361: adx++;
2362: goto loop;
2363: }
2364: /* --------------------------- */
2365:
2366: /*
2367: * Print an unsigned integer in base b.
2368: */
2369: printn(n, b)
2370: {
2371: register a;
2372:
2373: if(a = ldiv(n, b))
2374: printn(a, b);
2375: putchar(lrem(n, b) + '0');
2376: }
2377: /* --------------------------- */
2378:
2379: /*
2380: * Print a character on console.
2381: * Attempts to save and restore device
2382: * status.
2383: * If the switches are 0, all
2384: * printing is inhibited.
2385: */
2386: putchar(c)
2387: {
2388: register rc, s;
2389:
2390: rc = c;
2391: if(SW->integ == 0)
2392: return;
2393: while((KL->xsr&0200) == 0)
2394: ;
2395: if(rc == 0)
2396: return;
2397: s = KL->xsr;
2398: KL->xsr = 0;
2399: KL->xbr = rc;
2400: if(rc == '\n') {
2401: putchar('\r');
2402: putchar(0177);
2403: putchar(0177);
2404: }
2405: putchar(0);
2406: KL->xsr = s;
2407: }
2408: /* --------------------------- */
2409:
2410: /*
2411: * Panic is called on unresolvable
2412: * fatal errors.
2413: * It syncs, prints "panic: mesg" and
2414: * then loops.
2415: */
2416: panic(s)
2417: char *s;
2418: {
2419: panicstr = s;
2420: update();
2421: printf("panic: %s\n", s);
2422: for(;;)
2423: idle();
2424: }
2425: /* --------------------------- */
2426:
2427: /*
2428: * prdev prints a warning message of the
2429: * form "mesg on dev x/y".
2430: * x and y are the major and minor parts of
2431: * the device argument.
2432: */
2433: prdev(str, dev)
2434: {
2435:
2436: printf("%s on dev %l/%l\n", str, dev.d_major, dev.d_minor);
2437: }
2438: /* --------------------------- */
2439:
2440: /*
2441: * deverr prints a diagnostic from
2442: * a device driver.
2443: * It prints the device, block number,
2444: * and an octal word (usually some error
2445: * status register) passed as argument.
2446: */
2447: deverror(bp, o1, o2)
2448: int *bp;
2449: {
2450: register *rbp;
2451:
2452: rbp = bp;
2453: prdev("err", rbp->b_dev);
2454: printf("bn%l er%o %o\n", rbp->b_blkno, o1, o2);
2455: }
2456: /* --------------------------- */
2500: #
2501: /*
2502: */
2503:
2504: /*
2505: * Structure of the coremap and swapmap
2506: * arrays. Consists of non-zero count
2507: * and base address of that many
2508: * contiguous units.
2509: * (The coremap unit is 64 bytes,
2510: * the swapmap unit is 512 bytes)
2511: * The addresses are increasing and
2512: * the list is terminated with the
2513: * first zero count.
2514: */
2515: struct map
2516: {
2517: char *m_size;
2518: char *m_addr;
2519: };
2520: /* --------------------------- */
2521:
2522: /*
2523: * Allocate size units from the given
2524: * map. Return the base of the allocated
2525: * space.
2526: * Algorithm is first fit.
2527: */
2528: malloc(mp, size)
2529: struct map *mp;
2530: {
2531: register int a;
2532: register struct map *bp;
2533:
2534: for (bp = mp; bp->m_size; bp++) {
2535: if (bp->m_size >= size) {
2536: a = bp->m_addr;
2537: bp->m_addr =+ size;
2538: if ((bp->m_size =- size) == 0)
2539: do {
2540: bp++;
2541: (bp-1)->m_addr = bp->m_addr;
2542: } while ((bp-1)->m_size = bp->m_size);
2543: return(a);
2544: }
2545: }
2546: return(0);
2547: }
2548: /* --------------------------- */
2549:
2550: /*
2551: * Free the previously allocated space aa
2552: * of size units into the specified map.
2553: * Sort aa into map and combine on
2554: * one or both ends if possible.
2555: */
2556: mfree(mp, size, aa)
2557: struct map *mp;
2558: {
2559: register struct map *bp;
2560: register int t;
2561: register int a;
2562:
2563: a = aa;
2564: for (bp = mp; bp->m_addr<=a && bp->m_size!=0; bp++);
2565: if (bp>mp && (bp-1)->m_addr+(bp-1)->m_size == a) {
2566: (bp-1)->m_size =+ size;
2567: if (a+size == bp->m_addr) {
2568: (bp-1)->m_size =+ bp->m_size;
2569: while (bp->m_size) {
2570: bp++;
2571: (bp-1)->m_addr = bp->m_addr;
2572: (bp-1)->m_size = bp->m_size;
2573: }
2574: }
2575: } else {
2576: if (a+size == bp->m_addr && bp->m_size) {
2577: bp->m_addr =- size;
2578: bp->m_size =+ size;
2579: } else if (size) do {
2580: t = bp->m_addr;
2581: bp->m_addr = a;
2582: a = t;
2583: t = bp->m_size;
2584: bp->m_size = size;
2585: bp++;
2586: } while (size = t);
2587: }
2588: }
2589: /* --------------------------- */
2600: /*
2601: * Location of the users' stored
2602: * registers relative to R0.
2603: * Usage is u.u_ar0[XX].
2604: */
2605: #define R0 (0)
2606: #define R1 (-2)
2607: #define R2 (-9)
2608: #define R3 (-8)
2609: #define R4 (-7)
2610: #define R5 (-6)
2611: #define R6 (-3)
2612: #define R7 (1)
2613: #define RPS (2)
2614:
2615: #define TBIT 020 /* PS trace bit */
2650: #
2651: #include "../param.h"
2652: #include "../systm.h"
2653: #include "../user.h"
2654: #include "../proc.h"
2655: #include "../reg.h"
2656: #include "../seg.h"
2657:
2658: #define EBIT 1 /* user error bit in PS: C-bit */
2659: #define UMODE 0170000 /* user-mode bits in PS word */
2660: #define SETD 0170011 /* SETD instruction */
2661: #define SYS 0104400 /* sys (trap) instruction */
2662: #define USER 020 /* user-mode flag added to dev */
2663:
2664: /*
2665: * structure of the system entry table (sysent.c)
2666: */
2667: struct sysent {
2668: int count; /* argument count */
2669: int (*call)(); /* name of handler */
2670: } sysent[64];
2671: /* --------------------------- */
2672:
2673: /*
2674: * Offsets of the user's registers relative to
2675: * the saved r0. See reg.h
2676: */
2677: char regloc[9]
2678: {
2679: R0, R1, R2, R3, R4, R5, R6, R7, RPS
2680: };
2681: /* --------------------------- */
2682:
2683: /*
2684: * Called from l40.s or l45.s when a processor trap occurs.
2685: * The arguments are the words saved on the system stack
2686: * by the hardware and software during the trap processing.
2687: * Their order is dictated by the hardware and the details
2688: * of C's calling sequence. They are peculiar in that
2689: * this call is not 'by value' and changed user registers
2690: * get copied back on return.
2691: * dev is the kind of trap that occurred.
2692: */
2693: trap(dev, sp, r1, nps, r0, pc, ps)
2694: {
2695: register i, a;
2696: register struct sysent *callp;
2697:
2698: savfp();
2699: if ((ps&UMODE) == UMODE)
2700: dev =| USER;
2701: u.u_ar0 = &r0;
2702: switch(dev) {
2703:
2704: /*
2705: * Trap not expected.
2706: * Usually a kernel mode bus error.
2707: * The numbers printed are used to
2708: * find the hardware PS/PC as follows.
2709: * (all numbers in octal 18 bits)
2710: * address_of_saved_ps =
2711: * (ka6*0100) + aps - 0140000;
2712: * address_of_saved_pc =
2713: * address_of_saved_ps - 2;
2714: */
2715: default:
2716: printf("ka6 = %o\n", *ka6);
2717: printf("aps = %o\n", &ps);
2718: printf("trap type %o\n", dev);
2719: panic("trap");
2720:
2721: case 0+USER: /* bus error */
2722: i = SIGBUS;
2723: break;
2724:
2725: /*
2726: * If illegal instructions are not
2727: * being caught and the offending instruction
2728: * is a SETD, the trap is ignored.
2729: * This is because C produces a SETD at
2730: * the beginning of every program which
2731: * will trap on CPUs without 11/45 FPU.
2732: */
2733: case 1+USER: /* illegal instruction */
2734: if(fuiword(pc-2) == SETD && u.u_signal[SIGINS] == 0)
2735: goto out;
2736: i = SIGINS;
2737: break;
2738:
2739: case 2+USER: /* bpt or trace */
2740: i = SIGTRC;
2741: break;
2742:
2743: case 3+USER: /* iot */
2744: i = SIGIOT;
2745: break;
2746:
2747: case 5+USER: /* emt */
2748: i = SIGEMT;
2749: break;
2750:
2751: case 6+USER: /* sys call */
2752: u.u_error = 0;
2753: ps =& ~EBIT;
2754: callp = &sysent[fuiword(pc-2)&077];
2755: if (callp == sysent) { /* indirect */
2756: a = fuiword(pc);
2757: pc =+ 2;
2758: i = fuword(a);
2759: if ((i & ~077) != SYS)
2760: i = 077; /* illegal */
2761: callp = &sysent[i&077];
2762: for(i=0; i<callp->count; i++)
2763: u.u_arg[i] = fuword(a =+ 2);
2764: } else {
2765: for(i=0; i<callp->count; i++) {
2766: u.u_arg[i] = fuiword(pc);
2767: pc =+ 2;
2768: }
2769: }
2770: u.u_dirp = u.u_arg[0];
2771: trap1(callp->call);
2772: if(u.u_intflg)
2773: u.u_error = EINTR;
2774: if(u.u_error < 100) {
2775: if(u.u_error) {
2776: ps =| EBIT;
2777: r0 = u.u_error;
2778: }
2779: goto out;
2780: }
2781: i = SIGSYS;
2782: break;
2783:
2784: /*
2785: * Since the floating exception is an
2786: * imprecise trap, a user generated
2787: * trap may actually come from kernel
2788: * mode. In this case, a signal is sent
2789: * to the current process to be picked
2790: * up later.
2791: */
2792: case 8: /* floating exception */
2793: psignal(u.u_procp, SIGFPT);
2794: return;
2795:
2796: case 8+USER:
2797: i = SIGFPT;
2798: break;
2799:
2800: /*
2801: * If the user SP is below the stack segment,
2802: * grow the stack automatically.
2803: * This relies on the ability of the hardware
2804: * to restart a half executed instruction.
2805: * On the 11/40 this is not the case and
2806: * the routine backup/l40.s may fail.
2807: * The classic example is on the instruction
2808: * cmp -(sp),-(sp)
2809: */
2810: case 9+USER: /* segmentation exception */
2811: a = sp;
2812: if(backup(u.u_ar0) == 0)
2813: if(grow(a))
2814: goto out;
2815: i = SIGSEG;
2816: break;
2817: }
2818: psignal(u.u_procp, i);
2819:
2820: out:
2821: if(issig())
2822: psig();
2823: setpri(u.u_procp);
2824: }
2825: /* --------------------------- */
2826:
2827: /*
2828: * Call the system-entry routine f (out of the
2829: * sysent table). This is a subroutine for trap, and
2830: * not in-line, because if a signal occurs
2831: * during processing, an (abnormal) return is simulated from
2832: * the last caller to savu(qsav); if this took place
2833: * inside of trap, it wouldn't have a chance to clean up.
2834: *
2835: * If this occurs, the return takes place without
2836: * clearing u_intflg; if it's still set, trap
2837: * marks an error which means that a system
2838: * call (like read on a typewriter) got interrupted
2839: * by a signal.
2840: */
2841: trap1(f)
2842: int (*f)();
2843: {
2844:
2845: u.u_intflg = 1;
2846: savu(u.u_qsav);
2847: (*f)();
2848: u.u_intflg = 0;
2849: }
2850:
2851: /* --------------------------- */
2852: /*
2853: * nonexistent system call-- set fatal error code.
2854: */
2855: nosys()
2856: {
2857: u.u_error = 100;
2858: }
2859: /* --------------------------- */
2860:
2861: /*
2862: * Ignored system call
2863: */
2864: nullsys()
2865: {
2866: }
2867: /* --------------------------- */
2900: #
2901: /*
2902: */
2903:
2904: /*
2905: * This table is the switch used to transfer
2906: * to the appropriate routine for processing a system call.
2907: * Each row contains the number of arguments expected
2908: * and a pointer to the routine.
2909: */
2910: int sysent[]
2911: {
2912: 0, &nullsys, /* 0 = indir */
2913: 0, &rexit, /* 1 = exit */
2914: 0, &fork, /* 2 = fork */
2915: 2, &read, /* 3 = read */
2916: 2, &write, /* 4 = write */
2917: 2, &open, /* 5 = open */
2918: 0, &close, /* 6 = close */
2919: 0, &wait, /* 7 = wait */
2920: 2, &creat, /* 8 = creat */
2921: 2, &link, /* 9 = link */
2922: 1, &unlink, /* 10 = unlink */
2923: 2, &exec, /* 11 = exec */
2924: 1, &chdir, /* 12 = chdir */
2925: 0, &gtime, /* 13 = time */
2926: 3, &mknod, /* 14 = mknod */
2927: 2, &chmod, /* 15 = chmod */
2928: 2, &chown, /* 16 = chown */
2929: 1, &sbreak, /* 17 = break */
2930: 2, &stat, /* 18 = stat */
2931: 2, &seek, /* 19 = seek */
2932: 0, &getpid, /* 20 = getpid */
2933: 3, &smount, /* 21 = mount */
2934: 1, &sumount, /* 22 = umount */
2935: 0, &setuid, /* 23 = setuid */
2936: 0, &getuid, /* 24 = getuid */
2937: 0, &stime, /* 25 = stime */
2938: 3, &ptrace, /* 26 = ptrace */
2939: 0, &nosys, /* 27 = x */
2940: 1, &fstat, /* 28 = fstat */
2941: 0, &nosys, /* 29 = x */
2942: 1, &nullsys, /* 30 = smdate; inoperative */
2943: 1, &stty, /* 31 = stty */
2944: 1, &gtty, /* 32 = gtty */
2945: 0, &nosys, /* 33 = x */
2946: 0, &nice, /* 34 = nice */
2947: 0, &sslep, /* 35 = sleep */
2948: 0, &sync, /* 36 = sync */
2949: 1, &kill, /* 37 = kill */
2950: 0, &getswit, /* 38 = switch */
2951: 0, &nosys, /* 39 = x */
2952: 0, &nosys, /* 40 = x */
2953: 0, &dup, /* 41 = dup */
2954: 0, &pipe, /* 42 = pipe */
2955: 1, &times, /* 43 = times */
2956: 4, &profil, /* 44 = prof */
2957: 0, &nosys, /* 45 = tiu */
2958: 0, &setgid, /* 46 = setgid */
2959: 0, &getgid, /* 47 = getgid */
2960: 2, &ssig, /* 48 = sig */
2961: 0, &nosys, /* 49 = x */
2962: 0, &nosys, /* 50 = x */
2963: 0, &nosys, /* 51 = x */
2964: 0, &nosys, /* 52 = x */
2965: 0, &nosys, /* 53 = x */
2966: 0, &nosys, /* 54 = x */
2967: 0, &nosys, /* 55 = x */
2968: 0, &nosys, /* 56 = x */
2969: 0, &nosys, /* 57 = x */
2970: 0, &nosys, /* 58 = x */
2971: 0, &nosys, /* 59 = x */
2972: 0, &nosys, /* 60 = x */
2973: 0, &nosys, /* 61 = x */
2974: 0, &nosys, /* 62 = x */
2975: 0, &nosys /* 63 = x */
2976: };
2977: /* --------------------------- */
3000: #
3001: #include "../param.h"
3002: #include "../systm.h"
3003: #include "../user.h"
3004: #include "../proc.h"
3005: #include "../buf.h"
3006: #include "../reg.h"
3007: #include "../inode.h"
3008:
3009: /*
3010: * exec system call.
3011: * Because of the fact that an I/O buffer is used
3012: * to store the caller's arguments during exec,
3013: * and more buffers are needed to read in the text file,
3014: * deadly embraces waiting for free buffers are possible.
3015: * Therefore the number of processes simultaneously
3016: * running in exec has to be limited to NEXEC.
3017: */
3018: #define EXPRI -1
3019:
3020: exec()
3021: {
3022: int ap, na, nc, *bp;
3023: int ts, ds, sep;
3024: register c, *ip;
3025: register char *cp;
3026: extern uchar;
3027:
3028: /*
3029: * pick up file names
3030: * and check various modes
3031: * for execute permission
3032: */
3033:
3034: ip = namei(&uchar, 0);
3035: if(ip == NULL)
3036: return;
3037: while(execnt >= NEXEC)
3038: sleep(&execnt, EXPRI);
3039: execnt++;
3040: bp = getblk(NODEV);
3041: if(access(ip, IEXEC) || (ip->i_mode&IFMT)!=0)
3042: goto bad;
3043:
3044: /*
3045: * pack up arguments into
3046: * allocated disk buffer
3047: */
3048:
3049: cp = bp->b_addr;
3050: na = 0;
3051: nc = 0;
3052: while(ap = fuword(u.u_arg[1])) {
3053: na++;
3054: if(ap == -1)
3055: goto bad;
3056: u.u_arg[1] =+ 2;
3057: for(;;) {
3058: c = fubyte(ap++);
3059: if(c == -1)
3060: goto bad;
3061: *cp++ = c;
3062: nc++;
3063: if(nc > 510) {
3064: u.u_error = E2BIG;
3065: goto bad;
3066: }
3067: if(c == 0)
3068: break;
3069: }
3070: }
3071: if((nc&1) != 0) {
3072: *cp++ = 0;
3073: nc++;
3074: }
3075:
3076: /* read in first 8 bytes
3077: * of file for segment
3078: * sizes:
3079: * w0 = 407/410/411 (410 implies RO text) (411 implies sep ID)
3080: * w1 = text size
3081: * w2 = data size
3082: * w3 = bss size
3083: */
3084:
3085: u.u_base = &u.u_arg[0];
3086: u.u_count = 8;
3087: u.u_offset[1] = 0;
3088: u.u_offset[0] = 0;
3089: u.u_segflg = 1;
3090: readi(ip);
3091: u.u_segflg = 0;
3092: if(u.u_error)
3093: goto bad;
3094: sep = 0;
3095: if(u.u_arg[0] == 0407) {
3096: u.u_arg[2] =+ u.u_arg[1];
3097: u.u_arg[1] = 0;
3098: } else
3099: if(u.u_arg[0] == 0411)
3100: sep++; else
3101: if(u.u_arg[0] != 0410) {
3102: u.u_error = ENOEXEC;
3103: goto bad;
3104: }
3105: if(u.u_arg[1]!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) {
3106: u.u_error = ETXTBSY;
3107: goto bad;
3108: }
3109:
3110: /*
3111: * find text and data sizes
3112: * try them out for possible
3113: * exceed of max sizes
3114: */
3115:
3116: ts = ((u.u_arg[1]+63)>>6) & 01777;
3117: ds = ((u.u_arg[2]+u.u_arg[3]+63)>>6) & 01777;
3118: if(estabur(ts, ds, SSIZE, sep))
3119: goto bad;
3120:
3121: /*
3122: * allocate and clear core
3123: * at this point, committed
3124: * to the new image
3125: */
3126:
3127: u.u_prof[3] = 0;
3128: xfree();
3129: expand(USIZE);
3130: xalloc(ip);
3131: c = USIZE+ds+SSIZE;
3132: expand(c);
3133: while(--c >= USIZE)
3134: clearseg(u.u_procp->p_addr+c);
3135:
3136: /* read in data segment */
3137:
3138: estabur(0, ds, 0, 0);
3139: u.u_base = 0;
3140: u.u_offset[1] = 020+u.u_arg[1];
3141: u.u_count = u.u_arg[2];
3142: readi(ip);
3143:
3144: /*
3145: * initialize stack segment
3146: */
3147:
3148: u.u_tsize = ts;
3149: u.u_dsize = ds;
3150: u.u_ssize = SSIZE;
3151: u.u_sep = sep;
3152: estabur(u.u_tsize, u.u_dsize, u.u_ssize, u.u_sep);
3153: cp = bp->b_addr;
3154: ap = -nc - na*2 - 4;
3155: u.u_ar0[R6] = ap;
3156: suword(ap, na);
3157: c = -nc;
3158: while(na--) {
3159: suword(ap=+2, c);
3160: do
3161: subyte(c++, *cp);
3162: while(*cp++);
3163: }
3164: suword(ap+2, -1);
3165:
3166: /*
3167: * set SUID/SGID protections, if no tracing
3168: */
3169:
3170: if ((u.u_procp->p_flag&STRC)==0) {
3171: if(ip->i_mode&ISUID)
3172: if(u.u_uid != 0) {
3173: u.u_uid = ip->i_uid;
3174: u.u_procp->p_uid = ip->i_uid;
3175: }
3176: if(ip->i_mode&ISGID)
3177: u.u_gid = ip->i_gid;
3178: }
3179:
3180: /* clear sigs, regs and return */
3181:
3182: c = ip;
3183: for(ip = &u.u_signal[0]; ip < &u.u_signal[NSIG]; ip++)
3184: if((*ip & 1) == 0)
3185: *ip = 0;
3186: for(cp = &regloc[0]; cp < &regloc[6];)
3187: u.u_ar0[*cp++] = 0;
3188: u.u_ar0[R7] = 0;
3189: for(ip = &u.u_fsav[0]; ip < &u.u_fsav[25];)
3190: *ip++ = 0;
3191: ip = c;
3192:
3193: bad:
3194: iput(ip);
3195: brelse(bp);
3196: if(execnt >= NEXEC)
3197: wakeup(&execnt);
3198: execnt--;
3199: }
3200: /* --------------------------- */
3201:
3202: /* exit system call:
3203: * pass back caller's r0
3204: */
3205: rexit()
3206: {
3207:
3208: u.u_arg[0] = u.u_ar0[R0] << 8;
3209: exit();
3210: }
3211: /* --------------------------- */
3212:
3213: /* Release resources.
3214: * Save u. area for parent to look at.
3215: * Enter zombie state.
3216: * Wake up parent and init processes,
3217: * and dispose of children.
3218: */
3219: exit()
3220: {
3221: register int *q, a;
3222: register struct proc *p;
3223:
3224: u.u_procp->p_flag =& ~STRC;
3225: for(q = &u.u_signal[0]; q < &u.u_signal[NSIG];)
3226: *q++ = 1;
3227: for(q = &u.u_ofile[0]; q < &u.u_ofile[NOFILE]; q++)
3228: if(a = *q) {
3229: *q = NULL;
3230: closef(a);
3231: }
3232: iput(u.u_cdir);
3233: xfree();
3234: a = malloc(swapmap, 1);
3235: if(a == NULL)
3236: panic("out of swap");
3237: p = getblk(swapdev, a);
3238: bcopy(&u, p->b_addr, 256);
3239: bwrite(p);
3240: q = u.u_procp;
3241: mfree(coremap, q->p_size, q->p_addr);
3242: q->p_addr = a;
3243: q->p_stat = SZOMB;
3244:
3245: loop:
3246: for(p = &proc[0]; p < &proc[NPROC]; p++)
3247: if(q->p_ppid == p->p_pid) {
3248: wakeup(&proc[1]);
3249: wakeup(p);
3250: for(p = &proc[0]; p < &proc[NPROC]; p++)
3251: if(q->p_pid == p->p_ppid) {
3252: p->p_ppid = 1;
3253: if (p->p_stat == SSTOP)
3254: setrun(p);
3255: }
3256: swtch();
3257: /* no return */
3258: }
3259: q->p_ppid = 1;
3260: goto loop;
3261: }
3262: /* --------------------------- */
3263:
3264: /* Wait system call.
3265: * Search for a terminated (zombie) child,
3266: * finally lay it to rest, and collect its status.
3267: * Look also for stopped (traced) children,
3268: * and pass back status from them.
3269: */
3270: wait()
3271: {
3272: register f, *bp;
3273: register struct proc *p;
3274:
3275: f = 0;
3276: loop:
3277: for(p = &proc[0]; p < &proc[NPROC]; p++)
3278: if(p->p_ppid == u.u_procp->p_pid) {
3279: f++;
3280: if(p->p_stat == SZOMB) {
3281: u.u_ar0[R0] = p->p_pid;
3282: bp = bread(swapdev, f=p->p_addr);
3283: mfree(swapmap, 1, f);
3284: p->p_stat = NULL;
3285: p->p_pid = 0;
3286: p->p_ppid = 0;
3287: p->p_sig = 0;
3288: p->p_ttyp = 0;
3289: p->p_flag = 0;
3290: p = bp->b_addr;
3291: u.u_cstime[0] =+ p->u_cstime[0];
3292: dpadd(u.u_cstime, p->u_cstime[1]);
3293: dpadd(u.u_cstime, p->u_stime);
3294: u.u_cutime[0] =+ p->u_cutime[0];
3295: dpadd(u.u_cutime, p->u_cutime[1]);
3296: dpadd(u.u_cutime, p->u_utime);
3297: u.u_ar0[R1] = p->u_arg[0];
3298: brelse(bp);
3299: return;
3300: }
3301: if(p->p_stat == SSTOP) {
3302: if((p->p_flag&SWTED) == 0) {
3303: p->p_flag =| SWTED;
3304: u.u_ar0[R0] = p->p_pid;
3305: u.u_ar0[R1] = (p->p_sig<<8) | 0177;
3306: return;
3307: }
3308: p->p_flag =& ~(STRC|SWTED);
3309: setrun(p);
3310: }
3311: }
3312: if(f) {
3313: sleep(u.u_procp, PWAIT);
3314: goto loop;
3315: }
3316: u.u_error = ECHILD;
3317: }
3318: /* --------------------------- */
3319:
3320: /* fork system call.
3321: */
3322: fork()
3323: {
3324: register struct proc *p1, *p2;
3325:
3326: p1 = u.u_procp;
3327: for(p2 = &proc[0]; p2 < &proc[NPROC]; p2++)
3328: if(p2->p_stat == NULL)
3329: goto found;
3330: u.u_error = EAGAIN;
3331: goto out;
3332:
3333: found:
3334: if(newproc()) {
3335: u.u_ar0[R0] = p1->p_pid;
3336: u.u_cstime[0] = 0;
3337: u.u_cstime[1] = 0;
3338: u.u_stime = 0;
3339: u.u_cutime[0] = 0;
3340: u.u_cutime[1] = 0;
3341: u.u_utime = 0;
3342: return;
3343: }
3344: u.u_ar0[R0] = p2->p_pid;
3345:
3346: out:
3347: u.u_ar0[R7] =+ 2;
3348: }
3349: /* --------------------------- */
3350:
3351: /* break system call.
3352: * -- bad planning: "break" is a dirty word in C.
3353: */
3354: sbreak()
3355: {
3356: register a, n, d;
3357: int i;
3358:
3359: /* set n to new data size
3360: * set d to new-old
3361: * set n to new total size
3362: */
3363:
3364: n = (((u.u_arg[0]+63)>>6) & 01777);
3365: if(!u.u_sep)
3366: n =- nseg(u.u_tsize) * 128;
3367: if(n < 0)
3368: n = 0;
3369: d = n - u.u_dsize;
3370: n =+ USIZE+u.u_ssize;
3371: if(estabur(u.u_tsize, u.u_dsize+d, u.u_ssize, u.u_sep))
3372: return;
3373: u.u_dsize =+ d;
3374: if(d > 0)
3375: goto bigger;
3376: a = u.u_procp->p_addr + n - u.u_ssize;
3377: i = n;
3378: n = u.u_ssize;
3379: while(n--) {
3380: copyseg(a-d, a);
3381: a++;
3382: }
3383: expand(i);
3384: return;
3385:
3386: bigger:
3387: expand(n);
3388: a = u.u_procp->p_addr + n;
3389: n = u.u_ssize;
3390: while(n--) {
3391: a--;
3392: copyseg(a-d, a);
3393: }
3394: while(d--)
3395: clearseg(--a);
3396: }
3397: /* --------------------------- */
3400:
3401: /*
3402: * Everything in this file is a routine implementing a system call.
3403: *
3404: */
3405:
3406: #include "../param.h"
3407: #include "../user.h"
3408: #include "../reg.h"
3409: #include "../inode.h"
3410: #include "../systm.h"
3411: #include "../proc.h"
3412:
3413: getswit()
3414: {
3415:
3416: u.u_ar0[R0] = SW->integ;
3417: }
3418: /* --------------------------- */
3419:
3420: gtime()
3421: {
3422:
3423: u.u_ar0[R0] = time[0];
3424: u.u_ar0[R1] = time[1];
3425: }
3426: /* --------------------------- */
3427:
3428: stime()
3429: {
3430:
3431: if(suser()) {
3432: time[0] = u.u_ar0[R0];
3433: time[1] = u.u_ar0[R1];
3434: wakeup(tout);
3435: }
3436: }
3437: /* --------------------------- */
3438:
3439: setuid()
3440: {
3441: register uid;
3442:
3443: uid = u.u_ar0[R0].lobyte;
3444: if(u.u_ruid == uid.lobyte || suser()) {
3445: u.u_uid = uid;
3446: u.u_procp->p_uid = uid;
3447: u.u_ruid = uid;
3448: }
3449: }
3450: /* --------------------------- */
3451:
3452: getuid()
3453: {
3454:
3455: u.u_ar0[R0].lobyte = u.u_ruid;
3456: u.u_ar0[R0].hibyte = u.u_uid;
3457: }
3458: /* --------------------------- */
3459:
3460: setgid()
3461: {
3462: register gid;
3463:
3464: gid = u.u_ar0[R0].lobyte;
3465: if(u.u_rgid == gid.lobyte || suser()) {
3466: u.u_gid = gid;
3467: u.u_rgid = gid;
3468: }
3469: }
3470: /* --------------------------- */
3471:
3472: getgid()
3473: {
3474:
3475: u.u_ar0[R0].lobyte = u.u_rgid;
3476: u.u_ar0[R0].hibyte = u.u_gid;
3477: }
3478: /* --------------------------- */
3479:
3480: getpid()
3481: {
3482: u.u_ar0[R0] = u.u_procp->p_pid;
3483: }
3484: /* --------------------------- */
3485:
3486: sync()
3487: {
3488:
3489: update();
3490: }
3491: /* --------------------------- */
3492:
3493: nice()
3494: {
3495: register n;
3496:
3497: n = u.u_ar0[R0];
3498: if(n > 20)
3499: n = 20;
3500: if(n < 0 && !suser())
3501: n = 0;
3502: u.u_procp->p_nice = n;
3503: }
3504: /* --------------------------- */
3505:
3506: /*
3507: * Unlink system call.
3508: * panic: unlink -- "cannot happen"
3509: */
3510: unlink()
3511: {
3512: register *ip, *pp;
3513: extern uchar;
3514:
3515: pp = namei(&uchar, 2);
3516: if(pp == NULL)
3517: return;
3518: prele(pp);
3519: ip = iget(pp->i_dev, u.u_dent.u_ino);
3520: if(ip == NULL)
3521: panic("unlink -- iget");
3522: if((ip->i_mode&IFMT)==IFDIR && !suser())
3523: goto out;
3524: u.u_offset[1] =- DIRSIZ+2;
3525: u.u_base = &u.u_dent;
3526: u.u_count = DIRSIZ+2;
3527: u.u_dent.u_ino = 0;
3528: writei(pp);
3529: ip->i_nlink--;
3530: ip->i_flag =| IUPD;
3531:
3532: out:
3533: iput(pp);
3534: iput(ip);
3535: }
3536: /* --------------------------- */
3537:
3538: chdir()
3539: {
3540: register *ip;
3541: extern uchar;
3542:
3543: ip = namei(&uchar, 0);
3544: if(ip == NULL)
3545: return;
3546: if((ip->i_mode&IFMT) != IFDIR) {
3547: u.u_error = ENOTDIR;
3548: bad:
3549: iput(ip);
3550: return;
3551: }
3552: if(access(ip, IEXEC))
3553: goto bad;
3554: iput(u.u_cdir);
3555: u.u_cdir = ip;
3556: prele(ip);
3557: }
3558: /* --------------------------- */
3559:
3560: chmod()
3561: {
3562: register *ip;
3563:
3564: if ((ip = owner()) == NULL)
3565: return;
3566: ip->i_mode =& ~07777;
3567: if (u.u_uid)
3568: u.u_arg[1] =& ~ISVTX;
3569: ip->i_mode =| u.u_arg[1]&07777;
3570: ip->i_flag =| IUPD;
3571: iput(ip);
3572: }
3573: /* --------------------------- */
3574:
3575: chown()
3576: {
3577: register *ip;
3578:
3579: if (!suser() || (ip = owner()) == NULL)
3580: return;
3581: ip->i_uid = u.u_arg[1].lobyte;
3582: ip->i_gid = u.u_arg[1].hibyte;
3583: ip->i_flag =| IUPD;
3584: iput(ip);
3585: }
3586: /* --------------------------- */
3587:
3588: /*
3589: * Change modified date of file:
3590: * time to r0-r1; sys smdate; file
3591: * This call has been withdrawn because it messes up
3592: * incremental dumps (pseudo-old files aren't dumped).
3593: * It works though and you can uncomment it if you like. */
3594:
3595: smdate()
3596: {
3597: register struct inode *ip;
3598: register int *tp;
3599: int tbuf[2];
3600:
3601: if ((ip = owner()) == NULL)
3602: return;
3603: ip->i_flag =| IUPD;
3604: tp = &tbuf[2];
3605: *--tp = u.u_ar0[R1];
3606: *--tp = u.u_ar0[R0];
3607: iupdat(ip, tp);
3608: ip->i_flag =& ~IUPD;
3609: iput(ip);
3610: }
3611:
3612: /* --------------------------- */
3613:
3614: ssig()
3615: {
3616: register a;
3617:
3618: a = u.u_arg[0];
3619: if(a<=0 || a>=NSIG || a ==SIGKIL) {
3620: u.u_error = EINVAL;
3621: return;
3622: }
3623: u.u_ar0[R0] = u.u_signal[a];
3624: u.u_signal[a] = u.u_arg[1];
3625: if(u.u_procp->p_sig == a)
3626: u.u_procp->p_sig = 0;
3627: }
3628: /* --------------------------- */
3629:
3630: kill()
3631: {
3632: register struct proc *p, *q;
3633: register a;
3634: int f;
3635:
3636: f = 0;
3637: a = u.u_ar0[R0];
3638: q = u.u_procp;
3639: for(p = &proc[0]; p < &proc[NPROC]; p++) {
3640: if(p == q)
3641: continue;
3642: if(a != 0 && p->p_pid != a)
3643: continue;
3644: if(a == 0 && (p->p_ttyp != q->p_ttyp || p <= &proc[1]))
3645: continue;
3646: if(u.u_uid != 0 && u.u_uid != p->p_uid)
3647: continue;
3648: f++;
3649: psignal(p, u.u_arg[0]);
3650: }
3651: if(f == 0)
3652: u.u_error = ESRCH;
3653: }
3654: /* --------------------------- */
3655:
3656: times()
3657: {
3658: register *p;
3659:
3660: for(p = &u.u_utime; p < &u.u_utime+6;) {
3661: suword(u.u_arg[0], *p++);
3662: u.u_arg[0] =+ 2;
3663: }
3664: }
3665: /* --------------------------- */
3666:
3667: profil()
3668: {
3669:
3670: u.u_prof[0] = u.u_arg[0] & ~1; /* base of sample buf */
3671: u.u_prof[1] = u.u_arg[1]; /* size of same */
3672: u.u_prof[2] = u.u_arg[2]; /* pc offset */
3673: u.u_prof[3] = (u.u_arg[3]>>1) & 077777; /* pc scale */
3674: }
3675: /* --------------------------- */
3700: #
3701: #include "../param.h"
3702: #include "../systm.h"
3703: #include "../user.h"
3704: #include "../proc.h"
3705:
3706: #define UMODE 0170000
3707: #define SCHMAG 10
3708:
3709: /*
3710: * clock is called straight from
3711: * the real time clock interrupt.
3712: *
3713: * Functions:
3714: * reprime clock
3715: * copy *switches to display
3716: * implement callouts
3717: * maintain user/system times
3718: * maintain date
3719: * profile
3720: * tout wakeup (sys sleep)
3721: * lightning bolt wakeup (every 4 sec)
3722: * alarm clock signals
3723: * jab the scheduler
3724: */
3725: clock(dev, sp, r1, nps, r0, pc, ps)
3726: {
3727: register struct callo *p1, *p2;
3728: register struct proc *pp;
3729:
3730: /*
3731: * restart clock
3732: */
3733:
3734: *lks = 0115;
3735:
3736: /*
3737: * display register
3738: */
3739:
3740: display();
3741:
3742: /*
3743: * callouts
3744: * if none, just return
3745: * else update first non-zero time
3746: */
3747:
3748: if(callout[0].c_func == 0)
3749: goto out;
3750: p2 = &callout[0];
3751: while(p2->c_time<=0 && p2->c_func!=0)
3752: p2++;
3753: p2->c_time--;
3754:
3755: /*
3756: * if ps is high, just return
3757: */
3758:
3759: if((ps&0340) != 0)
3760: goto out;
3761:
3762: /*
3763: * callout
3764: */
3765:
3766: spl5();
3767: if(callout[0].c_time <= 0) {
3768: p1 = &callout[0];
3769: while(p1->c_func != 0 && p1->c_time <= 0) {
3770: (*p1->c_func)(p1->c_arg);
3771: p1++;
3772: }
3773: p2 = &callout[0];
3774: while(p2->c_func = p1->c_func) {
3775: p2->c_time = p1->c_time;
3776: p2->c_arg = p1->c_arg;
3777: p1++;
3778: p2++;
3779: }
3780: }
3781:
3782: /*
3783: * lightning bolt time-out
3784: * and time of day
3785: */
3786:
3787: out:
3788: if((ps&UMODE) == UMODE) {
3789: u.u_utime++;
3790: if(u.u_prof[3])
3791: incupc(pc, u.u_prof);
3792: } else
3793: u.u_stime++;
3794: pp = u.u_procp;
3795: if(++pp->p_cpu == 0)
3796: pp->p_cpu--;
3797: if(++lbolt >= HZ) {
3798: if((ps&0340) != 0)
3799: return;
3800: lbolt =- HZ;
3801: if(++time[1] == 0)
3802: ++time[0];
3803: spl1();
3804: if(time[1]==tout[1] && time[0]==tout[0])
3805: wakeup(tout);
3806: if((time[1]&03) == 0) {
3807: runrun++;
3808: wakeup(&lbolt);
3809: }
3810: for(pp = &proc[0]; pp < &proc[NPROC]; pp++)
3811: if (pp->p_stat) {
3812: if(pp->p_time != 127)
3813: pp->p_time++;
3814: if((pp->p_cpu & 0377) > SCHMAG)
3815: pp->p_cpu =- SCHMAG; else
3816: pp->p_cpu = 0;
3817: if(pp->p_pri > PUSER)
3818: setpri(pp);
3819: }
3820: if(runin!=0) {
3821: runin = 0;
3822: wakeup(&runin);
3823: }
3824: if((ps&UMODE) == UMODE) {
3825: u.u_ar0 = &r0;
3826: if(issig())
3827: psig();
3828: setpri(u.u_procp);
3829: }
3830: }
3831: }
3832: /* --------------------------- */
3833:
3834: /*
3835: * timeout is called to arrange that
3836: * fun(arg) is called in tim/HZ seconds.
3837: * An entry is sorted into the callout
3838: * structure. The time in each structure
3839: * entry is the number of HZ's more
3840: * than the previous entry.
3841: * In this way, decrementing the
3842: * first entry has the effect of
3843: * updating all entries.
3844: */
3845: timeout(fun, arg, tim)
3846: {
3847: register struct callo *p1, *p2;
3848: register t;
3849: int s;
3850:
3851: t = tim;
3852: s = PS->integ;
3853: p1 = &callout[0];
3854: spl7();
3855: while(p1->c_func != 0 && p1->c_time <= t) {
3856: t =- p1->c_time;
3857: p1++;
3858: }
3859: p1->c_time =- t;
3860: p2 = p1;
3861: while(p2->c_func != 0)
3862: p2++;
3863: while(p2 >= p1) {
3864: (p2+1)->c_time = p2->c_time;
3865: (p2+1)->c_func = p2->c_func;
3866: (p2+1)->c_arg = p2->c_arg;
3867: p2--;
3868: }
3869: p1->c_time = t;
3870: p1->c_func = fun;
3871: p1->c_arg = arg;
3872: PS->integ = s;
3873: }
3874: /* --------------------------- */
3900: #
3901: /*
3902: */
3903:
3904: #include "../param.h"
3905: #include "../systm.h"
3906: #include "../user.h"
3907: #include "../proc.h"
3908: #include "../inode.h"
3909: #include "../reg.h"
3910:
3911: /*
3912: * Priority for tracing
3913: */
3914: #define IPCPRI (-1)
3915:
3916: /*
3917: * Structure to access an array of integers.
3918: */
3919: struct
3920: {
3921: int inta[];
3922: };
3923: /* --------------------------- */
3924:
3925: /*
3926: * Tracing variables.
3927: * Used to pass trace command from
3928: * parent to child being traced.
3929: * This data base cannot be
3930: * shared and is locked
3931: * per user.
3932: */
3933: struct
3934: {
3935: int ip_lock;
3936: int ip_req;
3937: int ip_addr;
3938: int ip_data;
3939: } ipc;
3940: /* --------------------------- */
3941:
3942: /*
3943: * Send the specified signal to
3944: * all processes with 'tp' as its
3945: * controlling teletype.
3946: * Called by tty.c for quits and
3947: * interrupts.
3948: */
3949: signal(tp, sig)
3950: {
3951: register struct proc *p;
3952:
3953: for(p = &proc[0]; p < &proc[NPROC]; p++)
3954: if(p->p_ttyp == tp)
3955: psignal(p, sig);
3956: }
3957: /* --------------------------- */
3958:
3959: /*
3960: * Send the specified signal to
3961: * the specified process.
3962: */
3963: psignal(p, sig)
3964: int *p;
3965: {
3966: register *rp;
3967:
3968: if(sig >= NSIG)
3969: return;
3970: rp = p;
3971: if(rp->p_sig != SIGKIL)
3972: rp->p_sig = sig;
3973: if(rp->p_stat > PUSER)
3974: rp->p_stat = PUSER;
3975: if(rp->p_stat == SWAIT)
3976: setrun(rp);
3977: }
3978: /* --------------------------- */
3979:
3980: /*
3981: * Returns true if the current
3982: * process has a signal to process.
3983: * This is asked at least once
3984: * each time a process enters the
3985: * system.
3986: * A signal does not do anything
3987: * directly to a process; it sets
3988: * a flag that asks the process to
3989: * do something to itself.
3990: */
3991: issig()
3992: {
3993: register n;
3994: register struct proc *p;
3995:
3996: p = u.u_procp;
3997: if(n = p->p_sig) {
3998: if (p->p_flag&STRC) {
3999: stop();
4000: if ((n = p->p_sig) == 0)
4001: return(0);
4002: }
4003: if((u.u_signal[n]&1) == 0)
4004: return(n);
4005: }
4006: return(0);
4007: }
4008: /* --------------------------- */
4009:
4010: /*
4011: * Enter the tracing STOP state.
4012: * In this state, the parent is
4013: * informed and the process is able to
4014: * receive commands from the parent.
4015: */
4016: stop()
4017: {
4018: register struct proc *pp, *cp;
4019:
4020: loop:
4021: cp = u.u_procp;
4022: if(cp->p_ppid != 1)
4023: for (pp = &proc[0]; pp < &proc[NPROC]; pp++)
4024: if (pp->p_pid == cp->p_ppid) {
4025: wakeup(pp);
4026: cp->p_stat = SSTOP;
4027: swtch();
4028: if ((cp->p_flag&STRC)==0 || procxmt())
4029: return;
4030: goto loop;
4031: }
4032: exit();
4033: }
4034: /* --------------------------- */
4035:
4036: /*
4037: * Perform the action specified by
4038: * the current signal.
4039: * The usual sequence is:
4040: * if(issig())
4041: * psig();
4042: */
4043: psig()
4044: {
4045: register n, p;
4046: register *rp;
4047:
4048: rp = u.u_procp;
4049: n = rp->p_sig;
4050: rp->p_sig = 0;
4051: if((p=u.u_signal[n]) != 0) {
4052: u.u_error = 0;
4053: if(n != SIGINS && n != SIGTRC)
4054: u.u_signal[n] = 0;
4055: n = u.u_ar0[R6] - 4;
4056: grow(n);
4057: suword(n+2, u.u_ar0[RPS]);
4058: suword(n, u.u_ar0[R7]);
4059: u.u_ar0[R6] = n;
4060: u.u_ar0[RPS] =& ~TBIT;
4061: u.u_ar0[R7] = p;
4062: return;
4063: }
4064: switch(n) {
4065:
4066: case SIGQIT:
4067: case SIGINS:
4068: case SIGTRC:
4069: case SIGIOT:
4070: case SIGEMT:
4071: case SIGFPT:
4072: case SIGBUS:
4073: case SIGSEG:
4074: case SIGSYS:
4075: u.u_arg[0] = n;
4076: if(core())
4077: n =+ 0200;
4078: }
4079: u.u_arg[0] = (u.u_ar0[R0]<<8) | n;
4080: exit();
4081: }
4082: /* --------------------------- */
4083:
4084: /*
4085: * Create a core image on the file "core"
4086: * If you are looking for protection glitches,
4087: * there are probably a wealth of them here
4088: * when this occurs to a suid command.
4089: *
4090: * It writes USIZE block of the
4091: * user.h area followed by the entire
4092: * data+stack segments.
4093: */
4094: core()
4095: {
4096: register s, *ip;
4097: extern schar;
4098:
4099: u.u_error = 0;
4100: u.u_dirp = "core";
4101: ip = namei(&schar, 1);
4102: if(ip == NULL) {
4103: if(u.u_error)
4104: return(0);
4105: ip = maknode(0666);
4106: if(ip == NULL)
4107: return(0);
4108: }
4109: if(!access(ip, IWRITE) &&
4110: (ip->i_mode&IFMT) == 0 &&
4111: u.u_uid == u.u_ruid) {
4112: itrunc(ip);
4113: u.u_offset[0] = 0;
4114: u.u_offset[1] = 0;
4115: u.u_base = &u;
4116: u.u_count = USIZE*64;
4117: u.u_segflg = 1;
4118: writei(ip);
4119: s = u.u_procp->p_size - USIZE;
4120: estabur(0, s, 0, 0);
4121: u.u_base = 0;
4122: u.u_count = s*64;
4123: u.u_segflg = 0;
4124: writei(ip);
4125: }
4126: iput(ip);
4127: return(u.u_error==0);
4128: }
4129: /* --------------------------- */
4130:
4131: /*
4132: * grow the stack to include the SP
4133: * true return if successful.
4134: */
4135:
4136: grow(sp)
4137: char *sp;
4138: {
4139: register a, si, i;
4140:
4141: if(sp >= -u.u_ssize*64)
4142: return(0);
4143: si = ldiv(-sp, 64) - u.u_ssize + SINCR;
4144: if(si <= 0)
4145: return(0);
4146: if(estabur(u.u_tsize, u.u_dsize, u.u_ssize+si, u.u_sep))
4147: return(0);
4148: expand(u.u_procp->p_size+si);
4149: a = u.u_procp->p_addr + u.u_procp->p_size;
4150: for(i=u.u_ssize; i; i--) {
4151: a--;
4152: copyseg(a-si, a);
4153: }
4154: for(i=si; i; i--)
4155: clearseg(--a);
4156: u.u_ssize =+ si;
4157: return(1);
4158: }
4159: /* --------------------------- */
4160:
4161: /*
4162: * sys-trace system call.
4163: */
4164: ptrace()
4165: {
4166: register struct proc *p;
4167:
4168: if (u.u_arg[2] <= 0) {
4169: u.u_procp->p_flag =| STRC;
4170: return;
4171: }
4172: for (p=proc; p < &proc[NPROC]; p++)
4173: if (p->p_stat==SSTOP
4174: && p->p_pid==u.u_arg[0]
4175: && p->p_ppid==u.u_procp->p_pid)
4176: goto found;
4177: u.u_error = ESRCH;
4178: return;
4179:
4180: found:
4181: while (ipc.ip_lock)
4182: sleep(&ipc, IPCPRI);
4183: ipc.ip_lock = p->p_pid;
4184: ipc.ip_data = u.u_ar0[R0];
4185: ipc.ip_addr = u.u_arg[1] & ~01;
4186: ipc.ip_req = u.u_arg[2];
4187: p->p_flag =& ~SWTED;
4188: setrun(p);
4189: while (ipc.ip_req > 0)
4190: sleep(&ipc, IPCPRI);
4191: u.u_ar0[R0] = ipc.ip_data;
4192: if (ipc.ip_req < 0)
4193: u.u_error = EIO;
4194: ipc.ip_lock = 0;
4195: wakeup(&ipc);
4196: }
4197: /* --------------------------- */
4198:
4199: /*
4200: * Code that the child process
4201: * executes to implement the command
4202: * of the parent process in tracing.
4203: */
4204: procxmt()
4205: {
4206: register int i;
4207: register int *p;
4208:
4209: if (ipc.ip_lock != u.u_procp->p_pid)
4210: return(0);
4211: i = ipc.ip_req;
4212: ipc.ip_req = 0;
4213: wakeup(&ipc);
4214: switch (i) {
4215:
4216: /* read user I */
4217: case 1:
4218: if (fuibyte(ipc.ip_addr) == -1)
4219: goto error;
4220: ipc.ip_data = fuiword(ipc.ip_addr);
4221: break;
4222:
4223: /* read user D */
4224: case 2:
4225: if (fubyte(ipc.ip_addr) == -1)
4226: goto error;
4227: ipc.ip_data = fuword(ipc.ip_addr);
4228: break;
4229:
4230: /* read u */
4231: case 3:
4232: i = ipc.ip_addr;
4233: if (i<0 || i >= (USIZE<<6))
4234: goto error;
4235: ipc.ip_data = u.inta[i>>1];
4236: break;
4237:
4238: /* write user I (for now, always an error) */
4239: case 4:
4240: if (suiword(ipc.ip_addr, 0) < 0)
4241: goto error;
4242: suiword(ipc.ip_addr, ipc.ip_data);
4243: break;
4244:
4245: /* write user D */
4246: case 5:
4247: if (suword(ipc.ip_addr, 0) < 0)
4248: goto error;
4249: suword(ipc.ip_addr, ipc.ip_data);
4250: break;
4251:
4252: /* write u */
4253: case 6:
4254: p = &u.inta[ipc.ip_addr>>1];
4255: if (p >= u.u_fsav && p < &u.u_fsav[25])
4256: goto ok;
4257: for (i=0; i<9; i++)
4258: if (p == &u.u_ar0[regloc[i]])
4259: goto ok;
4260: goto error;
4261: ok:
4262: if (p == &u.u_ar0[RPS]) {
4263:
4264: ipc.ip_data =| 0170000; /* assure user space */
4265:
4266: ipc.ip_data =& ~0340; /* priority 0 */
4267: }
4268: *p = ipc.ip_data;
4269: break;
4270:
4271: /* set signal and continue */
4272: case 7:
4273: u.u_procp->p_sig = ipc.ip_data;
4274: return(1);
4275:
4276: /* force exit */
4277: case 8:
4278: exit();
4279:
4280: default:
4281: error:
4282: ipc.ip_req = -1;
4283: }
4284: return(0);
4285: }
4286: /* --------------------------- */
4300: /*
4301: * Text structure.
4302: * One allocated per pure
4303: * procedure on swap device.
4304: * Manipulated by text.c
4305: */
4306: struct text
4307: {
4308: int x_daddr; /* disk address of segment */
4309: int x_caddr; /* core address, if loaded */
4310: int x_size; /* size (*64) */
4311: int *x_iptr; /* inode of prototype */
4312: char x_count; /* reference count */
4313: char x_ccount; /* number of loaded references */
4314: } text[NTEXT];
4315: /* --------------------------- */
4350: #
4351: #include "../param.h"
4352: #include "../systm.h"
4353: #include "../user.h"
4354: #include "../proc.h"
4355: #include "../text.h"
4356: #include "../inode.h"
4357:
4358: /* Swap out process p.
4359: * The ff flag causes its core to be freed--
4360: * it may be off when called to create an image for a
4361: * child process in newproc.
4362: * Os is the old size of the data area of the process,
4363: * and is supplied during core expansion swaps.
4364: *
4365: * panic: out of swap space
4366: * panic: swap error -- IO error
4367: */
4368: xswap(p, ff, os)
4369: int *p;
4370: { register *rp, a;
4371:
4372: rp = p;
4373: if(os == 0)
4374: os = rp->p_size;
4375: a = malloc(swapmap, (rp->p_size+7)/8);
4376: if(a == NULL)
4377: panic("out of swap space");
4378: xccdec(rp->p_textp);
4379: rp->p_flag =| SLOCK;
4380: if(swap(a, rp->p_addr, os, 0))
4381: panic("swap error");
4382: if(ff)
4383: mfree(coremap, os, rp->p_addr);
4384: rp->p_addr = a;
4385: rp->p_flag =& ~(SLOAD|SLOCK);
4386: rp->p_time = 0;
4387: if(runout) {
4388: runout = 0;
4389: wakeup(&runout);
4390: }
4391: }
4392: * --------------------------- */
4393:
4394: /*
4395: * relinquish use of the shared text segment
4396: * of a process.
4397: */
4398: xfree()
4399: {
4400: register *xp, *ip;
4401:
4402: if((xp=u.u_procp->p_textp) != NULL) {
4403: u.u_procp->p_textp = NULL;
4404: xccdec(xp);
4405: if(--xp->x_count == 0) {
4406: ip = xp->x_iptr;
4407: if((ip->i_mode&ISVTX) == 0) {
4408: xp->x_iptr = NULL;
4409: mfree(swapmap, (xp->x_size+7)/8, xp->x_daddr);
4410: ip->i_flag =& ~ITEXT;
4411: iput(ip);
4412: }
4413: }
4414: }
4415: }
4416: /* --------------------------- */
4417:
4418: /* Attach to a shared text segment.
4419: * If there is no shared text, just return.
4420: * If there is, hook up to it:
4421: * if it is not currently being used, it has to be read
4422: * in from the inode (ip) and established in the swap space.
4423: * If it is being used, but is not currently in core,
4424: * a swap has to be done to get it back.
4425: * The full coroutine glory has to be invoked--
4426: * see slp.c-- because if the calling process
4427: * is misplaced in core the text image might not fit.
4428: * Quite possibly the code after "out:" could check to
4429: * see if the text does fit and simply swap it in.
4430: *
4431: * panic: out of swap space
4432: */
4433: xalloc(ip)
4434: int *ip;
4435: {
4436: register struct text *xp;
4437: register *rp, ts;
4438:
4439: if(u.u_arg[1] == 0) return;
4440: rp = NULL;
4441: for(xp = &text[0]; xp < &text[NTEXT]; xp++)
4442: if(xp->x_iptr == NULL) {
4443: if(rp == NULL)
4444: rp = xp;
4445: } else
4446: if(xp->x_iptr == ip) {
4447: xp->x_count++;
4448: u.u_procp->p_textp = xp;
4449: goto out;
4450: }
4451: if((xp=rp) == NULL) panic("out of text");
4452: xp->x_count = 1;
4453: xp->x_ccount = 0;
4454: xp->x_iptr = ip;
4455: ts = ((u.u_arg[1]+63)>>6) & 01777;
4456: xp->x_size = ts;
4457: if((xp->x_daddr = malloc(swapmap, (ts+7)/8)) == NULL)
4458: panic("out of swap space");
4459: expand(USIZE+ts);
4460: estabur(0, ts, 0, 0);
4461: u.u_count = u.u_arg[1];
4462: u.u_offset[1] = 020;
4463: u.u_base = 0;
4464: readi(ip);
4465: rp = u.u_procp;
4466: rp->p_flag =| SLOCK;
4467: swap(xp->x_daddr, rp->p_addr+USIZE, ts, 0);
4468: rp->p_flag =& ~SLOCK;
4469: rp->p_textp = xp;
4470: rp = ip;
4471: rp->i_flag =| ITEXT;
4472: rp->i_count++;
4473: expand(USIZE);
4474: out:
4475: if(xp->x_ccount == 0) {
4476: savu(u.u_rsav);
4477: savu(u.u_ssav);
4478: xswap(u.u_procp, 1, 0);
4479: u.u_procp->p_flag =| SSWAP;
4480: swtch();
4481: /* no return */
4482: }
4483: xp->x_ccount++;
4484: }
4485: /* --------------------------- */
4486:
4487: /* Decrement the in-core usage count of a shared text segment.
4488: * When it drops to zero, free the core space.
4489: */
4490: xccdec(xp)
4491: int *xp;
4492: {
4493: register *rp;
4494:
4495: if((rp=xp)!=NULL && rp->x_ccount!=0)
4496: if(--rp->x_ccount == 0)
4497: mfree(coremap, rp->x_size, rp->x_caddr);
4498: }
4500: /*
4501: * Each buffer in the pool is usually doubly linked into 2 lists:
4502: * the device with which it is currently associated (always)
4503: * and also on a list of blocks available for allocation
4504: * for other use (usually).
4505: * The latter list is kept in last-used order, and the two
4506: * lists are doubly linked to make it easy to remove
4507: * a buffer from one list when it was found by
4508: * looking through the other.
4509: * A buffer is on the available list, and is liable
4510: * to be reassigned to another disk block, if and only
4511: * if it is not marked BUSY. When a buffer is busy, the
4512: * available-list pointers can be used for other purposes.
4513: * Most drivers use the forward ptr as a link in their I/O
4514: * active queue.
4515: * A buffer header contains all the information required
4516: * to perform I/O.
4517: * Most of the routines which manipulate these things
4518: * are in bio.c.
4519: */
4520: struct buf
4521: {
4522: int b_flags; /* see defines below */
4523: struct buf *b_forw; /* headed by devtab of b_dev */
4524: struct buf *b_back; /* */
4525: struct buf *av_forw; /* position on free list, */
4526: struct buf *av_back; /* if not BUSY*/
4527: int b_dev; /* major+minor device name */
4528: int b_wcount; /* transfer count (usu. words) */
4529: char *b_addr; /* low order core address */
4530: char *b_xmem; /* high order core address */
4531: char *b_blkno; /* block # on device */
4532: char b_error; /* returned after I/O */
4533: char *b_resid; /* words not transferred after error */
4534:
4535: } buf[NBUF];
4536: /* --------------------------- */
4537:
4538: /*
4539: * Each block device has a devtab, which contains private state stuff
4540: * and 2 list heads: the b_forw/b_back list, which is doubly linked
4541: * and has all the buffers currently associated with that major
4542: * device; and the d_actf/d_actl list, which is private to the
4543: * device but in fact is always used for the head and tail
4544: * of the I/O queue for the device.
4545: * Various routines in bio.c look at b_forw/b_back
4546: * (notice they are the same as in the buf structure)
4547: * but the rest is private to each device driver.
4548: *
4549: */
4550:
4551: struct devtab
4552: {
4553: char d_active; /* busy flag */
4554: char d_errcnt; /* error count (for recovery) */
4555: struct buf *b_forw; /* first buffer for this dev */
4556: struct buf *b_back; /* last buffer for this dev */
4557: struct buf *d_actf; /* head of I/O queue */
4558: struct buf *d_actl; /* tail of I/O queue */
4559: };
4560: /* --------------------------- */
4561:
4562: /*
4563: * This is the head of the queue of available
4564: * buffers-- all unused except for the 2 list heads.
4565: */
4566: struct buf bfreelist;
4567:
4568: /*
4569: * These flags are kept in b_flags.
4570: */
4571: #define B_WRITE 0 /* non-read pseudo-flag */
4572: #define B_READ 01 /* read when I/O occurs */
4573: #define B_DONE 02 /* transaction finished */
4574: #define B_ERROR 04 /* transaction aborted */
4575: #define B_BUSY 010 /* not on av_forw/back list */
4576: #define B_PHYS 020 /* Physical IO potentially using UNIBUS map */
4577:
4578: #define B_MAP 040 /* This block has the UNIBUS map allocated */
4579:
4580: #define B_WANTED 0100 /* issue wakeup when BUSY goes off */
4581:
4582: #define B_RELOC 0200 /* no longer used */
4583: #define B_ASYNC 0400 /* don't wait for I/O completion */
4584:
4585: #define B_DELWRI 01000 /* don't write till block leaves available list */
4600: /* Used to dissect integer device code
4601: * into major (driver designation) and
4602: * minor (driver parameter) parts.
4603: */
4604: struct {
4605: char d_minor;
4606: char d_major;
4607: };
4608: /* --------------------------- */
4609: /* Declaration of block device
4610: * switch. Each entry (row) is
4611: * the only link between the
4612: * main unix code and the driver.
4613: * The initialization of the
4614: * device switches is in the
4615: * file conf.c.
4616: */
4617: struct bdevsw {
4618: int (*d_open)();
4619: int (*d_close)();
4620: int (*d_strategy)();
4621: int *d_tab;
4622: } bdevsw[];
4623: /* --------------------------- */
4624: /* Nblkdev is the number of entries
4625: * (rows) in the block switch. It is
4626: * set in binit/bio.c by making
4627: * a pass over the switch.
4628: * Used in bounds checking on major
4629: * device numbers.
4630: */
4631: int nblkdev;
4632:
4633: /* Character device switch.
4634: */
4635: struct cdevsw {
4636: int (*d_open)();
4637: int (*d_close)();
4638: int (*d_read)();
4639: int (*d_write)();
4640: int (*d_sgtty)();
4641: } cdevsw[];
4642: /* --------------------------- */
4643:
4644: /* Number of character switch entries.
4645: * Set by cinit/tty.c
4646: */
4647: int nchrdev;
4650:
4651:
4652:
4653:
4654:
4655:
4656: int (*bdevsw[])()
4657: {
4658: &nulldev, &nulldev, &rkstrategy, &rktab, /* rk */
4659: &nodev, &nodev, &nodev, 0, /* rp */
4660: &nodev, &nodev, &nodev, 0, /* rf */
4661: &nodev, &nodev, &nodev, 0, /* tm */
4662: &nodev, &nodev, &nodev, 0, /* tc */
4663: &nodev, &nodev, &nodev, 0, /* hs */
4664: &nodev, &nodev, &nodev, 0, /* hp */
4665: &nodev, &nodev, &nodev, 0, /* ht */
4666: 0
4667: };
4668:
4669: int (*cdevsw[])()
4670: {
4671: &klopen, &klclose, &klread, &klwrite, &klsgtty, /* console */
4672:
4673: &pcopen, &pcclose, &pcread, &pcwrite, &nodev, /* pc */
4674:
4675: &lpopen, &lpclose, &lpread, &lpwrite, &nodev, /* lp */
4676:
4677: &nodev, &nodev, &nodev, &nodev, &nodev, /* dc */
4678: &nodev, &nodev, &nodev, &nodev, &nodev, /* dh */
4679: &nodev, &nodev, &nodev, &nodev, &nodev, /* dp */
4680: &nodev, &nodev, &nodev, &nodev, &nodev, /* dj */
4681: &nodev, &nodev, &nodev, &nodev, &nodev, /* dn */
4682: &nulldev, &nulldev, &mmread, &mmwrite, &nodev, /* mem */
4683:
4684: &nulldev, &nulldev, &rkread, &rkwrite, &nodev, /* rk */
4685:
4686: &nodev, &nodev, &nodev, &nodev, &nodev, /* rf */
4687: &nodev, &nodev, &nodev, &nodev, &nodev, /* rp */
4688: &nodev, &nodev, &nodev, &nodev, &nodev, /* tm */
4689: &nodev, &nodev, &nodev, &nodev, &nodev, /* hs */
4690: &nodev, &nodev, &nodev, &nodev, &nodev, /* hp */
4691: &nodev, &nodev, &nodev, &nodev, &nodev, /* ht */
4692: 0
4693: };
4694:
4695: int rootdev {(0<<8)|0};
4696: int swapdev {(0<<8)|0};
4697: int swplo 4000; /* cannot be zero */
4698: int nswap 872;
4700: #
4701: /*
4702: */
4703:
4704: #include "../param.h"
4705: #include "../user.h"
4706: #include "../buf.h"
4707: #include "../conf.h"
4708: #include "../systm.h"
4709: #include "../proc.h"
4710: #include "../seg.h"
4711:
4712: /*
4713: * This is the set of buffers proper, whose heads
4714: * were declared in buf.h. There can exist buffer
4715: * headers not pointing here that are used purely
4716: * as arguments to the I/O routines to describe
4717: * I/O to be done-- e.g. swbuf, just below, for
4718: * swapping.
4719: */
4720: char buffers[NBUF][514];
4721: struct buf swbuf;
4722:
4723: /*
4724: * Declarations of the tables for the magtape devices;
4725: * see bdwrite.
4726: */
4727: int tmtab;
4728: int httab;
4729:
4730: /*
4731: * The following several routines allocate and free
4732: * buffers with various side effects. In general the
4733: * arguments to an allocate routine are a device and
4734: * a block number, and the value is a pointer to
4735: * to the buffer header; the buffer is marked "busy"
4736: * so that no on else can touch it. If the block was
4737: * already in core, no I/O need be done; if it is
4738: * already busy, the process waits until it becomes free.
4739: * The following routines allocate a buffer:
4740: * getblk
4741: * bread
4742: * breada
4743: * Eventually the buffer must be released, possibly with the
4744: * side effect of writing it out, by using one of
4745: * bwrite
4746: * bdwrite
4747: * bawrite
4748: * brelse
4749: */
4750:
4751: /*
4752: * Read in (if necessary) the block and return a buffer pointer.
4753: */
4754: bread(dev, blkno)
4755: {
4756: register struct buf *rbp;
4757:
4758: rbp = getblk(dev, blkno);
4759: if (rbp->b_flags&B_DONE)
4760: return(rbp);
4761: rbp->b_flags =| B_READ;
4762: rbp->b_wcount = -256;
4763: (*bdevsw[dev.d_major].d_strategy)(rbp);
4764: iowait(rbp);
4765: return(rbp);
4766: }
4767: /* --------------------------- */
4768:
4769: /*
4770: * Read in the block, like bread, but also start I/O on the
4771: * read-ahead block (which is not allocated to the caller)
4772: */
4773: breada(adev, blkno, rablkno)
4774: {
4775: register struct buf *rbp, *rabp;
4776: register int dev;
4777:
4778: dev = adev;
4779: rbp = 0;
4780: if (!incore(dev, blkno)) {
4781: rbp = getblk(dev, blkno);
4782: if ((rbp->b_flags&B_DONE) == 0) {
4783: rbp->b_flags =| B_READ;
4784: rbp->b_wcount = -256;
4785: (*bdevsw[adev.d_major].d_strategy)(rbp);
4786: }
4787: }
4788: if (rablkno && !incore(dev, rablkno)) {
4789: rabp = getblk(dev, rablkno);
4790: if (rabp->b_flags & B_DONE)
4791: brelse(rabp);
4792: else {
4793: rabp->b_flags =| B_READ|B_ASYNC;
4794: rabp->b_wcount = -256;
4795: (*bdevsw[adev.d_major].d_strategy)(rabp);
4796: }
4797: }
4798: if (rbp==0)
4799: return(bread(dev, blkno));
4800: iowait(rbp);
4801: return(rbp);
4802: }
4803: /* --------------------------- */
4804:
4805: /*
4806: * Write the buffer, waiting for completion.
4807: * Then release the buffer.
4808: */
4809: bwrite(bp)
4810: struct buf *bp;
4811: {
4812: register struct buf *rbp;
4813: register flag;
4814:
4815: rbp = bp;
4816: flag = rbp->b_flags;
4817: rbp->b_flags =& ~(B_READ | B_DONE | B_ERROR | B_DELWRI);
4818: rbp->b_wcount = -256;
4819: (*bdevsw[rbp->b_dev.d_major].d_strategy)(rbp);
4820: if ((flag&B_ASYNC) == 0) {
4821: iowait(rbp);
4822: brelse(rbp);
4823: } else if ((flag&B_DELWRI)==0)
4824: geterror(rbp);
4825: }
4826: /* --------------------------- */
4827:
4828: /*
4829: * Release the buffer, marking it so that if it is grabbed
4830: * for another purpose it will be written out before being
4831: * given up (e.g. when writing a partial block where it is
4832: * assumed that another write for the same block will soon follow).
4833: * This can't be done for magtape, since writes must be done
4834: * in the same order as requested.
4835: */
4836: bdwrite(bp)
4837: struct buf *bp;
4838: {
4839: register struct buf *rbp;
4840: register struct devtab *dp;
4841:
4842: rbp = bp;
4843: dp = bdevsw[rbp->b_dev.d_major].d_tab;
4844: if (dp == &tmtab || dp == &httab)
4845: bawrite(rbp);
4846: else {
4847: rbp->b_flags =| B_DELWRI | B_DONE;
4848: brelse(rbp);
4849: }
4850: }
4851: /* --------------------------- */
4852:
4853: /*
4854: * Release the buffer, start I/O on it, but don't wait for completion.
4855: */
4856: bawrite(bp)
4857: struct buf *bp;
4858: {
4859: register struct buf *rbp;
4860:
4861: rbp = bp;
4862: rbp->b_flags =| B_ASYNC;
4863: bwrite(rbp);
4864: }
4865: /* --------------------------- */
4866:
4867: /* release the buffer, with no I/O implied.
4868: */
4869: brelse(bp)
4870: struct buf *bp;
4871: {
4872: register struct buf *rbp, **backp;
4873: register int sps;
4874:
4875: rbp = bp;
4876: if (rbp->b_flags&B_WANTED)
4877: wakeup(rbp);
4878: if (bfreelist.b_flags&B_WANTED) {
4879: bfreelist.b_flags =& ~B_WANTED;
4880: wakeup(&bfreelist);
4881: }
4882: if (rbp->b_flags&B_ERROR)
4883: rbp->b_dev.d_minor = -1; /* no assoc. on error */
4884: backp = &bfreelist.av_back;
4885: sps = PS->integ;
4886: spl6();
4887: rbp->b_flags =& ~(B_WANTED|B_BUSY|B_ASYNC);
4888: (*backp)->av_forw = rbp;
4889: rbp->av_back = *backp;
4890: *backp = rbp;
4891: rbp->av_forw = &bfreelist;
4892: PS->integ = sps;
4893: }
4894: /* --------------------------- */
4895:
4896: /* See if the block is associated with some buffer
4897: * (mainly to avoid getting hung up on a wait in breada)
4898: */
4899: incore(adev, blkno)
4900: {
4901: register int dev;
4902: register struct buf *bp;
4903: register struct devtab *dp;
4904:
4905: dev = adev;
4906: dp = bdevsw[adev.d_major].d_tab;
4907: for (bp=dp->b_forw; bp != dp; bp = bp->b_forw)
4908: if (bp->b_blkno==blkno && bp->b_dev==dev)
4909: return(bp);
4910: return(0);
4911: }
4912: /* --------------------------- */
4913:
4914: /* Assign a buffer for the given block. If the appropriate
4915: * block is already associated, return it; otherwise search
4916: * for the oldest non-busy buffer and reassign it.
4917: * When a 512-byte area is wanted for some random reason
4918: * (e.g. during exec, for the user arglist) getblk can be called
4919: * with device NODEV to avoid unwanted associativity.
4920: */
4921: getblk(dev, blkno)
4922: {
4923: register struct buf *bp;
4924: register struct devtab *dp;
4925: extern lbolt;
4926:
4927: if(dev.d_major >= nblkdev)
4928: panic("blkdev");
4929:
4930: loop:
4931: if (dev < 0)
4932: dp = &bfreelist;
4933: else {
4934: dp = bdevsw[dev.d_major].d_tab;
4935: if(dp == NULL)
4936: panic("devtab");
4937: for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) {
4938: if (bp->b_blkno!=blkno || bp->b_dev!=dev)
4939: continue;
4940: spl6();
4941: if (bp->b_flags&B_BUSY) {
4942: bp->b_flags =| B_WANTED;
4943: sleep(bp, PRIBIO);
4944: spl0();
4945: goto loop;
4946: }
4947: spl0();
4948: notavail(bp);
4949: return(bp);
4950: }
4951: }
4952: spl6();
4953: if (bfreelist.av_forw == &bfreelist) {
4954: bfreelist.b_flags =| B_WANTED;
4955: sleep(&bfreelist, PRIBIO);
4956: spl0();
4957: goto loop;
4958: }
4959: spl0();
4960: notavail(bp = bfreelist.av_forw);
4961: if (bp->b_flags & B_DELWRI) {
4962: bp->b_flags =| B_ASYNC;
4963: bwrite(bp);
4964: goto loop;
4965: }
4966: bp->b_flags = B_BUSY | B_RELOC;
4967: bp->b_back->b_forw = bp->b_forw;
4968: bp->b_forw->b_back = bp->b_back;
4969: bp->b_forw = dp->b_forw;
4970: bp->b_back = dp;
4971: dp->b_forw->b_back = bp;
4972: dp->b_forw = bp;
4973: bp->b_dev = dev;
4974: bp->b_blkno = blkno;
4975: return(bp);
4976: }
4977: /* --------------------------- */
4978:
4979: /* Wait for I/O completion on the buffer; return errors
4980: * to the user.
4981: */
4982: iowait(bp)
4983: struct buf *bp;
4984: {
4985: register struct buf *rbp;
4986:
4987: rbp = bp;
4988: spl6();
4989: while ((rbp->b_flags&B_DONE)==0)
4990: sleep(rbp, PRIBIO);
4991: spl0();
4992: geterror(rbp);
4993: }
4994: /* --------------------------- */
4995:
4996: /* Unlink a buffer from the available list and mark it busy.
4997: * (internal interface)
4998: */
4999: notavail(bp)
5000: struct buf *bp;
5001: {
5002: register struct buf *rbp;
5003: register int sps;
5004:
5005: rbp = bp;
5006: sps = PS->integ;
5007: spl6();
5008: rbp->av_back->av_forw = rbp->av_forw;
5009: rbp->av_forw->av_back = rbp->av_back;
5010: rbp->b_flags =| B_BUSY;
5011: PS->integ = sps;
5012: }
5013: /* --------------------------- */
5014:
5015: /* Mark I/O complete on a buffer, release it if I/O is asynchronous,
5016: * and wake up anyone waiting for it.
5017: */
5018: iodone(bp)
5019: struct buf *bp;
5020: {
5021: register struct buf *rbp;
5022:
5023: rbp = bp;
5024: if(rbp->b_flags&B_MAP)
5025: mapfree(rbp);
5026: rbp->b_flags =| B_DONE;
5027: if (rbp->b_flags&B_ASYNC)
5028: brelse(rbp);
5029: else {
5030: rbp->b_flags =& ~B_WANTED;
5031: wakeup(rbp);
5032: }
5033: }
5034: /* --------------------------- */
5035:
5036: /* Zero the core associated with a buffer.
5037: */
5038: clrbuf(bp)
5039: int *bp;
5040: {
5041: register *p;
5042: register c;
5043:
5044: p = bp->b_addr;
5045: c = 256;
5046: do
5047: *p++ = 0;
5048: while (--c);
5049: }
5050: /* --------------------------- */
5051:
5052: /* Initialize the buffer I/O system by freeing
5053: * all buffers and setting all device buffer lists to empty.
5054: */
5055: binit()
5056: {
5057: register struct buf *bp;
5058: register struct devtab *dp;
5059: register int i;
5060: struct bdevsw *bdp;
5061:
5062: bfreelist.b_forw = bfreelist.b_back =
5063: bfreelist.av_forw = bfreelist.av_back = &bfreelist;
5064: for (i=0; i<NBUF; i++) {
5065: bp = &buf[i];
5066: bp->b_dev = -1;
5067: bp->b_addr = buffers[i];
5068: bp->b_back = &bfreelist;
5069: bp->b_forw = bfreelist.b_forw;
5070: bfreelist.b_forw->b_back = bp;
5071: bfreelist.b_forw = bp;
5072: bp->b_flags = B_BUSY;
5073: brelse(bp);
5074: }
5075: i = 0;
5076: for (bdp = bdevsw; bdp->d_open; bdp++) {
5077: dp = bdp->d_tab;
5078: if(dp) {
5079: dp->b_forw = dp;
5080: dp->b_back = dp;
5081: }
5082: i++;
5083: }
5084: nblkdev = i;
5085: }
5086: /* --------------------------- */
5087:
5088: /* Device start routine for disks
5089: * and other devices that have the register
5090: * layout of the older DEC controllers (RF, RK, RP, TM)
5091: */
5092: #define IENABLE 0100
5093: #define WCOM 02
5094: #define RCOM 04
5095: #define GO 01
5096: devstart(bp, devloc, devblk, hbcom)
5097: struct buf *bp;
5098: int *devloc;
5099: {
5100: register int *dp;
5101: register struct buf *rbp;
5102: register int com;
5103:
5104: dp = devloc;
5105: rbp = bp;
5106: *dp = devblk; /* block address */
5107: *--dp = rbp->b_addr; /* buffer address */
5108: *--dp = rbp->b_wcount; /* word count */
5109: com = (hbcom<<8) | IENABLE | GO |
5110: ((rbp->b_xmem & 03) << 4);
5111: if (rbp->b_flags&B_READ) /* command + x-mem */
5112: com =| RCOM;
5113: else
5114: com =| WCOM;
5115: *--dp = com;
5116: }
5117: /* --------------------------- */
5118:
5119: /* startup routine for RH controllers. */
5120: #define RHWCOM 060
5121: #define RHRCOM 070
5122:
5123: rhstart(bp, devloc, devblk, abae)
5124: struct buf *bp;
5125: int *devloc, *abae;
5126: {
5127: register int *dp;
5128: register struct buf *rbp;
5129: register int com;
5130:
5131: dp = devloc;
5132: rbp = bp;
5133: if(cputype == 70)
5134: *abae = rbp->b_xmem;
5135: *dp = devblk; /* block address */
5136: *--dp = rbp->b_addr; /* buffer address */
5137: *--dp = rbp->b_wcount; /* word count */
5138: com = IENABLE | GO |
5139: ((rbp->b_xmem & 03) << 8);
5140: if (rbp->b_flags&B_READ) /* command + x-mem */
5141: com =| RHRCOM; else
5142: com =| RHWCOM;
5143: *--dp = com;
5144: }
5145: /* --------------------------- */
5146:
5147: /*
5148: * 11/70 routine to allocate the
5149: * UNIBUS map and initialize for
5150: * a unibus device.
5151: * The code here and in
5152: * rhstart assumes that an rh on an 11/70
5153: * is an rh70 and contains 22 bit addressing.
5154: */
5155: int maplock;
5156: mapalloc(abp)
5157: struct buf *abp;
5158: {
5159: register i, a;
5160: register struct buf *bp;
5161:
5162: if(cputype != 70)
5163: return;
5164: spl6();
5165: while(maplock&B_BUSY) {
5166: maplock =| B_WANTED;
5167: sleep(&maplock, PSWP);
5168: }
5169: maplock =| B_BUSY;
5170: spl0();
5171: bp = abp;
5172: bp->b_flags =| B_MAP;
5173: a = bp->b_xmem;
5174: for(i=16; i<32; i=+2)
5175: UBMAP->r[i+1] = a;
5176: for(a++; i<48; i=+2)
5177: UBMAP->r[i+1] = a;
5178: bp->b_xmem = 1;
5179: }
5180: /* --------------------------- */
5181:
5182: mapfree(bp)
5183: struct buf *bp;
5184: {
5185:
5186: bp->b_flags =& ~B_MAP;
5187: if(maplock&B_WANTED)
5188: wakeup(&maplock);
5189: maplock = 0;
5190: }
5191: /* --------------------------- */
5192:
5193: /*
5194: * swap I/O
5195: */
5196: swap(blkno, coreaddr, count, rdflg)
5197: {
5198: register int *fp;
5199:
5200: fp = &swbuf.b_flags;
5201: spl6();
5202: while (*fp&B_BUSY) {
5203: *fp =| B_WANTED;
5204: sleep(fp, PSWP);
5205: }
5206: *fp = B_BUSY | B_PHYS | rdflg;
5207: swbuf.b_dev = swapdev;
5208: swbuf.b_wcount = - (count<<5); /* 32 w/block */
5209: swbuf.b_blkno = blkno;
5210: swbuf.b_addr = coreaddr<<6; /* 64 b/block */
5211: swbuf.b_xmem = (coreaddr>>10) & 077;
5212: (*bdevsw[swapdev>>8].d_strategy)(&swbuf);
5213: spl6();
5214: while((*fp&B_DONE)==0)
5215: sleep(fp, PSWP);
5216: if (*fp&B_WANTED)
5217: wakeup(fp);
5218: spl0();
5219: *fp =& ~(B_BUSY|B_WANTED);
5220: return(*fp&B_ERROR);
5221: }
5222: /* --------------------------- */
5223:
5224: /*
5225: * make sure all write-behind blocks
5226: * on dev (or NODEV for all)
5227: * are flushed out.
5228: * (from umount and update)
5229: */
5230: bflush(dev)
5231: {
5232: register struct buf *bp;
5233:
5234: loop:
5235: spl6();
5236: for (bp = bfreelist.av_forw; bp != &bfreelist; bp = bp->av_forw) {
5237:
5238: if (bp->b_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) {
5239: bp->b_flags =| B_ASYNC;
5240: notavail(bp);
5241: bwrite(bp);
5242: goto loop;
5243: }
5244: }
5245: spl0();
5246: }
5247: /* --------------------------- */
5248:
5249: /*
5250: * Raw I/O. The arguments are
5251: * The strategy routine for the device
5252: * A buffer, which will always be a special buffer
5253: * header owned exclusively by the device for this purpose
5254: * The device number
5255: * Read/write flag
5256: * Essentially all the work is computing physical addresses and
5257: * validating them.
5258: */
5259: physio(strat, abp, dev, rw)
5260: struct buf *abp;
5261: int (*strat)();
5262: {
5263: register struct buf *bp;
5264: register char *base;
5265: register int nb;
5266: int ts;
5267:
5268: bp = abp;
5269: base = u.u_base;
5270: /*
5271: * Check odd base, odd count, and address wraparound
5272: */
5273: if (base&01 || u.u_count&01 || base>=base+u.u_count)
5274: goto bad;
5275: ts = (u.u_tsize+127) & ~0177;
5276: if (u.u_sep)
5277: ts = 0;
5278: nb = (base>>6) & 01777;
5279: /*
5280: * Check overlap with text. (ts and nb now
5281: * in 64-byte clicks)
5282: */
5283: if (nb < ts)
5284: goto bad;
5285: /*
5286: * Check that transfer is either entirely in the
5287: * data or in the stack: that is, either
5288: * the end is in the data or the start is in the stack
5289: * (remember wraparound was already checked).
5290: */
5291: if ((((base+u.u_count)>>6)&01777) >= ts+u.u_dsize
5292: && nb < 1024-u.u_ssize)
5293: goto bad;
5294: spl6();
5295: while (bp->b_flags&B_BUSY) {
5296: bp->b_flags =| B_WANTED;
5297: sleep(bp, PRIBIO);
5298: }
5299: bp->b_flags = B_BUSY | B_PHYS | rw;
5300: bp->b_dev = dev;
5301: /*
5302: * Compute physical address by simulating
5303: * the segmentation hardware.
5304: */
5305: bp->b_addr = base&077;
5306: base = (u.u_sep? UDSA: UISA)->r[nb>>7] + (nb&0177);
5307: bp->b_addr =+ base<<6;
5308: bp->b_xmem = (base>>10) & 077;
5309: bp->b_blkno = lshift(u.u_offset, -9);
5310: bp->b_wcount = -((u.u_count>>1) & 077777);
5311: bp->b_error = 0;
5312: u.u_procp->p_flag =| SLOCK;
5313: (*strat)(bp);
5314: spl6();
5315: while ((bp->b_flags&B_DONE) == 0)
5316: sleep(bp, PRIBIO);
5317: u.u_procp->p_flag =& ~SLOCK;
5318: if (bp->b_flags&B_WANTED)
5319: wakeup(bp);
5320: spl0();
5321: bp->b_flags =& ~(B_BUSY|B_WANTED);
5322: u.u_count = (-bp->b_resid)<<1;
5323: geterror(bp);
5324: return;
5325: bad:
5326: u.u_error = EFAULT;
5327: }
5328: /* --------------------------- */
5329:
5330: /*
5331: * Pick up the device's error number and pass it to the user;
5332: * if there is an error but the number is 0 set a generalized
5333: * code. Actually the latter is always true because devices
5334: * don't yet return specific errors.
5335: */
5336: geterror(abp)
5337: struct buf *abp;
5338: {
5339: register struct buf *bp;
5340:
5341: bp = abp;
5342: if (bp->b_flags&B_ERROR)
5343: if ((u.u_error = bp->b_error)==0)
5344: u.u_error = EIO;
5345: }
5346: /* --------------------------- */
5350: #
5351: /*
5352: */
5353:
5354: /*
5355: * RK disk driver
5356: */
5357:
5358: #include "../param.h"
5359: #include "../buf.h"
5360: #include "../conf.h"
5361: #include "../user.h"
5362:
5363: #define RKADDR 0177400
5364: #define NRK 4
5365: #define NRKBLK 4872
5366:
5367: #define RESET 0
5368: #define GO 01
5369: #define DRESET 014
5370: #define IENABLE 0100
5371: #define DRY 0200
5372: #define ARDY 0100
5373: #define WLO 020000
5374: #define CTLRDY 0200
5375:
5376: struct {
5377: int rkds;
5378: int rker;
5379: int rkcs;
5380: int rkwc;
5381: int rkba;
5382: int rkda;
5383: };
5384: /* --------------------------- */
5385:
5386: struct devtab rktab;
5387: struct buf rrkbuf;
5388:
5389: rkstrategy(abp)
5390: struct buf *abp;
5391: {
5392: register struct buf *bp;
5393: register *qc, *ql;
5394: int d;
5395:
5396: bp = abp;
5397: if(bp->b_flags&B_PHYS)
5398: mapalloc(bp);
5399: d = bp->b_dev.d_minor-7;
5400: if(d <= 0)
5401: d = 1;
5402: if (bp->b_blkno >= NRKBLK*d) {
5403: bp->b_flags =| B_ERROR;
5404: iodone(bp);
5405: return;
5406: }
5407: bp->av_forw = 0;
5408: spl5();
5409: if (rktab.d_actf==0)
5410: rktab.d_actf = bp;
5411: else
5412: rktab.d_actl->av_forw = bp;
5413: rktab.d_actl = bp;
5414: if (rktab.d_active==0)
5415: rkstart();
5416: spl0();
5417: }
5418: /* --------------------------- */
5419:
5420: rkaddr(bp)
5421: struct buf *bp;
5422: {
5423: register struct buf *p;
5424: register int b;
5425: int d, m;
5426:
5427: p = bp;
5428: b = p->b_blkno;
5429: m = p->b_dev.d_minor - 7;
5430: if(m <= 0)
5431: d = p->b_dev.d_minor;
5432: else {
5433: d = lrem(b, m);
5434: b = ldiv(b, m);
5435: }
5436: return(d<<13 | (b/12)<<4 | b%12);
5437: }
5438: /* --------------------------- */
5439:
5440: rkstart()
5441: {
5442: register struct buf *bp;
5443:
5444: if ((bp = rktab.d_actf) == 0)
5445: return;
5446: rktab.d_active++;
5447: devstart(bp, &RKADDR->rkda, rkaddr(bp), 0);
5448: }
5449: /* --------------------------- */
5450:
5451: rkintr()
5452: {
5453: register struct buf *bp;
5454:
5455: if (rktab.d_active == 0)
5456: return;
5457: bp = rktab.d_actf;
5458: rktab.d_active = 0;
5459: if (RKADDR->rkcs < 0) { /* error bit */
5460: deverror(bp, RKADDR->rker, RKADDR->rkds);
5461: RKADDR->rkcs = RESET|GO;
5462: while((RKADDR->rkcs&CTLRDY) == 0) ;
5463: if (++rktab.d_errcnt <= 10) {
5464: rkstart();
5465: return;
5466: }
5467: bp->b_flags =| B_ERROR;
5468: }
5469: rktab.d_errcnt = 0;
5470: rktab.d_actf = bp->av_forw;
5471: iodone(bp);
5472: rkstart();
5473: }
5474: /* --------------------------- */
5475:
5476: rkread(dev)
5477: {
5478:
5479: physio(rkstrategy, &rrkbuf, dev, B_READ);
5480: }
5481: /* --------------------------- */
5482:
5483: rkwrite(dev)
5484: {
5485:
5486: physio(rkstrategy, &rrkbuf, dev, B_WRITE);
5487: }
5488: /* --------------------------- */
5500: /*
5501: * One file structure is allocated
5502: * for each open/creat/pipe call.
5503: * Main use is to hold the read/write
5504: * pointer associated with each open
5505: * file.
5506: */
5507: struct file
5508: {
5509: char f_flag;
5510: char f_count; /* reference count */
5511: int f_inode; /* pointer to inode structure */
5512: char *f_offset[2]; /* read/write character pointer */
5513: } file[NFILE];
5514: /* --------------------------- */
5515:
5516: /* flags */
5517: #define FREAD 01
5518: #define FWRITE 02
5519: #define FPIPE 04
5550: /*
5551: * Definition of the unix super block.
5552: * The root super block is allocated and
5553: * read in iinit/alloc.c. Subsequently
5554: * a super block is allocated and read
5555: * with each mount (smount/sys3.c) and
5556: * released with unmount (sumount/sys3.c).
5557: * A disk block is ripped off for storage.
5558: * See alloc.c for general alloc/free
5559: * routines for free list and I list.
5560: */
5561: struct filsys
5562: {
5563: int s_isize; /* size in blocks of I list */
5564: int s_fsize; /* size in blocks of entire volume */
5565: int s_nfree; /* number of in core free blocks (0-100) */
5566:
5567: int s_free[100]; /* in core free blocks */
5568: int s_ninode; /* number of in core I nodes (0-100) */
5569: int s_inode[100]; /* in core free I nodes */
5570: char s_flock; /* lock during free list manipulation */
5571: char s_ilock; /* lock during I list manipulation */
5572: char s_fmod; /* super block modified flag */
5573: char s_ronly; /* mounted read-only flag */
5574: int s_time[2]; /* current date of last update */
5575: int pad[50];
5576: };
5577: /* --------------------------- */
5600: /*
5601: * Inode structure as it appears on
5602: * the disk. Not used by the system,
5603: * but by things like check, df, dump.
5604: */
5605: struct inode
5606: {
5607: int i_mode;
5608: char i_nlink;
5609: char i_uid;
5610: char i_gid;
5611: char i_size0;
5612: char *i_size1;
5613: int i_addr[8];
5614: int i_atime[2];
5615: int i_mtime[2];
5616: };
5617: /* --------------------------- */
5618:
5619: /* modes */
5620: #define IALLOC 0100000
5621: #define IFMT 060000
5622: #define IFDIR 040000
5623: #define IFCHR 020000
5624: #define IFBLK 060000
5625: #define ILARG 010000
5626: #define ISUID 04000
5627: #define ISGID 02000
5628: #define ISVTX 01000
5629: #define IREAD 0400
5630: #define IWRITE 0200
5631: #define IEXEC 0100
5650: /* The I node is the focus of all
5651: * file activity in unix. There is a unique
5652: * inode allocated for each active file,
5653: * each current directory, each mounted-on
5654: * file, text file, and the root. An inode is 'named'
5655: * by its dev/inumber pair. (iget/iget.c)
5656: * Data, from mode on, is read in
5657: * from permanent inode on volume.
5658: */
5659: struct inode
5660: {
5661: char i_flag;
5662: char i_count; /* reference count */
5663: int i_dev; /* device where inode resides */
5664: int i_number; /* i number, 1-to-1 with device address */
5665:
5666: int i_mode;
5667: char i_nlink; /* directory entries */
5668: char i_uid; /* owner */
5669: char i_gid; /* group of owner */
5670: char i_size0; /* most significant of size */
5671: char *i_size1; /* least sig */
5672: int i_addr[8]; /* device addresses constituting file */
5673: int i_lastr; /* last logical block read (for read-ahead) */
5674:
5675: } inode[NINODE];
5676: /* --------------------------- */
5677:
5678: /* flags */
5679: #define ILOCK 01 /* inode is locked */
5680: #define IUPD 02 /* inode has been modified */
5681: #define IACC 04 /* inode access time to be updated */
5682: #define IMOUNT 010 /* inode is mounted on */
5683: #define IWANT 020 /* some process waiting on lock */
5684: #define ITEXT 040 /* inode is pure text prototype */
5685:
5686: /* modes */
5687: #define IALLOC 0100000 /* file is used */
5688: #define IFMT 060000 /* type of file */
5689: #define IFDIR 040000 /* directory */
5690: #define IFCHR 020000 /* character special */
5691: #define IFBLK 060000 /* block special, 0 is regular */
5692: #define ILARG 010000 /* large addressing algorithm */
5693: #define ISUID 04000 /* set user id on execution */
5694: #define ISGID 02000 /* set group id on execution */
5695: #define ISVTX 01000 /* save swapped text even after use */
5696: #define IREAD 0400 /* read, write, execute permissions */
5697: #define IWRITE 0200
5698: #define IEXEC 0100
5700: #
5701: #include "../param.h"
5702: #include "../systm.h"
5703: #include "../user.h"
5704: #include "../reg.h"
5705: #include "../file.h"
5706: #include "../inode.h"
5707:
5708: /*
5709: * read system call
5710: */
5711: read()
5712: {
5713: rdwr(FREAD);
5714: }
5715: /* --------------------------- */
5716:
5717: /*
5718: * write system call
5719: */
5720: write()
5721: {
5722: rdwr(FWRITE);
5723: }
5724: /* --------------------------- */
5725:
5726: /*
5727: * common code for read and write calls:
5728: * check permissions, set base, count, and offset,
5729: * and switch out to readi, writei, or pipe code.
5730: */
5731: rdwr(mode)
5732: {
5733: register *fp, m;
5734:
5735: m = mode;
5736: fp = getf(u.u_ar0[R0]);
5737: if(fp == NULL)
5738: return;
5739: if((fp->f_flag&m) == 0) {
5740: u.u_error = EBADF;
5741: return;
5742: }
5743: u.u_base = u.u_arg[0];
5744: u.u_count = u.u_arg[1];
5745: u.u_segflg = 0;
5746: if(fp->f_flag&FPIPE) {
5747: if(m==FREAD)
5748: readp(fp); else
5749: writep(fp);
5750: } else {
5751: u.u_offset[1] = fp->f_offset[1];
5752: u.u_offset[0] = fp->f_offset[0];
5753: if(m==FREAD)
5754: readi(fp->f_inode); else
5755: writei(fp->f_inode);
5756: dpadd(fp->f_offset, u.u_arg[1]-u.u_count);
5757: }
5758: u.u_ar0[R0] = u.u_arg[1]-u.u_count;
5759: }
5760: /* --------------------------- */
5761:
5762: /*
5763: * open system call
5764: */
5765: open()
5766: {
5767: register *ip;
5768: extern uchar;
5769:
5770: ip = namei(&uchar, 0);
5771: if(ip == NULL)
5772: return;
5773: u.u_arg[1]++;
5774: open1(ip, u.u_arg[1], 0);
5775: }
5776: /* --------------------------- */
5777:
5778: /*
5779: * creat system call
5780: */
5781: creat()
5782: {
5783: register *ip;
5784: extern uchar;
5785:
5786: ip = namei(&uchar, 1);
5787: if(ip == NULL) {
5788: if(u.u_error)
5789: return;
5790: ip = maknode(u.u_arg[1]&07777&(~ISVTX));
5791: if (ip==NULL)
5792: return;
5793: open1(ip, FWRITE, 2);
5794: } else
5795: open1(ip, FWRITE, 1);
5796: }
5797: /* --------------------------- */
5798:
5799: /*
5800: * common code for open and creat.
5801: * Check permissions, allocate an open file structure,
5802: * and call the device open routine if any.
5803: */
5804: open1(ip, mode, trf)
5805: int *ip;
5806: {
5807: register struct file *fp;
5808: register *rip, m;
5809: int i;
5810:
5811: rip = ip;
5812: m = mode;
5813: if(trf != 2) {
5814: if(m&FREAD)
5815: access(rip, IREAD);
5816: if(m&FWRITE) {
5817: access(rip, IWRITE);
5818: if((rip->i_mode&IFMT) == IFDIR)
5819: u.u_error = EISDIR;
5820: }
5821: }
5822: if(u.u_error)
5823: goto out;
5824: if(trf)
5825: itrunc(rip);
5826: prele(rip);
5827: if ((fp = falloc()) == NULL)
5828: goto out;
5829: fp->f_flag = m&(FREAD|FWRITE);
5830: fp->f_inode = rip;
5831: i = u.u_ar0[R0];
5832: openi(rip, m&FWRITE);
5833: if(u.u_error == 0)
5834: return;
5835: u.u_ofile[i] = NULL;
5836: fp->f_count--;
5837:
5838: out:
5839: iput(rip);
5840: }
5841: /* --------------------------- */
5842:
5843: /*
5844: * close system call
5845: */
5846: close()
5847: {
5848: register *fp;
5849:
5850: fp = getf(u.u_ar0[R0]);
5851: if(fp == NULL)
5852: return;
5853: u.u_ofile[u.u_ar0[R0]] = NULL;
5854: closef(fp);
5855: }
5856: /* --------------------------- */
5857:
5858: /*
5859: * seek system call
5860: */
5861: seek()
5862: {
5863: int n[2];
5864: register *fp, t;
5865:
5866: fp = getf(u.u_ar0[R0]);
5867: if(fp == NULL)
5868: return;
5869: if(fp->f_flag&FPIPE) {
5870: u.u_error = ESPIPE;
5871: return;
5872: }
5873: t = u.u_arg[1];
5874: if(t > 2) {
5875: n[1] = u.u_arg[0]<<9;
5876: n[0] = u.u_arg[0]>>7;
5877: if(t == 3)
5878: n[0] =& 0777;
5879: } else {
5880: n[1] = u.u_arg[0];
5881: n[0] = 0;
5882: if(t!=0 && n[1]<0)
5883: n[0] = -1;
5884: }
5885: switch(t) {
5886:
5887: case 1:
5888: case 4:
5889: n[0] =+ fp->f_offset[0];
5890: dpadd(n, fp->f_offset[1]);
5891: break;
5892:
5893: default:
5894: n[0] =+ fp->f_inode->i_size0&0377;
5895: dpadd(n, fp->f_inode->i_size1);
5896:
5897: case 0:
5898: case 3:
5899: ;
5900: }
5901: fp->f_offset[1] = n[1];
5902: fp->f_offset[0] = n[0];
5903: }
5904: /* --------------------------- */
5905:
5906: /*
5907: * link system call
5908: */
5909: link()
5910: {
5911: register *ip, *xp;
5912: extern uchar;
5913:
5914: ip = namei(&uchar, 0);
5915: if(ip == NULL)
5916: return;
5917: if(ip->i_nlink >= 127) {
5918: u.u_error = EMLINK;
5919: goto out;
5920: }
5921: if((ip->i_mode&IFMT)==IFDIR && !suser())
5922: goto out;
5923: /*
5924: * unlock to avoid possibly hanging the namei
5925: */
5926: ip->i_flag =& ~ILOCK;
5927: u.u_dirp = u.u_arg[1];
5928: xp = namei(&uchar, 1);
5929: if(xp != NULL) {
5930: u.u_error = EEXIST;
5931: iput(xp);
5932: }
5933: if(u.u_error)
5934: goto out;
5935: if(u.u_pdir->i_dev != ip->i_dev) {
5936: iput(u.u_pdir);
5937: u.u_error = EXDEV;
5938: goto out;
5939: }
5940: wdir(ip);
5941: ip->i_nlink++;
5942: ip->i_flag =| IUPD;
5943:
5944: out:
5945: iput(ip);
5946: }
5947: /* --------------------------- */
5948:
5949: /*
5950: * mknod system call
5951: */
5952: mknod()
5953: {
5954: register *ip;
5955: extern uchar;
5956:
5957: if(suser()) {
5958: ip = namei(&uchar, 1);
5959: if(ip != NULL) {
5960: u.u_error = EEXIST;
5961: goto out;
5962: }
5963: }
5964: if(u.u_error)
5965: return;
5966: ip = maknode(u.u_arg[1]);
5967: if (ip==NULL)
5968: return;
5969: ip->i_addr[0] = u.u_arg[2];
5970:
5971: out:
5972: iput(ip);
5973: }
5974: /* --------------------------- */
5975:
5976: /* sleep system call
5977: * not to be confused with the sleep internal routine.
5978: */
5979: sslep()
5980: {
5981: char *d[2];
5982:
5983: spl7();
5984: d[0] = time[0];
5985: d[1] = time[1];
5986: dpadd(d, u.u_ar0[R0]);
5987:
5988: while(dpcmp(d[0], d[1], time[0], time[1]) > 0) {
5989: if(dpcmp(tout[0], tout[1], time[0], time[1]) <= 0 ||
5990: dpcmp(tout[0], tout[1], d[0], d[1]) > 0) {
5991: tout[0] = d[0];
5992: tout[1] = d[1];
5993: }
5994: sleep(tout, PSLEP);
5995: }
5996: spl0();
5997: }
5998: /* --------------------------- */
6000: #
6001: #include "../param.h"
6002: #include "../systm.h"
6003: #include "../reg.h"
6004: #include "../buf.h"
6005: #include "../filsys.h"
6006: #include "../user.h"
6007: #include "../inode.h"
6008: #include "../file.h"
6009: #include "../conf.h"
6010:
6011: /*
6012: * the fstat system call.
6013: */
6014: fstat()
6015: {
6016: register *fp;
6017:
6018: fp = getf(u.u_ar0[R0]);
6019: if(fp == NULL)
6020: return;
6021: stat1(fp->f_inode, u.u_arg[0]);
6022: }
6023: /* --------------------------- */
6024:
6025: /*
6026: * the stat system call.
6027: */
6028: stat()
6029: {
6030: register ip;
6031: extern uchar;
6032:
6033: ip = namei(&uchar, 0);
6034: if(ip == NULL)
6035: return;
6036: stat1(ip, u.u_arg[1]);
6037: iput(ip);
6038: }
6039: /* --------------------------- */
6040:
6041: /*
6042: * The basic routine for fstat and stat:
6043: * get the inode and pass appropriate parts back.
6044: */
6045: stat1(ip, ub)
6046: int *ip;
6047: {
6048: register i, *bp, *cp;
6049:
6050: iupdat(ip, time);
6051: bp = bread(ip->i_dev, ldiv(ip->i_number+31, 16));
6052: cp = bp->b_addr + 32*lrem(ip->i_number+31, 16) + 24;
6053: ip = &(ip->i_dev);
6054: for(i=0; i<14; i++) {
6055: suword(ub, *ip++);
6056: ub =+ 2;
6057: }
6058: for(i=0; i<4; i++) {
6059: suword(ub, *cp++);
6060: ub =+ 2;
6061: }
6062: brelse(bp);
6063: }
6064: /* --------------------------- */
6065:
6066: /*
6067: * the dup system call.
6068: */
6069: dup()
6070: {
6071: register i, *fp;
6072:
6073: fp = getf(u.u_ar0[R0]);
6074: if(fp == NULL)
6075: return;
6076: if ((i = ufalloc()) < 0)
6077: return;
6078: u.u_ofile[i] = fp;
6079: fp->f_count++;
6080: }
6081: /* --------------------------- */
6082:
6083: /*
6084: * the mount system call.
6085: */
6086: smount()
6087: {
6088: int d;
6089: register *ip;
6090: register struct mount *mp, *smp;
6091: extern uchar;
6092:
6093: d = getmdev();
6094: if(u.u_error)
6095: return;
6096: u.u_dirp = u.u_arg[1];
6097: ip = namei(&uchar, 0);
6098: if(ip == NULL)
6099: return;
6100: if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0)
6101: goto out;
6102: smp = NULL;
6103: for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
6104: if(mp->m_bufp != NULL) {
6105: if(d == mp->m_dev)
6106: goto out;
6107: } else
6108: if(smp == NULL)
6109: smp = mp;
6110: }
6111: if(smp == NULL)
6112: goto out;
6113: (*bdevsw[d.d_major].d_open)(d, !u.u_arg[2]);
6114: if(u.u_error)
6115: goto out;
6116: mp = bread(d, 1);
6117: if(u.u_error) {
6118: brelse(mp);
6119: goto out1;
6120: }
6121: smp->m_inodp = ip;
6122: smp->m_dev = d;
6123: smp->m_bufp = getblk(NODEV);
6124: bcopy(mp->b_addr, smp->m_bufp->b_addr, 256);
6125: smp = smp->m_bufp->b_addr;
6126: smp->s_ilock = 0;
6127: smp->s_flock = 0;
6128: smp->s_ronly = u.u_arg[2] & 1;
6129: brelse(mp);
6130: ip->i_flag =| IMOUNT;
6131: prele(ip);
6132: return;
6133:
6134: out:
6135: u.u_error = EBUSY;
6136: out1:
6137: iput(ip);
6138: }
6139: /* --------------------------- */
6140:
6141: /*
6142: * the umount system call.
6143: */
6144: sumount()
6145: {
6146: int d;
6147: register struct inode *ip;
6148: register struct mount *mp;
6149:
6150: update();
6151: d = getmdev();
6152: if(u.u_error)
6153: return;
6154: for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
6155: if(mp->m_bufp!=NULL && d==mp->m_dev)
6156: goto found;
6157: u.u_error = EINVAL;
6158: return;
6159:
6160: found:
6161: for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
6162: if(ip->i_number!=0 && d==ip->i_dev) {
6163: u.u_error = EBUSY;
6164: return;
6165: }
6166: (*bdevsw[d.d_major].d_close)(d, 0);
6167: ip = mp->m_inodp;
6168: ip->i_flag =& ~IMOUNT;
6169: iput(ip);
6170: ip = mp->m_bufp;
6171: mp->m_bufp = NULL;
6172: brelse(ip);
6173: }
6174: /* --------------------------- */
6175:
6176: /*
6177: * Common code for mount and umount.
6178: * Check that the user's argument is a reasonable
6179: * thing on which to mount, and return the device number if so.
6180: */
6181: getmdev()
6182: {
6183: register d, *ip;
6184: extern uchar;
6185:
6186: ip = namei(&uchar, 0);
6187: if(ip == NULL)
6188: return;
6189: if((ip->i_mode&IFMT) != IFBLK)
6190: u.u_error = ENOTBLK;
6191: d = ip->i_addr[0];
6192: if(ip->i_addr[0].d_major >= nblkdev)
6193: u.u_error = ENXIO;
6194: iput(ip);
6195: return(d);
6196: }
6197: /* --------------------------- */
6200: #
6201: /*
6202: */
6203:
6204: #include "../param.h"
6205: #include "../inode.h"
6206: #include "../user.h"
6207: #include "../buf.h"
6208: #include "../conf.h"
6209: #include "../systm.h"
6210:
6211: /*
6212: * Read the file corresponding to
6213: * the inode pointed at by the argument.
6214: * The actual read arguments are found
6215: * in the variables:
6216: * u_base core address for destination
6217: * u_offset byte offset in file
6218: * u_count number of bytes to read
6219: * u_segflg read to kernel/user
6220: */
6221: readi(aip)
6222: struct inode *aip;
6223: {
6224: int *bp;
6225: int lbn, bn, on;
6226: register dn, n;
6227: register struct inode *ip;
6228:
6229: ip = aip;
6230: if(u.u_count == 0)
6231: return;
6232: ip->i_flag =| IACC;
6233: if((ip->i_mode&IFMT) == IFCHR) {
6234: (*cdevsw[ip->i_addr[0].d_major].d_read)(ip->i_addr[0]);
6235: return;
6236: }
6237:
6238: do {
6239: lbn = bn = lshift(u.u_offset, -9);
6240: on = u.u_offset[1] & 0777;
6241: n = min(512-on, u.u_count);
6242: if((ip->i_mode&IFMT) != IFBLK) {
6243: dn = dpcmp(ip->i_size0&0377, ip->i_size1,
6244: u.u_offset[0], u.u_offset[1]);
6245: if(dn <= 0)
6246: return;
6247: n = min(n, dn);
6248: if ((bn = bmap(ip, lbn)) == 0)
6249: return;
6250: dn = ip->i_dev;
6251: } else {
6252: dn = ip->i_addr[0];
6253: rablock = bn+1;
6254: }
6255: if (ip->i_lastr+1 == lbn)
6256: bp = breada(dn, bn, rablock);
6257: else
6258: bp = bread(dn, bn);
6259: ip->i_lastr = lbn;
6260: iomove(bp, on, n, B_READ);
6261: brelse(bp);
6262: } while(u.u_error==0 && u.u_count!=0);
6263: }
6264: /* --------------------------- */
6265:
6266: /*
6267: * Write the file corresponding to
6268: * the inode pointed at by the argument.
6269: * The actual write arguments are found
6270: * in the variables:
6271: * u_base core address for source
6272: * u_offset byte offset in file
6273: * u_count number of bytes to write
6274: * u_segflg write to kernel/user
6275: */
6276: writei(aip)
6277: struct inode *aip;
6278: {
6279: int *bp;
6280: int n, on;
6281: register dn, bn;
6282: register struct inode *ip;
6283:
6284: ip = aip;
6285: ip->i_flag =| IACC|IUPD;
6286: if((ip->i_mode&IFMT) == IFCHR) {
6287: (*cdevsw[ip->i_addr[0].d_major].d_write)(ip->i_addr[0]);
6288: return;
6289: }
6290: if (u.u_count == 0)
6291: return;
6292:
6293: do {
6294: bn = lshift(u.u_offset, -9);
6295: on = u.u_offset[1] & 0777;
6296: n = min(512-on, u.u_count);
6297: if((ip->i_mode&IFMT) != IFBLK) {
6298: if ((bn = bmap(ip, bn)) == 0)
6299: return;
6300: dn = ip->i_dev;
6301: } else
6302: dn = ip->i_addr[0];
6303: if(n == 512)
6304: bp = getblk(dn, bn); else
6305: bp = bread(dn, bn);
6306: iomove(bp, on, n, B_WRITE);
6307: if(u.u_error != 0)
6308: brelse(bp); else
6309: if ((u.u_offset[1]&0777)==0)
6310: bawrite(bp); else
6311: bdwrite(bp);
6312: if(dpcmp(ip->i_size0&0377, ip->i_size1,
6313: u.u_offset[0], u.u_offset[1]) < 0 &&
6314: (ip->i_mode&(IFBLK&IFCHR)) == 0) {
6315: ip->i_size0 = u.u_offset[0];
6316: ip->i_size1 = u.u_offset[1];
6317: }
6318: ip->i_flag =| IUPD;
6319: } while(u.u_error==0 && u.u_count!=0);
6320: }
6321: /* --------------------------- */
6322:
6323: /* Return the logical maximum
6324: * of the 2 arguments.
6325: */
6326: max(a, b)
6327: char *a, *b;
6328: {
6329:
6330: if(a > b)
6331: return(a);
6332: return(b);
6333: }
6334: /* --------------------------- */
6335:
6336: /* Return the logical minimum
6337: * of the 2 arguments.
6338: */
6339: min(a, b)
6340: char *a, *b;
6341: {
6342:
6343: if(a < b)
6344: return(a);
6345: return(b);
6346: }
6347: /* --------------------------- */
6348:
6349:
6350: /* Move 'an' bytes at byte location
6351: * &bp->b_addr[o] to/from (flag) the
6352: * user/kernel (u.segflg) area starting at u.base.
6353: * Update all the arguments by the number
6354: * of bytes moved.
6355: *
6356: * There are 2 algorithms,
6357: * if source address, dest address and count
6358: * are all even in a user copy,
6359: * then the machine language copyin/copyout
6360: * is called.
6361: * If not, its done byte-by-byte with
6362: * cpass and passc.
6363: */
6364: iomove(bp, o, an, flag)
6365: struct buf *bp;
6366: {
6367: register char *cp;
6368: register int n, t;
6369:
6370: n = an;
6371: cp = bp->b_addr + o;
6372: if(u.u_segflg==0 && ((n | cp | u.u_base)&01)==0) {
6373: if (flag==B_WRITE)
6374: cp = copyin(u.u_base, cp, n);
6375: else
6376: cp = copyout(cp, u.u_base, n);
6377: if (cp) {
6378: u.u_error = EFAULT;
6379: return;
6380: }
6381: u.u_base =+ n;
6382: dpadd(u.u_offset, n);
6383: u.u_count =- n;
6384: return;
6385: }
6386: if (flag==B_WRITE) {
6387: while(n--) {
6388: if ((t = cpass()) < 0)
6389: return;
6390: *cp++ = t;
6391: }
6392: } else
6393: while (n--)
6394: if(passc(*cp++) < 0)
6395: return;
6396: }
6397: /* --------------------------- */
6400: #
6401: #include "../param.h"
6402: #include "../conf.h"
6403: #include "../inode.h"
6404: #include "../user.h"
6405: #include "../buf.h"
6406: #include "../systm.h"
6407:
6408: /* Bmap defines the structure of file system storage
6409: * by returning the physical block number on a device given the
6410: * inode and the logical block number in a file.
6411: * When convenient, it also leaves the physical
6412: * block number of the next block of the file in rablock
6413: * for use in read-ahead.
6414: */
6415: bmap(ip, bn)
6416: struct inode *ip;
6417: int bn;
6418: {
6419: register *bp, *bap, nb;
6420: int *nbp, d, i;
6421:
6422: d = ip->i_dev;
6423: if(bn & ~077777) {
6424: u.u_error = EFBIG;
6425: return(0);
6426: }
6427: if((ip->i_mode&ILARG) == 0) {
6428:
6429: /* small file algorithm */
6430:
6431: if((bn & ~7) != 0) {
6432:
6433: /* convert small to large */
6434:
6435: if ((bp = alloc(d)) == NULL)
6436: return(NULL);
6437: bap = bp->b_addr;
6438: for(i=0; i<8; i++) {
6439: *bap++ = ip->i_addr[i];
6440: ip->i_addr[i] = 0;
6441: }
6442: ip->i_addr[0] = bp->b_blkno;
6443: bdwrite(bp);
6444: ip->i_mode =| ILARG;
6445: goto large;
6446: }
6447: nb = ip->i_addr[bn];
6448: if(nb == 0 && (bp = alloc(d)) != NULL) {
6449: bdwrite(bp);
6450: nb = bp->b_blkno;
6451: ip->i_addr[bn] = nb;
6452: ip->i_flag =| IUPD;
6453: }
6454: rablock = 0;
6455: if (bn<7)
6456: rablock = ip->i_addr[bn+1];
6457: return(nb);
6458: }
6459:
6460: /* large file algorithm */
6461:
6462: large:
6463: i = bn>>8;
6464: if(bn & 0174000)
6465: i = 7;
6466: if((nb=ip->i_addr[i]) == 0) {
6467: ip->i_flag =| IUPD;
6468: if ((bp = alloc(d)) == NULL)
6469: return(NULL);
6470: ip->i_addr[i] = bp->b_blkno;
6471: } else
6472: bp = bread(d, nb);
6473: bap = bp->b_addr;
6474:
6475: /* "huge" fetch of double indirect block */
6476:
6477: if(i == 7) {
6478: i = ((bn>>8) & 0377) - 7;
6479: if((nb=bap[i]) == 0) {
6480: if((nbp = alloc(d)) == NULL) {
6481: brelse(bp);
6482: return(NULL);
6483: }
6484: bap[i] = nbp->b_blkno;
6485: bdwrite(bp);
6486: } else {
6487: brelse(bp);
6488: nbp = bread(d, nb);
6489: }
6490: bp = nbp;
6491: bap = bp->b_addr;
6492: }
6493:
6494: /* normal indirect fetch */
6495:
6496: i = bn & 0377;
6497: if((nb=bap[i]) == 0 && (nbp = alloc(d)) != NULL) {
6498: nb = nbp->b_blkno;
6499: bap[i] = nb;
6500: bdwrite(nbp);
6501: bdwrite(bp);
6502: } else
6503: brelse(bp);
6504: rablock = 0;
6505: if(i < 255)
6506: rablock = bap[i+1];
6507: return(nb);
6508: }
6509: /* --------------------------- */
6510:
6511: /*
6512: * Pass back c to the user at his location u_base;
6513: * update u_base, u_count, and u_offset. Return -1
6514: * on the last character of the user's read.
6515: * u_base is in the user address space unless u_segflg is set.
6516: */
6517: passc(c)
6518: char c;
6519: {
6520:
6521: if(u.u_segflg)
6522: *u.u_base = c; else
6523: if(subyte(u.u_base, c) < 0) {
6524: u.u_error = EFAULT;
6525: return(-1);
6526: }
6527: u.u_count--;
6528: if(++u.u_offset[1] == 0)
6529: u.u_offset[0]++;
6530: u.u_base++;
6531: return(u.u_count == 0? -1: 0);
6532: }
6533: /* --------------------------- */
6534:
6535: /*
6536: * Pick up and return the next character from the user's
6537: * write call at location u_base;
6538: * update u_base, u_count, and u_offset. Return -1
6539: * when u_count is exhausted. u_base is in the user's
6540: * address space unless u_segflg is set.
6541: */
6542: cpass()
6543: {
6544: register c;
6545:
6546: if(u.u_count == 0)
6547: return(-1);
6548: if(u.u_segflg)
6549: c = *u.u_base; else
6550: if((c=fubyte(u.u_base)) < 0) {
6551: u.u_error = EFAULT;
6552: return(-1);
6553: }
6554: u.u_count--;
6555: if(++u.u_offset[1] == 0)
6556: u.u_offset[0]++;
6557: u.u_base++;
6558: return(c&0377);
6559: }
6560: /* --------------------------- */
6561:
6562: /*
6563: * Routine which sets a user error; placed in
6564: * illegal entries in the bdevsw and cdevsw tables.
6565: */
6566: nodev()
6567: {
6568:
6569: u.u_error = ENODEV;
6570: }
6571: /* --------------------------- */
6572:
6573: /*
6574: * Null routine; placed in insignificant entries
6575: * in the bdevsw and cdevsw tables.
6576: */
6577: nulldev()
6578: {
6579: }
6580: /* --------------------------- */
6581:
6582: /*
6583: * copy count words from from to to.
6584: */
6585: bcopy(from, to, count)
6586: int *from, *to;
6587: {
6588: register *a, *b, c;
6589:
6590: a = from;
6591: b = to;
6592: c = count;
6593: do
6594: *b++ = *a++;
6595: while(--c);
6596: }
6597: /* --------------------------- */
6600: #
6601: /*
6602: */
6603:
6604: #include "../param.h"
6605: #include "../user.h"
6606: #include "../filsys.h"
6607: #include "../file.h"
6608: #include "../conf.h"
6609: #include "../inode.h"
6610: #include "../reg.h"
6611:
6612: /*
6613: * Convert a user supplied
6614: * file descriptor into a pointer
6615: * to a file structure.
6616: * Only task is to check range
6617: * of the descriptor.
6618: */
6619: getf(f)
6620: {
6621: register *fp, rf;
6622:
6623: rf = f;
6624: if(rf<0 || rf>=NOFILE)
6625: goto bad;
6626: fp = u.u_ofile[rf];
6627: if(fp != NULL)
6628: return(fp);
6629: bad:
6630: u.u_error = EBADF;
6631: return(NULL);
6632: }
6633: /* --------------------------- */
6634:
6635: /*
6636: * Internal form of close.
6637: * Decrement reference count on
6638: * file structure and call closei
6639: * on last closef.
6640: * Also make sure the pipe protocol
6641: * does not constipate.
6642: */
6643: closef(fp)
6644: int *fp;
6645: {
6646: register *rfp, *ip;
6647:
6648: rfp = fp;
6649: if(rfp->f_flag&FPIPE) {
6650: ip = rfp->f_inode;
6651: ip->i_mode =& ~(IREAD|IWRITE);
6652: wakeup(ip+1);
6653: wakeup(ip+2);
6654: }
6655: if(rfp->f_count <= 1)
6656: closei(rfp->f_inode, rfp->f_flag&FWRITE);
6657: rfp->f_count--;
6658: }
6659: /* --------------------------- */
6660:
6661: /*
6662: * Decrement reference count on an
6663: * inode due to the removal of a
6664: * referencing file structure.
6665: * On the last closei, switchout
6666: * to the close entry point of special
6667: * device handler.
6668: * Note that the handler gets called
6669: * on every open and only on the last
6670: * close.
6671: */
6672: closei(ip, rw)
6673: int *ip;
6674: {
6675: register *rip;
6676: register dev, maj;
6677:
6678: rip = ip;
6679: dev = rip->i_addr[0];
6680: maj = rip->i_addr[0].d_major;
6681: if(rip->i_count <= 1)
6682: switch(rip->i_mode&IFMT) {
6683:
6684: case IFCHR:
6685: (*cdevsw[maj].d_close)(dev, rw);
6686: break;
6687:
6688: case IFBLK:
6689: (*bdevsw[maj].d_close)(dev, rw);
6690: }
6691: iput(rip);
6692: }
6693: /* --------------------------- */
6694:
6695: /*
6696: * openi called to allow handler
6697: * of special files to initialize and
6698: * validate before actual IO.
6699: * Called on all sorts of opens
6700: * and also on mount.
6701: */
6702: openi(ip, rw)
6703: int *ip;
6704: {
6705: register *rip;
6706: register dev, maj;
6707:
6708: rip = ip;
6709: dev = rip->i_addr[0];
6710: maj = rip->i_addr[0].d_major;
6711: switch(rip->i_mode&IFMT) {
6712:
6713: case IFCHR:
6714: if(maj >= nchrdev)
6715: goto bad;
6716: (*cdevsw[maj].d_open)(dev, rw);
6717: break;
6718:
6719: case IFBLK:
6720: if(maj >= nblkdev)
6721: goto bad;
6722: (*bdevsw[maj].d_open)(dev, rw);
6723: }
6724: return;
6725:
6726: bad:
6727: u.u_error = ENXIO;
6728: }
6729: /* --------------------------- */
6730:
6731: /*
6732: * Check mode permission on inode pointer.
6733: * Mode is READ, WRITE or EXEC.
6734: * In the case of WRITE, the
6735: * read-only status of the file
6736: * system is checked.
6737: * Also in WRITE, prototype text
6738: * segments cannot be written.
6739: * The mode is shifted to select
6740: * the owner/group/other fields.
6741: * The super user is granted all
6742: * permissions except for EXEC where
6743: * at least one of the EXEC bits must
6744: * be on.
6745: */
6746: access(aip, mode)
6747: int *aip;
6748: {
6749: register *ip, m;
6750:
6751: ip = aip;
6752: m = mode;
6753: if(m == IWRITE) {
6754: if(getfs(ip->i_dev)->s_ronly != 0) {
6755: u.u_error = EROFS;
6756: return(1);
6757: }
6758: if(ip->i_flag & ITEXT) {
6759: u.u_error = ETXTBSY;
6760: return(1);
6761: }
6762: }
6763: if(u.u_uid == 0) {
6764: if(m == IEXEC && (ip->i_mode &
6765: (IEXEC | (IEXEC>>3) | (IEXEC>>6))) == 0)
6766: goto bad;
6767: return(0);
6768: }
6769: if(u.u_uid != ip->i_uid) {
6770: m =>> 3;
6771: if(u.u_gid != ip->i_gid)
6772: m =>> 3;
6773: }
6774: if((ip->i_mode&m) != 0)
6775: return(0);
6776:
6777: bad:
6778: u.u_error = EACCES;
6779: return(1);
6780: }
6781: /* --------------------------- */
6782:
6783: /*
6784: * Look up a pathname and test if
6785: * the resultant inode is owned by the
6786: * current user.
6787: * If not, try for super-user.
6788: * If permission is granted,
6789: * return inode pointer.
6790: */
6791: owner()
6792: {
6793: register struct inode *ip;
6794: extern uchar();
6795:
6796: if ((ip = namei(uchar, 0)) == NULL)
6797: return(NULL);
6798: if(u.u_uid == ip->i_uid)
6799: return(ip);
6800: if (suser())
6801: return(ip);
6802: iput(ip);
6803: return(NULL);
6804: }
6805: /* --------------------------- */
6806:
6807: /*
6808: * Test if the current user is the
6809: * super user.
6810: */
6811: suser()
6812: {
6813:
6814: if(u.u_uid == 0)
6815: return(1);
6816: u.u_error = EPERM;
6817: return(0);
6818: }
6819: /* --------------------------- */
6820:
6821: /*
6822: * Allocate a user file descriptor.
6823: */
6824: ufalloc()
6825: {
6826: register i;
6827:
6828: for (i=0; i<NOFILE; i++)
6829: if (u.u_ofile[i] == NULL) {
6830: u.u_ar0[R0] = i;
6831: return(i);
6832: }
6833: u.u_error = EMFILE;
6834: return(-1);
6835: }
6836: /* --------------------------- */
6837:
6838: /*
6839: * Allocate a user file descriptor
6840: * and a file structure.
6841: * Initialize the descriptor
6842: * to point at the file structure.
6843: *
6844: * no file -- if there are no available
6845: * file structures.
6846: */
6847: falloc()
6848: {
6849: register struct file *fp;
6850: register i;
6851:
6852: if ((i = ufalloc()) < 0)
6853: return(NULL);
6854: for (fp = &file[0]; fp < &file[NFILE]; fp++)
6855: if (fp->f_count==0) {
6856: u.u_ofile[i] = fp;
6857: fp->f_count++;
6858: fp->f_offset[0] = 0;
6859: fp->f_offset[1] = 0;
6860: return(fp);
6861: }
6862: printf("no file\n");
6863: u.u_error = ENFILE;
6864: return(NULL);
6865: }
6866: /* --------------------------- */
6900: #
6901: /*
6902: */
6903:
6904: #include "../param.h"
6905: #include "../systm.h"
6906: #include "../filsys.h"
6907: #include "../conf.h"
6908: #include "../buf.h"
6909: #include "../inode.h"
6910: #include "../user.h"
6911:
6912: /*
6913: * iinit is called once (from main)
6914: * very early in initialization.
6915: * It reads the root's super block
6916: * and initializes the current date
6917: * from the last modified date.
6918: *
6919: * panic: iinit -- cannot read the super
6920: * block. Usually because of an IO error.
6921: */
6922: iinit()
6923: {
6924: register *cp, *bp;
6925:
6926: (*bdevsw[rootdev.d_major].d_open)(rootdev, 1);
6927: bp = bread(rootdev, 1);
6928: cp = getblk(NODEV);
6929: if(u.u_error)
6930: panic("iinit");
6931: bcopy(bp->b_addr, cp->b_addr, 256);
6932: brelse(bp);
6933: mount[0].m_bufp = cp;
6934: mount[0].m_dev = rootdev;
6935: cp = cp->b_addr;
6936: cp->s_flock = 0;
6937: cp->s_ilock = 0;
6938: cp->s_ronly = 0;
6939: time[0] = cp->s_time[0];
6940: time[1] = cp->s_time[1];
6941: }
6942: /* --------------------------- */
6943: /* --------------------------- */
6944:
6945: /*
6946: * alloc will obtain the next available
6947: * free disk block from the free list of
6948: * the specified device.
6949: * The super block has up to 100 remembered
6950: * free blocks; the last of these is read to
6951: * obtain 100 more . . .
6952: *
6953: * no space on dev x/y -- when
6954: * the free list is exhausted.
6955: */
6956: alloc(dev)
6957: {
6958: int bno;
6959: register *bp, *ip, *fp;
6960:
6961: fp = getfs(dev);
6962: while(fp->s_flock)
6963: sleep(&fp->s_flock, PINOD);
6964: do {
6965: if(fp->s_nfree <= 0)
6966: goto nospace;
6967: bno = fp->s_free[--fp->s_nfree];
6968: if(bno == 0)
6969: goto nospace;
6970: } while (badblock(fp, bno, dev));
6971: if(fp->s_nfree <= 0) {
6972: fp->s_flock++;
6973: bp = bread(dev, bno);
6974: ip = bp->b_addr;
6975: fp->s_nfree = *ip++;
6976: bcopy(ip, fp->s_free, 100);
6977: brelse(bp);
6978: fp->s_flock = 0;
6979: wakeup(&fp->s_flock);
6980: }
6981: bp = getblk(dev, bno);
6982: clrbuf(bp);
6983: fp->s_fmod = 1;
6984: return(bp);
6985:
6986: nospace:
6987: fp->s_nfree = 0;
6988: prdev("no space", dev);
6989: u.u_error = ENOSPC;
6990: return(NULL);
6991: }
6992: /* --------------------------- */
6993: /* --------------------------- */
6994:
6995: /*
6996: * place the specified disk block
6997: * back on the free list of the
6998: * specified device.
6999: */
7000: free(dev, bno)
7001: {
7002: register *fp, *bp, *ip;
7003:
7004: fp = getfs(dev);
7005: fp->s_fmod = 1;
7006: while(fp->s_flock)
7007: sleep(&fp->s_flock, PINOD);
7008: if (badblock(fp, bno, dev))
7009: return;
7010: if(fp->s_nfree <= 0) {
7011: fp->s_nfree = 1;
7012: fp->s_free[0] = 0;
7013: }
7014: if(fp->s_nfree >= 100) {
7015: fp->s_flock++;
7016: bp = getblk(dev, bno);
7017: ip = bp->b_addr;
7018: *ip++ = fp->s_nfree;
7019: bcopy(fp->s_free, ip, 100);
7020: fp->s_nfree = 0;
7021: bwrite(bp);
7022: fp->s_flock = 0;
7023: wakeup(&fp->s_flock);
7024: }
7025: fp->s_free[fp->s_nfree++] = bno;
7026: fp->s_fmod = 1;
7027: }
7028: /* --------------------------- */
7029: /* --------------------------- */
7030:
7031: /*
7032: * Check that a block number is in the
7033: * range between the I list and the size
7034: * of the device.
7035: * This is used mainly to check that a
7036: * garbage file system has not been mounted.
7037: *
7038: * bad block on dev x/y -- not in range
7039: */
7040: badblock(afp, abn, dev)
7041: {
7042: register struct filsys *fp;
7043: register char *bn;
7044:
7045: fp = afp;
7046: bn = abn;
7047: if (bn < fp->s_isize+2 || bn >= fp->s_fsize) {
7048: prdev("bad block", dev);
7049: return(1);
7050: }
7051: return(0);
7052: }
7053: /* --------------------------- */
7054: /* --------------------------- */
7055:
7056: /*
7057: * Allocate an unused I node
7058: * on the specified device.
7059: * Used with file creation.
7060: * The algorithm keeps up to
7061: * 100 spare I nodes in the
7062: * super block. When this runs out,
7063: * a linear search through the
7064: * I list is instituted to pick
7065: * up 100 more.
7066: */
7067: ialloc(dev)
7068: {
7069: register *fp, *bp, *ip;
7070: int i, j, k, ino;
7071:
7072: fp = getfs(dev);
7073: while(fp->s_ilock)
7074: sleep(&fp->s_ilock, PINOD);
7075: loop:
7076: if(fp->s_ninode > 0) {
7077: ino = fp->s_inode[--fp->s_ninode];
7078: ip = iget(dev, ino);
7079: if (ip==NULL)
7080: return(NULL);
7081: if(ip->i_mode == 0) {
7082: for(bp = &ip->i_mode; bp < &ip->i_addr[8];)
7083: *bp++ = 0;
7084: fp->s_fmod = 1;
7085: return(ip);
7086: }
7087: /*
7088: * Inode was allocated after all.
7089: * Look some more.
7090: */
7091: iput(ip);
7092: goto loop;
7093: }
7094: fp->s_ilock++;
7095: ino = 0;
7096: for(i=0; i<fp->s_isize; i++) {
7097: bp = bread(dev, i+2);
7098: ip = bp->b_addr;
7099: for(j=0; j<256; j=+16) {
7100: ino++;
7101: if(ip[j] != 0)
7102: continue;
7103: for(k=0; k<NINODE; k++)
7104:
7105: if(dev==inode[k].i_dev && ino==inode[k].i_number)
7106: goto cont;
7107: fp->s_inode[fp->s_ninode++] = ino;
7108: if(fp->s_ninode >= 100)
7109: break;
7110: cont:;
7111: }
7112: brelse(bp);
7113: if(fp->s_ninode >= 100)
7114: break;
7115: }
7116: fp->s_ilock = 0;
7117: wakeup(&fp->s_ilock);
7118: if (fp->s_ninode > 0)
7119: goto loop;
7120: prdev("Out of inodes", dev);
7121: u.u_error = ENOSPC;
7122: return(NULL);
7123: }
7124: /* --------------------------- */
7125: /* --------------------------- */
7126:
7127: /*
7128: * Free the specified I node
7129: * on the specified device.
7130: * The algorithm stores up
7131: * to 100 I nodes in the super
7132: * block and throws away any more.
7133: */
7134: ifree(dev, ino)
7135: {
7136: register *fp;
7137:
7138: fp = getfs(dev);
7139: if(fp->s_ilock)
7140: return;
7141: if(fp->s_ninode >= 100)
7142: return;
7143: fp->s_inode[fp->s_ninode++] = ino;
7144: fp->s_fmod = 1;
7145: }
7146: /* --------------------------- */
7147: /* --------------------------- */
7148:
7149: /*
7150: * getfs maps a device number into
7151: * a pointer to the incore super
7152: * block.
7153: * The algorithm is a linear
7154: * search through the mount table.
7155: * A consistency check of the
7156: * in core free-block and i-node
7157: * counts.
7158: *
7159: * bad count on dev x/y -- the count
7160: * check failed. At this point, all
7161: * the counts are zeroed which will
7162: * almost certainly lead to "no space"
7163: * diagnostic
7164: * panic: no fs -- the device is not mounted.
7165: * this "cannot happen"
7166: */
7167: getfs(dev)
7168: {
7169: register struct mount *p;
7170: register char *n1, *n2;
7171:
7172: for(p = &mount[0]; p < &mount[NMOUNT]; p++)
7173: if(p->m_bufp != NULL && p->m_dev == dev) {
7174: p = p->m_bufp->b_addr;
7175: n1 = p->s_nfree;
7176: n2 = p->s_ninode;
7177: if(n1 > 100 || n2 > 100) {
7178: prdev("bad count", dev);
7179: p->s_nfree = 0;
7180: p->s_ninode = 0;
7181: }
7182: return(p);
7183: }
7184: panic("no fs");
7185: }
7186: /* --------------------------- */
7187: /* --------------------------- */
7188:
7189: /*
7190: * update is the internal name of
7191: * 'sync'. It goes through the disk
7192: * queues to initiate sandbagged IO;
7193: * goes through the I nodes to write
7194: * modified nodes; and it goes through
7195: * the mount table to initiate modified
7196: * super blocks.
7197: */
7198:
7199:
7200:
7201: update()
7202: {
7203: register struct inode *ip;
7204: register struct mount *mp;
7205: register *bp;
7206:
7207: if(updlock)
7208: return;
7209: updlock++;
7210: for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
7211: if(mp->m_bufp != NULL) {
7212: ip = mp->m_bufp->b_addr;
7213: if(ip->s_fmod==0 || ip->s_ilock!=0 ||
7214: ip->s_flock!=0 || ip->s_ronly!=0)
7215: continue;
7216: bp = getblk(mp->m_dev, 1);
7217: ip->s_fmod = 0;
7218: ip->s_time[0] = time[0];
7219: ip->s_time[1] = time[1];
7220: bcopy(ip, bp->b_addr, 256);
7221: bwrite(bp);
7222: }
7223: for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
7224: if((ip->i_flag&ILOCK) == 0) {
7225: ip->i_flag =| ILOCK;
7226: iupdat(ip, time);
7227: prele(ip);
7228: }
7229: updlock = 0;
7230: bflush(NODEV);
7231: }
7232: /* --------------------------- */
7233: /* --------------------------- */
7250: #
7251: #include "../param.h"
7252: #include "../systm.h"
7253: #include "../user.h"
7254: #include "../inode.h"
7255: #include "../filsys.h"
7256: #include "../conf.h"
7257: #include "../buf.h"
7258:
7259: /*
7260: * Look up an inode by device,inumber.
7261: * If it is in core (in the inode structure),
7262: * honor the locking protocol.
7263: * If it is not in core, read it in from the
7264: * specified device.
7265: * If the inode is mounted on, perform
7266: * the indicated indirection.
7267: * In all cases, a pointer to a locked
7268: * inode structure is returned.
7269: *
7270: * printf warning: no inodes -- if the inode
7271: * structure is full
7272: * panic: no imt -- if the mounted file
7273: * system is not in the mount table.
7274: * "cannot happen"
7275: */
7276: iget(dev, ino)
7277: {
7278: register struct inode *p;
7279: register *ip2;
7280: int *ip1;
7281: register struct mount *ip;
7282:
7283: loop:
7284: ip = NULL;
7285: for(p = &inode[0]; p < &inode[NINODE]; p++) {
7286: if(dev==p->i_dev && ino==p->i_number) {
7287: if((p->i_flag&ILOCK) != 0) {
7288: p->i_flag =| IWANT;
7289: sleep(p, PINOD);
7290: goto loop;
7291: }
7292: if((p->i_flag&IMOUNT) != 0) {
7293:
7294: for(ip = &mount[0]; ip < &mount[NMOUNT]; ip++)
7295: if(ip->m_inodp == p) {
7296: dev = ip->m_dev;
7297: ino = ROOTINO;
7298: goto loop;
7299: }
7300: panic("no imt");
7301: }
7302: p->i_count++;
7303: p->i_flag =| ILOCK;
7304: return(p);
7305: }
7306: if(ip==NULL && p->i_count==0)
7307: ip = p;
7308: }
7309: if((p=ip) == NULL) {
7310: printf("Inode table overflow\n");
7311: u.u_error = ENFILE;
7312: return(NULL);
7313: }
7314: p->i_dev = dev;
7315: p->i_number = ino;
7316: p->i_flag = ILOCK;
7317: p->i_count++;
7318: p->i_lastr = -1;
7319: ip = bread(dev, ldiv(ino+31,16));
7320: /*
7321: * Check I/O errors
7322: */
7323: if (ip->b_flags&B_ERROR) {
7324: brelse(ip);
7325: iput(p);
7326: return(NULL);
7327: }
7328: ip1 = ip->b_addr + 32*lrem(ino+31, 16);
7329: ip2 = &p->i_mode;
7330: while(ip2 < &p->i_addr[8])
7331: *ip2++ = *ip1++;
7332: brelse(ip);
7333: return(p);
7334: }
7335: /* --------------------------- */
7336:
7337: /*
7338: * Decrement reference count of
7339: * an inode structure.
7340: * On the last reference,
7341: * write the inode out and if necessary,
7342: * truncate and deallocate the file.
7343: */
7344: iput(p)
7345: struct inode *p;
7346: {
7347: register *rp;
7348:
7349: rp = p;
7350: if(rp->i_count == 1) {
7351: rp->i_flag =| ILOCK;
7352: if(rp->i_nlink <= 0) {
7353: itrunc(rp);
7354: rp->i_mode = 0;
7355: ifree(rp->i_dev, rp->i_number);
7356: }
7357: iupdat(rp, time);
7358: prele(rp);
7359: rp->i_flag = 0;
7360: rp->i_number = 0;
7361: }
7362: rp->i_count--;
7363: prele(rp);
7364: }
7365: /* --------------------------- */
7366:
7367: /*
7368: * Check accessed and update flags on
7369: * an inode structure.
7370: * If either is on, update the inode
7371: * with the corresponding dates
7372: * set to the argument tm.
7373: */
7374: iupdat(p, tm)
7375: int *p;
7376: int *tm;
7377: {
7378: register *ip1, *ip2, *rp;
7379: int *bp, i;
7380:
7381: rp = p;
7382: if((rp->i_flag&(IUPD|IACC)) != 0) {
7383: if(getfs(rp->i_dev)->s_ronly)
7384: return;
7385: i = rp->i_number+31;
7386: bp = bread(rp->i_dev, ldiv(i,16));
7387: ip1 = bp->b_addr + 32*lrem(i, 16);
7388: ip2 = &rp->i_mode;
7389: while(ip2 < &rp->i_addr[8])
7390: *ip1++ = *ip2++;
7391: if(rp->i_flag&IACC) {
7392: *ip1++ = time[0];
7393: *ip1++ = time[1];
7394: } else
7395: ip1 =+ 2;
7396: if(rp->i_flag&IUPD) {
7397: *ip1++ = *tm++;
7398: *ip1++ = *tm;
7399: }
7400: bwrite(bp);
7401: }
7402: }
7403: /* --------------------------- */
7404:
7405: /*
7406: * Free all the disk blocks associated
7407: * with the specified inode structure.
7408: * The blocks of the file are removed
7409: * in reverse order. This FILO
7410: * algorithm will tend to maintain
7411: * a contiguous free list much longer
7412: * than FIFO.
7413: */
7414: itrunc(ip)
7415: int *ip;
7416: {
7417: register *rp, *bp, *cp;
7418: int *dp, *ep;
7419:
7420: rp = ip;
7421: if((rp->i_mode&(IFCHR&IFBLK)) != 0)
7422: return;
7423: for(ip = &rp->i_addr[7]; ip >= &rp->i_addr[0]; ip--)
7424: if(*ip) {
7425: if((rp->i_mode&ILARG) != 0) {
7426: bp = bread(rp->i_dev, *ip);
7427:
7428: for(cp = bp->b_addr+512; cp >= bp->b_addr; cp--)
7429: if(*cp) {
7430: if(ip == &rp->i_addr[7]) {
7431: dp = bread(rp->i_dev, *cp);
7432:
7433: for(ep = dp->b_addr+512; ep >= dp->b_addr; ep--)
7434: if(*ep)
7435: free(rp->i_dev, *ep);
7436: brelse(dp);
7437: }
7438: free(rp->i_dev, *cp);
7439: }
7440: brelse(bp);
7441: }
7442: free(rp->i_dev, *ip);
7443: *ip = 0;
7444: }
7445: rp->i_mode =& ~ILARG;
7446: rp->i_size0 = 0;
7447: rp->i_size1 = 0;
7448: rp->i_flag =| IUPD;
7449: }
7450: /* --------------------------- */
7451:
7452: /*
7453: * Make a new file.
7454: */
7455: maknode(mode)
7456: {
7457: register *ip;
7458:
7459: ip = ialloc(u.u_pdir->i_dev);
7460: if (ip==NULL)
7461: return(NULL);
7462: ip->i_flag =| IACC|IUPD;
7463: ip->i_mode = mode|IALLOC;
7464: ip->i_nlink = 1;
7465: ip->i_uid = u.u_uid;
7466: ip->i_gid = u.u_gid;
7467: wdir(ip);
7468: return(ip);
7469: }
7470: /* --------------------------- */
7471:
7472: /*
7473: * Write a directory entry with
7474: * parameters left as side effects
7475: * to a call to namei.
7476: */
7477: wdir(ip)
7478: int *ip;
7479: {
7480: register char *cp1, *cp2;
7481:
7482: u.u_dent.u_ino = ip->i_number;
7483: cp1 = &u.u_dent.u_name[0];
7484: for(cp2 = &u.u_dbuf[0]; cp2 < &u.u_dbuf[DIRSIZ];)
7485: *cp1++ = *cp2++;
7486: u.u_count = DIRSIZ+2;
7487: u.u_segflg = 1;
7488: u.u_base = &u.u_dent;
7489: writei(u.u_pdir);
7490: iput(u.u_pdir);
7491: }
7492: /* --------------------------- */
7500: #
7501: #include "../param.h"
7502: #include "../inode.h"
7503: #include "../user.h"
7504: #include "../systm.h"
7505: #include "../buf.h"
7506:
7507: /*
7508: * Convert a pathname into a pointer to
7509: * an inode. Note that the inode is locked.
7510: *
7511: * func = function called to get next char of name
7512: * &uchar if name is in user space
7513: * &schar if name is in system space
7514: * flag = 0 if name is sought
7515: * 1 if name is to be created
7516: * 2 if name is to be deleted
7517: */
7518: namei(func, flag)
7519: int (*func)();
7520: {
7521: register struct inode *dp;
7522: register c;
7523: register char *cp;
7524: int eo, *bp;
7525:
7526: /*
7527: * If name starts with '/' start from
7528: * root; otherwise start from current dir.
7529: */
7530:
7531: dp = u.u_cdir;
7532: if((c=(*func)()) == '/')
7533: dp = rootdir;
7534: iget(dp->i_dev, dp->i_number);
7535: while(c == '/')
7536: c = (*func)();
7537: if(c == '\0' && flag != 0) {
7538: u.u_error = ENOENT;
7539: goto out;
7540: }
7541:
7542: cloop:
7543: /*
7544: * Here dp contains pointer
7545: * to last component matched.
7546: */
7547:
7548: if(u.u_error)
7549: goto out;
7550: if(c == '\0')
7551: return(dp);
7552:
7553: /*
7554: * If there is another component,
7555: * dp must be a directory and
7556: * must have x permission.
7557: */
7558:
7559: if((dp->i_mode&IFMT) != IFDIR) {
7560: u.u_error = ENOTDIR;
7561: goto out;
7562: }
7563: if(access(dp, IEXEC))
7564: goto out;
7565:
7566: /* Gather up name into
7567: * users' dir buffer.
7568: */
7569:
7570: cp = &u.u_dbuf[0];
7571: while(c!='/' && c!='\0' && u.u_error==0) {
7572: if(cp < &u.u_dbuf[DIRSIZ])
7573: *cp++ = c;
7574: c = (*func)();
7575: }
7576: while(cp < &u.u_dbuf[DIRSIZ])
7577: *cp++ = '\0';
7578: while(c == '/')
7579: c = (*func)();
7580: if(u.u_error)
7581: goto out;
7582:
7583: /* Set up to search a directory. */
7584:
7585: u.u_offset[1] = 0;
7586: u.u_offset[0] = 0;
7587: u.u_segflg = 1;
7588: eo = 0;
7589: u.u_count = ldiv(dp->i_size1, DIRSIZ+2);
7590: bp = NULL;
7591:
7592: eloop:
7593:
7594: /*
7595: * If at the end of the directory,
7596: * the search failed. Report what
7597: * is appropriate as per flag.
7598: */
7599:
7600: if(u.u_count == 0) {
7601: if(bp != NULL)
7602: brelse(bp);
7603: if(flag==1 && c=='\0') {
7604: if(access(dp, IWRITE))
7605: goto out;
7606: u.u_pdir = dp;
7607: if(eo)
7608: u.u_offset[1] = eo-DIRSIZ-2; else
7609: dp->i_flag =| IUPD;
7610: return(NULL);
7611: }
7612: u.u_error = ENOENT;
7613: goto out;
7614: }
7615:
7616: /*
7617: * If offset is on a block boundary,
7618: * read the next directory block.
7619: * Release previous if it exists.
7620: */
7621:
7622: if((u.u_offset[1]&0777) == 0) {
7623: if(bp != NULL)
7624: brelse(bp);
7625: bp = bread(dp->i_dev,
7626: bmap(dp, ldiv(u.u_offset[1], 512)));
7627: }
7628:
7629: /* Note first empty directory slot
7630: * in eo for possible creat.
7631: * String compare the directory entry
7632: * and the current component.
7633: * If they do not match, go back to eloop.
7634: */
7635:
7636: bcopy(bp->b_addr+(u.u_offset[1]&0777), &u.u_dent, (DIRSIZ+2)/2);
7637:
7638: u.u_offset[1] =+ DIRSIZ+2;
7639: u.u_count--;
7640: if(u.u_dent.u_ino == 0) {
7641: if(eo == 0)
7642: eo = u.u_offset[1];
7643: goto eloop;
7644: }
7645: for(cp = &u.u_dbuf[0]; cp < &u.u_dbuf[DIRSIZ]; cp++)
7646: if(*cp != cp[u.u_dent.u_name - u.u_dbuf])
7647: goto eloop;
7648:
7649:
7650: /* Here a component matched in a directory.
7651: * If there is more pathname, go back to
7652: * cloop, otherwise return.
7653: */
7654:
7655: if(bp != NULL)
7656: brelse(bp);
7657: if(flag==2 && c=='\0') {
7658: if(access(dp, IWRITE))
7659: goto out;
7660: return(dp);
7661: }
7662: bp = dp->i_dev;
7663: iput(dp);
7664: dp = iget(bp, u.u_dent.u_ino);
7665: if(dp == NULL)
7666: return(NULL);
7667: goto cloop;
7668:
7669: out:
7670: iput(dp);
7671: return(NULL);
7672: }
7673: /* --------------------------- */
7674:
7675: /*
7676: * Return the next character from the
7677: * kernel string pointed at by dirp.
7678: */
7679: schar()
7680: {
7681:
7682: return(*u.u_dirp++ & 0377);
7683: }
7684: /* --------------------------- */
7685:
7686: /* Return the next character from the
7687: * user string pointed at by dirp.
7688: */
7689: uchar()
7690: {
7691: register c;
7692:
7693: c = fubyte(u.u_dirp++);
7694: if(c == -1)
7695: u.u_error = EFAULT;
7696: return(c);
7697: }
7698: /* --------------------------- */
7700: #include "../param.h"
7701: #include "../systm.h"
7702: #include "../user.h"
7703: #include "../inode.h"
7704: #include "../file.h"
7705: #include "../reg.h"
7706:
7707: /*
7708: * Max allowable buffering per pipe.
7709: * This is also the max size of the
7710: * file created to implement the pipe.
7711: * If this size is bigger than 4096,
7712: * pipes will be implemented in LARG
7713: * files, which is probably not good.
7714: */
7715: #define PIPSIZ 4096
7716:
7717: /*
7718: * The sys-pipe entry.
7719: * Allocate an inode on the root device.
7720: * Allocate 2 file structures.
7721: * Put it all together with flags.
7722: */
7723: pipe()
7724: {
7725: register *ip, *rf, *wf;
7726: int r;
7727:
7728: ip = ialloc(rootdev);
7729: if(ip == NULL)
7730: return;
7731: rf = falloc();
7732: if(rf == NULL) {
7733: iput(ip);
7734: return;
7735: }
7736: r = u.u_ar0[R0];
7737: wf = falloc();
7738: if(wf == NULL) {
7739: rf->f_count = 0;
7740: u.u_ofile[r] = NULL;
7741: iput(ip);
7742: return;
7743: }
7744: u.u_ar0[R1] = u.u_ar0[R0];
7745: u.u_ar0[R0] = r;
7746: wf->f_flag = FWRITE|FPIPE;
7747: wf->f_inode = ip;
7748: rf->f_flag = FREAD|FPIPE;
7749: rf->f_inode = ip;
7750: ip->i_count = 2;
7751: ip->i_flag = IACC|IUPD;
7752: ip->i_mode = IALLOC;
7753: }
7754: /* --------------------------- */
7755:
7756: /* Read call directed to a pipe.
7757: */
7758: readp(fp)
7759: int *fp;
7760: {
7761: register *rp, *ip;
7762:
7763: rp = fp;
7764: ip = rp->f_inode;
7765: loop:
7766: /* Very conservative locking.
7767: */
7768: plock(ip);
7769: /* If the head (read) has caught up with
7770: * the tail (write), reset both to 0.
7771: */
7772: if(rp->f_offset[1] == ip->i_size1) {
7773: if(rp->f_offset[1] != 0) {
7774: rp->f_offset[1] = 0;
7775: ip->i_size1 = 0;
7776: if(ip->i_mode&IWRITE) {
7777: ip->i_mode =& ~IWRITE;
7778: wakeup(ip+1);
7779: }
7780: }
7781:
7782: /* If there are not both reader and
7783: * writer active, return without
7784: * satisfying read.
7785: */
7786: prele(ip);
7787: if(ip->i_count < 2)
7788: return;
7789: ip->i_mode =| IREAD;
7790: sleep(ip+2, PPIPE);
7791: goto loop;
7792: }
7793: /* Read and return
7794: */
7795: u.u_offset[0] = 0;
7796: u.u_offset[1] = rp->f_offset[1];
7797: readi(ip);
7798: rp->f_offset[1] = u.u_offset[1];
7799: prele(ip);
7800: }
7801: /* --------------------------- */
7802:
7803: /* Write call directed to a pipe.
7804: */
7805: writep(fp)
7806: {
7807: register *rp, *ip, c;
7808:
7809: rp = fp;
7810: ip = rp->f_inode;
7811: c = u.u_count;
7812: loop:
7813: /* If all done, return.
7814: */
7815: plock(ip);
7816: if(c == 0) {
7817: prele(ip);
7818: u.u_count = 0;
7819: return;
7820: }
7821: /* If there are not both read and
7822: * write sides of the pipe active,
7823: * return error and signal too.
7824: */
7825: if(ip->i_count < 2) {
7826: prele(ip);
7827: u.u_error = EPIPE;
7828: psignal(u.u_procp, SIGPIPE);
7829: return;
7830: }
7831: /* If the pipe is full,
7832: * wait for reads to deplete
7833: * and truncate it.
7834: */
7835: if(ip->i_size1 == PIPSIZ) {
7836: ip->i_mode =| IWRITE;
7837: prele(ip);
7838: sleep(ip+1, PPIPE);
7839: goto loop;
7840: }
7841: /* Write what is possible and
7842: * loop back.
7843: */
7844: u.u_offset[0] = 0;
7845: u.u_offset[1] = ip->i_size1;
7846: u.u_count = min(c, PIPSIZ-u.u_offset[1]);
7847: c =- u.u_count;
7848: writei(ip);
7849: prele(ip);
7850: if(ip->i_mode&IREAD) {
7851: ip->i_mode =& ~IREAD;
7852: wakeup(ip+2);
7853: }
7854: goto loop;
7855: }
7856: /* --------------------------- */
7857:
7858: /* Lock a pipe.
7859: * If its already locked,
7860: * set the WANT bit and sleep.
7861: */
7862: plock(ip)
7863: int *ip;
7864: {
7865: register *rp;
7866:
7867: rp = ip;
7868: while(rp->i_flag&ILOCK) {
7869: rp->i_flag =| IWANT;
7870: sleep(rp, PPIPE);
7871: }
7872: rp->i_flag =| ILOCK;
7873: }
7874: /* --------------------------- */
7875:
7876: /* Unlock a pipe.
7877: * If WANT bit is on,
7878: * wakeup.
7879: * This routine is also used
7880: * to unlock inodes in general.
7881: */
7882: prele(ip)
7883: int *ip;
7884: {
7885: register *rp;
7886:
7887: rp = ip;
7888: rp->i_flag =& ~ILOCK;
7889: if(rp->i_flag&IWANT) {
7890: rp->i_flag =& ~IWANT;
7891: wakeup(rp);
7892: }
7893: }
7894: /* --------------------------- */
7900: /*
7901: * A clist structure is the head
7902: * of a linked list queue of characters.
7903: * The characters are stored in 4-word
7904: * blocks containing a link and 6 characters.
7905: * The routines getc and putc (m45.s or m40.s)
7906: * manipulate these structures.
7907: */
7908: struct clist
7909: {
7910: int c_cc; /* character count */
7911: int c_cf; /* pointer to first block */
7912: int c_cl; /* pointer to last block */
7913: };
7914: /* --------------------------- */
7915:
7916: /*
7917: * A tty structure is needed for
7918: * each UNIX character device that
7919: * is used for normal terminal IO.
7920: * The routines in tty.c handle the
7921: * common code associated with
7922: * these structures.
7923: * The definition and device dependent
7924: * code is in each driver. (kl.c dc.c dh.c)
7925: */
7926: struct tty
7927: {
7928: struct clist t_rawq; /* input chars right off device */
7929: struct clist t_canq; /* input chars after erase and kill */
7930: struct clist t_outq; /* output list to device */
7931: int t_flags; /* mode, settable by stty call */
7932: int *t_addr; /* device address (register or startup fcn) */
7933:
7934: char t_delct; /* number of delimiters in raw q */
7935: char t_col; /* printing column of device */
7936: char t_erase; /* erase character */
7937: char t_kill; /* kill character */
7938: char t_state; /* internal state, not visible externally */
7939:
7940: char t_char; /* character temporary */
7941: int t_speeds; /* output+input line speed */
7942: int t_dev; /* device name */
7943: };
7944: /* --------------------------- */
7945:
7946:
7947: char partab[]; /* ASCII table: parity, character class */
7948:
7949:
7950:
7951: #define TTIPRI 10
7952: #define TTOPRI 20
7953:
7954: #define CERASE '#' /* default special characters */
7955: #define CEOT 004
7956: #define CKILL '@'
7957: #define CQUIT 034 /* FS, cntl shift L */
7958: #define CINTR 0177 /* DEL */
7959:
7960: /* limits */
7961: #define TTHIWAT 50
7962: #define TTLOWAT 30
7963: #define TTYHOG 256
7964:
7965: /* modes */
7966: #define HUPCL 01
7967: #define XTABS 02
7968: #define LCASE 04
7969: #define ECHO 010
7970: #define CRMOD 020
7971: #define RAW 040
7972: #define ODDP 0100
7973: #define EVENP 0200
7974: #define NLDELAY 001400
7975: #define TBDELAY 006000
7976: #define CRDELAY 030000
7977: #define VTDELAY 040000
7978:
7979: /* Hardware bits */
7980: #define DONE 0200
7981: #define IENABLE 0100
7982:
7983: /* Internal state bits */
7984: #define TIMEOUT 01 /* Delay timeout in progress */
7985: #define WOPEN 02 /* Waiting for open to complete */
7986:
7987: #define ISOPEN 04 /* Device is open */
7988: #define SSTART 010 /* Has special start routine at addr */
7989:
7990: #define CARR_ON 020 /* Software copy of carrier-present */
7991:
7992: #define BUSY 040 /* Output in progress */
7993: #define ASLEEP 0100 /* Wakeup when output done */
8000: #
8001: /* KL/DL-11 driver */
8002: #include "../param.h"
8003: #include "../conf.h"
8004: #include "../user.h"
8005: #include "../tty.h"
8006: #include "../proc.h"
8007: /* base address */
8008: #define KLADDR 0177560 /* console */
8009: #define KLBASE 0176500 /* kl and dl11-a */
8010: #define DLBASE 0175610 /* dl-e */
8011: #define NKL11 1
8012: #define NDL11 0
8013: #define DSRDY 02
8014: #define RDRENB 01
8015: struct tty kl11[NKL11+NDL11];
8016: struct klregs {
8017: int klrcsr;
8018: int klrbuf;
8019: int kltcsr;
8020: int kltbuf;
8021: }
8022: /* --------------------------- */
8023: klopen(dev, flag)
8024: { register char *addr;
8025: register struct tty *tp;
8026: if(dev.d_minor >= NKL11+NDL11) {
8027: u.u_error = ENXIO;
8028: return;
8029: }
8030: tp = &kl11[dev.d_minor];
8031: if (u.u_procp->p_ttyp == 0) {
8032: u.u_procp->p_ttyp = tp;
8033: tp->t_dev = dev;
8034: }
8035: /* set up minor 0 to address KLADDR
8036: * set up minor 1 thru NKL11-1 to address from KLBASE
8037: * set up minor NKL11 on to address from DLBASE
8038: */
8039: addr = KLADDR + 8*dev.d_minor;
8040: if(dev.d_minor)
8041: addr =+ KLBASE-KLADDR-8;
8042: if(dev.d_minor >= NKL11)
8043: addr =+ DLBASE-KLBASE-8*NKL11+8;
8044: tp->t_addr = addr;
8045: if ((tp->t_state&ISOPEN) == 0) {
8046: tp->t_state = ISOPEN|CARR_ON;
8047: tp->t_flags = XTABS|LCASE|ECHO|CRMOD;
8048: tp->t_erase = CERASE;
8049: tp->t_kill = CKILL;
8050: }
8051: addr->klrcsr =| IENABLE|DSRDY|RDRENB;
8052: addr->kltcsr =| IENABLE;
8053: }
8054: /* --------------------------- */
8055: klclose(dev)
8056: { register struct tty *tp;
8057: tp = &kl11[dev.d_minor];
8058: wflushtty(tp);
8059: tp->t_state = 0;
8060: }
8061: /* --------------------------- */
8062: klread(dev)
8063: { ttread(&kl11[dev.d_minor]);
8064: }
8065: /* --------------------------- */
8066: klwrite(dev)
8067: { ttwrite(&kl11[dev.d_minor]);
8068: }
8069: /* --------------------------- */
8070: klxint(dev)
8071: { register struct tty *tp;
8072: tp = &kl11[dev.d_minor];
8073: ttstart(tp);
8074: if (tp->t_outq.c_cc == 0 || tp->t_outq.c_cc == TTLOWAT)
8075: wakeup(&tp->t_outq);
8076: }
8077: /* --------------------------- */
8078: klrint(dev)
8079: { register int c, *addr;
8080: register struct tty *tp;
8081: tp = &kl11[dev.d_minor];
8082: addr = tp->t_addr;
8083: c = addr->klrbuf;
8084: addr->klrcsr =| RDRENB;
8085: if ((c&0177)==0)
8086: addr->kltbuf = c; /* hardware botch */
8087: ttyinput(c, tp);
8088: }
8089: /* --------------------------- */
8090: klsgtty(dev, v)
8091: int *v;
8092: { register struct tty *tp;
8093: tp = &kl11[dev.d_minor];
8094: ttystty(tp, v);
8095: }
8096: /* --------------------------- */
8100: # / * general TTY subroutines */
8101:
8102: #include "../param.h"
8103: #include "../systm.h"
8104: #include "../user.h"
8105: #include "../tty.h"
8106: #include "../proc.h"
8107: #include "../inode.h"
8108: #include "../file.h"
8109: #include "../reg.h"
8110: #include "../conf.h"
8111:
8112: /* Input mapping table-- if an entry is non-zero, when the
8113: * corresponding character is typed preceded by "\" the escape
8114: * sequence is replaced by the table value. Mostly used for
8115: * upper-case only terminals.
8116: */
8117: char maptab[]
8118: {
8119: 000,000,000,000,004,000,000,000,
8120: 000,000,000,000,000,000,000,000,
8121: 000,000,000,000,000,000,000,000,
8122: 000,000,000,000,000,000,000,000,
8123: 000,'|',000,'#',000,000,000,'`',
8124: '{','}',000,000,000,000,000,000,
8125: 000,000,000,000,000,000,000,000,
8126: 000,000,000,000,000,000,000,000,
8127: '@',000,000,000,000,000,000,000,
8128: 000,000,000,000,000,000,000,000,
8129: 000,000,000,000,000,000,000,000,
8130: 000,000,000,000,000,000,'~',000,
8131: 000,'A','B','C','D','E','F','G',
8132: 'H','I','J','K','L','M','N','O',
8133: 'P','Q','R','S','T','U','V','W',
8134: 'X','Y','Z',000,000,000,000,000,
8135: };
8136: /* --------------------------- */
8137: /* The actual structure of a clist block manipulated by
8138: * getc and putc (mch.s)
8139: */
8140: struct cblock {
8141: struct cblock *c_next;
8142: char info[6];
8143: };
8144: /* --------------------------- */
8145: /* The character lists-- space for 6*NCLIST characters */
8146: struct cblock cfree[NCLIST];
8147: /* List head for unused character blocks. */
8148: struct cblock *cfreelist;
8149:
8150: /* structure of device registers for KL, DL, and DC
8151: * interfaces-- more particularly, those for which the
8152: * SSTART bit is off and can be treated by general routines
8153: * (that is, not DH).
8154: */
8155: struct {
8156: int ttrcsr;
8157: int ttrbuf;
8158: int tttcsr;
8159: int tttbuf;
8160: };
8161: /* --------------------------- */
8162: /* The routine implementing the gtty system call.
8163: * Just call lower level routine and pass back values.
8164: */
8165: gtty()
8166: {
8167: int v[3];
8168: register *up, *vp;
8169:
8170: vp = v;
8171: sgtty(vp);
8172: if (u.u_error)
8173: return;
8174: up = u.u_arg[0];
8175: suword(up, *vp++);
8176: suword(++up, *vp++);
8177: suword(++up, *vp++);
8178: }
8179: /* --------------------------- */
8180: /* The routine implementing the stty system call.
8181: * Read in values and call lower level.
8182: */
8183: stty()
8184: {
8185: register int *up;
8186:
8187: up = u.u_arg[0];
8188: u.u_arg[0] = fuword(up);
8189: u.u_arg[1] = fuword(++up);
8190: u.u_arg[2] = fuword(++up);
8191: sgtty(0);
8192: }
8193: /* --------------------------- */
8194: /* Stuff common to stty and gtty.
8195: * Check legality and switch out to individual
8196: * device routine.
8197: * v is 0 for stty; the parameters are taken from u.u_arg[].
8198: * c is non-zero for gtty and is the place in which the device
8199: * routines place their information.
8200: */
8201: sgtty(v)
8202: int *v;
8203: {
8204: register struct file *fp;
8205: register struct inode *ip;
8206: if ((fp = getf(u.u_ar0[R0])) == NULL)
8207: return;
8208: ip = fp->f_inode;
8209: if ((ip->i_mode&IFMT) != IFCHR) {
8210: u.u_error = ENOTTY;
8211: return;
8212: }
8213: (*cdevsw[ip->i_addr[0].d_major].d_sgtty)(ip->i_addr[0], v);
8214: }
8215: /* --------------------------- */
8216: /* Wait for output to drain, then flush input waiting. */
8217: wflushtty(atp)
8218: struct tty *atp;
8219: {
8220: register struct tty *tp;
8221: tp = atp;
8222: spl5();
8223: while (tp->t_outq.c_cc) {
8224: tp->t_state =| ASLEEP;
8225: sleep(&tp->t_outq, TTOPRI);
8226: }
8227: flushtty(tp);
8228: spl0();
8229: }
8230: /* --------------------------- */
8231: /* Initialize clist by freeing all character blocks, then count
8232: * number of character devices. (Once-only routine)
8233: */
8234: cinit()
8235: {
8236: register int ccp;
8237: register struct cblock *cp;
8238: register struct cdevsw *cdp;
8239: ccp = cfree;
8240: for (cp=(ccp+07)&~07; cp <= &cfree[NCLIST-1]; cp++) {
8241: cp->c_next = cfreelist;
8242: cfreelist = cp;
8243: }
8244: ccp = 0;
8245: for(cdp = cdevsw; cdp->d_open; cdp++)
8246: ccp++;
8247: nchrdev = ccp;
8248: }
8249: /* --------------------------- */
8250: /* flush all TTY queues
8251: */
8252: flushtty(atp)
8253: struct tty *atp;
8254: {
8255: register struct tty *tp;
8256: register int sps;
8257: tp = atp;
8258: while (getc(&tp->t_canq) >= 0);
8259: while (getc(&tp->t_outq) >= 0);
8260: wakeup(&tp->t_rawq);
8261: wakeup(&tp->t_outq);
8262: sps = PS->integ;
8263: spl5();
8264: while (getc(&tp->t_rawq) >= 0);
8265: tp->t_delct = 0;
8266: PS->integ = sps;
8267: }
8268: /* --------------------------- */
8269: /* transfer raw input list to canonical list,
8270: * doing erase-kill processing and handling escapes.
8271: * It waits until a full line has been typed in cooked mode,
8272: * or until any character has been typed in raw mode.
8273: */
8274: canon(atp)
8275: struct tty *atp;
8276: {
8277: register char *bp;
8278: char *bp1;
8279: register struct tty *tp;
8280: register int c;
8281:
8282: tp = atp;
8283: spl5();
8284: while (tp->t_delct==0) {
8285: if ((tp->t_state&CARR_ON)==0)
8286: return(0);
8287: sleep(&tp->t_rawq, TTIPRI);
8288: }
8289: spl0();
8290: loop:
8291: bp = &canonb[2];
8292: while ((c=getc(&tp->t_rawq)) >= 0) {
8293: if (c==0377) {
8294: tp->t_delct--;
8295: break;
8296: }
8297: if ((tp->t_flags&RAW)==0) {
8298: if (bp[-1]!='\\') {
8299: if (c==tp->t_erase) {
8300: if (bp > &canonb[2])
8301: bp--;
8302: continue;
8303: }
8304: if (c==tp->t_kill)
8305: goto loop;
8306: if (c==CEOT)
8307: continue;
8308: } else
8309: if (maptab[c] && (maptab[c]==c || (tp->t_flags&LCASE))) {
8310: if (bp[-2] != '\\')
8311: c = maptab[c];
8312: bp--;
8313: }
8314: }
8315: *bp++ = c;
8316: if (bp>=canonb+CANBSIZ)
8317: break;
8318: }
8319: bp1 = bp;
8320: bp = &canonb[2];
8321: c = &tp->t_canq;
8322: while (bp<bp1)
8323: putc(*bp++, c);
8324: return(1);
8325: }
8326: /* --------------------------- */
8327: /* Place a character on raw TTY input queue, putting in delimiters
8328: * and waking up top half as needed.
8329: * Also echo if required.
8330: * The arguments are the character and the appropriate
8331: * tty structure.
8332: */
8333: ttyinput(ac, atp)
8334: struct tty *atp;
8335: {
8336: register int t_flags, c;
8337: register struct tty *tp;
8338:
8339: tp = atp;
8340: c = ac;
8341: t_flags = tp->t_flags;
8342: if ((c =& 0177) == '\r' && t_flags&CRMOD)
8343: c = '\n';
8344: if ((t_flags&RAW)==0 && (c==CQUIT || c==CINTR)) {
8345: signal(tp, c==CINTR? SIGINT:SIGQIT);
8346: flushtty(tp);
8347: return;
8348: }
8349: if (tp->t_rawq.c_cc>=TTYHOG) {
8350: flushtty(tp);
8351: return;
8352: }
8353: if (t_flags&LCASE && c>='A' && c<='Z')
8354: c =+ 'a'-'A';
8355: putc(c, &tp->t_rawq);
8356: if (t_flags&RAW || c=='\n' || c==004) {
8357: wakeup(&tp->t_rawq);
8358: if (putc(0377, &tp->t_rawq)==0)
8359: tp->t_delct++;
8360: }
8361: if (t_flags&ECHO) {
8362: ttyoutput(c, tp);
8363: ttstart(tp);
8364: }
8365: }
8366: /* --------------------------- */
8367: /* put character on TTY output queue, adding delays,
8368: * expanding tabs, and handling the CR/NL bit.
8369: * It is called both from the top half for output, and from
8370: * interrupt level for echoing.
8371: * The arguments are the character and the tty structure.
8372: */
8373: ttyoutput(ac, tp)
8374: struct tty *tp;
8375: {
8376: register int c;
8377: register struct tty *rtp;
8378: register char *colp;
8379: int ctype;
8380:
8381: rtp = tp;
8382: c = ac&0177;
8383: /* Ignore EOT in normal mode to avoid hanging up
8384: * certain terminals.
8385: */
8386: if (c==004 && (rtp->t_flags&RAW)==0)
8387: return;
8388: /* Turn tabs to spaces as required
8389: */
8390: if (c=='\t' && rtp->t_flags&XTABS) {
8391: do
8392: ttyoutput(' ', rtp);
8393: while (rtp->t_col&07);
8394: return;
8395: }
8396: /* for upper-case-only terminals,
8397: * generate escapes.
8398: */
8399: if (rtp->t_flags&LCASE) {
8400: colp = "({)}!|^~'`";
8401: while(*colp++)
8402: if(c == *colp++) {
8403: ttyoutput('\\', rtp);
8404: c = colp[-2];
8405: break;
8406: }
8407: if ('a'<=c && c<='z')
8408: c =+ 'A' - 'a';
8409: }
8410: /* turn <nl> to <cr><lf> if desired.
8411: */
8412: if (c=='\n' && rtp->t_flags&CRMOD)
8413: ttyoutput('\r', rtp);
8414: if (putc(c, &rtp->t_outq))
8415: return;
8416: /* Calculate delays.
8417: * The numbers here represent clock ticks
8418: * and are not necessarily optimal for all terminals.
8419: * The delays are indicated by characters above 0200,
8420: * thus (unfortunately) restricting the transmission
8421: * path to 7 bits.
8422: */
8423: colp = &rtp->t_col;
8424: ctype = partab[c];
8425: c = 0;
8426: switch (ctype&077) {
8427: /* ordinary */
8428: case 0:
8429: (*colp)++;
8430: /* non-printing */
8431: case 1:
8432: break;
8433: /* backspace */
8434: case 2:
8435: if (*colp)
8436: (*colp)--;
8437: break;
8438: /* newline */
8439: case 3:
8440: ctype = (rtp->t_flags >> 8) & 03;
8441: if(ctype == 1) { /* tty 37 */
8442: if (*colp)
8443: c = max((*colp>>4) + 3, 6);
8444: } else
8445: if(ctype == 2) { /* vt05 */
8446: c = 6;
8447: }
8448: *colp = 0;
8449: break;
8450: /* tab */
8451: case 4:
8452: ctype = (rtp->t_flags >> 10) & 03;
8453: if(ctype == 1) { /* tty 37 */
8454: c = 1 - (*colp | ~07);
8455: if(c < 5)
8456: c = 0;
8457: }
8458: *colp =| 07;
8459: (*colp)++;
8460: break;
8461: /* vertical motion */
8462: case 5:
8463: if(rtp->t_flags & VTDELAY) /* tty 37 */
8464: c = 0177;
8465: break;
8466: /* carriage return */
8467: case 6:
8468: ctype = (rtp->t_flags >> 12) & 03;
8469: if(ctype == 1) { /* tn 300 */
8470: c = 5;
8471: } else
8472: if(ctype == 2) { /* ti 700 */
8473: c = 10;
8474: }
8475: *colp = 0;
8476: }
8477: if(c)
8478: putc(c|0200, &rtp->t_outq);
8479: }
8480: /* --------------------------- */
8481: /* Restart typewriter output following a delay
8482: * timeout.
8483: * The name of the routine is passed to the timeout
8484: * subroutine and it is called during a clock interrupt.
8485: */
8486: ttrstrt(atp)
8487: {
8488: register struct tty *tp;
8489:
8490: tp = atp;
8491: tp->t_state =& ~TIMEOUT;
8492: ttstart(tp);
8493: }
8494: /* --------------------------- */
8495: /*
8496: * Start output on the typewriter. It is used from the top half
8497: * after some characters have been put on the output queue,
8498: * from the interrupt routine to transmit the next
8499: * character, and after a timeout has finished.
8500: * If the SSTART bit is off for the tty the work is done here,
8501: * using the protocol of the single-line interfaces (KL, DL, DC);
8502: * otherwise the address word of the tty structure is
8503: * taken to be the name of the device-dependent startup routine.
8504: */
8505: ttstart(atp)
8506: struct tty *atp;
8507: {
8508: register int *addr, c;
8509: register struct tty *tp;
8510: struct { int (*func)(); };
8511:
8512: tp = atp;
8513: addr = tp->t_addr;
8514: if (tp->t_state&SSTART) {
8515: (*addr.func)(tp);
8516: return;
8517: }
8518: if ((addr->tttcsr&DONE)==0 || tp->t_state&TIMEOUT)
8519: return;
8520: if ((c=getc(&tp->t_outq)) >= 0) {
8521: if (c<=0177)
8522: addr->tttbuf = c | (partab[c]&0200);
8523: else {
8524: timeout(ttrstrt, tp, c&0177);
8525: tp->t_state =| TIMEOUT;
8526: }
8527: }
8528: }
8529: /* --------------------------- */
8530: /* Called from device's read routine after it has
8531: * calculated the tty-structure given as argument.
8532: * The pc is backed up for the duration of this call.
8533: * In case of a caught interrupt, an RTI will re-execute.
8534: */
8535: ttread(atp)
8536: struct tty *atp;
8537: {
8538: register struct tty *tp;
8539:
8540: tp = atp;
8541: if ((tp->t_state&CARR_ON)==0)
8542: return;
8543: if (tp->t_canq.c_cc || canon(tp))
8544: while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0);
8545: }
8546: /* --------------------------- */
8547: /* Called from the device's write routine after it has
8548: * calculated the tty-structure given as argument.
8549: */
8550: ttwrite(atp)
8551: struct tty *atp;
8552: {
8553: register struct tty *tp;
8554: register int c;
8555: tp = atp;
8556: if ((tp->t_state&CARR_ON)==0)
8557: return;
8558: while ((c=cpass())>=0) {
8559: spl5();
8560: while (tp->t_outq.c_cc > TTHIWAT) {
8561: ttstart(tp);
8562: tp->t_state =| ASLEEP;
8563: sleep(&tp->t_outq, TTOPRI);
8564: }
8565: spl0();
8566: ttyoutput(c, tp);
8567: }
8568: ttstart(tp);
8569: }
8570: /* --------------------------- */
8571: /* Common code for gtty and stty functions on typewriters.
8572: * If v is non-zero then gtty is being done and information is
8573: * passed back therein;
8574: * if it is zero stty is being done and the input information is in the
8575: * u_arg array.
8576: */
8577: ttystty(atp, av)
8578: int *atp, *av;
8579: {
8580: register *tp, *v;
8581: tp = atp;
8582: if(v = av) {
8583: *v++ = tp->t_speeds;
8584: v->lobyte = tp->t_erase;
8585: v->hibyte = tp->t_kill;
8586: v[1] = tp->t_flags;
8587: return(1);
8588: }
8589: wflushtty(tp);
8590: v = u.u_arg;
8591: tp->t_speeds = *v++;
8592: tp->t_erase = v->lobyte;
8593: tp->t_kill = v->hibyte;
8594: tp->t_flags = v[1];
8595: return(0);
8596: }
8597: /* --------------------------- */
8600: #
8601: /* PC-11 Paper tape reader/punch driver */
8602:
8603: #include "../param.h"
8604: #include "../conf.h"
8605: #include "../user.h"
8606:
8607: #define PCADDR 0177550
8608:
8609: #define CLOSED 0
8610: #define WAITING 1
8611: #define READING 2
8612: #define EOF 3
8613:
8614: #define RDRENB 01
8615: #define IENABLE 0100
8616: #define DONE 0200
8617: #define BUSY 04000
8618: #define ERROR 0100000
8619:
8620: #define PCIPRI 30
8621: #define PCOPRI 40
8622: #define PCOLWAT 50
8623: #define PCOHWAT 100
8624: #define PCIHWAT 250
8625:
8626: struct {
8627: int pcrcsr;
8628: int pcrbuf;
8629: int pcpcsr;
8630: int pcpbuf;
8631: };
8632: /* --------------------------- */
8633:
8634: struct clist {
8635: int cc;
8636: int cf;
8637: int cl;
8638: };
8639: /* --------------------------- */
8640:
8641: struct pc11 {
8642: int pcstate;
8643: struct clist pcin;
8644: struct clist pcout;
8645: } pc11;
8646: /* --------------------------- */
8647:
8648: pcopen(dev, flag)
8649: {
8650: extern lbolt;
8651:
8652: if (flag==0) {
8653: if (pc11.pcstate!=CLOSED) {
8654: u.u_error = ENXIO;
8655: return;
8656: }
8657: pc11.pcstate = WAITING;
8658: while(pc11.pcstate==WAITING) {
8659: PCADDR->pcrcsr = IENABLE|RDRENB;
8660: sleep(&lbolt, PCIPRI);
8661: }
8662: } else {
8663: PCADDR->pcpcsr =| IENABLE;
8664: pcleader();
8665: }
8666: }
8667: /* --------------------------- */
8668:
8669: pcclose(dev, flag)
8670: {
8671: if (flag==0) {
8672: spl4();
8673: while (getc(&pc11.pcin) >= 0);
8674: PCADDR->pcrcsr = 0;
8675: pc11.pcstate = CLOSED;
8676: spl0();
8677: } else
8678: pcleader();
8679: }
8680: /* --------------------------- */
8681:
8682: pcread()
8683: {
8684: register int c;
8685:
8686: spl4();
8687: do {
8688: while ((c = getc(&pc11.pcin)) < 0) {
8689: if (pc11.pcstate==EOF)
8690: goto out;
8691: if ((PCADDR->pcrcsr&(ERROR|BUSY|DONE))==0)
8692: PCADDR->pcrcsr =| IENABLE|RDRENB;
8693: sleep(&pc11.pcin, PCIPRI);
8694: }
8695: } while (passc(c)>=0);
8696: out:
8697: spl0();
8698: }
8699: /* --------------------------- */
8700:
8701: pcwrite()
8702: {
8703: register int c;
8704:
8705: while ((c=cpass())>=0)
8706: pcoutput(c);
8707: }
8708: /* --------------------------- */
8709:
8710: pcstart()
8711: {
8712: register int c;
8713:
8714: if (PCADDR->pcpcsr&DONE && (c = getc(&pc11.pcout)) >= 0)
8715: PCADDR->pcpbuf = c;
8716: }
8717: /* --------------------------- */
8718:
8719: pcrint()
8720: {
8721: if (pc11.pcstate==WAITING) {
8722: if (PCADDR->pcrcsr&ERROR)
8723: return;
8724: pc11.pcstate = READING;
8725: }
8726: if (pc11.pcstate==READING) {
8727: if (PCADDR->pcrcsr&ERROR)
8728: pc11.pcstate = EOF;
8729: else {
8730: putc(PCADDR->pcrbuf, &pc11.pcin);
8731: if (pc11.pcin.cc < PCIHWAT)
8732: PCADDR->pcrcsr =| IENABLE|RDRENB;
8733: }
8734: wakeup(&pc11.pcin);
8735: }
8736: }
8737: /* --------------------------- */
8738:
8739: pcpint()
8740: {
8741:
8742: pcstart();
8743: if (pc11.pcout.cc <= PCOLWAT)
8744: wakeup(&pc11.pcout);
8745: }
8746: /* --------------------------- */
8747:
8748: pcoutput(c)
8749: {
8750: if (PCADDR->pcpcsr&ERROR) {
8751: u.u_error = EIO;
8752: return;
8753: }
8754: if (pc11.pcout.cc >= PCOHWAT)
8755: sleep(&pc11.pcout, PCOPRI);
8756: putc(c, &pc11.pcout);
8757: spl4();
8758: pcstart();
8759: spl0();
8760: }
8761: /* --------------------------- */
8762:
8763: pcleader()
8764: {
8765: register int i;
8766:
8767: i = 100;
8768: do
8769: pcoutput(0);
8770: while (--i);
8771: }
8772: /* --------------------------- */
8800: #
8801: /*
8802: */
8803:
8804: /*
8805: * LP-11 Line printer driver
8806: */
8807:
8808: #include "../param.h"
8809: #include "../conf.h"
8810: #include "../user.h"
8811:
8812: #define LPADDR 0177514
8813:
8814: #define IENABLE 0100
8815: #define DONE 0200
8816:
8817: #define LPPRI 10
8818: #define LPLWAT 50
8819: #define LPHWAT 100
8820: #define EJLINE 60
8821: #define MAXCOL 80
8822:
8823: struct {
8824: int lpsr;
8825: int lpbuf;
8826: };
8827: /* --------------------------- */
8828:
8829: struct {
8830: int cc;
8831: int cf;
8832: int cl;
8833: int flag;
8834: int mcc;
8835: int ccc;
8836: int mlc;
8837: } lp11;
8838: /* --------------------------- */
8839:
8840: #define CAP 01 /* Set to 0 for 96-char printer, else to 01 */
8841:
8842: #define EJECT 02
8843: #define OPEN 04
8844: #define IND 010 /* Set to 0 for no indent, else to 010 */
8845:
8846:
8847: #define FORM 014
8848:
8849:
8850: lpopen(dev, flag)
8851: {
8852:
8853: if(lp11.flag & OPEN || LPADDR->lpsr < 0) {
8854: u.u_error = EIO;
8855: return;
8856: }
8857: lp11.flag =| (IND|EJECT|OPEN);
8858: LPADDR->lpsr =| IENABLE;
8859: lpcanon(FORM);
8860: }
8861: /* --------------------------- */
8862:
8863: lpclose(dev, flag)
8864: {
8865: lpcanon(FORM);
8866: lp11.flag = 0;
8867: }
8868: /* --------------------------- */
8869:
8870: lpwrite()
8871: {
8872: register int c;
8873:
8874: while ((c=cpass())>=0)
8875: lpcanon(c);
8876: }
8877: /* --------------------------- */
8878:
8879: lpcanon(c)
8880: {
8881: register c1, c2;
8882:
8883: c1 = c;
8884: if(lp11.flag&CAP) {
8885: if(c1>='a' && c1<='z')
8886: c1 =+ 'A'-'a'; else
8887: switch(c1) {
8888:
8889: case '{':
8890: c2 = '(';
8891: goto esc;
8892:
8893: case '}':
8894: c2 = ')';
8895: goto esc;
8896:
8897: case '`':
8898: c2 = '\'';
8899: goto esc;
8900:
8901: case '|':
8902: c2 = '!';
8903: goto esc;
8904:
8905: case '~':
8906: c2 = '^';
8907:
8908: esc:
8909: lpcanon(c2);
8910: lp11.ccc--;
8911: c1 = '-';
8912: }
8913: }
8914:
8915: switch(c1) {
8916:
8917: case '\t':
8918: lp11.ccc = (lp11.ccc+8) & ~7;
8919: return;
8920:
8921: case FORM:
8922: case '\n':
8923: if((lp11.flag&EJECT) == 0 ||
8924: lp11.mcc!=0 || lp11.mlc!=0) {
8925: lp11.mcc = 0;
8926: lp11.mlc++;
8927: if(lp11.mlc >= EJLINE && lp11.flag&EJECT)
8928: c1 = FORM;
8929: lpoutput(c1);
8930: if(c1 == FORM)
8931: lp11.mlc = 0;
8932: }
8933:
8934: case '\r':
8935: lp11.ccc = 0;
8936: if(lp11.flag&IND)
8937: lp11.ccc = 8;
8938: return;
8939:
8940: case 010:
8941: if(lp11.ccc > 0)
8942: lp11.ccc--;
8943: return;
8944:
8945: case ' ':
8946: lp11.ccc++;
8947: return;
8948:
8949: default:
8950: if(lp11.ccc < lp11.mcc) {
8951: lpoutput('\r');
8952: lp11.mcc = 0;
8953: }
8954: if(lp11.ccc < MAXCOL) {
8955: while(lp11.ccc > lp11.mcc) {
8956: lpoutput(' ');
8957: lp11.mcc++;
8958: }
8959: lpoutput(c1);
8960: lp11.mcc++;
8961: }
8962: lp11.ccc++;
8963: }
8964: }
8965: /* --------------------------- */
8966:
8967: lpstart()
8968: {
8969: register int c;
8970:
8971: while (LPADDR->lpsr&DONE && (c = getc(&lp11)) >= 0)
8972: LPADDR->lpbuf = c;
8973: }
8974: /* --------------------------- */
8975:
8976: lpint()
8977: {
8978: register int c;
8979:
8980: lpstart();
8981: if (lp11.cc == LPLWAT || lp11.cc == 0)
8982: wakeup(&lp11);
8983: }
8984: /* --------------------------- */
8985:
8986: lpoutput(c)
8987: {
8988: if (lp11.cc >= LPHWAT)
8989: sleep(&lp11, LPPRI);
8990: putc(c, &lp11);
8991: spl4();
8992: lpstart();
8993: spl0();
8994: }
8995: /* --------------------------- */
9000: #
9001: /*
9002: */
9003:
9004: /*
9005: * Memory special file
9006: * minor device 0 is physical memory
9007: * minor device 1 is kernel memory
9008: * minor device 2 is EOF/RATHOLE
9009: */
9010:
9011: #include "../param.h"
9012: #include "../user.h"
9013: #include "../conf.h"
9014: #include "../seg.h"
9015:
9016: mmread(dev)
9017: {
9018: register c, bn, on;
9019: int a, d;
9020:
9021: if(dev.d_minor == 2)
9022: return;
9023: do {
9024: bn = lshift(u.u_offset, -6);
9025: on = u.u_offset[1] & 077;
9026: a = UISA->r[0];
9027: d = UISD->r[0];
9028: spl7();
9029: UISA->r[0] = bn;
9030: UISD->r[0] = 077406;
9031: if(dev.d_minor == 1)
9032: UISA->r[0] = (ka6-6)->r[(bn>>7)&07] + (bn & 0177);
9033:
9034: c = fuibyte(on);
9035: UISA->r[0] = a;
9036: UISD->r[0] = d;
9037: spl0();
9038: } while(u.u_error==0 && passc(c)>=0);
9039: }
9040: /* --------------------------- */
9041:
9042: mmwrite(dev)
9043: {
9044: register c, bn, on;
9045: int a, d;
9046:
9047: if(dev.d_minor == 2) {
9048: c = u.u_count;
9049: u.u_count = 0;
9050: u.u_base =+ c;
9051: dpadd(u.u_offset, c);
9052: return;
9053: }
9054: for(;;) {
9055: bn = lshift(u.u_offset, -6);
9056: on = u.u_offset[1] & 077;
9057: if ((c=cpass())<0 || u.u_error!=0)
9058: break;
9059: a = UISA->r[0];
9060: d = UISD->r[0];
9061: spl7();
9062: UISA->r[0] = bn;
9063: UISD->r[0] = 077406;
9064: if(dev.d_minor == 1)
9065: UISA->r[0] = (ka6-6)->r[(bn>>7)&07] + (bn & 0177);
9066:
9067: suibyte(on, c);
9068: UISA->r[0] = a;
9069: UISD->r[0] = d;
9070: spl0();
9071: }
9072: }
9073: /* --------------------------- */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment