Unisoft_V.1.0_kernel_listing Unisoft V.1.0 Kernel Listing

User Manual: Unisoft_V.1.0_kernel_listing

Open the PDF directly: View PDF PDF.
Page Count: 340

DownloadUnisoft_V.1.0_kernel_listing Unisoft V.1.0 Kernel Listing
Open PDF In BrowserView PDF
ivec.s

Fri Sep

5 19:08:57 1986

1

copyright 1982 Unisoft corporation

bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr

Interrupt vector dispatch table
One entry per interrupt vector location
.text
.globl
dispatc:
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bsr
bST

bsr
bsr
bsr
bsr
bsr
bsr
bsr

_dispatc, .Jl!lIvect, _tevect
I fault
lfault
lbuserr
laddrerr
lfault
lfault
lfault
lfault
lfault
lfault
lfault
lfault
lfault
1 fault
lfault
lfault
lfault
lfault
I fault
lfault
lfault
lfault
lfault
lfault
lfault
llintr
kbintr
piS
pi4
pi3
scintr
!'_1'!li
lsyscall
lfault
lfault
lfault
lfault
I fault
1 fault
lfault
lfault
lfault
I fault
lfault
I fault
lfault
lfault
lfault
lfault
I fault
1 fault
1 fault
I fault
1 fault
1 fault
1 fault
lfault
lfault
lfault
lfault
lfault
lfault
lfault
lfault
lfault
lfault
lfault

2
3
5
6

9

10
11
12
13
14
15

16
17

18
19
20
21
22

23
24
25

26
27
28
29
30
31
32
33

34
35

36
37

38
39
40
41
42
43
44
45

46
47

48
49
50
51
52
53
54
55
56
57
58
59

60
61
62
63
64
65
66

Reset: Initial SSP
Reset: Initial PC
Bus Error
Address Error
Illegal Instruction
Zero Divide
CHK Instruction
TRAPV Instruction
privilege Violation
Trace
Line 1010 Emulator
Line 1111 Emulator
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
spurious Interrupt
Level 1 pp 0, sony, vert retrace (clock)
Level
cops, mouse, rtclock, buttons
Level
exp slot 3 (default 2-port card)
Level
exp slot 2 (default 2-port card)
Level
exp slot 1 (default 2-port card)
Level
scc chip
Level
Interrupt Autovector
System Call
TRAP Instruction Vector
TRAP Instruction Vector
TRAP Instruction Vector
TRAP Instruction Vector
TRAP Instruction Vector
TRAP Instruction Vector
TRAP Instruction Vector
TRAP Instruction Vector
TRAP Instruction Vector
TRAP Instruction Vector
TRAP Instruction Vector
TRAP Instruction Vector
TRAP Instruction Vector
TRAP Instruction Vector
TRAP Instruction Vector
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved,
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(Unassigned, reserved)
(User Interrupt Vector)
(User Interrupt Vector)
(User Interrupt Vectorl

lfault
I fault
lfault
I fault
lfault
!fault
I fault
I fault
lfault
lfault
lfault
lfault
I fault
lfault
I fault
lfault
I fault
lfault
lfault
I fault
I fault
I fault
I fault
lfault
lfault
I fault
lfault
lfault

67

68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85

86
87

88
89
90
91
92
93
94

(User
(User
(User
(User
(User
(Vser
(User
(User
(User
(User
(User
(User
(User
(User
(User
(User
(User
(User
(User
(User
(User
(User
(User
(User
(User
(User
(User
(User

Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt
Interrupt

Vector)
Vector)
Vector)
vector)
Vector)
vector)
Vector)
vector)
Vector)
Vector)
vector)
Vector)
Vector)
Vector)
Vector)
vector)
Vector)
vector)
Vector)
Vector)
Vector)
Vector)
Vector)
Vector)
Vector)
Vector)
Vector)
Vector)

values for expansion card interrupt vectors when Priam
pmvect:
bsr
27
Level
exp slot
pmint3
Level
exp slot
28
bsr
pmint2
Level
exp slot
29
bsr
pmintl

card present.
3, Priam card
2, Priam card
1, Priam card

Values for expansion card interrupt vectors when Techmar card present.
_tevect:
27
Level 3 exp slot 3, Tecmar card
bsr
teint3
Level 4 exp slot 2, Tecmar card
bsr
teint2
28
Level
exp slot 1, Tecmar card
bsr
teintl
29
Put actual "C" routine name onto the stack and call the system
interrupt dispatcher
.globl
lfault: jmp
lbuserr: jmp
laddrerr: jmp
lsyscall: jmp

call, fault, buserr, addrerr, syscall, _idle fIg
fault
bus err
addrerr
syscall

I tty interrupt priority entry point
.globl _spltty
fetch current CPU priority
_spltty:movw
sr,dO
movw
tOx2600, sr
set priority 6
rts

.globl
1lintr: movw
movl
movw
jmp
. glob!
kbintr: movl
clrw
jmp
pi3:

pi4:

_llintr
tOx2600, sr
t llintr, sp@
ldleflg, sp@call

i

kbintr
kbintr, sp@

go to spl6
push call address
clock needs old value so cheat
jump to cOOllllon interrupt handler

call

push call address
device number
jump to cornmon interrupt handler

.globl
movl
rnovw
jrnp

J'Pintr
t ppintr, sp@
ti, sp@call

push call address
device number
jump to cornmon interrupt handler

movl
rnovw
jmp

t ppintr, sp@

sp@-

t"4, sp@call

push call address
device number
jump to cornm~n interrupt handler

Fri Sep

ivec.s
piS:

t _ppintr, sp@

movl
movw
jmp

t7, sp@call

.. globl

Jm!intr

5 19:08:57 1986

push call address
device number
jump to common interrupt handler

pmint3: movl
movw
jmp

t_pmintr, sp@
t2, sp@call

push call address
device number
jump to common interrupt handler

pmint2: movl
movw
jmp

tJ»Uintr,sp@
H, sp@call

push call address
device number
jump to common interrupt handler

pmintl: movl
clrw
jmp

t J»Uintr , sp@
sp@call

push call address
device number
jump to common interrupt handler

.globl
scintr: movl
movw
jmp

scintr
t_scintr,sp@
H, sp@call

push call address
device number
jump to common interrupt handler

.globl
movl
movw
jmp

_nm.ikey
t_rnnikey, sp@
to, sp@call

push call address
device number
jump to common interrupt handler

.globl
teint3 : movl
movw
jmp

teintr
f_teintr, sp@
t2, sp@call

push call address
device number
jump to common interrupt handler

teint2: movl
movw
jmp

t _ teintr, sp@
H, sp@call

push call address
device number
jump to common interrupt handler

teintl: movl
clrw
jmp

t_teintr, sp@
sp@call

push call address
device number
jump to common interrupt handler

rnni:

2

mch.s

Fri Sep

5 19:08:47 1986

I USIZE dependencies
USIZE
= Ox800
PGSIZE ~ 512
PAGESHIFT- 9

Size of U area
Size of a page
Page shift

I Configuration dependencies
HIGH
Ox2700
LOW
- Ox2000
USTART - OxO
PAGEBASE= OxAOOOOO
UDOT
- OxFAOOOO
UBASE
= PAGEBASE+UDOT

High priority supervisor mode (spl 7)
Low priority, supervisor mode (spl 0)
Start of user program
Base page address
Logical start of U dot
U dot page map address

SETUP_O
SETUP_l
SEG1_0
SEG1_l
SEG2_0
SEG2_1

=

-

OxFCE012
OxFCE010
OxFCE008
OxFCEOOA
OxFCEOOC
OxFCEOOE

. globl
. data
_u
~ UDOT
cputype: . word
. text
.globl
start:

movw
movl
andl
movl
clrbss: movl
cmpl
jcs

1$:

Turn
Turn
Turn
Turn
Turn
Turn

setup bit off
setup bit on
SEGl bit off
SEGl bit on
SEG2 bit off
SEG2 bit on

_ u, _ segoff

I Local copy of _cputype, 0 if 68000
start, _end, _edata, _main, _cputype, _dispatc
tHIGH, sr
t end+PGSIZE+USIZE-l, d7
i::PGSIZE, d7
t edata, aO
to,aO@+
d7,aO
clrbss

sp17
End of unix
Round to nearest click
Start clearing here
Clear bss

sp@(4),dO
sp@(8),aO
tHIGH, sr
to,SEG1_0
to,SEG2_0
_segoff,dO
to,SETUP_l
dO, UDOT+Ox8008
tOx7FC, UDOT+Ox8000
to,SETUP_O
to,SEG1_l
to,SEG2_0
aO@+,tOxFCFC
tLOW,sr
aO@,al
tl,dO
ale

I spl commands
. globl

_splhi,_spI7 ,_spI6, _sp15,_sp14, _sp13, _spI2, _spll, _splO, _ splx

Start of U dot
Calculate U dot page entry
Calculate U dot page entry
Set Contex 0
Set Contex 0
Enable MMl1 modification
Read segment origin
Disable MMl1 modification
Take just what is valid
Save segment offset
Add segment offset
Enable MMl1 modification
Segment origin
Segment access and length (4 clicks)
Disable MMl1 modification
Subtract off segment offset
Set stack at top of U area
initialize raster display

_splx:

d7, sp@_main

Click address of udot to main
Long jump to unix, init returns here

clrl
movl
clrw
rte

sp@tusTART, sp@-

Indicate short 4 byte stack format
Starting program address
New sr value
Call init

SP@-

.globl
movl
movl

save, resume.
-;p@+,alsp@,aD

qsave
return address
i ptr to label_t

"I

return address
ptr to label_t

_resume:movl
movl
movw
movb
movb
addw
movb
movw
mavw
mavb
movb
movb
moveml
movw
movl
moveq
jmp

subl
moveq
Isrl
movb
movb
movb
movw
movb
andl
movw
addl
movb
movw
movw
movb
subl
movl

movl
jsr

return

sp@+,al
sp@,aO
HO, aO
a6,aO@+
a7,aO@+
al,aO@+
fO,dO
ale

Illegal instruction vector
movec
vbr,dO
No trap. Must be 68010
Local copy

tUSIZE,d7
tPAGESHIFT, dl
dl,d7
to,SEGl 0
to,SEG2-0
to, SETUP 1
0+Ox8008:-dl
to, SETUP 0
tOxFFF,dl
dl,_segoff
dl,d7
to, SETUP 1
d7, UDOT+Ox8008
tOx7FC, UDOT+OxBOOO
to, SETUP 0
dl,d7
tUDOT+USIZE, sp

save d2-d7, a2-a7
save return address

tOxFCFC, aO@
al,aO@(48)
to,dO
ale

_qsa'le: mo'll
movl
addw
movl
movl
movl
moveq
jmp

_splhi:
_sp17 : movw
movw
rts
_sp16: movw
movw
rts
_sp15: movw
movw
rts
_sp14: movw
movw
rts
_sp13: movw
movw
rts
_sp12: movw
movw
rts
_spll: movw
movw
rts
splO: movw
movw
rts

sa-Ie and restore of register sets
save:

moveml
movl
moveq
jmp

I Determine cpu type
movl
U$,16
. word
Ox4E7A
. word
Ox080l
movl
t68010, cputype
movw
tl,cputyPe

jsr

i

1

movw
rts

.data
.globl
_idleflg: . word
.text
. globl
_idle: movw
movw
movw
idlel: tstw
- waitloc:bne

save a6
save a7
save return address
return
click address of new udot
ptr to label_t
spl 7
Set contex 0
Set contex 0
Add segment offset
Enable MMlJ modification
Segment origin
Segment access and length (2k)
Disable MMU modification
Set contex 1
Set Contex 1
restore the registers
restore spl 0
fetch the original pc
return 1
return

sr,dO
tOx2700,sr

fetch current CPU priority
set priority 7

sr,dO
tOx2600, sr

fetch current CPU priority
set priority 6

sr,dO
tOx2500, sr

fetch current CPU priority
set priority 5

sr,dO
tOx2400, sr

fetch current CPU priority
set priority 4

sr,dO
tOx2300, sr

fetch current CPU priority
set priority 3

sr,dO
tOx2200,sr

fetch current CPU priority
set priority 2

sr,dO
tOx2l00, sr

fetch current CPU priority
set priority 1

sr,dO
tOx2000, sr

fetch current CPU priority
set priority 0

sp@ (6), sr

I set priority

_idleflg
0
_idle, idlel, waitloc
Fetch current CPU priority
sr,dO
Set idle flagtl,_idleflg
Set priority zero
tOx2000, sr
wait for interrup-;;
_idleflg
Pseudo location addr used by kernel profiling
idlel

mch.s

Fri Sep

5 19:08:47 1986

movw
rts

dO,sr

.globl
.globl

buserr, addrerr, fault, call, _busaddr
_runrun, _trap

clrw
clrw
moveml
movl
movl
movl
subl
asrl
resched:movl
jsr
addql
jsr
btst
jne
tstb
jeq
movl
jra

2$:

sp@(60),aO
aO,usp
to,SEGl 1
to,SEG2-0
sp@+,tO~7FFF
flO, sp

movl
movl
movb
movb
moveml
addw
rte

I Restore priority
4$:

sp@_idleflg
tOxFFFF,sp@usp,aO
aO, sp@ (60)
sp@(66),dO
t_dispatc+4,dO
f2,dO
dO, sp@_trap
t4,sp
checknet
is, sp@ (70)
2$
runrun
2$
t256,dO
resched

fault:

this makes ps long aligned
clear idle flag
save all registers

check for net int requests
did we come from user mode?
no, just continue
should we reschedule?
no, just return normally
256 is reschedule trap number
go back into trap

2$:

restore usr stack ptr
set Contex 1
set Contex 1
restore all other registers
sp, pop fault pc, and alignment word

syscall, _syscall
sp@I
tOxFFFF, sp@I
usp,aO
aO, sp@ (60)
t5, sp@ (70)
3$
_syscall
checknet
runrun
2$
t256,dO
resched

2$:

movl
movl
moveml
addw
rte

sp@(60),aO
aO,usp
sp@+,tOx7FFF
tlO,sp

moveml
addql
movl
jra

sp@+,tOx7FFF
restore registers
t6, sp
I sp, pop fault pc, and alignment word
t _ dispatc+l32, sp@ I simulate a bsr
fault

this makes ps long aligned
save all registers
save usr stack ptr
did we come from user mode?
no, error !!!
Process syste!!! call
check for net int requests
should we reschedule?
no, just return normally
256 is reschedule trap number
go back into trap

restore user stack pointer
restore all other registers
sp, pop fault pc, and alignment word

Bus error entry, this has its stack somewhat different. We will
call a C routine to save the info then fix the stack to look like a trap.
These entries will be called directly from interrupt vector.
buserr: tstw
bne
moveml
jsr
moveml
addql
35 :
mov1
bra

cputype
3$
tOxCOCO, sp@busaddr
sp@+, tOx303
t8,sp
I
t_dispatctl2, sp@1
fault

test cpu type
branch if 68010
save registers that C clobbers
save the info for a bus or address error
restore registers
pop bsr address, fcode, aaddr and ireg
simulate a bsr

addrerr : tstw
bne
movem1
jsr
moveml

cputype
4$
tOxcOCO, sp@busaddr
-;p@-t,fOx303

test cpu type
branch if 68010
save registers that C clobbers
save the info for a bus or address error
r~store registers

addql
movl
bra

t8, sp
pop bsr address, fcode, aaddr and ireg
t dispatc+l6, sp@ I simulate a bsr
fault

common interrupt dispatch
call:

save usr stack ptr
return ptr from the jsr
subtract dispatch table offset
calculate vector number
argument to trap
C handler for traps and faults

.globl
syscall: clrw
moveml
movl
movl
btst
jne
jsr
jsr
tstb
jeq
movl
jra

3$:

2

moveml
clrw
movl
movl
movl
movl
jsr
addql
jsr
btst
jne
tstb
jeq
movl
jra

tOxFFFF, sp@_idleflg
usp, aO
aO, sp@(60)
sp@(66),aO
sp,sp@aO@
t4,sp
checknet
t5,sp@(70)
2$
runrun
2$
t256,dO
resched

movl
movl
movb
movb
moveml
addw
rte

sp@(60),aO
aO,usp
to,SEGl_l
to,SEG2_0
sp@+, tOx7FFF
flO,sp

save all registers
clear idle flag
save usr stack ptr
fetch interrupt routine address
push argument list pointer onto stack
jump to actual interrupt handler
check for net int requests
did we come from user mode?
no, just continue
should we reschedule?
no, just return normally
256 is reschedule trap number
go back into trap

restore usr stack ptr
set Contex 1
set Contex 1
restore all other registers
sp, pop fault pc, and alignment word
return from whence called

General purpose code
.globl

_tstb, _getusp, _getsr

tstb

Sp@(O)

stack probe instruction prototype

_getusp:movl
movl
rts

usp,aO
aO,dO

get the user stack pointer

_getsr: moveq
movw
rts

to,dO
sr,dO

-

tstb:

I get the sr

Net int request handler
.globl _netisr, _netintr, _svstak
I . globl chkstak
checknet:
tstl
netisr
net requesting soft interrupt?
beq
3$
no: return
movw
tOx2700,sr
set priority 7
tstb
innet
already in net code?
bne
3$
yes: return
movb
t1, innet
no: set flag -> in the net code
movl
sp, svstak
save stack, get net stack
movl
t netstak+2996, sp
Imovw
tOx2600, sr
set priority 6
movw
tOx2000,sr
set priority
jsr
_netintr
do tasks
movl
_svstak, sp
clrb
innet
clear flag
3$:
rts

innet:

. data
. byte
.text
.q10bl

csl, _chkstak

first. staqe of checkstack routine. save regs, call real routine
I csl:
I moveml
tOxFFFF, sp@I save all reqister s
I jsr
chkstak
I really check the stack
I movemlsp@t, fOxFFFF
I restore all reqister s

Fri Sep

m.ch.s
Irts

5 19:08:47 1986

3

Fri Sep

bmfont.h

5 19:07:40 1986

fdefine FONTHORZ
fdefine FONTVERT
char bmfont [1
oxoo,
OxIO,
Ox4S,
Ox4S,
OxIO,
OxOO,
Ox60,
Ox08,
Ox08,
Ox40,
OxIO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
Ox78,
OxIO,
Ox78,
Ox78,
Ox08,
OxFC,
Ox38,
OxFC,
Ox78,
Ox78,
OxOO,
OxOO,
Ox08,
OxOO,
Ox40,
Ox78,
Ox38,
Ox30,
OxF8,
Ox78,
OxFS,
OxFC,
OxFC,
Ox78,
Ox84,
Ox38,
OxIC,
Ox84,
Ox80,
Ox84,
Ox84,
Ox78,
OxF8,
Ox78,
OxF8,
Ox78,
Ox7C,
Ox84,
Ox84,
Ox84,
Ox84,
Ox44,
OxFC,
Ox78,
OxOO,
Ox78,
OxIO,
OxOO,
O'x20,
OxOO,
OxSO,
OxOO,
Ox04,
OxOO,
OxIS,
OxOO,

oxoo,
OxIO,
Ox4S,
Ox4S,
Ox3C,
OxC4,
Ox90,
OxlO,
OxIO,
Ox20,
OxS4,
OxIO,
OxOO,
OxOO,
OxOO,
Ox04,
Ox84,
Ox30,
OxS4,
OxS4,
Ox18,
Ox80,
Ox40,
Ox84,
Ox84,
Ox84,
OxOO,
OxOO,
OxIO,
OxOO,
Ox20,
Ox84,
Ox44,
Ox48,
Ox44,
Ox84,
Ox44,
Ox80,
Ox80,
Ox84,
Ox84,
OxIO,
OxOS,
Ox88,
Ox80,
OxCC,
OxC4,
Ox84,
Ox84,
Ox84,
Ox84,
Ox84,
OxIO,
Ox84,
Ox84,
Ox84,
Ox84,
Ox44,
Ox04,
Ox40,
oxe~,

OxOS,
Ox2S,
OxOO,
OXIO,
OxOO,
OxSO,
OxOO,
Ox04,
OxOO,
Ox24,
OxOO,

-

(

OxOO,
OxIO,
Ox4S,
OxFC,
Ox50,
OxC8,
Ox90,
Ox20,
Ox20,
OxIO,
Ox3S,
OxIO,
OxOO,
OxOO,
OxOO,
Ox08,
Ox8C,
OxSO,
Ox04,
Ox04,
Ox28,
OxFO,
Ox80,
Ox08,
Ox84,
Ox84,
Ox30,
Ox30,
Ox20,
OxF8,
OxIO,
Ox04,
Ox94,
Ox84,
Ox44,
Ox80,
Ox44,
Ox80,
Ox80,
Ox80,
Ox84,
OxIO,
Ox08,
Ox90,
Ox80,
OXB4,
OxA4,
Ox84,
Ox84,
Ox84,
Ox84,
Ox80,
OxIO,
Ox84,
Ox84,
Ox84,
Ox4S,
Ox44,
OxOS,
Ox40,
Ox40,
OxOS,
Ox44,
OxOO,
OXO!,
Ox70,
OxBS,
Ox7S,
Ox74,
Ox7S,
Ox20,
Ox74,

oxOO,
OxIO,
OxOO,
Ox48,
Ox38,
OxIO,
Ox60,
OxOO,
Ox20,
OxIO,
Ox7C,
Ox7C,
OxOO,
OxFC,
OxOO,
OxIO,
OxB4,
OxIO,
Ox18,
Ox3S,
Ox48,
Ox08,
OxF8,
OxIO,
Ox78,
Ox7C,
Ox30,
Ox30,
Ox40,
OxOO,
Ox08,
Ox18,
OxAC,
OxFC,
Ox78,
Ox80,
Ox44,
OxFO,
OxFO,
Ox9C,
OxFC,
OxIO,
Ox08,
OxEO,
Ox80,
OxB4,
Ox94,
Ox84,
OxF8,
Ox84,
OxF8,
Ox78,
OxIO,
Ox84,
Ox48,
OxB4,
Ox30,
Ox38,
Ox30,
Ox40,
Ox20,
Ox08,
OxOO,
OxOO,
IhcOO,
OxOS,
OXC4,
Ox80,
OxSC,
Ox84,
OxFS,
Ox8C,

Oxoo,
OxOO,
OxOO,
OxFC,
Ox14,
Ox20,
Ox94,
OxOO,
Ox20,
OxIO,
Ox38,
OxIO,
OxOO,
OxOO,
Ox30,
Ox20,
OxC4,
OxIO,
Ox60,
Ox04,
OxFC,
Ox04,
Ox84,
Ox20,
Ox84,
Ox04,
OxOO,
OxOO,
Ox20,
OxF8,
OxIO,
Ox20,
Ox98,
Ox84,
Ox44,
Ox80,
Ox44,
Ox80,
Ox80,
Ox84,
Ox84,
OxIO,
Ox08,
Ox90,
Ox80,
Ox84,
Ox8C,
Ox84,
Ox80,
Ox94,
Ox90,
Ox04,
OxIO,
Ox84,
Ox48,
OxB4,
Ox48,
OxIO,
Ox40,
Ox40,
OxIO,
Ox08,
OxOO,
OxOO,
OXOO,
Ox78,
Ox84,
Ox80,
OxS4,
OxFC,
Ox20,
Ox8C,

oxOO,
Oxoo,
OxOO,
Ox48,
Ox78,
Ox4C,
OxS8,
OxOO,
OxIO,
Ox20,
OxS4,
OxIO,
Ox30,
OxOO,
Ox30,
Ox40,
OxS4,
OxIO,
Ox80,
Ox84,
OxOS,
Ox88,
Ox84,
Ox20,
Ox84,
Ox08,
Ox30,
Ox30,
OxIO,
OxOO,
Ox20,
OxOO,
Ox40,
Ox84,
Ox44,
Ox84,
Ox44,
Ox80,
Ox80,
Ox84,
Ox84,
OxIO,
Ox88,
Ox88,
Ox80,
Ox84,
Ox84,
Ox84,
Ox80,
Ox88,
Ox88,
Ox84,
OxIO,
Ox84,
Ox30,
OxCC,
OxS4,
OxIO,
oxeo,
Ox40,
OxOS,
OxOS,
OxOO,
OxOO,
OxOO,
Ox88,
OxC4,
Ox80,
OxSC,
Ox80,
Ox20,
Ox74,

OxOO,
OxIO,
OxOO,
Ox48,
OxIO,
Ox8C,
Ox74,
OxOO,
Ox08,
Ox40,
OxIO,
OxOO,
Ox30,
OxOO,
OxOO,
OxSO,
Ox78,
Ox7C,
OxFC,
Ox78,
Ox08,
Ox70,
Ox78,
Ox20,
Ox78,
Ox70,
Ox30,
Ox30,
Ox08,
OxOO,
Ox40,
Ox20,
Ox3C,
Ox84,
OxF8,
Ox78,
OxF8,
OxFC,
Ox80,
Ox78,
Ox84,
Ox38,
Ox70,
Ox84,
OxFC,
Ox84,
Ox84,
Ox78,
Ox80,
Ox74,
Ox84,
Ox78,
OxIO,
Ox78,
Ox30,
Ox84,
OxS4,
OxIO,
OxFC,
Ox7S,
Ox04,
Ox78,
OxOO,
OxOO,
OxOO,
Ox74,
OxBS,
Ox78,
Ox74,
Ox78,
Ox20,
Ox04,

oxoo,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
Ox60,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
Ox60,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxFE,
Oxoo,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
Ox78,

1*
/*
/*
/*
/*
1*
/*
1*
/*
/*
/*
/*
/*
/*
1*
/*
1*
1*
1*
1*
/*
1*
1*
/*
1*
1*
/*
1*
1*
1*
/*
1*
1*
/*
/*
1*
/*
/*
/*
/*
/*
/*
1*
1*
1*
1*
1*
1*
1*
1*
1*
1*
1*
1*
1*
1*
/*
1*
1*
1*
/*
1*
1*
1*
1*
1*
1*

space *1
*/
u

*1

f */
$ *1
% */

*1
, */
*1
*/
* *1
+ */
, *1
- */
*/
*/
*/
*/
*1
*1
*1
*/
*1
*1
*1
*1
*1
*1
< *1
~ *1
> *1
*1
*1
A *1
B *1
C */
D */
E *1
F */
G */
H */
I *1
J *1
K *1
L *1
M *1
N *1
0 *1
p *1
Q *1
R *1
s */
T *1
u *1
v *1
w *1
x */
y *1
z */
[ *1
\ *1
1 */
*1
*1
*1
a *1
b *1
/* c *1
I" d *1
&

~

..

/* e *1

1* f *1
/* g */

1
Oxso,
OxIO,
Ox08,
OxSO,
Ox30,
Oxoo,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
Ox20,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
Ox38,
OxIO,
OxEO,
OxOO,
OxAA,
);

Oxso,
OxOO,
OxOO,
Ox80,
OxIO,
Oxoo,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
Ox20,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
Ox40,
OxIO,
OxIO,
Ox62,
OxS4,

oxBS,
Ox30,
OxIS,
Ox8S,
OxIO,

axES,
OxFS,
Ox38,
OxBS,
Ox74,
OxBS,
Ox7C,
OxF8,
Ox84,
Ox84,
Ox44,
Ox84,
Ox84,
OxFC,
Ox40,
OxIO,
OxIO,
OxD6,
OxAA,

oxC4,
OxIO,
OxOS,
Ox90,
OxIO,
Ox54,
Ox44,
Ox44,
OxC4,
Ox8C,
OxC4,
Ox80,
Ox20,
Ox84,
Ox84,
Ox44,
Ox48,
Ox84,
Ox08,
OxCO,
OxIO,
OxIS,
Ox8C,
OxS4,

Ox84,
OxIO,
OxOS,
OxAO,
OxIO,
Ox54,
Ox44,
Ox44,
OxC4,
Ox8C,
Ox80,
Ox78,
0x20,
OxS4,
OxS4,
OxS4,
Ox30,
Ox8C,
Ox30,
Ox40,
OxIO,
OxIO,
OxOO,
OxAA,

Ox84,
OxIO,
OxOS,
oxDO,
OxIO,
Ox54,
Ox44,
Ox44,
OxB8,
Ox74,
OxSO,
Ox04,
Ox24,
Ox8C,
Ox48,
OxS4,
Ox4S,
Ox74,
Ox40,
Ox40,
OxIO,
OxIO,
OxOO,
OxS4,

Ox84,
Ox38,
Ox88,
Ox88,
Ox3S,
Ox54,
Ox44,
Ox38,
Ox80,
Ox04,
OxSO,
OxFS,
Ox18,
Ox74,
Ox30,
Ox6C,
OxS4,
Ox04,
OxFC,
Ox38,
OxIO,
OxEO,
OxOO,
OxAA,

Oxoo,
OxOO,
Ox70,
oxOO,
OxOO,
OxOO,
OxOO,
OxOO,
Ox80,
Ox04,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
OxOO,
Ox78,
OxOO,
OxOO,
OxIO,
OxOO,
OxOO,
Ox54,

/*
/*
1*
/*
/*
/*
1*
/*
/*
/*
1*
/*
/*
/*
/*
1*
/*
1*
1*
/*
/*
1*
/*
/*

h *1
i */
j */
k */
1 *1
m

n
o
p
q
r
s
t
u
v
w
x

y
z

-

*1
*1
*/
*1
*1
*1
*/
*/
*1
*/
*/
*1
*/
*1
*/
*1
*1
*1
*/

Fri Sep

cops.h

5 19:07:34 1986

1

1*

* Copyright 19S2 UniSoft corporation
* Use of this material is subject to your disclosure agreement with

*

AT&T, western Electric and UniSoft Corporation.

*

Definitions relating to the COPS and Keyboard SY6522 interface.

*/
tdefine
"define
tdefine
tdefine
fdefine
"define
tdefine
fdefine

/* Breakdown of e ifr (Interrupt Flag Register) of 6522 *1
i* ca2 -- handshake with COPs, not intr source *I
FCA2
OxOI
/* cal -- intr latch for input from COPS *1
FCAI
Ox02
/* shft -- completed eight shifts */
FSHFT
Ox04
1* cb2 -- output to speaker (if suitably programmed) */
OxOS
FCB2
/* cbl -- unused */
FCBl
OxlO
/* timeout of timer two -- unused */
FTlMER2 Ox20
/* timeout of timer one -- lOms clock *1
FTlMERI Ox40
/* interrupt happened (cleared by clearing intr) */
FIRQ
OxSO

struct device e {
char e_fO [1];
char e fl [1]:
char e-f2[1]:
char e:=f3 [1]:
char e f4 [1] :
char e:=f5[1]:
char e f6[1]:
char e-f7[I]:
char e-fS [1]:
char e:= f9 [1] :
char e fa [1] :
char e-fb[l]:
char efc[l];
char e:=fd[l]:
char e fe [1];
char e:=ff[ll:

char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char

e_irb;
e ira;
e:=ddrb:
e_ddra:
e tlcl;
e:=tlch:
e_tlll:
e_tllh;
e_t2cl;
e_t2ch;
e_sr;
e_acr;
eycr;
e_ifr;
e_ier;
e_aira;

1* Keyboard SY6522 VIA *1
1* I/O register B *1
/* I/O register A *1
1* Data Dir reg B *1
/* Data Dir reg A */
/* TI low Latches Counter * /
/* TI hi Latches Counter * I
1* TI low Latches * /
1* TI hi Latches */
/* T2 low Latches Counter */
1* T2 hi Latches Counter */
/*
/*
/*
/*

Shift Register * /
Aux ctrl Reg * I
Perif ctrl Reg * I
Int Flag Reg * I
1* Int Ena Reg *1
/* Alt e_ira (no handshake) */

};

tdefine COPSADDR «struct device_e *) (STDIO+OxDDSO))

1* A port definitions */

1* Connects PR (reset pulse line) to the controller reset switch if low,

*

or the parity reset latch if high (when set as an output).

*1
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

CR
CRDY
PR
FDIR
VC2
VCI
VCO
KBIN

OxSO
Ox40
Ox20
OxlO
OxOS
Ox04
Ox02
OxOI

1* goes low when cops ready for command *1
1* works with CR to get pport parity error */
/* floppy dir interrupt request */

cv.h

J:!"

r i Sep

5 19:07:44 1986

1

/"
" Corvus definitions
" (C) 1984 UniSoft Corp. of Berkeley CA

*
*

UniPlus Source Code. This progra1!! is proprietary
with Unisoft Corporation and is not to be reproduced
" or used in any manner except as authorized in
" writing by Unisoft.

*/
1* block number to virtual drive *1
tdefine cvbtovd(b)
«(b)>>16 & Oxf)+l)
/* virtual drive to block number */
tdefine cvvdtob(vd)
«( (vd) -1) .. Oxf) «

16)

/* cv_stat bits */
tdefine ST_BUSY
tdefine ST_HTOC

Ox02
OxOl

/* host to controller direction */

/* normal mode commands "/
tdefine
tdefine
tdefine
tdefine
Nefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

N READ
N-WRITE
N-PARAM
N-DIAGN
N- R128
N-R256
N- R5l2
N~)n28
N W256
N-W5l2
N:=BOOT

Ox02
Ox02
OxlO
Oxll
Ox12
Ox22
Ox32
Ox13
Ox23
Ox33
Ox14

/* sunol only - copy from one virtual drive to another
(such as tape to disk or disk to tape)

*/
tdefine N_COPY

OxE3

/* diagnostic mode commands */
tdefine
tdefine
tdefine
tdefine
He fine

D RESET
D-FORMAT
D-VERIFY
D- RFIRMWARE
D:=WFIRMWARE

OxOO
OxO 1
Ox07
Ox32
Ox33

tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

/* semaphore commands ,,/
S_INITO
Oxla
S_INITI
OxlO
S_LOCKO
OxOb
S_LOCKI
OxOl
S ULOCKO
OxOb
S:=ULOCKI
Oxll
S_STATO
Oxla
S_STATI
Ox4l
S_STAT2
Ox03

/* normal mode return status */
tdefine NS FATAL
Ox80
/* mask " /
tdefine NS:=VERIFY
Ox40
/* mask ,,/
tdefine NS RECOVER
Ox20
/" mask */
tdefine NS- HFAULT
OxOO
tdefine NS-STINE
OxOl
tdefine NS- SFAULT
Ox02
tdefine NS- SERROR
Ox03
tdefine NS- HCRC
Ox04
tdefine NS-ZFAULT
Ox05
tdefine NS- ZTINE
Ox06
tdefine NS-OFFLINE
Ox07
tdefinelfS- t9F~ULT
oxoe
tdefine NSOx09
tdefine NS:=RFAULT
OxOa
tdefine NS_DATACRC
OxOb

d-profile .1;;;

Fri Sep

5 19:07:34 1986

/" Profile Controller Definitions
* Unless otherwise noted this information comes from an undated
.. document titled ' PROFILE COMMUNICATIONS PROTOCOL' and is apparently
.. either version 3.96 or 3.98
*/
I" command codes *1
I * read command ,,/
'define PROREAD
0
/* write command */
'define PROWRITE
1
/* write/verify command */
'define PROWRITEV
2
/* States (responses read from profile) */
/* Kept in pd._state and pd_nxtst to determine what to do on intr */
'define
'define
tdefine
tdefine
tdefine
'define
'define
'define

SERR
SCMD
SRDBLK
SWRTD
SVERD
SFINI
SPERFORM
SSTOP

pseudo state for err and initialization * /
waiting for a command */
ready to read a block * /
ready to receive for write data */
ready to receive for verify data */
1* pseudo state for write status pickup *1
waiting
to do actual write or verify */
1*
/* pseudo state for idle * /
/*
/*
/*
/*
/*

6

1* Responses sent in reply to controller (messages) */
Ox55
tdefine PGO
1* Proceed to next state (exec cmd) *1
OxOO
tdefine PIDL
/* Quit and return to idle loop *1
1* Polling Delays */
'define RSPTlME
OxCOOO

/* response timeout (-1 ms) */

1* Operation status word breakdown.

Mefine
tdefine
tdefine
tdefine
'define
tdefine
'define

* and kept in pd. sbuf.
*/
1* Breakdown of
FAIL
OxOl
TIMEOUT Ox04
CRCERR Ox08
SEEKERR Ox10
NOTABLE Ox20
ABORTED Ox40
GOAHEAD Ox80

tdefine
tdefine
tdefine
tdefine
'define
'define

BADSEEK
SPARED
RDSTATS
BLKTABO
SECTABO
SEEKER2

Returned for each command

status bits for status Byte 1 *1
/* Operation unsuccessful */
/* Couldn't read header after 9 revs "/
1* CRC error while trying to read/write *1
/* Unable in 3 tries to read 3 con sec sec*/
/* Data table not in RAM (spare updated) *1
/* >532 bytes sent or no spare table read"/
/* If the profile received Ox55 last time*/

1* Breakdown of status bits for status Byte 2 *1
Ox02
1* Seek to wrong track occured *1
Ox04
1* set if sparing occured *1
Ox08
1* Ctrl unable to read status sector *1
OxlO
1* Bad block table overflow: > 100 bads *1
Ox40
1* Spared Sector table overflow >32 secs*1
Ox80

/* unable in 1 try to read 3 consec secs*1

1* Breakdown of status bits for Status Byte 3 *1
'define PARITYE OxOl
/* Parity error *1
tdefine BADRESP Ox02
/* If Ctrl gave a bad response */
tdefine WASREST Ox04
/* If Ctrl was reset * /
tdefine BLKIDMM Ox20
/* Block id at end of sector mismatch */
tdefine BLKNINV Ox40
/* Block number invalid */
tdefine RESETP Ox80
/* Ctrl has been reset */
/* Status byte 4 is the t of errs rereading after read err*/
/* Mask to remove redundant bits from status word */
tdefine STATMSK Ox8000
/* Controller Command Format */
struct cmd {
char
char
char
char
char
char

p_cmd;
p_high;
p_mid;
p_Iow;
p_retry;
p_thold;

/*
/*
/*
/*
/*
1*

command register */
high block byte *1
mid block byte */
low block byte * /
retry count */
threshold count *l

};

'define
tdefine
tdefine
tdefine
tdefine

MAXBLOCK 19455
SECSIZE 512
LOG SS 9
NSEC
16
NRETRY 10

/*
/*
/*
1*
1*

Last sector on disk * /
Number of bytes per sector */
Log (base 2) (SECSIZE) */
Number of sectors/track */
Number of chksum error retries *,'

1
extern struct device_d "pro_da[];
fdefine logical (x)
fdefine interleave (x)
fdefine physical (x)

(minor (x) & 7)
(minor (x) & Ox8)
«minor (x) & OxFOI »

/* eight logicals per phys */
/* interleave bit for swaping */
4)/* 10 physical devs */

/* Since there my be up to ten devices active the driver locals have been
* collected into this structure to allow easy swithing between them.
*/
struct prodata
/* physical dev pointer * /
struct device_d *pd_da;
pd._cmdb;
struct cmd
1* command buffer * I
*pd_actv;
struct buf
I" ptr to active buf */
/* present block being transferred */
pd._blkno;
daddr_t
/* max blk number for this log dev *1
pd limit;
daddr_t
/* present core address *1
pd._addr;
caddr_t
1* present count *1
pd._bcount;
long
/* Status */
pd._sbuf;
long
1* mode of operation flags *1
pd._flags;
long
/* state of controller */
pd. state;
short
pd._nxtst;
short
1* next state scheduled for disk * /
pd._unit;
short
1* phys unit number of this dev * /
pd. offline;
/* wait for disk to come online again */
short
*p~err;
char
/* err mesg for last error */
prodata (NPPDEVS] ;

1* Breakdown of bits in pd. flags above: *1
fdefine NOCHKSUM
OxOl
1* diasble checksums failure on reads *1
fdefine NOPARITY
Ox02
1* disable fail on parity errors *1
extern char pro_ secmap (] ;
fifndef NODEBUG
fdefine DEBUG (xl printf x
felse
fdefine DEBUG (x)
fendif

kb.h
short
short
short
short
char
char
char
char
char
char
char

J:!"ri Sep

5 19:07:37 1986

kb_keycount;
kb_reptrap;
kb_repwait;
kb_repdlay;
kb chrbuf;

kb-ctrl;
kb::: shft;
kb lock;
kb-state:
kb:::idcode;
kb_lastc;

1* state of cops processor *1

1

5 19:07:29 1986

Fri Sep

keyboard.h

1

1* Flags in conversion tables to pick out non-character generating
* keys.

*1
/* iNhen a character is received from the COPS (depending on the state of
.. the shift keys) a table is used to convert it into the ascii equiv.
* If the result is one of the following then it wasn't a keycode at all
* but one of the reset/mouse/clock/plug codes.

*/
tdefine
tdefine
ide fine
tdefine
Mefine
tdefine
tdefine
tdefine
tdefine
tdefine

Imp
KSC
DIP
DIB
D2P
D2B
PPP
MSB
MSP
OFF

/* mouse or reset state flag * /
1* disk inserted into drive one *1
/*
/*
/*
/*
/*
/*
/*

KB_CTRL
KB_SHFT
KB_LOCK
KB_OFF
KB_MSP
KB_ MSB
KB_PPORT
KB D2B
KB- D2P
KB- DIB
KB- DlP
KB-STATE
KB=IMP

/* Cops
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

reset codes */
KB KBCOPS OxFF
KB- IOCOPS OxFE
KB-UNPLUG OxFD
KB- CLOCKT OxFC
KB-SFTOFF OxFB
KB- RESERV OxFO
KB=RDCLK OxEO

OxO
Oxl
Ox2
Ox6
Ox7
Ox8
Ox9
OxA
OxE
OxC
OxD
OxE
OxF

*'

ROpt Ox4E
LOpt Ox7C
Lck Ox7D
sft Ox7E
Cmd Ox7F

1* ASCII codes */
tdefine Del Ox7F
fdefine Bkp Ox08
fdefine Esc OxlB
fdefine Nl OxOA
tdefine Cr OxOD
tdefine Tab Ox09

Del, '-', Alt, Art, '7',
Imp, Imp, Imp, Imp, Imp,
, -', , =' ,'\ \', Imp, 'p',
'9', 'a', 'u', 'i', Ij',
'e', '6', '7', '8', '5',
'a', '2', '3', '4', '1',

'6', Adn,
'2', '3', Nl,
Imp, Imp, Imp, Imp, Imp, Imp,
Imp, Imp, , /', , 1', Esc, Imp,
':','\", I " ',',
'0',
'r', 't', 'y', ", I f I, 'g', 'h', 'v', 'e', 'b' , 'n',
'q', 's', 'w', Tab, 'z', 'x', 'd', Esc, LCK, SFT, CMD,

{ /* convert keycode to shift-locked ascii character
3
4
5
6
8
9
ABC
D
E
F*/
D2P, D2B, PPP, MSB, MSP, OFF, Imp, Imp, Imp, Imp, Imp, Imp, Imp,
Imp, Imp, Imp, Imp, Imp, Imp, Imp, Imp, Imp, Imp, Imp, Imp, Imp,
Art, , 7', , 8', , 9', Aup, , 4', , 5', , 6', Adn, ' . ' , , 2', , 3' , Nl,

I~I~I~I~I~I~I~I~I~I~I~I~I~I~I~I~

' - ' , ' \ \ ' , Imp, 'P', Bkp,

Nl, Imp,

Cr, '0', Imp, Imp,

'I', '1', Esc, Imp,

'9', '0', 'U', 'I', IJI, 'Kit 1[', '1 ' , 'M', 'L', ';','\", I ' ' , ' ,
'0',
'E', '6', '7', '8', '5', 'R', 'T', 'Y', ", 'F', 'G', 'H', 'V', 'C', 'B', 'N',

'A', '2', '3', '4', '1', 'Q', 'S', 'W', Tab, 'Z', 'X', 'D', EsC, LCK, SFT, CMD,
I;
char ToUA [] = { /* Convert keycode into uppercase ascii character
o 1
2
3
4
5
6
7
8
9
ABC
D
E
F*/
KSC, D1P, DlB, D2P, D2B, PPP, MSB, MSP, OFF, Imp, Imp, Imp, Imp, Imp, Imp, Imp,
I~I~I~I~I~I~I~I~I~I~I~I~I~I~I~I~

Del, '-', '+', '*', '7',
Imp, Imp, Imp, Imp, Imp,
'_', '+', '1', Imp, 'P',
1(', I)', 'U', 'I', 'J',
'E'~

''''', '&' t

'A', '@', 'f',

'*'~

'%'~

'8', '9', '1', '4', '5', '6',
Imp, Imp, Imp, Imp, Imp, Imp,
Bkp, Nl, Imp, Cr, '0', Imp,
'K', '{', '}', 'M', 'L', ':',

"
'.', '2', '3', NIl'
Imp, Imp, Imp, Imp, Imp,
Imp, ''?', '1', Esc, Imp,
'"' "
'<', '>', '0',

'R', 'T', 'Y', 1_', 'F', 'G', 'H', 'V', 'C', 'B', 'N',

'$', '!', 'Q', 'S', 'W', Tab, 'Z', 'X', 'D', Esc, LCK, SFT, CMD,

I;

1* mapped onto escape */
/* SHIFT key */
/* SHIFT key */
/ * COMMAND key * /

fdefine Nil
char altkpad []
a
1
2
Nil, Nil, Nil,
Nil, Nil, Nil,
Nil, 'm', 'P',
Nil, Nil, Nil,
Nil, Nil, Nil,
Nil, Nil, Nil,
Nil, Nil, Nil,
Nil, Nil, Nil,

0
{
/* convert keycode into alternate keypad
3
5
6
7
8
9
ABC
Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil,
Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil,
'Q', 'w', 'x', 'y', 'R', 't', 'u', 'v', '1', 'n',
Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil,
Nil, Nil, Nil, Nil, Nil, Nil, , p', Nil, Nil, Nil,
Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil,
Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil,
Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil, Nil,

=

I;

/"* backspace key */

char *ccvtab [1 ToLA,
ToCC,
ToUA,
ToUA,

I;
/** NOTES on character mapping
Left Option -> Esc
Clear
-> Del
Enter
-> Nl
arrows
-> cursor motion in appropriate direction (sequence \E[ control h
right arrow -> control 1

*.

'8', '9', Aup, '4', '5',
Imp, Imp, Imp, Imp, Imp,
Bkp, Nl, Imp, Cr,' 0',
'k', '[', ']', 'm',. '1',

I;

'-'

1* Case change keys
tdefine
Mefine
tdefine
tdefine
tdefine

**/

char ToCC [] =
o
1
2
KSC, D1P, DlB,
Imp, Imp, Imp,
Del, , -', Alt,

/* shift key */
/ * command key * /

tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

('k'&Ox1F)
(' j' &Ox1F)

I~I~I~I~I~I~I~I~I~I~I~I~I~I~I~I~

disk 1 button pushed * /
disk inserted into lower drive */
disk 2 button pushed */
parrallel port plug */
mouse button */
mouse plug */
soft off .. I

/* Alpha lock on *1

tdefine LCK OxF2
tdefine SFT OxFl
tdefine CMD OxFO

('h' &OxlF)
(' l ' &Ox1F)

char ToLA(] = { /* convert key code to lowercase ascii character
012345
ABC
D
E
F*/
KSC, D1P, D1B, D2P, D2B, PPP, MSB, MSP, OFF, Imp, Imp, Imp, Imp, Imp, Imp, Imp,

1* invalid keycode * /

OxFF
OxFE
OxFD
OxFC
OxFB
OxFA
OxF9
OxF8
OxF7
OxF6

-> control k
-> control j

** up arrow
** down arrow
fdefine Cth
fdefine Ctl
fdefine Ctk
fdefine ctj

"*

(v>=' A') U

(v<='D') )

{

/* LCK up, SFT up */
/ * LCK down, SFT up * /
/ * LCK up, SFT down * I
1* LCK down, SFT down */

mode values
D
E
F* /
Nil, Nil, Nil,
Nil, Nil, Nil,
'rt, 's', 'M',
Nil, Nil, Nil,
, q', Nil, Nil,
Nil, Nil, Nil,
Nil, Nil, Nil,
Nil, Nil, Nil,

12.h
int
int
int
int
char
char
char
int
int
char
char
char

12 dtime;
12=:dtrap;
12_dimcont;
12_crate;
12_rcflag;
12 dimmed;
12-bvol;
12=:bpitch;
12 btime;
12-contrast;
12-desired;
12=:defcont;

Eri Sep

5 19:07:41 1986
/*
/*
/"
/"
/*
/*
1*
/"
/*
/"
1*
1*

1

seconds idle before dimming * /
time at which screen will goes dim (mch. s) */
contrast setting when dimmed */
rate at which contrast change occurs ,,/
timeout pending flag for ramp contrast ,,/
contrast is dimmed *1
bell volurnn ,,/
bell pitch */
bell time */
current contrast setting ,,/
desired contrast "I
default contrast ,,/

Fri Sep

local.h

5 19:07:36 1986

1

1* Various machine specific constants *1
1*

* states needed for muli-byte cops input sequences.

*1
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

NOF.Ml>.-LWAIT
MOUSERD
YMOUSE
RESETCODE
SHUTDOWN
CLKREAD

1* must be last * /
720
360

tdefine MAXXLOC
tdefine MAXYLOC

1* Raster Display information ... *1
1* Lowest possible (most dim) contrast setting "/
tdefine TOTALDIM Ox3F
tdefine SCRNSIZE Ox8000

I" 32K */

1* contrast value set by boot rom ,,/
tdefine ONCONT Ox20
tdefine MlIXROW 40
tdefine MAXCOL 90
tdefine BPL
tdefine V RESO
tdefine H:=RESO

90
9

1* The Real Time Clock and Timer (wrist watch type)

* This device hangs off the I/O board cops and is communicated with

*

*
*

through the console VIA (ie. 12copscmd). The command byte is as follows:
Ox02
read clock data; the setting of the clock is returned as
a seven byte reset code.
Ox2C
start clock and alarm set cycle. upto 16 nibbles of alarm
and clock data (aaaaa y ddd hh mm ss t) may be sent as the
low nibble of the following clock command.
Ox1n
write nibble 'n' to clock (only valid after Ox2C cmd)
Ox25
terminates setup cycle and enables clock, timer is still
diabled.
The Clock is connected to the power circuitry and can turn the system off
or be programed to turn it when the timer underflows.
Ox20
disbles the clock, timer, and shuts the system off.
Ox23
shuts off system leaving clock enabled and timer set to
power up on underflow.

*/
tdefine
tdefine
tdefine
tdefine
tdefine

SHUTOFF
READCLOCK
SETCLOCK
CLKNIBBLE
STRTCLOCK

Ox21
Ox02
Ox2C
Ox10
Ox25

1* Other extrainous cops commands */
Ox7F
tdefine MOUSEON
tdefine MOUSEOFF
Ox70
tdefine ENT LOW
Ox6F
tdefine ENT-HI
Ox52
tdefine NMI- LOW
Ox60
tde fine NMI-HI
Ox50
tdefine INn-HI
Ox40
tdefine INn-LOW
Ox30
tdefine KBENABLE
OxOO
struct rtime {
time_t
long
short
"hart
short
short
short
short
}:

1*
1*
/*
1*
1*
/*
1*
/*
1*

mouse on and int's every 28 ms */
mouse off * I
low nibble of lights *1
high nibble of lights * /
low nibble of NMI key ,,/
high nibble of NMI key * I
high nibble of indicator lights */
low nibble of indicator lights * I
enable keyboard *1

/* See page 35 LHRM "I
rt_tod;
/" Seconds since the Epoch *I
rt_alrm;
/" Seconds remaining to trigger alarm "I
rt_year;
/* year
(0 - 15) *1
rt _day;
1* julian day
n - 366) .,
rt hour:
1* hour
(0 - 23) *1
rt:=min;
/* minute
(0 - 59) *1
rt sec:
1*
second
(0 - 59) *1
rt- tenth;
1* tenths of a second
(0 - 9) *1

tdefine MILLIRATE (lOCO/HZ)

/* rate of 1:imer in milliseconds "I

tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

1*
BOOTDEV (* (char *) (Ox1B3»
1*
NSLOTS 3
1*
SLOTIDS « short *) (Ox298»
1*
SLOTID2 « short ") (Ox29A»
SLOTID3 «short *) (Ox29C))
1*
OxFFF
SLOTMASK
1*
ID_ APLNET
1
1*
ID_ 2PORT
2
1*
ID_PRO
1*
ID PRIAM
1*
1*
ExPlVECT
27
devtoslot(d)
«
(d)~O) Z 2
/* dev 0 is ivec 29, dev 1

«

boot device ID (used in system III) *1
number of expansion slots *1
expansion slot 1 card ID *1
expansion slot 2 card ID *1
expansion slot 3 card 10 *1
card type (ID t) of type code *1
card ID for applenet */
card ID for 2-port card * I
card ID for ProFile card *I
card ID for Priam card */
intr vector for 1st of 3 exp cards */
(d)=2) Z 0 : 1) )
is ivec 28, dev 2 is ivec 27 */

Fri Sep

mmu.h

5 19:07:31 1986

1

/*
" Copyright 19S2 unisoft Corporation

* Use of this code is subject to your disclosure agreement with AT&T,
" Western Electric, and UniSoft Corporation
*!
Ide fine NUMCONTX
Ide fine MEMEND
'define MEMBASE

/* number of user contexts */
/* Addr of logical end of mem */
1* Addr of phys beg of mem */

(char H) (Ox2AS)
(long *) (Ox2A4)

/*

*

Constants and definitions

"/
tdefine SPECIO
fdefine STDIO

/* Special I/O address */
/* Standard I/O address *1

OxFEOOOO
OxFCOOOO

1* Special I/O Space Locations */
Idefine STATUSA (char *1 (STDIO+OxFSOO)
fdefine
fdefine
fdefine
Ide fine
tdefine
fdefine
tdefine
'define
tdefine
tdefine
tdefine
tdefine

/* Status Register address */

STATUS "(short *) (STATUSA)
MEMERR * (char *) (STDIO+OxFOOO)
SETUP 0 * (char *) (STDIO+OxE012)
SETUP-1 * (char *) (STDIO+OxE010)
SEG1 () * (char *) (STDIO+OxEOOS)
SEG1-1 * (char *) (STDIO+OxEOOA)
SEG2-0 * (char *1 (STDlO+OxEOOC)
SEG2-1 * (char *) (STDIO+OxEOOE)
VRON* (char *1 (STDIO+OxE01A)
VROFF
" (char "I (STDIO+OxEOlS)
VIDADDR .. (char *) (STDIO+OxESOO)
ADDRMASK OxFFFFFF

/*
/*
/*
/*
/*
/*

/*
/*
/*
/*
/*

/* Status Register */
Memory Error Address Latch */
Turn setup bit off "I
Turn setup bit on * /
Turn SEG1 bit off */
Turn SEG1 bit on */
Turn SEG2 bit off */
Turn SEG2 bit on */
Turn Video retrace int on */
Turn Video retrace int off */
Video address latch * /
relevant address bits *1

/*

*

Access Control Bits

*1
tdefine ASROS
tdefine ASRO

Ox400
Ox500
Ox600
ASRW
Ox700
OxSOO
ASIO
ASINVAL OxCOO
ASSPIO OxFOO
PROTMASK OxFOO

tdefine ASRWS
tdefine
tdefine
fdefine
fdefine
tdefine

tdefine UDOTBASE

/*
/*
/*
1*
/*
/*
/*
/*

Address
Address
Address
Address
Address
Address
Address
Address

space
space
space
space
space
space
space
space

is read only stack

*/

is read only */
is read write stack *1
is read write */
is I/O "I
is invalid */
is special I/O */
protection mask * /
/* Logical base of udot area */

OxFAOOOO

/* Special I/O Bits ,,/
tdefine BSEGORIG
OxS

/* Segment Origin Register * /

/*

* Definitions for memory management.
*/
Ide fine NPAGEPERSEG
256
tdefine SEGMASK
OxFEOOOO
fdefine OFFMASK
Ox1FFFF
tdefine PAGEMASK
Ox1FEOO
tdefine PAGESIZE
512
tdefine PAGESHIFT
tdefine DISPMASK
OxOO1FF
tdefine SEGBASE
OxFFF
tdefine SEGNMASK
Ox3F
tdefine SEGSHIFT
17
'define VIRTSHIFT
9
tdefine ACCLIM
OxOOSOOO
Ide fine ACCSEG
OxOOSOO8

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

/*

number mappable pages per segment * /
mask for segment number as address * /
Offset mask for virtual address */
Page mask for virtual address * /
bytes per page */
page shift for virtual addr */
Disp mask for virtual address */
mask for segment base */
mask for segment number as number */
shift for segment number */
seg shift for virtual address */
Access Limit Register */
Access Segment Register * /

/* Status register bits */

1* Soft Memory Error */
/* Hard Memory Error */

+define S _ 9MEMERR
'define S_HMEMERR
'define S_VR

Ox1
Ox2
Ox4

'define vtoseq (x)

( (int) (x)

/*

vertical Retrace ,,/
&

SEGMASK)

/ * size of the current process
#define procsize (p)
( (p) ->p_size)

*/

/* macros to eliminate sep I/D
'define fuiword (x)
fuword (x)
'define suiword (x, yl
suword (x, yl

*/

ms.h

.I:!"ri Sep

5 19:07:30 1986

1*

* IC) 1983, 1984 Unisoft Corp. of Berkeley CA

*
*

UniPlus Source Code. This program is proprietary
with Unisoft Corporation and is not to be reproduced
* or used in any manner except as authorized in
* writing by Unisoft.

* Driver definitions for the Lisa mouse.
*/
tdefine
tdefine
tdefine
tdefine
He fine
tdefine
tdefine

1* Types of mouse interrupts * I
M FLUSH 0
/* timeout, mouse records out of date */
M-PLUG 1
/* mouse unplugged or plugged in */
M-BUT
2
/* button changed * /
M-CTL
3
/* apple key changed */
M:=SFT
/* shift key changed */
M VRT
/* verticle retrace interrupt (unused) */
M:=MOVE
/ * mouse moved * /

1

pport.h

Fri Sep

5 19:07:38 1986

1

/"
" Copyright 19S2 UniSoft Corporation
* Use of this material is subject to your disclosure agreement with
* AT&T, Western Electric and UniSoft Corporation.

* Parallel Port interface definitions
*/
struct device d {
char d_fO [1]:
char d_fl [7];
char d f2 [7];
char d-f3 [7];
char d-f4 [7];
char d-f5[7]:
char d-f6[7] :
char d=f7[7] :
char d fS[7];
char d-f9[7] ;
char d-fa[7] ;
char d=fb[7] ;
char d fc[7];
char c(fd[7] ;
char d fe[7];
char d=ff[7] ;

char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char

d irb;
(:ira;
~ddrb;

d_ddra;
d_tlcl:
d tlch;
d-tlll:
d=tllh:
d t2cl:
d=t2ch:
d_sr;
d acr;
d:J>cr:
~ifr:

d ier;
d=aira;

/*
/*
/*
1*
/*
/*
/*
/*
/*
/*
/*
/"
/*
/*
/*
/*

I/O register B *1
I/O register A */
Data Dir reg B * I
Data Dir reg A *I
T1 low Latches Counter "/
T1 hi Latches Counter "/
T1 low Latches * /
T1 hi Latches */
T2 low Latches Counter * /
T2 hi Latches Counter */
Shift Register * /
Aux Ctrl Reg */
Perif ctrl Reg */
Int Flag Reg * I
Int Ena Reg * /
Alt d_ira (no handshake) */

};

idefine PPADDR (struct device_d *) (STDIO + OxD900)

idefine
tdefine
tdefine
tdefine
tdefine
tdefine
ide fine
tdefine

/* Breakdown of d irb byte (above) [pg. 45 LHRM APR-S2] *1
OCD
Ox01
/* open cable detect (paper empty) *1
BSY
Ox02
/* Busy bit (handshake line) *1
DEN
Ox04
1* Disk Enable (buffers which drive interface lines) */
DRW
OxOS
/* Direction (Disk Read/Write) off = write to disk *1
CMD
Ox10
/" CMD bit (printer ON/OFF line) *1
PCRK
Ox20
1* enable parity check(input for printer/out for disk) */
DSKDIAG Ox40
WCNT
OxSO

idefine NPPDEVS 10
I" number of parallel port devices */
tdefine PPOK!x) «(x»O) && «x)<9) && «(x)!=3) && «x)!-6»
1* 1,2,4,5,7,S *1
tdefine PPSLOT(x)
«x)/3) 1* expansion slot number from physical unit */

priam.h

5 19:07:36 1986

Fri Sep

/*
" Priam datatower definitions

*
11:

*
*
*

(C) 1984 UniSoft Corp. of Berkeley CA
UniPlus Source Code. This progra...TC. is proprietary
with Unisoft Corporation and is not to be reproduced
or used in any manner except as authorized in
writing by Unisoft.

*1
struct pm base {
j* read registers *1
uchar t status; char xxO;
union-{
ushort WData;
uchar_t PData [2];
I Data;
tdefine data
Data.WData
tdefine pdata
Data.PData[O]
uchar t rO;
char xxl;
uchar:=t rl;
char xx2;
uchar_t r2;
char xx3;
uchar_t r3;
char xx4;
uchar_ t r4;
char xx5;
uchar_t r5;
char xx6;
I;

tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

/* write registers */
cmdreg status
pO
rO'
pl
rl
p2
r2
p3
r3
p4
r4
p5
r5

tdefine
tdefine
tdefine
tdefine
tdefine

/* channel definitions */
DISK
NOTUSED
TAPE
2
HOST
3
SPECIAL 4

/* status register * /
/* rlw disk data register */
1* write only high byte for packet "/
normal word access "I
byte access for packet (format) */
result 0' */
result
*/
result
*1
I" result 3 *1
*1
1* result
I" result
*1

/*
1*
1*
/*
1*

1*
1*
1*
1*

command register */
parameter 0 *1
parameter 1 *1
parameter
*I
/* parameter
*1
1* parameter
"I
1* parameter
*I

IDLING
INITING
DREADING
DWRITING
TREADING
TWRITING
TCONT

0

6

/* read parity register (pmpaddr, 10 select space) */
tdefine parity status
tdefine PMPERROR
O'x80
/* extract parity FF on reads *1
/* status register bits *1
tdefine CMD_REJECT
O'x80
tdefine CMD_DONE
ax40
tdefine CMD_SDONE
Ox20
tdefine BTR_INT
O'xlO'
tdefine ISR_BUSY
O'xa8
tdefine DTREO
axQ4
O'xQ2
tdefine RW REO
tdefine DBUS_ ENA
axO'l

tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

PMNREAD
PMWRITE
PMREAD
PMWMRK
PMRMRK
PMVERIFY
PMREWIND
PMERASE
PMCBTI
PMPKTXFER
PMPKTRST
PMPKTRES
PMPKTABRT
PMADVANCE
PMRETEN

/* results *1
tdefine NPMRES
tdefine PMCTY?E
tdefine PMICOMP
tdefine PMECCERR
tdefine PMDTIMOUT
tdefine PMNH(r)
tdefine PMNC (rl, r2)
tdefine PMNS (r)

1*
1*
1*
1*
1*
1*
1*
1*

command reject *1
command completion request *1
special command completion * /
block transfer - interrupt *1
interface busy * I
data transfer request *1
r Iw request * I
data bus enabled * /

1*
1*
1*
1*
1*
1*
1*
1*
1*
1*
1*
1*
1*
1*
1*

O'x43
Ox52
Ox53
Ox62
Ox63
Ox64
Ox6A
Ox6F
OxOl
OxEO
OxE8
OxEl
OxBF
OxCO
OxCl

read data, retries disabled * I
write data, retries enabled *1
read data, retries enabled *1
write tape file mark *1
read tape file mark * I
verify tape mark * 1
rewind tape * I
erase tape * I
clear "block transfer intr- *1
transfer packet (used for format) *1
read packet status *1
resume packet operation *1
abort packet * I
advance file marks *1
retension tape * I

6
1* number of result registers *1
Ox30
1* error completion type mask (rQ) *1
QxlQ
1* init complete (rO) *1
Qxll
1* ECC error (rO) *1
Qx33
1* timeout error (rO) *1
(int) «r) » 4) 1* no. heads (rl after PMSPINUP) *1
(int)((rl)&QxF)«8)I(r2»/* no. cyls (rl,r2 after PMSPINUP) *1
(int) (r)
1* no. heads (r3 after PMSPINUP) *1

1* parameters ,,/
tdefine PMLOGSECT
tdefine PMPSELl
tdefine PM1PARMS

Qx40
OxQl
OxQ7

I * log. sector mode (pl) * I
1* parm select 1 (pl) *1
1* parm select 1 parameters (p2)
disable high performance I
block transfer intr enabled I

tdefine PMPSELO
tdefine PMOPARMS

QxQO
Qx03

1* parm select 0' (pl) *1
1* parm select 0' parameters (p2)

block transfer timer disable ,,/

auto. defect management enabled I
init. complete intr disabled I
command complete intr enabled I
enable parity "I
tdefine PMCARD
tdefine PMHISEL
1* 10 sel space
tdefine pmlosel (ul
tdefine pmpaddr(u)
1* hi sel space
tdefine pmaddr (u)

1* flag definitions */
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

1

Ox40QO'
1* offset to next card *1
O'x2QOQ
1* offset to hi select space *1
(boot ROM and parity) *1
(O'xFCO'O'O'O + «u) * PMCARD»
«struct pm base *)pmlosel(u»
(data handlIng) *1
«struct pm_base *) (pmlosel (u) + PMHISEL»

1* interface control bits (added to pmaddr) */
tdefine PM N
O'x2O'O
/* no device cycle *1
tdefine PM-I
O'xlO'O'
1* interrupt enable *1
tdefine PM:=B
O'xQ80
1* byte mode */
tdefine PM_W
O'xO'4O'
1* waiting (while U wait) */
tdefine PM_P
OxO'20
1* parity checking enabled *1
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
'define
tdefine

pmNaddr (p)
pmIaddr (p)
pmBaddr (p)
pmWaddr (p)
pmPaddr (pI
pmBWaddr (p)
pmBladdr (pI
pmBIfIaddr (pI

( (struct
( (struct
( (struct
( (struct
( (struct
( (struct
( (struct
( (struct

pm_base
pm_base
pm_base
pm_base
pm_base
pm_base
pm base
pm_base

*)

*)
*)
*)
*)
*1
*1
*1

«(long)p)
«(long)p)
« (longlp)
« (long) pI
«(long)p)
«(long)p)
«Ilonqlp)
« (longlpl

+ PM NI)
+ PM:=II I
+ PM_B) I
+ PM_WI I
+ PM_P»
+PM_B
PMW»
+ PM_B
PM:=Il I
+ PM_B + PM_W + PM_I)

1*
* Format disc packet. parameters structure

*1
/ * commands * /
tdef:i:ne PMRESE'!'

tdefine
tdefine
'define
tdefine
tdefine
tdefine
tdefine

PMSMODE
PMRMODE
PMSETP
PMSPINUPW
PMRDEVPHS
PMSPINDN
PMNWRITE

O'x1
O'x8
Ox9
oxe
ax82
O'x85
ax8l
Ox42

1* software ~set * I
/ * set mode * 1
1* read mode *1
/* specify parameters *1
1* sequence up disk and wait */
/* read device parms * 1
/* sequence down di s k * /
/* write data, retries disabled */

struct pmfmtparms {
unsigned char
tdefine PMFMT
unsigned char
unsigned char
tdefine PMFBD
unsigned char
unsigned short
unsigned char

pm opcode;

Ox02
pm_devsel:
pm_scntl:
Ox8a
pm fill:
pm- ssize;
pm:=dcntl;

1* operation code - PMFMT * I
/* opcode for format *1
1* device select - a (no daisy chaining) */
/ * sector control: FBD, media type * /
/" fill byte disable "/
/* sector control: fill byte *;
/ * sector control: sector size "I
/* defect control: DMD, t spare sectors '/

priam.h
tdefine PMDMD
unsigned
unsigned
unsigned
unsigned
u..."lsigned

Fri Sep
char
char
char
char
char

Ox80
pm ncyl;
pm-cif;
pm-hif;
pm-sif;
p.'tI.:=sitl;

5 19:07:36 1986
1*
1*
1*
1*
1*
1*

2

defect mapping disable *1
defect control: t alternate cylinders *1
interleave control: cyl interleave factor *1
interleave control: head interleave factor *1
interleave control: sect interleave factor "I
interleave control:
sector interleave table length * I

};

1*

*

Packet status report structure (used by packet-based format command)

*!
struct pmfmtstat
unsigned char
unsigned char
tdefine PMPKTCOMP
unsigned char
unsigned char
unsigned char

pmyid;
pmystate;
OxOD
pm tdf;
pmyristat;
pm_xx [32] ;

1*
1*
1*
1*
1*
1*

packet ID * I
packet state *1
packet completed, not resumeable *1
termination device flag *1
primary termination status *1
more status - unused "I

};

1*

*

Header structure
Used by the lisa office system. It's 4 bytes longer than the
header for the profile, to include the size of the disk, but
otherwise the same (see profile. h) .

*1
struct pmheader (
unsigned short
unsigned short
unsigned short
unsigned short
unsigned int
unsigned short
unsigned int
unsigned short
unsigned int

pm_version;
pm_volume;
pm_fileid;
pm_csl;
pm cs2;
pm_relpage;
pm_nblk;
pmJ>blk;
pm_size;

1* unused *1
/* unused *1
/* must be OxAAAA for the boot block * /
/* unused */
1* unused */
/" unused */
/* unused *1
1* unused *1
size of disk *1
1* unused

-

};

tdefine HDRSIZE (sizeof (struct pmheader»
tdefine FILEID OxAAAA
1* file id for boot block
tdefine TIMELIMIT
tdefine NPM

500000

I * timeout

0

*I

f about 5 secs.

*I

Fri Sep

profile.h

5 19:07:32 1986

I" Disk Header Layout
" Used by the lisa office system

"I
struct proheader
unsigned short
u.'"l.signed short

unsigned short
unsigned short
unsigned int
unsigned short
unsigned int
unsigned short

ph_version;
ph datastk:2,
ph-reserved: 6,
ph-volume: 8;
ph- fileid;
ph::::havcsum:l,
ph_dataused:15;
ph_abspage:24,
ph chksum: 8;
ph-relpage;
ph-forward: 24,
ph- bckhigh: 8;
ph::::bCklOW;

I" as version number *1
1* kind of info in this block *1
1*
1*
1*
1*
1*
1*
/*
1*
I*
1*

disk volumn number *1
type of file *1
whether ph chksum is valid *1
valid byte-count *1
page in filesystem */
checksum *1
page in file *1
next block *1
high byte of prev block *1
low word of prev block */

};

tdefine HDRSIZE (sizeof (struct proheader»
struct proidblk
char
char
short
char
char
char
char
char
char
};

pi devn[13];
p(~dnum[3] ;
pi_revn;
pi blkcnt [3] ;
pi-blksiz [2];
pi::::spavail;
pi_spalloc;
pi_bbcnt;
pi_blist [486];

1*
I*
1*
1*
I"
1*
1*
1*
1*

device name *1
device number (currently 0) *1
micro code revision number */
number of useable blocks *I
number of bytes per block * I
number of spare sectors avail *1
number of spare sectors allocated *1
number of bad blocks below *1
list of bad and spared sectors *1

1

reboot.h

Fri Sep

5 19:07:33 1986

1*
" (C) 1984 UniSoft Corp. of Berkeley CA

* UniPlus Source Code. This program is proprietary
" with Unisoft Corporation and is not to be reproduced

* or used in any manner except as authorized in

*

writing by Unisoft.

*/

/* This is the command value for the console ioctl which
" jumps to the start of unix. It is only compiled into
* the installation unix sunix.
*/
fdefine RESTART ('R'«8)
/* restart unix */

1

scc.h

Fri Sep

5 19:07:39 1986

1
tdefine W4CLK32
fdefine W4CLK64

/*
Zilog ZS530 SCC Chip
Copyright 19S1 UniSoft Corporation
*/
/" read
fdefine
fdefine
fdefine
fdefine
fdefine
fdefine
fdefine
tdefine

register 0 bits */
RORXRDY OxOI
ROZERO Ox02
ROTXRDY Ox04
RODCD
OxOS
ROSYNC OxlO
ROCTS
Ox20
ROUNDERRUN Ox40
ROBREAK OxSO

/* read
tdefine
fdefine
fdefine
fdefine
fdefine
tdefine

register 1 bits * /
RIALLSENT
OxOI
RIRESIDUE
OxOE
RIPARERR
OxlO
RIOVRERR
Ox20
RIFRMERR
Ox40
RIENDFRAME
OxSO

1*
/*
/*
/*
/*

receiver is ready *1
zero count */
transmitter is ready */
data carrier detect *1
sync */
/ * clear to send * /
/* transmitter under run */
/" break */

/*
/*
/*
/*
/*
/*

ASync mode: all data cleared transmitter */
residue bits (see tables) */
parity error */
lost characters due to overrun */
CRC or framing error */
SDLC: end of frame * /

/* write register 0 - command register * /
tdefine WONULL
OxOO
1* null code "/
tdefine WOPOINTHIGH
OxOS
/* select second bank of registers */
fdefine WOREXT
OxlO
/* reset external/status interrupt */
fdefine WOABORT
OxlS
/* send abort * /
fdefine WORXINT
Ox20
/* enable interrupt on next Rx char */
fdefine WORTXPND
/* reset transmitter interrupt pending */
Ox2S
fdefine WORERROR
Ox30
/ * error reset * /
tdefine WORIUS
/* reset highest interrupt under service */
Ox3S
fdefine WORXCRC
/* reset Rx crc checker */
Ox40
tdefine WOTXCRC
/* reset Tx crc generator */
oxSO
tdefine WOTXURUN
OxcO
/* reset Tx underrun/eom latch */
/* write register 1 - xmit/rcv interrupt and data xfer mode * /
fdefine WIEXTIEN
OxOl
/* external interrupt enable *1
fdefine WlTXIEN
Ox02
1* transmitter interrupt enable */
fdefine NIPSC
Ox04
/* parity is a special condition *1
fdefine WIRXDI
OxOO
1* Rx int disable */
fdefine WlRXIFIRST
OxOS
1* Rx interrupt on first char or special */
fdefine WlRXIALL
OxlO
1* Rx interrupt on all chars or special *1
fdefine WIRXISC
OxlS
1* Rx interrupt on special condition only *1
fdefine WlWDMARCV
Ox20
/* wait/dma request on receive/transmit *1
fdefine WlWDMARF
Ox40
1* wait/dma request function */
fdefine WlWDMARE
OxSO
I" wait/dma request enable */

/* write register

- interrupt vector */

/* write register 3 - receive parameters and control */
tdefine W3RXENABLE
OxOl
/* Rx enable */
tdefine W3SCLI
Ox02
/* sync character load inhibit */
fdefine N3ASM
Ox04
/ * address search mode (sdlc) * /
fdefine W3RXCRC
OxOS
/* Rx crc enable */
fdefine W3EHUNT
OxlO
/ * enter hunt mode * /
tdefine N3AUTOENABLES
Ox20
/" auto enables * I
fdefine N35BIT
OxOO
/* 5 bit data */
fdefine W36BIT
Ox80
/* 6 bit data * /
tdefine W37BIT
Ox40
/*
bit data .. /
fdefine W3SBIT
OxCO
/* 8 bit data */

/* write register
- xmit/rcv misc parameters and modes */
tdefine W4PARENABLE
OxOl
/* parity enable * /
tdefine W4PAREVEN
Ox02
/* even parity * /
fdefine W4ENSYNC
OxOO
/ * enable sync modes * /
fdefine W4lSTOP
Ox04
/* 1 stop bit * /
tde fine 1f415STOP
Oxos
1* 1. S stop bits *!
tdefine W42STOP
OxOC
/* 2 stop bits * /
tdefine W48SYNC
OxOO
/* 8 bit sync character * /
tdefine W4l6SYNC
OxlO
/* 16 bit sync character */
fdefine W4SDLC
Ox20
/* sdlc mode (01111110 flag) */
tdefine W4EXTSYNC
Ox30
1* external sync mode * I
tdefine W4CLKI
OxOO
/* X 1 clock mode */
fdefine W4CLK16
Ox40
/* X 16 clock mode xi

OxSO
OxCO

/* X 32 clock mode */
/* X 64 clock mode */

/* write register 5 - transmit parameter and control */
tdefine W5TXCRC
OxOl
/* Tx crc enable */
fdefine ~5RTS
Ox02
/* rts */
·Mefine W5CRC16
Ox04
/* crc-16/sdlc */
fdefine W5TXENABLE
OxOS
/* transmitter enable */
OxlO
/* send break */
tdefine W5BREAK
tdefine WS5BIT
OxOO
/* 5 or less bit data */
fdefine W56BIT
Ox40
/* 6 bit data * /
tdefine W57BIT
Ox20
/* 7 bit data * /
tdefine WSSBIT
Ox60
/* S bit data */
tdefine WSDTR
OxSO
/* data terminal ready */
/* write register

- sync chars or sdlc address field */

/* write register

- sync chars or sdlc address flaq */

/* write register

- transmit buffer */

/* write register 9 - master interrupt control ,,/
fdefine W9VIS
OxOl
1* vector includes status */
tdefine W9NV
Ox02
1* no vector */
tdefine W9DLC
Ox04
/ * disable lower chain * /
tdefine W9MIE
OxOS
/* master interrupt enable * /
fdefine W9HIGHSTATUS
OxlO
/* status high/low */
fdefine W9BRESET
Ox40
/* channel b reset */
fdefine W9ARESET
OxSO
/* channel a reset */
fdefine W9HRESET
OxCO
/* force hardware reset */
/* write register 10 - misc transmitter/receiver control bits */
fdefine Wl06BITSYNC
OxOI
/* 6 bit/8 bit sync */
tdefine WlOLOOP
Ox02
/* loop mode */
tdefine WlOAUR
Ox04
/* abort/flag on underrun */
tdefine WIOMAR!<
Ox08
/* mark/flag idle */
tdefine WIOAPOLL
OxlO
/* go active on poll */
fdefine WlONRZ
OxOO
/* nrz * /
tdefine WlONRZI
Ox20
/* nrzi * /
tdefine WlOFMl
Ox40
/* fml * /
fdefine WlOFMO
Ox60
/* fmO * /
tdefine WlOCRCPRESET
Ox80
/* crc preset I/O * /
/* write register 11 - clock control mode * /
tdefine W110XTAL
OxOO
/* crystal output */
fdefine W110XCLK
OxOl
/* transmit clock *1
fdefine W110BR
Ox02
/* baud rate generator output */
fdefine W110DPLL
Ox03
/* dpll output */
fdefine W11TRxC
Ox04
/* TRxC 0/1 * /
tdefine W11TRTxC
OxOO
/* transmit clock RTxC pin */
tdefine W11 TTRxC
OxOS
/* transmit clock TRxC pin */
tdefine W11TBR
OxlO
/* transmit clock baud rate generator */
tdefine W11 TDPLL
OxlS
/* transmit clock dpll output */
fdefine W11RRTxC
OxOO
/* receive clock RTxC pin */
fdefine W11RTRxC
Ox20
/* receive clock TRxC pin */
tdefine WllRBR
Ox40
/* receive clock baud rate generator */
tdefine W11RDPLL
Ox60
/* receive clock dpll output */
fdefine WllXTAL
OxSO
/* crystal */
/* write register 12 - lower byte of baud rate generator */
/* write register 13 - upper byte of baud rate generator */
/* write register 14 - misc control bits */
fdefine W14BRGE
OxOl
/* baud rate generator enable * /
fdefine W14BRINT
Ox02
/ * baud rate generator internal * /
fdefine W14DTRREQ
Ox04
i* dtr/req function */
tdefine W14AUTOECHO
Ox08
/* auto echo */
tdef'irre 9f14LOCI':LLB
OxIO
1* local loop back * I
OxOO
tdefine W14NULL
/ * null command * /
tdefine W14ESM
Ox20
/* enter search mode */
Ox40
fdefine W14RMC
/* reset missing clock * /
Ox60
fdefine W14DDPLL
/* disable dpll */
Ox80
tdefine W14SBRGEN
i* set source baud rate generator *1
OxAO
fdefine W14SRTxC
i* set source RTxC */
Idefine W14SFM
OxCD
/* set fm mode * /

Fri Sep

scc.h
tdefine Wl4SNRZI
struct device
char
char

DxED

5 19:07:39 1986

I * set nrzi mode

*/

durnl;
csr;

char

du..~

char

data;

[3];

I;

1* structure for storage of port reset code and baud generator speed
*/
strllct scline !
char reset;
long speed;
I;

2

Fri Sep

sony.h

5 19:07:43 1986

1
{define
fdefine
fdefine
fdefine
fdefine

1*

*

sony definitions

*

IC) 1984 UniSoft corp. of Berkeley CA

SN_STMASK
SN_CLRINT
SN_WAITRM
SN_GOAWAY
SN_CLEARMSK

Ox86
Ox8?
Ox88
Ox89
Ox??

* UniPlus Source Code. This program is proprietary
1* ROM revision number indicates twiggy vs. sony and fast vs. slow timer. *1
fdefine ROMMASK
OxEO
1* look at these bits only *1
fdefine ROMTW
Ox80
1* O-twiggies, I-sony *1
fdefine ROMSLOW
Ox20
1* for Lisa 2s, O=fast, I-slow *1

.. with Unisoft Corporation and is not to be reproduced
* or used in any manner except as authorized in
* writing by Unisoft.

*;
struct s_iob
char
char
tdefine mask
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char

{
dumOO;
dum01;
crnd
dum02;
dum03;
dum04;
dum05;
dum06;
dumO? ;
dum08;
dum09;
dum11;
dum12;
dum13;
dum14 [23];
dum15 [15];
dum16[?] ;
dum1? [21] ;
dum18 [49];
dum19;
durn20;
durn21;
durn22;
durn23;
durn24;
durn25;
durn26[88] ;

unsigned char gobyte;
unsigned char crnd;
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned

char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char
char

drive;
side;
sector;
track;
unused;
confirm;
status;
format;
type;
error;
seek;
rom id;
diskin;
drv connect;
int~_status;
d_strt_bitslip;
d end bitslip;
d::::checksum;
a_strt_bitslip;
a end bitslip;
a - wrng sector;
wrng-track:
a::::checksum;
crnd_index;

1*
1*
1*
1*

FCC031
FCC041
FCC049
FCC05F

*1
*1
*1
*1

a

};

struct sn hdr {
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned

short
short
short
short
short
short

version;
volume;
fileid;
relpg;
dum1;
durn2;

1*
1*
1*
1*
1*
1*

unused *1
unused *1
must be OxAAAA for the boot block *1
unused *1
unused */
unused */

};

tdefine FILEID
tdefine
tdefine
tdefine
tdefine

1* file id for boot block *1

OxAAAA

SNIOB «struct s iob *) OxFCCOOO)
SN_HDRBUF OxFCC3E8
1* 12-byte header of 524-byte buffer *1
SN_DATABUF OxFCC400
1* real 512-byte buffer *1
SN_CMD_BASE OxFCC103
/* where the old commands are */

tdefine NSN
tdefine SN_MAXBN

1* SONY
tdefine
fdefine
tdefine
tdefine
tdefine
fdefine
tdefine
tdefine
tdefine
tdefine

COMMANDS *1
SN_READ
SN_WRITE
SN_EJECT
SN_FORMAT
SN_VERIFY
SN_FMTTRK
SN_VFYTRK
SN_RDBRUT

tdefine
fdefine
fdefine
tdefine
fdefine

SN_SHAKE
SN_CMD
SN_SEEK
SN_CALL
SN_CLRST

800

SN_WRTBRUT

SN_CLAMP
Ox80
Ox81
Ox83
Ox84
Ox8S

Fri Sep

sunol.h

5 19:07:33 1986

1

1*

* Sunol definitions

*

(C) 1984 Unisoft corp. of Berkeley CA

* UniPlus Source Code. This proqra."!l is proprietary
* with Unisoft Corporation and is not to be reproduced

*
*

or used in any manner except as authorized in
writing by Unisoft.

*1
1*
This block is returned when a Uqet drive parameters" command is
issued.

*1
struct sdparam {
char fwmsg[31];
1* firmware message *1
unsigned char revision; 1* revision number *1
unsigned char romv;
/* ROM version */
/* next four bytes are for entire disk * /
unsigned char spt;
1* sectors per track */
unsigned char tpc;
1* tracks per cylinder *1
unsigned char cpd lsb; /* cylinders per drive (least sig byte) */
unsigned char cpd-msb; /* cylinders per drive (most sig byte) * /
/* next three bytes are for specific virtual drive */
unsigned char nblk Isb; /* capacity in 512-byte blks (least sig byte) *1
unsigned char nblk-nsb; /* capacity in 512-byte blks (next sig byte) */
unsigned char nblk-msb; /* capacity in 512-byte blks (most sig byte) *1
char fill[88];
1* fill to 128 bytes */
);

/*
This block is used to issue a copy command which copies from one
virtual drive to another. The tape unit is virtual drive 9, and
the disk can be divided into virtual drives 1-7. If the command
returns a non-zero status then the amount that was not copied is
specified in 10 bytes corresponding to the bytes from srcvd to
mcount. These blocks can be transferred using normal reads and
writes (in start/stop mode) .
*/
struct copyparam
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned

(
char
char
char
char
char
char
char
char
char
char
char
char

);

tdefine TAPEVD

9

command;
srcvd;
lsrcstart;
msrcstart;
filll;
destvd;
Ideststart;
mdeststart;
fil12;
lcount;
mcount;
chksum;

/* copy command - OxE3 */
/* source virtual drive *1

/ * source starting sector * I
1*
1*
1*
/*
1*
/*
/*
/*
1*

source starting sector */
upper byte of starting sector *1
destination virtual drive *1
destination starting sector */
destination starting sector *1
upper byte of starting sector * /
sector count for copy *1
sector count for copy *1
all 12 bytes add to zero * /

swapsz.h

Fri Sep

5 19:07:30 1986

1*

*

(C) 1984 UniSoft Corp. of Berkeley CA

*

UniPlus Source Code. This program is proprietary
* with Unisoft Corporation and is not to be reproduced
or used in any rna.~'").er except as authorized in
* writing by Unisoft.

*1
tdefine PRNSW!>..P 2400
tdefine CVNSWAP 3959
tdefine PMNSWAP 4000

1* swap size for ProFile *1
1* swap size for Corvus *1
1* swap size for Pria...'!l *!

1

Fri Sep

acct.c

5 19:07:45 1986

1

1* @(t) acct. c
1.2 *1
tinclude "sys/param.h"
tinclude "sys/types.h"
tinclude "sysl systm.h"
tinclude "sys/acct.h"
tinclude "sys/dir .h"
tinclude "sys/siqnal.h"
tinclude "sys/user .h"
tinclude "sys/errno.h n
tinclude ·sys/inode.h u
tinclude "sys/file.h"

ap->ac stime = compress (up->u stime);
ap->ac-etime - compress(lbolt-- up->u ticks);
ap->ac-mem - compress (up->u mem);
ap->ac-io = compress{up->u loch);
ap->ac-rw - compress (up->u-ior+up->u iow);
ap->ac-uid = up->u ruid; ap->ac=gid - up->u=rgid;
ap->ac tty ~ up->u ttyp 2 up->u ttyd
NODEV;
ap->ac-stat - st; ap->ac=flag - up->u_acflag;
siz - ip->i size;
up->u_offset = siz;
up->u base - (caddr t) ap;
up->u=count = sizeof(acctbuf);
up->u_segflg = 1;
up->u error - 0;
up->u~)imit = (daddr_t) 5000;
up->u fmode - FWRITE;
writel (ip);
if (up->u_error)
ip->i size = siz;
prele(ip);
-

1*
" Perform process accounting functions.

*1
sysacct ()
(

register struct inode "ip;
register struct a {
char
"fname ;
} "uap;
static aclock;
uap

~

(struct a *)u.u ap;

i f (aclock II ! suser (l)

return;
aclock++;
switch (uap->fname)
case NULL:
i f (acctp) (
plock (acctp) ;
iput (acctp) ;
acctp - NULL;
break;
default:

1*
" Produce a pseudo-floating point representation
with 3 bits base-8 exponent, 13 bits fraction.
*1
compress (t)
register time t t;
{
register exp = 0, round = 0;

*

while (t >- 8192)
exp++;
round = t&04;
t

if (acctp)
u.u_error - EBUSY;
break;
ip = namei(uchar, 0);
i f (ip - NULL)
break;
if «ip->i_mode & IFMT) != IFREG)
u.u_error = EACCES;
else
(void) access (ip, limITE);
if (u.u error) {
-iput (ip);
break;
acctp = ip;
prele(ip) ;
aclock--;

1*
" On exit, write a record on the accounting file.
*1
acct(st)
{

register struct inode "ip;
register struct user *up;
register struct acct "ap;
off_t siz;
i f «ip-acctp)
return;
up = &u;
plock (ip) ;
ap - &acctbuf;
bcopy( (caddr t)up->u comm, (caddr tlap->ac comrn, sizeof(ap->ac_comrn)):
ap->ac btime-. up->u- start;
ap->ac:='utirne - compress (up->u_U1:imej ;

»= 3;

i f (round) (
t++;
i f It >- 8192) {
t

»= 3;

exp++;
return «exp«13) + t);

E'ri Sep

af.c

5 19:09:24 1986

/*
aLc
4.7
82/10/17
finc1ude "sys/param.h"
tinclude "sys/config.h"
tinclude "sys/errno.h"
tinclude "sys/types .h"
tinclude "sys/ systm. h"
tinclude "net/misc.h"
tinclude "netl socket. h"
tinclude "net/ socketvar. h"
tinclude "net/mbuf .h"
tinclude "net/protosw. h"
tincluds -net/af .h"

*1

1*

*

Address family support routines

"I
int
null hash (), nUll_netmatch () ;
fdefine AFNULL \

tifdef INET
extern int inet hash (), inet_ netmatch () ;
tdefine AFINET "\
telse
tdefine AFINET
tendif

AFNULL

tifdef PUP
extern int pup hash(), pup_netmatch();
tdefine AFPUP "\
telse
tdefine AFPUP
tendif

AFNULL

struct afswitch afswitch[AF_MAXJ - {
AFNULL, AFNULL, AFINET, AFINET, AFPUP,
AFNULL, AFNULL, AFNULL, AFNULL, AFNULL,
AFNULL
};

/*ARGSUSED* /
null_hash (addr, hpj
struct sockaddr "addr;
struct afhash *hp;

hp->afh_nethash - hp->afh_hosthash - 0;
/*ARGSUSED* /
null_netmatch(a1, a2)
struct sockaddr *a1, *a2;
return (0);

1

Fri Sep

alloc.c

5 19:07:46 1986

I" @(t)alloc.c 1.4 "I
'include "sys/param.h"
tinclude "sys/types .h lO
tinclude "sys/sysmacros .h lO
tinclude "sys/systm.h"
tinclude "sys/mou.,t.h"
tinclude Rsys/filsys. hOI
#include "sys/fblk.h"
'include ·sys/buf .h"
'include ·sys/inode .h"
'include "sys/file.h"
tinclude ·.syg!ino~h"
tinclude ·sys/dir .h"
tinclude ·sys/signal.h"
tinclude • sys/user. h"
'include ·sys/errno.h"
'include ·sys/var.h"

1
fp->s tfree - 0;
delay(v. v hz«2);
prdev("no-space", dev);
u.u_error - ENOSPC;
return (NULL) ;

I"

* place the specified disk block back on the free list of the
" specified device.

"I
free (dev. bno)
dey t dey;
daddr t 000;
{
register struct filsys "fp;
register struct buf "bp;
fp = getfs (dev);
fp->s fmod = 1;
while(fp->s flock I
(voId) sleep(
if (badblock(fp, bno,
return;
if (fp->s nfree <- 0)
fp->s nfree fp->s::::free[O]

/*

*
*

alloc will obtain the next available free disk block from the free list
of the specified device.
" The super block has up to NICFREE remembered free blocks;
" the last of these is read to obtain NICFREE more . . .
" no space on dey x/y -- when the free list is exhausted.

*1
struct buf
alloc(dev)
dev_t dey;

*

register daddr t bno;
register struct filsys "fp;
register struct buf "bp;

Prevent "dups in free"

*1
bp = getblk(dev, SUPERB);
bcopy( (caddr t) fp, bp->b_un.b_addr, sizeof(struct filsys»;
fp->s fmod --0;
fp->s-time = time;
bwrite (bp) ;
fp->s flock - 0;
wakeup ( (caddr_t) &fp->s_flock);

=

bno;

1*

* Check that a
" and the size
" This is used
" garbage file

block number is in the range between the I list
of the device.
mainly to check that a
system has not been mounted.

" bad block on dey x/y

*

= 0;

fp->s_free[fp->s_nfree++]
fp->s tfree++;
fp->s::::fmod - 1;

brelse (bp) ;

1*

{

1;

if (fp->s_nfree >- NICFREE)
fp->s flock++;
bp - getblk(dev, 0001;
(bp->b un. b fblk) ->df nfree - fp->s _ nfree;
bcopy«caddr t)fp->s free,
(caddr t) (bp=>b un.b fblk)->df free,
sizeof(fp->s_free) 1;fp->s nfree = 0;
bwrite(bp) ;
fp->s flock = 0;
wakeup ( (caddr_t) &fp->s_flock);

{

fp = getfs (dev) ;
while (fp->s flock)
(voId) sleep ( (caddr_t) &fp->s_flock, PINOD);
do (
if (fp->s_nfree <- 0)
goto nospace;
bno = fp->s free[--fp->s nfree];
i f (bno = 0)
goto nospace;
} while (badblock(fp, bno, dev»;
i f (fp->s nfree <= 0) (
fp->s flock++;
bp - bread(dev, bno);
if (u.u error = 0) (
- fp->s nfree - (bp->b un.b fblk) ->df nfree;
bcopy( (caddr t) (bp->b un.b fblk) ->df free,
(caddr_tlfp->s_free, sIzeof(fp->;_free»;

(caddr t) &fp->s flock, PINOD);
dev»-

not in range

"I
badblock (fp, bn, devl
register struct filsys "fp;
daddr_t bn;
dey t dey;
{

-

if (bn < fp->s isize I I bn >= fp->s_fsizel
prdev("bad block", devl;
return (1 I ;
return (0) ;

if ifp->s_nfree <- 0 i i fp->s_nfree > NICFREE)
prdev("Bad free count", dev);
goto nospace;
bp = -;etblk (dev, bno):
clrbuf (bp) ;
if (fp->s_tfree) fp->s_tfree--;
fp->s fmod - 1;
return (bpi;
nospace:
fp->s_nfree - 0;

1*
.. Allocate an unused I node on the specified device.
.. Used with file creation.
.. The algorithm keeps up to NICINOD spare I nodes in the
.. super block. When this runs out, a linear search through the
.. I list is instituted to pick up NICINOD more.
*/
st ruct inode "
ialloc(dev, mode, nlinkl
dev_t dev;

Fri Sep

alloc.c

5 19:07:46 1986

2
return (NULL) ;

register struct filsys *fp;
register struct inode *ip;
register i;
register struct buf *bp;
struct dinode *dp;
ino_t ino;
daddr_ t adr;

1*
* Free the specified I node on the specified device.
* The algorithm stores up to NICINOD I nodes in the super
* block and throws away any more.

*1
ifree(dev, ino)
dev_t dey;
ino_t ino;

fp - getfs (dev) ;
loop:
while !fp->s ilock)
(voId) sleep «caddr t) &fp->s ilock, PINOD);
if (fp->s nino de > 0
&& (ino - fp->s inode [--fp->s ninode))
ip - iget(dev, ino);
if (ip - NULL)
return (NULL) ;
if (ip->i mode - 0) {
/; found inode: update now to avoid races * I
ip->i mode - mode;
ip->i-nlink - nlink;
ip->i-flag 1- IACCI IUPDI ICHGI ISYN;
ip->i-uid - u.u uid;
ip->Cgid - u.u-gid;
ip->i-size - 0;for (1=0; ii addr[i) - 0;
i f (fp->s_tinodel fp->s_tinode--;
fp->s fmod - 1;
iupdat (ip, &time, &time);
return (ip) ;

(

register struct filsys *fp;
fp - getfs (dev) ;
fp->s tinode++;
i f (fp->s_iloCk)
return;
fp->s fmod - 1;
i f (fp->s nino de >= NICINOD) {
if (ino < fp->s inode[O])
fp->s_inode[O] - ino;
return;
fp->s_inode [fp->s_ninode++)

ino;

1*
* getfs maps a device number into a pointer to the incore super block.
* The algorithm is a linear search through the mount table.
* A consistency check of the in core free-block and i-node counts.
* bad count on dey x/y -- the count
check failed. At this point, all
the counts are zeroed which will
almost certainly lead to "no space"
diagnostic
* panic: no fs -- the device is not mounted.
this "cannot happen"

1*
* Inode was allocated after all.
* Look some more.

*1
iupdat (ip, &time, &time);
iput(ip) ;
goto loop;

*1

fp->s ilock++;
fp->s-ninode - NICINOD;
ino = - F sINOS (dev, fp-> s inode [OJ) ;
for (adr = FsITOD (dev, ino); adr < fp->s_isize; adr++) {
bp = bread(dev, adr);
if (u.u_error) (
brelse (bp) ;
ino += FsINOPB(dev);
continue;

struct filsys *
getfs(dev)
dey t dey;
(

-

register struct mount *mp;
register struct filsys *fp;
for(mp - &mount[O); mp < (struct mount *)v.ve_mount; mp++)
if (mp->m flags = MINUSE && mp->m dey - dey) (
fp = mp->m bufp->b un.b filsys;
i f (fp->s nfree > NICFREE II fp->s nino de > NICINOD)
p~dev("bad count", dev); fp->s nfree = 0;
fp->s=:ninode = 0;

dp = bp->b un.b dino;
for(i-O; fs nino de <- 0)

b~eak;
i f (dp->di mode == 0)
fp=>s_ inode [--fp->s_ ninode]

=

return(fp) ;
ino;
panic("no fs");
return (NULL) ;

brelse (bp) ;
if (fp->s_ninode <= 0)
break;

/*
fp->s ilock = 0;
wakeup «caddr t) &fp->s ilock);
i f (fp->s ninode > 0) (
fp->s inode[fp->s ninode-l) ~ 0;
fp->s::)node[Ol - 0;
}

* update is the internal name of ' sync'. It goes through the disk
* queues to initiate sandbagged 10; goes through the I nodes to write
* modified nodes; and it goes through the mount table to initiate modified
* super blocks.
*1
update ()

i f (fp->s ninode !- NICINOD)

fp->s ninode - NICINOD;
goto loop;
}

fp->s ninode - 0;
prdev("OUt of inodes", dev);
u. u error - ENOSPC;
fp->s_tinode - 0;

register struct inode *ip;
register struct mount *mp;
register struct filsys *fp;
register struct user *up;
static struct inode uinode;
i f (uinode.i_flaq)

alloc.c

Fri Sep

5 19:07:46 1986

return;
up .. &u;
uinode . i flag++;
uinode.(~mode - IFBLK;
for(mp = &mount[O]; mp < (struct mount *)v.ve_mount; mp++)
if (mp->m flaqs -- MINUSE) {
fp = mp->m_bufp->b_un.b_filsys;
i f (fp->s fmod--O I I fp->s Hock! =0 I I
fp->s flock!-O II fp->s-ronly!-O)
continue;
fp->s fmod = 0;
fp->s-time - time;
uinode. i rdev = mp->m dev;
up->~error = 0;
up->u_offset - SUPERBOFF;
up->u count = sizeof (struct filsys);
up->u=:base .. (caddr_t) fp;
up->u_segflg = 1;
up->u fmode - FWRITE IFSYNC;
writeI (&uinode);
for (ip

=

&inode [0]; ip < (struct inode *) v. ve inode; ip++)
i f «ip->i flag&ILOCK)=O && ip->i cOUnt!~O
&& (ip->i_flag&(IACCIIUPDIICHG))) "{
ip->i_flag 1= lLOCK;
ip->i count++;
iupdat (ip, &time, &time);
iput(ip) ;

bflush (NODEV) ;
uinode.i_flag .. 0;

3

Fri Sep

bio.c

5 19:08:15 1986

1

1* @(t)bio.c
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
~include

tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

1. 7 *1
"sys/param.h"
"sys/types .h"
"sys/mmu.h"
"sysl sysmacros. hOI
·sysl SySt.l'll. hOI
·sys/sysinfo.h"
·sys/dir. h"
"sys/signa1.h"
"sys/user.h"
"sys/errno.h"
"sys/buf .h"
·sys/iobuf .h"
·sys/conf .h M
·sys/proc.h"
Hsys/seg.h"
"sys/var .h"
"sys/scat.h"

*1
struct buf "
bread(dev, blkno)
dey t dey:
daddr_t blkno:
register struct buf "bp:
sysinfo .lread++:
bp = getblk(dev, blkno):
i f (bp->b_flags&B_DONE)
return (bp) ;
bp->b flags 1= BREAD:
bp->b-bcount = FSBSIZE (dev):
(*bdevsw[bmajor (dev)] .d_strategy) (bp):
u.u ior++:
sysInfo. bread++:
iowait (bp);
return (bp) :

1*
.. swap IO headers .

.. I
struct

buf

swbuf [NSWB] :

1*
..
*
*
..
*
*

The following several routines allocate and free
buffers with various side effects. In general the
arguments to an allocate routine are a device and
a block nlll!lber, and the value is a pointer to
to the buffer header: the buffer is marked "busy"
so that no one else can touch it. If the block was
* already in core, no IIO need be done: if it is
"" already busy, the process waits until it becomes free.
* The following routines allocate a buffer:
getblk
bread
breada
* Eventually the buffer must be released, possibly with the
" side effect of writing it out, by using one of
bwrite
bdwrite
bawrite
brelse

/*
.. Read in the block, like bread, but also start 1/0 on the
* read-ahead block (which is not allocated to the caller)
*1
struct buf *
breada (dev, blkno, rablkno)
dey t dey:
daddr_t blkno, rablkno:
{

register struct buf "bp, "rabp;
bp - NULL;
if (!incore(dev, blkno»
sysinfo .lread++;
bp - getblk(dev, blkno);
i f «bp->b_flagS&B_DONE) - 0) {
bp->b_flags 1= B_READ;
bp->b bcount - FsBSIZE (dev) :
(*bdevsw[bmajor(dev)].d strategy) (bp):
u . u_ior++;
sysinfo .bread++;

*1
if (rablkno && bfreelist.b bcount>l && !incore(dev, rablkno»
rabp = getblk(dev,-rablkno);
i f (rabp->b_flags & B_DONE)
brelse (rabp);
else (
rabp->b flags 1= B READIB ASYNC;
rabp->b-bcount - FSBSIZE (dev) :
(""bdevsw[bmajor(dev) l.d_strategy) (rabp);
u. u ior++:
sysInfo. bread++;

1*
* Unlink a buffer from the available list and mark it busy.
* (internal interface)

*'

tdefine notavail (bp)
(\
register s: \
s - spl6():\
bp->av_back->av_forw = bp->av_forw:\
bp->av forw->av back - bp->av back: \
bp->b flags 1= B BUSY: \
bfreelist.b bcount--; \
splx(s): \ -

i f (bp

=-

NULL)

return (bread (dev, blkno»:
iowa it (bp):
return (bp) ;

/*
"
"
"
"

Pick up the device's error number and pass it to the user:
if there is an error but the nlll!lber is 0 set a generalized
code. Actually the latter is always true because devices
don't yet return specific errors.

*1
tdefine geterror (bp)
! '.
i f (bp->b flags&B ERROR) \
if «u.u_error = bp->b_error) =0) \
u.u_error = EIO:\
/*
.. Read in (if necessary) the block and return a buffer pOinter.

1*
* write the buffer, waiting for completion.
.. Then release the buffer.

"" /

bwrite(bp)
register struct buf *bp;
register flag;
sysinfo .lwrite++;
flag - bp->b_flags;
bp->b_flags &- -(B_READ I B_DONE I B_ERROR ; B_DELWRI);
(*bdevsw[bmajor(bp->b_deV)] .d_strategy) (bp);
u.u_iow++:

(

Fri Sep

bio.c

5 19:08:15 1986

2

sysinfo. bwrite++:

)

i f «flag&B ASYNC)

bp->b_flags &- -(B_WANTEDIB_BUSYIB_ASYNCIB_AGEI:
bfreelist. b_ bcount ++:
splx(s) :

0) {
iowait (bp):
brelse (bp) :
) else i f (flag & B_DELWRIl

1*

else

:I< See if the block is associated with some buffer
* (mainly to avoid getting hung up on a wait in breada)

geterror (bp) :

*1
1*

*

*
"
*
*
*

Release the buffer, marking it so that if it is grabbed
for another purpose it will be written out before being
given up (e.g. when writing a partial block where it is
assumed that another write for the same block will soon follow).
This can't be done for magtape, since writes must be done
in the same order as requested.

incore (dev, blkno)
register dey t dey;
daddr t blkno;
{
register struct buf *bp:
register struct buf *dp:

-

blkno - FsLTOP(dev, blkno):
dp - bhash(dev, blkno):
for (bp=dp->b_forw: bp != dp: bp = bp->b_forwl
if (bp->b blkno-blkno && bp->b_dev=dev && (bp->b_flags&B_STALEI=O)
return (1) :
return (0) :

*/
bdwrite (bpI
register struct buf *bp;
{

sysinfo.lwrite++:
bp->b flags 1- B DELWRI
bp->b-resid = 0:brelse (bp) :

B_DONE:

/*
* Release the buffer, start I/O on it, but don't wait for completion.
*/
bawrite (bp)
register struct bUf *bp:
{

/*
* Assign a buffer for the given block. If the appropriate
* block is already associated, return it; otherwise search
" for the oldest non-busy buffer and reassign it.
*/
struct buf *
getblk(dev, blkno)
register dey t dey;
daddr_t blkno:
{

register struct buf "bp:
register struct buf "dp:

if (bfreelist. b bcount>4)
bp->b flags 1= B ASYNC;
bwrite (bp): -

/"
* release the buffer, with no I/O implied.
*/
brelse(bp)
register struct buf *bp:
{

register struct buf *"backp:
register s;
i f (bp->b flags&B WANTED)

wakeup ( (caddr t)bp);
i f (bfreelist. b flags&B WANTED) {

bfreeliit.b flags &= -B WANTED:
wakeup ( (Caddr_t) &bfreeiistl:

blkno - FsLTOP (dev, blkno);
loop:
SPLO ():
dp - bhash{dev, blkno):
i f (dp - NULL)
panic ("devtab") :
for (bp=dp->b_forw: bp != dp: bp - bp->b_forw) {
i f (bp->b_blkno!=blkno II bp->b_dev!=dev II bp->b_flags&B_STALE)
continue;
SPL6() ;
i f (bp->b flags&B BUSY)
bp->b_flags 1= B_WANTED:
syswai t . iowai t ++;
(void) sleep ( (caddr t)bp, PRIBIO+2):
syswait.iowait--: goto loop;
)

SPLO ();
notavail (bp) :
return (bp) :

i f (bp->b_flags&B_ERROR) {

bp->b flags I- B_STALEIB_AGE:
bp->b::::flags &= - (B ERROR IB DELWRI);
bp->b_error - 0: -

SPL6 () :
if (bfreelist. av forw =- &bfreelist) {
bfreelist. b flags 1- B WANTED:
(void) sleep «caddr_t) &bfreelist, PRIBIO+lI:
goto loop:

/* Put buffer on freelist, at the beginning if B_AGE, otherwise at the end. *1
s = sp16():
if (bp->b flags & B_AGE) I
backp - &bfreelist. av forw:
(*backp) ->av back - bp:
bp->av forw :: *backp:
*bac!cp-- bp:
bp->av back = &bfreelist:
} else (
backp - &bfreelist. av back:
(*backp) ->av forw - bp:
bp->av back :: *backp:
*backp- - bp;
bp->av~forw - &bfreelist;

SPLO II:
bp - bfreelist. av_ forw:
tifdef OLD
notavail (bp) :
i f (bp->b flags , B DELWRI)
bp->b_flags-I- B_ASYNC:
bwrite (bp) :
goto loop:
telse

bio.c

Fri Sep

5 19:08:15 1986

bflush (NODEV) ;
goto loop;

3
iodone(bp)
register struct buf *bp;
{

notavail (bp) ;
bp->b flags 1= B DONE;
i f (bp->b flagS&B }I..5YNC)
brelse(bp);
else {
bp->b flags &= -B WANTED;
wakeup ( (Caddr_t)bp);

tendif
bp->b flags = B BUSY;
bp->b-back->b forw ~ bp->b forw;
bp->b- forw->b-back - bp->b-back;
bp->b-forw = dp->b forw; bp->b-back - dp; dp->b- forw->b back - bpi
dp->b=:forw - bPI
bp->b dev = dev;
bp->b-blkno = blkno;
bp->b- bcount - F sBSIZE (dev) ;
return (bp) ;

/*

*

Zero the core associated with a buffer.

*1
clrbuf(bp)
struct buf *bp;

/*

{

* get an empty block,
* not assigned to any particular device

*/
struct buf
geteblk()

clear ( (caddr t)bp->b un.b words,
bp->b_resid :; 0;
-

(int)bp->b_bcount);

*
/*
* swap I/O

{

register struct buf *bp;
register struct buf *dp;

*/
swap(blkno, coreaddr, count, rdflg)
daddr_ t blkno;
register coreaddr, count;

loop:
SPL6 () ;
while (bfreelist.av forw -- &bfreelist) {
bfreelist. b-flags 1= B WANTED;
(void) sleep ( (caddr_ t) &bfreelist, PRIBIO+l);

{

static struct buf *sbp:
register struct buf *bp;
register int c;

}

SPLO () ;
dp = &bfreelist;
bp - bfreelist. av forw;
notavail (bp) ;
if (bp->b flags & B DELWRI)
bp->b flags-I- B ASYNC;
b~rite (bpj;

-

goto loop;
bp->b flags = B BUSY I B AGE;
bp->b-back->b fon - bp->b forw;
bp->b- forw->b-back = bp->b-back;
bp->b-forw - dp->b forw; bp->b=:back = dp; dp->b_forw->b_back = bpi
dp->b forw - bpi
bp->b-dev - (dev t)NODEV;
bp->b-bcount = SBUFSIZE;
return (bp) ;

/*
* wait for I/O completion on the buffer; return errors
* to the user.

*/
iowait(bp)
register struct bUf *bp;
{

syswait. iowait++;
SPL6 () ;
while «bp->b flags&B DONE)==O)
(void) Sleep«Caddr_t)bp, PRIBIO);
SPLO () ;

tifdef SWAP TRACE
printf("SWAP %s %d disk-Ox%x core=Ox%x\n",
(rdflg~B_READ) ,?uIN":"OUT", count, blkno, coreaddr);
tendif SWAP TRACE
syswai t . swap++;
if (sbp-NULL)
sbp - &swbuf[O];
bp = sbp++;
if (sbp > &swbuf[NSWB-l])
sbp = &swbuf[O];
SPL6 ();
while (bp->b flags&B BUSY)
bp->b flags 1= B WANTED;
(void) sleep( (caddr_t)bp, PSWP+l);
bp->b_flags - B_BUSY
B_PHYS I rdflg;
SPLO () ;
bp->b dey - swapdev;
tifdef NONSCATLOAD
bp->b un.b addr = (caddr_t)ctob(coreaddr);
while-(count> 0)
if (count <= btoc (MAXCOUNT»
c - count;
else
c - btoc (MAXCOUNT) ;
bp->b bcount - ctob (c) ;
bp->b-blknO - swplo+blkno;
(*bdevsw[ (short) bmajor (swapdev) 1 • d strategy) (bp);
u.u iosw++;
if (rdflg) {
sysinfo. swapin++;
sysinfo.bswapin +- ctod(c);
} else {
sysinfo. swapout++;

syswa!t. iowalt--;
geterror (bp) ;

1*

*

Mark Ilo complete on a buffer, release it if I/O is asym:hro!'.olls,
* and wake up anyone waiting for it.

*/

syslnro.bswapout +- ctod!c);
I
SPL6 () ;
while «bp->b flags&B DONE) ==0)
(voidl sleep( (caddr_tlbp, PSWP);
SPLO () ;
bp->b un.b addr +- ctob(c);
bp->b~)lags &- -B_DONE;

bio.c

Fri Sep

5 19:08:15 1986

if (bp->b flags & B ERROR)
panic("IO err in swap");
count
c;
blkno +- ctod(c);

lelse
tdefine sindex coreaddr
while (count> OJ
if (sindex -= SCATEND) (
printf ("swap error: swapping beyond process\n");
break;
c - memcontig (sindex, count);
bp->b un.b addr - (caddr t)ctob(ixtoc(sindex»;
bp->b-bcooot = ctob(c); bp->b=blkno = swplo+blkno;

4

/*
* Raw I/O. The arguments are
The strategy routine for the device
A buffer header, sometimes of a special type owned by the
device, and sometimes from the physio pool of headers.
The device number
Read/write flag
* Essentially all the work is computing physical addresses and
* validating them.
*/
physio (strat, bp, dev, rw)
register struct buf *bp;
int (*strat) ();
{

tifdef SWAP TRACE
printf("

register struct user "up;
register struct proc *p;
register unsigned base;
register unsigned limit;
register unsigned dsstart, dsend;
int
hpf;

SWAP %s %d disk-Ox%x sindex-Ox%x\n",
(rdflg-=B_READ) ?"IN":"OUT", c, blkno, sindex);

tendif SWAP TRACE
(*bdevsw [(short)bmajor (swapdev) ].d strategy) (bp);
u.u iosw++;
if (rdflg) (
sysinfo. swapin++;
sysinfo.bswapin +- ctod(c);
) else (
sysinfo. swapout ++;
sysinfo.bswapout += ctod(c);

up = &u;
p = up->uyrocp;
base - (unsigned) up->u_base;
dsstart = v. v ustart + ctob (stoc (ctos (up->u tsize»);
dsend = dsstart + ctob(up->u_dsize);
limit - base + up->u_count - 1;

SPL6 () ;
while «bp->b flags&B DONE) -=0)
(void) sleep( (caddr_t) bp, PSWP);
SPLO () ;
bp->b flags &= -B DONE;
if (bp->b flags &- B ERROR)
panic!"IO err in swap");
count -= c;
blkno +- ctod(c);
while (c-- > a && sindex != SCATEND)
sindex - scatmap [sindex] . sc_index;

/*

* Check that transfer is either entirely in the
" virtual data space or in the virtual stack space
*/

if (limit < base)
/* wraparound, base < 0, count <= 0 */
goto bad;
if (base >- dsstart && limit < dsend)
goto cont;
if (base >- v.v_uend - ctob(up->u_ssize) && limit < v.v_uend)
goto cont;
if (rw !- B READ && base >= v.v ustart &&
limit <-v.v_ustart + ctOb(up->u_tsize»
goto cont;
if (chkphys ( (int) base, limit»
goto cont;

tendif
if (bp->b flags&B WANTED)
wakeup ( (caddr_t) bp);
bp->b flags &= - (B BUSY 1B WANTED 1B PHYS);
syswalt.swap--;
Hfndef NONS CAT LOAD
return (sindex) ;
tendif

bad:
up->u error - EFAULT;
return;

)

cont:

/"
"
"
"
"

if (rw)
make sure all write-behind blocks
on dev (or NODEV for all)
are flushed out.
(from umount and update)

*/

bflush (dev)
dev_t dev;
{

register struct buf *bp;
SPL6 () ;
for (bp - bfreelist.av forw; bp != &bfreelist;) (
if (bp->b_flagS&B_DELWRI && (dev -- NODEVlldev--bp->b_dev»
bp->b flags 1- B ASYNC;
notavail (bp) ;
bwrite (bp) ;
SPL6 () ;
bp - bfreelist.av_forw;
) else {
if (bp->av forw) bp - bp->av forw;
else panic("bflush: bad free-list\n");
}

SPLO () :

sysinfo. phread++;
else
sysinfo. phwri te++;
syswait .physio++;
tifndef NONSCATLOAD
i f «p->p_flag&SCONTIG)--O)
p->p flag 1= SSWAPIT;
i f (runout) (
runout = 0;
wakeup ( (caddr_ t) &runout) ;
)

i f (runin) (
runin - 0;
wakeup! (caddr_t) &runin);
)

SPL6 () ;
while (p->p flago&SCONTIG)--O)
(void) sleep( (caddr_t) scatmap, PRIBIO);
lendif
hpf - (bp - NULL);
SPL6 () ;
if (hpf) {
while «bp = pfreelisLav_forw) == NUL"")

Fri Sep

clist.c

5 19:07:47 1986

1
splx(s) ;

1* @(t)clist.c 1.2 "I
'include "sys/param.h"
tinclude "sys/types.h"
'include "sys/tty.h"

'endif
return(-ll;
cfreelist. c _next - bp->c_next;
bp->c next = NULL;
bp->c-fir st - 0; bp->c last - 0;
if (obp ~ NULL)
p->c_cf - bp;
else
obp->c_next ~ bp;
p->c_cl = bpI

qetc(p}

register struct clist "p;
(

register struct cblock "bp;
register int c;
tifdef mcG80!)!)

I"
bp->c_data[bp->c_last++] = c;
p->c cc++;
tifdef mc68000
d7,sr") ;
asm("
movw
telse
splx(s) ;
tendif
return (0) ;

" Note use of d6

"I
tifndef lint
register int s
tendif
asm("
asm("

movw
movw

!);

sr,d6") ;
tOx2600,sr") ;

telse
register int s;
s = sp16 ();

struct cblock "
getcf()

'endif

{

if (p->c_cc > 0) (
p->c cc--;
bp =-p->c cf;
c - bp->c-data[bp->c firstH]&0377;
if (bp->c-first ~ bp->c last) {
if «p->c cf - bp->c next) - NULL)
p=>c cl - NULL;
bp->c next =-cfreelist.c next;
cfreelist. c next - bp; if (cfreeli;t.c flag) (
cfreelist . c flag - 0;
wakeup ( (caddr_t) &cfreelist);

register struct cblock "bp;
register struct chead "cf;
tifdef mc68000

I"
" Note use of d7
*1
tifndef lint
register int s - 0;
tendif
asm("
asm("

movw
movw

sr,d7") ;
tOx2600, srH);

telse

I else
c = -1;
tifdef mc68000
asm("
movw
d6,sr") ;
telse
splx(s) ;
'endif
return (c) ;

register int s;
s = sp16();
tendif

putc(c, p)
register struct clist "p;
(

register struct cblock *bp, "obp;
tifdef mc68000
1*
* Note use of d7
*1
.ifndef lint
register int s = 0;
tendif

cf = &cfreelist;
if «bp = cf->c next) ! = NULL) (
cf->c_n;xt = bp->c_next;
bp->c next - NULL;
bp->c-first = 0;
bp->c::::last - cf->c_size;
I
.ifdef mc68000
asm("
movw
d7,sr") ;
telse
splx(s) ;
tendif
return (bpI;

putcf(bp)
register struct cblock "bp;
(

register struct chead *cf;
asm("
asm("

movw
movw

sr,d7") ;
tOx2600,sr");

tifdef mc68000

'else

register int
s - sp16();

/*
s;

tendif
if «bp

p->c_cl) == NULL II bp->c_last == (char)cfreelist.c_size)
obp - bp;
i f «bp - cfreelist. c_next) - NULL)
=

" Note use of d7
*1
ti fndef lint
register int s = 0;
tendif
asm("
asm("

I i fdef mc68000

asrn("
telse

movw

d7, sr");

movw
rnovw

telse
register int s;

sr,d7") ;
tOx2600, sr"l ;

Fri Sep

clist.c

5 19:07:47 1986

s - spl6():
tendif
cf - &cfreelist;
bp->c_next = cf->c_next:
cf->c next = bp;
if (cf->c flag) {
cf->C flag - 0;
wakeup ( (caddr_t) cf);
)

tifdef mc68000
asm(n
movw
telse
splx(s) ;
tendif
J

d7, sr"l;

2
p->c_cc += bp->c_last - bp->c_first:
tifdef mc68000
d7,srH):
asm(U
movw
telse
splx(s) ;
tendif

tifdef notdef
getcbp(p, cp, n)
struct clist *p;
register char *cp;
register n;
{

register
register
register
register

struct cblock *
getcb(p)
register struct clist *p;

while (n) {
if «bp

p->c cf) =- NULL)
break;op - &bp->c data [bp->c first];
on = bp->c last - bp->; first;
i f (n >= on) {
bcopy (op, cp, on);
cp += on;
n -= on;
if «p->c_cf = bp->c_next) = NULL)
p->c cl - NULL;
bp->c next = - cfreelist. c next;
cfreelist. c _next - bpI } else {
bcopy (op, cp, n);
bp->c_first += n;
cp += n;

{

register struct cblock *bp;
tifdef mc68000

1*

* Note use of d7

*1
tifndef lint
register int s - 0;
tendif
asm("
asm("

sr,d7") ;
tOx2600, sr");

movw
movw

struct cblock *bp;
char *op;
on;
char *acp = cp;

telse
register int s;
s = spl6();

=

n = 0;

tendif

break;
if «bp - p->c cf) !- NULL) {
p->c c; -- bp->c last - bp->c first;
if (tp->C_Cf = bp->c_next) =-NULL)
p->c_ cl - NULL;

n

= cp - acp;
p->c_cc -= n;
return(n) :

}

tifdef mc68000
asm("
movw
telse
splx(s) :
tendif
return (bp) ;

}

d7,sr") ;

tendif
tifdef notdef
putcbp(p, cp, n)
struct clist *p;
register char *cp:
register n:

putcb (bp, p)
register struct cblock *bp;
register struct clist *p;

{

register
register
register
register

(

tifdef mc68000

struct cblock *bp, *obp;
char *op;
on;
char *acp = cp;

1*
* Note use of d7

*1
tifndef lint
register int s
tendif
asm("
asm("

movw
movw

=

0;
sr,d7");
tOx2600, sr");

telse
register int s;
s = spl6 () ;
tendif
if (p->c_cl -- NULL)
p->c_cf - bpi
else
p->c cl->c next
p->c cl - bp;
bp->c_next = NULL;

bpi

while (n) {
if «bp - p->c_cl) - NULL II bp->c_last -- cfreelist.c_size)
obp = bpI
if «bp - cfreelist.c_next) - NULL)
break;
cfreelist. c _next - bp->c_next;
bp->c next = NULL;
bp->c-first - 0; bp->c last - 0;
if (abp == NULL)
p->c_cf - bpi
else
obp->c next - bp:
p->c_cl = bpi ap = &bp->c data [bp->c last];
on - cfreelIst.c size -= bp->c last;
if In >- on) ( bcapy (cp, ap, on);
cp t - an;

clist.c

Fri Sep

5 19:07:47 1986

bp->c_last += on;
n -- on;
I else {
bcopy(cp, op, n);
cp += n;
bp->c last +- n;
n

=

0;

break;

n - cp - acp;

p->c cc +return(n) ;
I
tendif

n;

3

cJ.ock.c

Fri Sep

5 19:07:47 1986

/ * (H t I clock. c 1. 1 *!
tinclude "sys/param.h"
tinclude "sys/config.h"
tinclude "sys/types.h"
tinclude "sys/mmu.h"
finclude "sys!sysl"..acros.h"
tinclude "sys/systm.hu
tinclude "sys/sysinfo.h"
tinclude ·sys!callo.h"
tinclude "sys/dir.h"
tinclude "sys/signal.h u
tinclude "sys/user, hOI
tinclude "sys/proc.h"
tinclude "sys/text.h u
tinclude "sys/psl.h"
finclude ·sys/var.h"
tinclude ·sys/reg. hOI
Hfdef UCB NET
tinclude "net/misc .hM
tinclude "net/protosw.h"
tinclude "net/socket.h"
tinclude ·net/if .h M
tinclude IOnet/in_systm.h"
tendif

1
*/
if (panicstr)
clkstop() :
return;

up = &u;
ps - ap->ays;
if (Up->u_stack[O) !- STKMAGIC)
panic(IOInterrupt stack overflow");

/*
* Time moves on for protocols.

*1
if (! netoff) (
--protoslow; --protofast; --ifnetslow;
if(protoslow<-O II protofast<-O II ifnetslow<=O)
schednetisr (NETISR_CLOCK) ;

tendif

/*

* callouts
* if none, just continue
* else update first non-zero time

tifdef VIRTUAL451
tdefine args
buserr
tdefine ays
ber_sr
tdefine aJ>C
berJ>C
tdefine a_deY
ber_dev
tendif

*1
if(callout[Oj.c func - NULL)
goto out;
p2 - &callout (0) ;
while (p2->c_ time<~O && p2->c_ func! -NULL)
p2++;
p2->c_ time--;

/*
* clock is called straight from
* the real time clock interrupt.

*

Functions:
reprime clock
implement call outs
maintain userlsystem times
maintain date
profile
alarm clock signals
jab the scheduler

/*

*

if (BASEPRI (ps) )
goto out;

1*

*/

* if any callout active, update first non-zero time
* then process necessary callouts
*/

tdefine PRF_ON 01
extern prfstat;
time_t

spltty() ;
if(callout[O).c time <= 0) (
p1 = &callout (0) ;
while (p1->c_ func ! - 0 && p1->c_time <= 0) (
(*p1->c_func) (p1->c_arg);
p1++;

time, lbolt;

1*
* Protoslow is like lbolt, but for slow protocol timeouts, counting
• up to (hz/PR_SLOWHZI, then causing a pfslowtimo () .
* Protofast is like lbolt, but for fast protocol timeouts, counting
* up to (hz/PR_FASTHZI, then causing a pffasttimo().
*1
extern int
protoslow;
extern int
protofast;
extern int
ifnetslow;
extern short
netoff;
tendif
clock (ap)
struct args *ap;
(

register struct callo ·pI, *p2;
register struct user *up;
register struct proc *pp;
register a, ps;
static short Iticks;
static rqlen, sqlen;

/*
• i f panic stop clock

if ps is high, just return

*1

)

p2 - &callout (0) ;
while (p2->c func = pI->c func)
p2->c time - pI->c time;
p2->c-arg - pI->c arg;
p1++;p2++;

out:
if (prfstat & PRF_ON)
prfintr( (caddr_t)ap->ayc, ps);
if (USERMODE (ps» {
a = CPU USER;
up->u utime++;
if (up->uyrof.pr_SCale)
addupc ( (unsigned) ap->a_pc, &up->uyrof, 1);
} else
if (ap->a dey !- 0) {
1* dey has old idleflg in i t -/
if (syswait. iowait+syswait. swap+syswait .physio)
a - CPU_j(A.IT;

clock.c

Fri Sep

5 19:07:47 1986

i f (syswait.iowait)
sysinfo.wait[w 10]++;
if (syswait.swap)
sysinfo.wait[w SWAPj++;
if (syswait.physio)
sysinfo. wait [N_PIO] ++;

2

1*

*
*

tilneout is called to arrange that fun (arg) is called in tiln/HZ seconds.
An entry is sorted into the callout structure.
.. The tilne in each structure entry is the number of HZ's more
* than the previous entry. In this way, decrementing the
• first entry has the effect of updating all entries.

else
) else
a - CPU KER.1iEL;
up->u_stilne++ ;

*

The panic is there because there is nothing

* intelli;ent to bs done if an entry won't fit.
*1
sysinfo. cpu [a] ++;
pp - up->uyrocp;
i f (pp->p_stat=SRUNI
up->u mem +~ (unsigned) (v. v usize+procsize (pp) ) ;
i f (Pp->p_textp) {
a = pp->p textp->x ccount;
i f (a~O II a-I) up->u_mem +- pp->p_textp->x_size;
else
up->u mem +=
(unsigned short)pp->p_textp->x_size
(short) a;
i f (pp->p_cpu < 80)
pp->p cpu++;
lbolt++;
- 1* tilne in ticks *1
i f (--lticks <- 0) {
i f (BASEPRI (ps) )
return;
Iticks += v.v hz;
++tilne;
if «tilne & 3) ~ 0)
1* entry to load average *1
loadav() ;
runrun++;
rqlen = 0:
sqlen = 0;
for(pp = &prec[O]; pp < (struct proc *)v.veyroc: pp++)
if (pp->p stat) {
if (pp->p tilne !- 127)
pp->p tilne++;
i f (pp->p clktim)
if (--pp->p clktiln - 0)
psi~al (pp, SIGALRM):
pp->p cpu »- 1;
i f (pp->pyri >= (PUSER-NZERO»
{
pp->pyri - (pp->p_cpu»l) + PUSER +
pp->p_nice - NZERO;

tilneout (fun, arg, tiln)
int (*fun) ();
caddr t arg;
int tIm.;
register struct callo ·p1, ·p2;
register int t;
int s;
t = tiln;
pI - &callout [0] ;
s = sp17 ();
while(p1->c func != 0 && p1->c_tilne <= t) {
t
pl->c tilne;
p1++;
-

-=

)

if (pI >= (struct callo "I v . ve call-l)
panic("Tilneout table overflow");
pl->c tilne -= t;
p2 - pI;
while (p2->c func ! - 0)
p2++;
while (p2 >- pI) {
(p2+1) ->c tilne - p2->c tilne;
(p2+11->c-func - p2->c-func:
(p2+ 1) ->c- arg = p2->c arg:
p2--:
-

1
p1->c tilne - t;
p1->c-func = fun:
pl->c-arg = arg:
splx(s) ;

fdefine PDELAY
delay (ticks)

(PZERO-1)

{

extern wakeup () ;
int s;

i f (pp->p stat = SRUN)
if (pp->p flag & SLOAD)
rqlen++;
else
sqlen++;

i f (ticks<=O)
return;
s = sp17 ();
timeout (wakeup, (caddr_t)u.uyrocp+1, ticks);
(void) sleep( (caddr_t) u. uyrocp+1, PDELAY);
splx(s) ;

i f (rqlen) {

sysinfo. runque += rqlen;
sysinfo. runocc++;
}

1*

i f (sqlen)

{
sysinfo. swpque +- sqlen;
sysinfo. swpocc++;

}

i f (runin!-O) {
run in - 0;
setrun(&proc(O]) :

* From here down is load average code
,,/
struct lavnum {
unsigned short high;
unsigned short low;
):

struct lavnum avenrun [3] ;

}

tifdef VIRTUJI...L451
i f (runout!-O)

{
runout - 0;
setrun('proc[O]) ;

)

itendif VIRTUAL451

1*

* Constants for averages over 1, 5, and 15 minutes
* when sampling at 4 second intervals.
.. (Using' , fixed-point' with 16 binary digits to right)
*/

clock.c

Sep

struct lavnum cexp[3] =
( 61309, 4227 I,
( 64667, 869 I,
( 65245, 291 ),
I:

5 19:07:47 1986

(

1* (x = exp(-1/15) * 65536) , 1 - x *1
1* (x = exp(-1/75) " 65536) , 1 - x *1
1* (x - exp(-1/225) • 65536) , 1 - x *1

1* called once every four seconds *1
loadavO
{

register
register
register
register
register

struct lavnum *avg;
struct lavnum *rcexp:
unsigned int j;
unsigned short nrun;
struct proc .p;

nrun = 0;
for (p - &proc[O]: p < (struct proc ·)v.veyroc; p++) (
i f (p->p flag & SSYS)
continue;
i f (p->p stat) {
switch (p->p_stat)
case SSLEEP:
case SSTOP:
i f (p->pyri <- PZERO)
nrun++:
break;
case SRUN:
case SIDL:
nrun++;
break;

1*
* Compute a tenex style load average of a quantity on
* 1, 5 and 15 minute intervals.
* (Using' fixed-point' with 16 binary digits to right)

*1
avg = avenrun;
rcexp - cexp;
for ( ; avg < &avenrun[3]; avg++, rcexp++) {
j = «avg->low * rcexp->high + 32768) »
+ (avg->high * rcexp->high)
+ (nrun * rcexp->low):
avg->low = j & 65535;
avg->high = j » 16;

16)

3

5 19:08:36 1986

Fri Sep

co.c

1

1*
tp - co ttptr[dev).tt tty;
tp->t index = dey;
SPL6();
if «tp->t_state&(ISOPENIWOPEN» - 0) (
tp->tyroc = coproc;
ttinit Itp) ;
tp->t state = WOPEN I CARR_ON;
if (dev - CONSOLE) (
tp->t iflag = ICRNL I ISTRIP;
tP-><~oflag - OPOST I ONLCR I TAB3;
tp->t Iflag - ... ;:) ... <> I lCMON i ECHO i BCROK;
tp->t=cflag = sspeed I CS8 I CREAD I HUPCL;

" Ie) 1984 Unisoft Corp. of Berkeley CA

* UniPlus Source Code. This program is proprietary
" with Unisoft Corporation and is not to be reproduced
* or used in any manner except as authorized in
" writing by Unisoft.
*

co.c - "console U (ie, bitmap screen and keyboard) driver for the lisa.

*1
tinclude Usys!param. h U
tinclude "sys/config.h"
tinclude "sys/types. h"
tinclude ·sys/systm.h"
tinclude "sys/dir.h u
tinclude "sys/signal.h"
tinclude "sys/user.h"
tinclude "sys/errno.h"
tinclude "sys/file.h"
tinclude ·sys/tty. h"
tinclude ·sys/termio. h"
tinclude "sys/conf. h"
tinclude ·sys/sysinfo.h"
tinclude "sys/var.h"
tinclude "sys/reg.h"
tinclude ·setjmp.h u
tinclude ·sys/ioctl.h u
tinclude "sys/kb.h"
tinclude ·sys/al ioctl.h u
tifdef SUNIX
tinclude "sys/reboot.h"
tendif SUNIX
tinclude Usys/mmu.h"
tinclude ·sys/cops.h"
tinclude ·sys/12.h u

SPLO ();
("linesw[tp->t_line) .l_open) (tp);

I" ARGSUSED "I
coclose (dev, flag)
(

register struct tty "tp;
tp = co ttptr[dev).tt tty;
(*linesw[tp->t_line) .i_cIOSe) (tp);
coread (dev)
(

struct tty "tp;
tp - co ttptr [dey] . tt tty;
(*linesw[tp->t_line) .i_read) (tp);

cowrite (dev)
int
coproc () ;
extern int co cnt;
extern struct-tty co_tty[);
extern struct ttyptr co_ttptr[];
extern char bmbck, bmnormal;
extern char *bmscrn;

{

struct tty *tp;
tp = co ttptr[devj .tt tty;
(*linesw[tp->t_line] .i_write) (tp);

1* pointer to screen -- initialized in bminit *1

1* calls to the putc routine are made indirectly through
* the te_putc pointer which is used to
* keep track of the current state for escape character
" processing, ie, although initialized to point to
* the normal putc, an escape character causes other
* functions to process the next character (s)

1* ARGSUSED *1
coioctl (dev, cmd, arg, mode)
{

int i;
switch (cmd) (

register struct tty *tp;

case AL SBVOL:
-12_bVOl - arg & 7;
break;
case AL SBPITCH:
-12 bpi tch = arg & OxlFFF;
break;
case AL SBTlME:
-if (arg <- 0)
arg = 1;
if (arg > 10 * v.v hz)
arg - 10 *-V.V_hZ;
12_btime = arg;
break;
case AL SDIMTlME:
-12 dtime - arg;
12-dtrap ~ Ibolt + l2_dtime;
break;
case AL SDIMCONT:
-12 dimcont = (-arg) & OxFF;
break;
case AL_SDIMRATE:

if (dev >- co_cnt) <
u.u_error - ENXIO;
return;

break;
case AL SCOHTRAST:
-l2.....dafcont -

*1
extern int vtyutc () ;
int (*teyutc) () -vtyutc;
I*tifdef SUN IX
extern caddr t start;
tendif SUNIX-

*1
struct device
char
char
char

csr;
idum[2] ;
dbuf;

1* Command status register *1
1* fillers *1
1* data buffer * I

};

/" ARGSUSED * I
coopen(dev, flaq)
register dey;
(

(-arg) , OxFF;

1* limit to 10 seconds *1

co.c

Fri Sep

case

case

case

case

case

case

case

case

case

case

case

case

case

5 19:08:36 1986

12_desired ~ 12_defcont;
12ramp(O) ;
break;
AL SREPWAIT:
-kb_repwait - arg;
break;
AL SREPDELAY:
- kb_ repdlay = arg;
break;
AL GBVOL:
-i = 12 bvol;
if (Copyout«caddr_t)&i, (caddr_t)arq, 4))
u.u_error = EFAULT;
break;
AL GBPITCH:
-if (copyout«caddr_t)&12_bpitch, (caddr_t)arg, 4»
u.u_error - EFAULT;
break;
AL GBTlME:
-if (copyout( (caddr_t) &l2_btime, (caddr_t)arg, 4»
u.u_error = EFAULT;
break;
AL GDIMTlME:
-if (copyout «caddr_t) &l2_dtime, (caddr_t) arg, 4»
u.u_error = EFAULT;
break;
AL GDIMCONT:
-i = (-12 dimcont) & OxFF;
i f (copyout«caddr_t)&i, (caddr_t)arg, 4»
u.u_error = EFAULT;
break;
AL GDIMRATE:
-if (copyout( (caddr_t)&12_crate, (caddr_t)arg, 4»
u.u_error - EFAULT;
break;
AL GCONTRAST:
-i = (-12 defcont) & OxFF;
i f (Copyout«caddr_t)&i, (caddr_t)arg, 4»
u. u_error = EFAULT;
break;
AL GREPWAIT:
-i = kb repwait & OxFFFF;
i f (copyout«caddr_t)&i, (caddr_t)arg, 4»
u.u_error = EFAULT;
break;
AL GREPDELAY:
- i = kb repdlay & OxFFFF;
i f (copyout «caddr_t) &i, (caddr_t) arg, 4»
u.u_error = EFAULT;
break;
AL GBMADDR:
-if (copyout«caddr_t)&bmscrn, (caddr_t)arg, 4»
u.u_error = EFAULT;
break;
AL REWIDEO:
-if (arg > 0)
i = 0;
else if (arg = 0)
i - -1;
else
-1;
i = Ibmbck) '1
if (bmbck !- i) (
bmswitch () ;
bmsinv() ;
bmbck - i;
bmnormal - bmbck;
break;

"1 fdef SUNIX
case RESTART:
1* jump to the start of unix *1
reinit I);
(lint 1*) 1»OxCOOO) ();
break;
tend i f SUNIX
default:
(void) ttiocom(co_ttptr[OJ .tt_tty, cmd, arg, mode);

2
break;

coproc (tp, cmd)
register struct tty "tp;
(

register struct ccblock *tbuf;
extern ttrstrt () ;
switch (cmd) {
tp->t_state &- -TIMEOUT;
goto start;
case T_WFLUSH:
tbuf - &tp->t tbuf;
tbuf->c size
tbuf->c count;
tbuf->c-count = 0;
1* fall-through xl
case T_RESUME:
tp->t state &- -TTSTOP;
goto start;

==

start:

i f (tp->t state & (TTSTOP I TIMEOUT I BUSY) )
break;
tbuf = &tp->t tbuf;
i f «tbUf->cytr = 0) II (tbuf->c count
0»
i f (tbuf->cytr)
tbuf->cytr -= tbuf->c_size;
if (! (CPRES & (Xlinesw[tp->t line].l output) (tp»)
break;
--

==

(xteyutc) «*tbuf->c_ptr++) &Ox?f);
tbuf->c count--;
sysinfo-:-xmtint++;
/* this is the xmit interrupt */
splx (spll () ) ;
goto start;
case T_SUSPEND:
tp->t state 1- TTSTOP;
break7
case T_BLOCK:
break;
case T RFLUSH:
- if (! (tp->t state&TBLOCK»
break;
/* fall through * /
case T_UNBLOCK:
break;
case T_BREAK:
break;

cointr (dev)
{

register struct ccblock *cbp;
register int c, lcnt, flg;
struct tty xtp;
register char ctmp;
char lbuf[3];
sysinfo. rcvint++;
c = kb_chrbuf;
tp = co ttptr[dev].tt tty;
if (tp->t rbuf. c ptr
NULL)
return; tundef NULLDEBUG
tifdef NULLOEBU.G

=-

Fri Sep

co.c
if ( c

=-

Oxoo )

5 19:08:36 1986

3

{

sccdebug () ;
return;
#endif

if (tp=>t iflag & IXCN) {
ctmp - c & 0177;
if (tp->t state & TTSTOP) {
if (ctmp = CSTART II tp->t iflag & lXANY)
(*tp->tyroc) (tp, T=:RESUME);
} else
i f (etmp ~ eSTOP)
I*tp->tyroc) (tp, T_SUSPEND);
)

if (ctmp

=
CSTART II ctmp return;

CSTOP)

/*
* Check for errors

*/
lcnt = 1;
flg = tp->t iflag;
if (flg&ISTRIP)
c &~ 0177:
else {
i f Ic ~ 0377 && flg&PARMRK)
lbuf[l] = 0377:
lent = 2;

/*

* Stash character in r _buf
*/
cbp = &tp->t rbuf;
i f (lent !- 1) {
lbuf[O] = c;
while (lent)
*cbp->c ptr++ - lbuf[--lcnt]:
if (--cbp->c count = 0) {
Cbp->cytr -= cbp->c_size;
(*linesw[tp->t_line] .l_inputl (tp);
)

if (cbp->c size !- cbp->c count) {
Cbp->cytr -= cbp=>c_size - cbp->c_count:
(*linesw[tp->t_line] .l_input) (tp);
)

) else {
*cbp->cytr - c;
cbp->c count--:
(*line-;w[tp->t_line] .1_input) (tp);

/*
* This version of putchar writes directly to the bitmap display
* for those last-ditch situations when you just have to get stuff to the CRT.
*/
coputchar (c)
register c;
{

(*te putc) (c

& Ox7F);

i f ("C--'\n')

(*te_putc) (' \r' );

conf.c

Fri Sep

5 19:08:35 1986

1

1*
Configuration information

*1
1* tdefine
tdefine
tdefine
tdefine
#define
tdefine
Me fine
tdefine
Me fine
tdefine
tdefine
tdefine
Jdefine
Jdefine
tdefine
tdefine
tdefine
tdefine
Jdefine
tdefine
Jdefine
tdefine
tdefine
tdefine
tdefine
Jdefine
Jdefine
tdefine
Jdefine
Jdefine
Jdefine
tdefine
tdefine
tdefine
fdefine
tdefine
Jdefine
tdefine
tdefine
tdefine
tdefine
tdefine
Jdefine
Jdefine
Jdefine
fdefine
fdefine
fdefine
fdefine
fdefine
fdefine
fdefine
fdefine
Jdefine
fdefine

NBUF
30
NINODE 50
NFlLE
60
NMOUNT 8
CMAPSIZ 50
1* also in reinit. c * I
SMAPSIZ 50
/* also in reinit.c *1
CXMAPSIZ 50
NCALL
15
NPROC
30
NTEXT
20
NSVTEXT 20
NCLIST 100
STACKGAP 8
NSABUF 5
POWER
0
MAXUP
25
NHBUF
64
NPBUF
4
NFLOCK 200
X25LINKS
X25BUFS 256
X25MAPS 30
(16*1024)
X25BYTES
CSIBNUM 20
VPMBSZ 8192
MESG
1
MSGMAP 100
MSGMAX 8192
MSGMNB 16384
MSGMNI 50
MSGSSZ 8
MSGTQL 40
MSGSEG 1024
SEMA
1
SEMMAP 10
SEMMNI 10
SEMMNS 60
SEMMNU 30
SBMMSL 25
SEMOPM 10
SEMUME 10
SEMVMX 32767
SEMAEM 16384
SHMEM
SHMMAX (128*1024)
SHMMIN 1
SHMMNI 100
SHMBRK 16
SHMALL 512
STIHBUF (ST_O*4)
STOHBUF (ST 0*4)
STNPRNT (ST-0»2)
STIBSZ 8192
STOBSZ 8192

+include
+include
#include
finclude
#include
finclude
tinc1ude
tinc1ude
.include
flnc1ude
finclude
finclude
finclude
finclude

"sys/param.h"
Hsys/config. h"
·sys/mmu.h"
"sys/types. h"
.sysl sysmacros. h II
·sys/conf .h"
·sys{cpuid. h"
Hsys/space.h ll
·sys/io.h"
"sys/termio .h"
Hsys/req. h"
"sys/scc.h"
Hsys/pport .h"
"sys/swapsz.h"

extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern

nodev ( I, nulldev () ;
proopen (), proread (), prowrite (), prostrategy (), proprint (), proioctl () ;
snbopen (), sncopen (), snbclose (I, sncclose (), snread (), snwrite (), snstrategy (), snprint (), sni
cvopen (), cvread (), cvwrite (), cvstrategy (), cvprint () ;
pmopen (), pmread (), pmwrite (j, pmstrategy (), pmprint (), pmioctl () ;
coopen (), coclose (), coread (), cowri te (), coioctl () ;
syopen (), syread (), sywri te (), syioctl () ;
mmread (), mmwrite () ;
scopen ( ), scclose ( ), scread ( ), scwr i te ( ), scioctl () ;
erropen (), errclose (), errread () ;
proread (), prowritE (), proioctl (j ;
ejioctl () ;
msopen (), msclose ( ), msread (), msioctl () ;
lpopen (), lpclose (), lpwrite (), lpioctl () ;
skopen (), skclose (), skwri te () ;
rtcread (), rtcwrite () ;
teopen (), teclose (), teread (), tewrite (), teioctl () ;

f!fdef
extern
extern
extern
tend!f

UCB
intint
int

NET
ptsopen (), ptsclose (), ptsread (), ptswrite () ;
ptcopen (), ptcclose 0, ptcread (), ptcwrite () ;
ptsioctl (), ptcioctl () ;

-

struct bdevsw bdevsw [)
{
proopen, nulldev,
snbopen, snbclose,
cvopen,
nulldev,
pmopen,
nulldev,

pro strategy ,
snstrategy ,
cvstrategy ,
pmstrategy ,

proprint,
snprint,
cvprint,
pmprint,

*1
I"
*1
I"
2
1*
*1
/* 3 "I

};

struct cdevsw cdevsw[) ~ {
coopen, coclose,
syopen, nUlldev,
nulldev, nulldev,
erropen, errclose,
scopen, scclose,
proopen, nUlldev,
sncopen, sncclose,
nulldev, nulldev,
lpopen, lpclose,
msopen, msclose,
skopen, skclose,
cvopen, nUlldev,
pmopen, nulldev,
nulldev, nulldev,
teopen, teclose,
fifdef UCB_NET
nodev,
nodev,
nodev,
nodev,
nodev,
nodev,
nodev,
nodev,
nodev,
nodev,
ptcopen, ptcclose,
ptsopen, ptsclose,
tendif

coread,
syread,
mmread,
err read,
scread,
pro read,
snread,
nodev,
nodev,
msread,
nodev,
cvread,
pmread,
rtcread,
teread,

cowrite,
sywrite,
mmwrite,
nodev,
scwrite,
prowrite,
snwrite,
nodev,
lpwrite,
nodev,
skwrite,
cvwrite,
pmwrite,
rtcwrite,
tewrite,

coioctl,
syioctl,
nodev,
nodev,
scioctl,
proioctl,
snioctl,
ejioctl,
lpioctl,
msioctl,
nodev,
nulldev,
pmioctl,
nulldev,
teioctl,

0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,

I"
/*
I"
/*
I"
1*
1*
/"
1*
/*
1*
I"
/"
/*

nodev,
nodev,
nodev,
nodev,
nodev,
ptcread,
ptsread,

nodev,
nodev,
nodev,
nodev,
nodev,
ptcwrite,
ptswrite,

nodev,
nodev,
nodev,
nodev,
nodev,
ptcioctl,
ptsioctl,

0,
0,
0,
0,
0,
0,
0,

f"
1*
f*
f"
I"
1*
I"

*1
*1
*/
"I
*1
"I
"I
7 "I
8 *1
9 *1

1
2
3
4
5
6

10 */
11 *1

12 "/
13 *1
/* 14 */
15 ,,/
16 *1
17 *1
18 "I
19 *1
ptc 20 *1
pts 21 "I

);

int
int

bdevcnt
cdevcnt

=
~

sizeof (bdevsw) Isizeof(bdevsw (0) );
sizeof (cdevsw) Isizeof(cdevsw (0) );

tifdef SUNIX
1* Sony (installation) root filesystem *1
dev_t
rootdev = makedev(l, 0);
dev_t
pipedev ~ makedev(l, 0);
dey t
dumpdev - makedev (1, 0);
1* nswap and swapdev are set in lisainit in config.c *1
dey t
swapdev - makedev (0, 1);
daddr t swplo - 0;
int nswap PRNSWAP;
telse SUNIX
I * ProFile root file system * I
tdefine ROOTBASE
0
1* (port * 16) for port-O,1,2,4,5,7, or 8 *1
dev_t
rootdev - makedev(O, ROOTBASE)
dey t
pipedeY - maltedeY(O, ROOTBASE}
dey::t

IiUlJlPd.ev - ma.ltedey (0. ROOTBASE)

Fri Sep

conf.c

5 19:08:35 1986

dev t
swapdev - makedev(O, ROOTBASE + 1):
daddr t swplo - 0:
int nswap PRHSWAP:
tendif SUNIX

int
int
int

!*dUl!lp)!l - nulldev:
dump_addr - OxOOOO;
(*pwr clr [ ) ) ()
(int (*) 010

=

{

C*dev_init[J) ()

*1
tdefine TTHIGH
Hfdef TTLOW
tdefine M
tdefine N
tendif
tifdef TTHIGH
tdefine M
tdefine N
tendif
(
tthiwat[16]
int
60*M,
O*M,
60*M,
120*M, 180*M, 180*M,

-

};

int

2

=

-

);

{

(int (*) () 0

int

}:

tifdef SCC_CONSOLE
int
scputchar ( ) ;
int
(*putchar) ()
telse
int
coputchar ( ) ;
int
(*putcharj ()
tendif

ttlowat [16]
20*N,
O*N,
40*N,
60*N,

20*N,
60*N,

60*M,
240*M,

60*M,
240*M,

240*M,

60*M,
100*M,

12ii*M,
100*M,

20*N,
80*N,

20*N,
80*N,

20*N,
80*N,

20*N,
50*N,

40*N,
50*N,

60*,M,

I;
=

scputchar;

1*
* Default terminal characteristics

*1
=

coputchar;

char

tifdef UCB NET
tdefine PTC DEV 20
int ptc_dev-- PTC_DEV;
tendif

ttcchar [NCC]
CINTR,
CQUIT,
CERASE,
CKILL,
CEOF,

=

(

0,
0,

o

int co cnt = 1;
struct-tty co_tty [1) ;

);

struct ttyptr co ttptr [) =
1,
&co_tty[O),

(

1* tt_addr field not used *1

0,

Hfdef lint
1* LINTLIBRARY *;
forlint ()
(

};

bminit ();
nmikey() ;
llintr«struct args *)0);
kbintr() ;
scintr struct args *) 0) ;
pmintr struct args *) 0) :
ebintr(O) ;
netintr() :

int sc cnt ~ NSC;
struct-tty sc tty[NSC);
char sc_mode.'!!.[NSC);

«
«

struct ttyptr sc ttptr [I = {
OxFCD240~
&sc tty[l],
OxFCD242,
&sc-tty[O],
0,

-

tendif

};

struct scline sc_line [] - (
W9BRESET,
(4000000/16),
W9ARESET,
(4000000/16),

1* clock frequency b *1
1* clock frequency a *1

):

tif NTE != 0
int te cnt - NTE;
struct-tty te tty [NTE] ;
char te dparai[NTE];
char te::::modem[NTE];

1* net 89 */

I:

struct ttyptr te_ttptr[NTE+l];
tendif

1* +1 for pstat *;

1*
* pointers to ttyptr structures for terminal monitoring programs

*1
struct ttyptr *tty stat []
co_ttptr, sc ttptr,
t i f NTE !.-O
te_ttptr,
tendif

tifdef UCB NET
Hnclude 
tinclude 
extern struct uba driver ebdriver;
struct uba_device-ubdinit[] - {
unit,
addr,
flags*1
/* driver,
0,
(caddr_t)5, Ox59002908 I,
{ &ebdriver,

=

{

I;

;*
• tty output low and high water marks

int iff noarp - 0;
tendif -

1* 0 -> do ARP:

not 0 -> no ARP */

confiq.c

Fri Sep

5 19:08:54 1986

1

1*
i<

This file contains
1. oem modifiable configuration personality parameters
2. oem modifiable system specific kernel personality code

*I

1* Some of the initialization requires that interrupts be enabled to

* pick up coded sequences from the keyboard cops.

*
*

.. ;

-Hnclude
-Hnclude
tinclude
tinclude
tinclude
tinclude
-Hnclude
Hnclude
-Hnclude
-Hnclude
-Hnclude
-Hnclude
-Hnclude
tinclude
Hnclude
tinclude
-Hnclude
tinclude
tinclude
tinclude
-Hnclude
Hnclude
Hnclude
tinclude

"sys/param.h"
"sys/config .h"
"sys/mmu.h"
"sys/types. h U
"sys/sysmacros .h"
• sys! syst.!!!.. hOI
·sys/map.h"
·sys/dir.h"
·sys/signal.h"
.sys/user.h u
"sys/errno.h"
·sys/proc .h"
·sys/buf.h ll
"sys/iobuf . hOI
"sys/reg.h"
·sys/file.h"
·sys/inode .h"
·sys/seg.h"
·sys/acct.h"
Hsys/sysinfo.h"
·sys/var.h"
"sys/ipc.h"
"sys/shm.h H
·sys/termio.h"

-Hnclude
-Hnclude
tinclude
-Hnclude
tinclude
Hnclude
tinclude

·sys/conf .h"
·sys/cops.h"
"sys/pport .h lO
·sys/local. h"
"sys/12.h"
·sys/kb.h u
"sys/swapsz .h"

If interrupts were
masked out then the time returned by READCLOCK would fill the
buffer and KBENABLE, which also returns a value, would have trouble.

SPL1 ():
12copscmd (MOUSEOFF) :
12copscmd (READCLOCK) :
12copscmd (KBENABLE) :

1*
I"
/*
I"

ok, do it to me *1
shut off mouse interrupts *1
get time of day *1
enable keyboard * I

sninit (j;

I" sony initialization "I

1* Nait 'til the clock data (from READCLOCK) and keyboard ID (from
KBENABLE) have come in, and the keyboard is back in NORMALKAIT *1
while (kb state);
time = rt'Ime.rt_tod:
1* it should be at level 7 for the rest

SPL7 ():

(1)

*1

1* Find out what's in each of the expansion slots.
*1
for (i = 0, sidp - SLOTIDS: i < NSLOTS: i++, sidp++)
slot [i] = OxFF:
I" not supported "I
slotid - *sidp & SLOTMASK:
if (! slotid) {
if (iocheck( (caddr t) (STDIO+i"Ox4000+l»))
printf("ExPansion slot %d: quad serial card\n",
i+1) :
if (teinit (i) - 0)

1*
* point to interrupt vector,
* set tecmar quad serial board inter lac,
" and initialize hdwr

"I
ip - &«long ") 0) [EXPIVECT+devtoslot (i)]:
"ip = (long)tevect + (long) (devtoslot(i)«2):

I "char oemmsg [] "Unisoft Systems distribution system release 1. 5": * I
cha:: oe!!lll!sg[] = "UniSoft Systems pre-distribution system (release 1.5+)":
int
int
int
int
char

sspeed = B9600:
parityno - 28:
cmask = CMASK:
cdlimit - CDLIMIT:
slot [NSLOTS]:

1*
1*
1*
1*
1*

continue:
printf("Expansion slot %d: ", i+1):
switch (slotid) {
case ID APLNET:
- printf ("applenet card\nU ) :
break:
case ID PRO:
-printf("proFile card\n"):
break;
case ID 2PORT:
-printf(Mtwo port card\n"):
slot[i] = PRO:
1* valid *1
break;
case ID PRIAM:
-printf("priam card\n");
ip - &«long *) 0) [EXPIVECT+devtoslot(i)]:
1* point to int vector */
*ip - (long)prnvect + (long) (devtoslot(i)«2);
1* set to Priam intr *1
if (prncinit(i) -- 0)
1* initialize controller *1
slot[i] = PM3; /* valid *1
break;
default:
printf(lIcard ID Dx%x\n", slotid):

default console speed *1
parity interrupt vector *1
default file creation mask *1
default file size limit "I
card ID numbers for expansion cards *1

1*
* Kernel initialization functions.
* Called from main. c while at sp17 in the kernel.

*1
oem7init ()

/* alias (formerly) "lisainit" *1

(

tifdef SUNIX
int dev:
extern dev_t swapdev:
extern int nswap:
tendif SUNIX
extern struct rtime rtime:
extern int prnvect [ ] :
extern int tevect [ ] :
register short * sidp:
register slotid, i;
register long *ip:
12init () :

/ * slot ID pointer * I

/* setup the COPS ports */

1* This mess disables tr.e ve:::t:'cle retrace interrl;.pt, for nu'~.
*1
do (
VRON - 1:
I while «STATUS' S_VRI (- 01;
do {

VROFF - 1;
} while «STATUS & S_VR) -- 0);

scini t () ;
1* SCC serial initialization * /
Hfdef UCB NET
netinit() ;
.endif
/. Now enabie t.he vertlcle retrace int.errupt., used for t.he system
*/
do (
VRON - 1;
) while «STATUS & S_VR) !- 0);
Eftief SUNIX

0100.<.

SPLO () ;
1*~.Qis

is the fiJ:at unix bootedciurinq

inat~l.l.~,tiOD

so fi-noei swapdev. '"

config.c

Fri Sep

2

5 19:08:54 1986

if (rootdev ~ makedev(SN1, 01) {
while (chkdev (dev - getdevnam () ) )
printf("Unable to use that device\nTry again: \nU);
printf("\n\nswapdev = Ox%x\n\n", dev);
swapdev - dey;
if {rn.ajor{dev} = PRO} nswap - PRNSWAP;
else i f Imajor(dev) - PM3) nswap = PMNSWAP;
else i f (major (dev) -= CV2) nswap = CVNSWAP;
else panic ("cannot determine size of swapdev"l;

setppint (addr, fncl
struct device d *addr;
int (*fnc)();{

register int i;
extern int cvint (), proint:r (), Ipintr () ;
for (i=O; ip_ flag++;
tendif

if( (i

=

ap->a devl -= 0) {
if (fnc - pi fnc [i] )
fncli) ;
return;

/* special case for pp 0 * /

}

struct device_d
PPADDR,
(struct
(struct
(struct
(struct
(struct
(struct
!struct
(struct
(struct

*pro_ da [NPPDEVS] = {
device d
device-d
device-d
device-d
device-d
device-d
device-d
device-d
device=:d

*1
*1
*I
*)
*1
*)

*1
"I
*)

(STDIO+Ox2000),
(STDIO+Ox2BOO),
(STDIO+Ox3000),
(STDIO+Ox6000) ,
(STDIO+Ox68001,
(STDIO+Ox70001,
(STDIO+OxAOOO),
(STDIO+OxABOO),
(STDIO+OxBOOO)

/*
/*
/*
/*
/*
/*
/*
/*

1*
/*
/*

DEV
OxOO
Ox10
Ox20
Ox30
Ox40
Ox50
Ox60
Ox70
Ox80
Ox90

Description * /
parallel port * /
FPC port 0 slot 1
FPC port 1 slot 1
FPC port
slot 1
FPC port
slot
FPC port
slot
FPC port
slot
FPC port
slot
FPC port
slot
FPC port
slot 3

*/

*/

!!! * /
*/

*/
! ! ! "I
"/

*I
!!!" I

);

int (*pi_fnc[NPPDEVS]) ();

/* slots for interrupt handler addresses * I

/* Set the interrupt handler for a given parallel port controller.
"/

j
i + 2;
while (i < j) {
dp=proda[i];
if «a =-dp->d ifr) & FCAl) {
asm(" - nop ");
dp->d ifr - a; /* reset interrupt * I
if (fnc - pi fnc[i]) {
i f (fnc -- Ipintr)
Ipflg[iJ - 0;
else if (fnc l- ebintr &&
fnc ! - prointr "
fnc !- cvint) (
printf(lIpi fnc[%d] - Gx%x invalid! !\n",
i,fnc);
return:

config.c

Fri Sep

5 19:08:54 1986

3

fnc(i) ;
return;

default:
printf ("Invalid input. Try again. \n") ;
goto retry;

lifdef INTDUMP

}

printf("Where will the disk be?\n");
i f i (dev - PRO) i i (dev - CV2») i
printf("Enter: '0' for builtin port\n");
printf ("
, l' for Expansion Slot 1, Bottom Port\n");
printf("
'2' for Expansion Slot 1, Top port\n");
printf ("
, 4' for Expansion Slot 2, Bottom Port\n Ol ) ;
printf("
'5' for Expansion Slot 2, Top Port\n");
printf{!!
! 7!
for Expansion Slot 3, Bottom Port\n"j;
, 8' for Expansion Slot 3, Top Port\n");
printf("
p - gets 0 ;
switch (p[O])
case ' 0' :
case ' l' :
case '2' :
case '4' :
case '5' :
case '7':
case'8':
unit - p[O] - '0';
break;
default:
printf("Invalid input. Try again. \n");
goto retry;

ppdump (i, dp) ;
tendif INTD1JMP

return;

i++;

lifdef INTDUMP
ppdump (n, p)
register struct device_ d *p;
{

printf ("pport %d: ",n);
printf("ifr=%x acr=%x pcr=%x ddra=%x ddrb=%x irb=%x\n",
p->d_ifr&OxFF I p->d_acr&OxFF, p->dycr&OxFF, p->~ddra&OxFF,
p->d_ddrb&OxFF, p->d_irb&OxFF);
lendif INTDUMP

/*
called from clock if there's a panic in progress
*/
clkstop()
(

)

VROFF -

1;

/*

) else ( /* dey = PM3 */
printf("Enter: '0' for Slot l\nU);
printf("
'1' for Slot 2\n");
printf(U
'2' for Slot 3\nU ) ;
p = gets!);
switch (p[O])
case '0':
case '1':
case '2':
unit = p[O] - '0';
break;
default:
printf(illnvalid input. Try again. \nii);
goto retry;

disable vertical retrace intr * /

nmikey()
{

int i;
register short status;

/* added 7/25/84 to provide more info than "NMI key".
1<
(taken from section 2.8 of Lisa Theory of Operations)
*/
printf("non-maskable interrupt: ");
status - STATUS;
if (status & S SMEMERR)
print£("soft memory error\n");
else if (status & S HMEMERR)
printf ("hard memory error\n");
else
printf(lIpower failure/keyboard reset\n");
lifdef HOWFAR
showbus() ;
lendif HOWFAR
for (i-OxcOOOOO; i>O; i--)

chkdev(d)
(

return (*ooevsw[bmajor (d) j.d_open) (minor (d) , FREAD I FWRITE);

/* delay */

lifdef SUNIX
1* Get swap device name
*/
getdevnam ()
(

char *p, *gets () ;
int unit, dey;
retry:
printf("\n\nWhere is the swap area?\n");
printf("Enter: 'p' for builtin disk or a profile disk\n");
printf ("
'c' for Corvus disk\n");
printf("
'pm' for Priam disk\n");
p - gets ();
switch (p[O])
case 'p':
dey - PRO;
if (p[l] ~ 'm')
dey = PM3;
break;
case 'e':

dey - CV2;
break;

return makedev!dev, (unit«4) I 1 );

/*
* This version of getchar reads directly from the keyboard in order to get
* swapdev when the parallel port is not available. It will not work once
* the console has been formally opened.
*1
char kb getchr;
cogetchar ( )
{

SPLO 0;
while (kb state) ;
kb getch-;; = 1;
whIle (kb getchr)
return kb::::chrbuf;

/* wait for kb driver to finish special crnd *1
1* wait flag * I
1* wait for it to happen *1

1* Kernel get string routine.
• Useful for getting information from the console before the system
• comes up. The getchar routine will not work once the console has
1< been opened.
*/
int (*getchar) () - cogetchar;
extern int (·putchar) () ;
char Qet.sbu.f{lUOJ:

Fri Sep

config.c

5 19:08:54 1986

char *
gets ()
{

register char *p;
register char c;
extern short kb_keycolL."lt;
p = getsbuf;
while (e = (*getchar) ()
switch (c) {
case '\r':
case '\n':
goto out;
case '\b':
i f (p > getsbuf)
p--;

break;
ease'@' :
case ' X, &OxlF:
/* line kill "/
i f (p > getsbuf) {
p = getsbuf;
e = '\n';
/* echo a newline */
break;
default:
*p++

= e;

(*putehar) (c);
i f (p >- getsbuf + sizeof (getsbuf»

{
printf ("\nlnput line too long, try again ... \nU);
p - getsbuf;

out:
*p - , \0';
(*putehar) (' \n');
return getsbuf;
tendif SUNIX

4

context.c·
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

Fri Sep

5 19:08:16 1986

cxtail (ex);

"sys/param.h"
Hsys/confiq. h"
"sys/mmu.h"
"sys/types.h"
"sys/sysmacros .h"
• sys/systm.h"
"sys/sysinfo.h"
• sysl callo. h"
"sys/dir.h"
Hsys/siqnal.h"
"sys/user .h"
"sys/ipc .h Ol
"sys/shm.h"
"sys/proc.h"
"sys/text.h"
·sys/psl.h"
·sys/var.h"
Msys/context.h"
"sys/map.h"

1*
Release the context associated with
* a given context structure and
* move it to the head of the queue
*/
exrelse (ex)
reqister struct context *cx;
reqister struct context **backp;
i f (cx

1* tdefine HOWFAR *1
extern struct shminfo
struct context cxhdr:

1

1* shared memory info structure * I

shminfo:

1* head of context structure */

/*
* Allocate a new context freeinq one if necessary

0)
return;

~

tifdef HOWFAR
printf(OIReleasinq 'lsd seqs for cx 'lsd\n", ex->cx_dsize, cx->cx_num);
tendif
cxrfree (ex):
ex->cx back->cx forw = cx->cx forw;
cx->cx- forw->exback = cx->cx-back:
backp:; (struct-context **)&cXhdr.cx_forw:
(*backp) ->cx back = cx:
cx->ex forw :: *backp;
*backp- = ex;
cx->ex_back = &cxhdr;

*1
struct context *
cxalloc()

1*
* Release the context associated with
* a qiven context structure

{

reqister struct context *cx;

*1
/*
* search for unused context
*I
for (cx = cxhdr.ex forw: cx !- &cxhdr; cx
if (cx->cxYroc - 0)
return (cxunlink(cx) );
/*
" return the context on top of the queue
*/
cx = cxhdr.cx_forw;
cxrfree (cx);
return (cxunlink (cx) );

cxrfree (cx)
reqister struct context *cx;
{
=

cx->cx_forw)

/*

" Find first used context and free it
*/
cxfree ()
{

register struct context *cx:
for (cx - cxhdr.cx forw: cx !- &cxhdr; cx - cx->cx_forw)
if (Cx->cx~roc) {
cxrelse(cx) ;
return(O) ;
return(-l) ;

reqister struct proc *p;
reqister struct exphys *cxp;
reqister struct exshm *cxs;
int i;
if «p - cx->cxyroc) =
return;
if (ex->cx dsize > 0)

NULL)

tifdef HOWFAR
printf ("Freeinq 'lsd data seqments at 'lsd for pid 'lsd\n",
cx->ex_dsize, cx->ex_daddr, p->pyid);
tendif
if (cx->cx daddr -- 0)
prIntf("cxrfree error. cx daddr = O\n");
mfree (cxmap, (short) cx->cx dsize, - (short) cx->cx_daddr);
cx->cx_dsize = 0;
cx->ex_ daddr = 0;
cxp - &cx->cxJ>hys [0] ;
for (i-O; icxJ>hsize) {
mfree (cxmap, (short) cxp->cxyhsize,
(short) cxp->cx phaddr);
cxp->cx phsize - 0;
cxp->cx~haddr - 0;
cxp++;

/*
* Initialize the context structure linked list
*/
cxinit ()
{

reqister struct context .cx;
register i;
i = USERCX;
cx - &cxhdr;
cx->cx forw = cx->cx back - cx:
for (Cx - &context [0]; cx < &context [NUMUCONTXj; cx++) !
cx->cx_num = cxntocx(i++):

cxs - &cx->cx shm[O];
for (i=O; i <-shminfo.Shmseg; i++) {
if (cxs->ex shmsize) {
mfr;e (cxmap, (short) cxs->cx shmsize,
(short)cxs->cx shmaddr);
cxs->cx shmsize - 0; CX9->CX shmaddr - 0;

=:

cxs++;
cx->cx_proc - 0;
p->p_cont.ext. - o.

Fri Sep

context.c

5 19:08:16 1986

I"
" Put a context buffer onto the tail of the context queue
"I
cxta:i.l (cx)
register struct context "cx:
(

register struct context **backp:
backp = (struct context * *) &cxhdr. cx_back:
("backp) ->cx forw - cx;
cx->cx_back
*backp:
"backp - ex;
cx->cx_ forw = &cxhdr;

=

I"
" Release context resources associated
" with a text segment.
"I
cxtxfree (xpl
register struct text "xp:
(

register struct proc "p;
&proc[O]; p < (struct proc *)v.veJ>roc; p++)
xp)
Cxrelse (p->p context):
i f (xp->x exaddr = 0 I I xp->x size = 0)
return:
mfree (cxmap, (short) ctos (xp->x size), (short)xp->x_cxaddr);
xp->x_ cxaddr = 0:
for (p

=

i f (p->p textp -

/*
" unlink a context structure from the queue

"I
struct context "
exunlink (cx)
register struct context *cx;
(

cx->ex_ back->cx_ forw
cx->cx forw->cx back
return(cx);
-

=
=

cx->ex_ forw:
cx->cx_back;

/*
" Free all shared text segments
"/
txfree()
(

register struct text "xp:
register struct proc *p;
int n;
n -

0;

for (p

=

&proc[O]; p < (struct proc *)v.veJ>roc; p++) (
i f «xp - p->p_textp) !- NULL) {
cxrelse (p->p context):
i f (xp->x exiddr && xp->x size) {
mfree (cxmap, (short) ctos (xp->x_size),
(short)xp->x_cxaddr) ;
xp->x_cxaddr - 0;
n++;

return(n) ;

2

5 19:08:37 1986

E'ri Sep

cv.c
I*tdefine HOWFAR*I
tdefine INTSON

1
extern char slot [ ] ;

1* defined for an interrupting disk *1
punit - physical (dev);
if (punit) {
1* for expansion slot check slot number and type *1
if (!PPOK(punitl II (slot[PPSLOT(punit)] !- PRO» {

1*

*

Corvus Disk System

*I
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

return 1;

Usys/param.h"
"sys/config.h"
"sys/mmu.h"
"sys/types .h"
"sys/sysmacros .h"
"sys/dir.h"
"sys/signal.h"
"sys/user.h"
"sys/errno.h"
"sys/utsname. hOI
"sys/buLh"
·sys/eloq.h"
"sys/erec.h"
·sys/iobuf .h"
"sys/systm.h"
"sys/var.h"
"sys/altblk.h H
"sys/diskformat.h"
"setjmp.h"
"sys/cops.h"
"sys/pport.h"
·sys/dyrofile.h"
"sys/cv.h H
"sys/swapsz.h"

devp - pro_da[punit];
u.u_error - a;
if (iocheck(&devp->d ifr»
1* board there '1 *1
if (cv addr(punit) !- devpl {
1* not already setup *1
- if (setppint «cv addr (punit) = devpl, cvint»
goto fail;
if (cvinit (&prodata [punit] I)
freeppin (devp) ;
goto fail;
}

} else (
fail:
u.u error - ENXIO;
cv addr(punit) ~ (struct device_d *) 0;
return 1;
return 0;

1*
Hfdef notdef
tdefine logical (x)
tdefine interleave (x)
tdefine physical (x)
tendif
tdefine cv addr (dl
tdefine cvwait (a)

1* defined in dyrofile.h *1
(minor (x) & 7)
1* eight logicals per phys *1
(minor (x) & Ox8)
1* interleave bit for swapping
«minor(x) & OxFO) » 4)/* 10 physical devs *1

* cvinit - initialize drive first time

*1

*1
cvinit(p)
register struct prodata *p;
{

(prodata[d].pd dal
while « (a) ->d_Irb

&

ST_BUSY) -

register struct device_d *devp - p->pd_da;
register char irb;
register char zero = 0;
int pI;

0)

1*

*
*

the total space on the corvus h series is:
306 cylinders are there but corvus reserves
* 304 cylinders * 20 sectors per track * 6 heads
36480

pI = spl6 ();
if (devp = PPADDRI
devp->d ddrb &= Ox5C;
devp->dJx:r = Ox6B;
devp->d ddra - zero;
devp->d~)rb 1- CMDIDRW;
devp->d ddrb 1- Ox7C;
devp->d::::irb &- -DEN;
} else
devp->dycr = Ox6B;
devp->d ddra = zero;
devp->d::::irb = CMDIDRW;
devp->d_ddrb = Ox7C;

=

* The first 100 blocks are reserved for the boot program and
* are inaccessible via unix.

*1
tdefine MAXBOOT 100
struct cv sizes {
daddr t sz _offset;
daddr-t sz size;
cv_slzes[]-- {
CVNSWAP+lOl,
32420,
101,
CVNSWAP,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
101,
1000000

1*
1*
1*
1*
1*
1*
1*
1*

a:
b:
c:
d:
e:
f:
q:
h:

root file system *1
swap area (3959 blocks) *1
unused *1
unused *1
unused *1
unused *1
unused *1
file system using entire disk *1

};

struct iostat cvstat [NPPDEVS] ;
struct iobuf cvtab = tabinit (CV2, cvstat) ;
struct buf cvrbuf;

1*

*

cvopen - check for existence of controller

*1
cvopen (dev)
register dev;
{

register punit;
register struct device_d *devp;
int cvint ();

1* active buffer header *1

1*
1*
1*
1*

port B bits: 0,1,5,7 to in, 2,3,4,6 to out *1
set controller CA2 pulse mode strobe *1
set port A bits to input **1
set command = false set direction - in *1

1* set enable - true *1
1 * set controller CA2 pul se mode strobe * 1
1* set port A bits to input **1
1* set command = false set direction = in *1

tifdef

INTSON
devp->d ier - FIRQ IFCAl;
irb = devp->d irb;
tifdef lint
pI - irb;
tendif lint
p->pd_state - SCMD;
tendif INTSON
splx(pl) ;
return 0;

cvstrategy (bpi
register struct but *bp:
!
register punit, lunit, bn;
punit - physical (bp->b devl;
lunit - logical (bp->b dey) ;
bn - bp->b blkno + cv-sizes [lunit] . sz offset;
i f (bp->b_blkno < 0 II bn <- MAXBOOT)-{

Fri Sep

CV.C

2

5 19:08:37 1986

Hfdef HOWFAR
prdev("cvstrategy: illegal blkno", bp->b dev);
printf(Ublkno=%d bcount-%d\n", bP->b_blkno, bp->b_bcount);

caddr t cv buf;
int cv_count;

bp->b flags 1- B_ERROR;
iOdone (bp) :
return;

cvrw(dev, blkno, n, flag, buff)
register dey;
register daddr t blkno;
register n, flag;
register caddr t buff;

tendif HOWFAR

cvstat[punit].io_ops++;
tifdef INTSON
bp->b_resid = bn;
/" resid for disksort ,,/
SPL6 ();
disksort (&cvtab, bp);
felse INTSON
bp->av forw - (struct buf ")NULL; /* last of all bufs */
if (cvtab.b actf ~ NULL)
cvtab.b_actf = bp;
1* empty - put on front *1
else
cvtab.b actl->av foni - bp; /" else put at end "/
cvtab. b_actl - bp;
tendif INTSON
if (cvtab.b active - 0)
cvstart() ;
tifdef INTSON
SPLO ();
telse INTSON
while (cvtab.b active)
cvint (I;
tendif INTSON
return;

-

{

register punit;
register struct device_d "addr;
punit-physical (dev) ;
cv_buf = buff;
cv count - n;
if- (cvop(punit, 4, flag-B_READ Z N_R512 : N_W512,
blkno & Oxff, blkno»S & Oxff) < 0)
goto bad;

(blkno»16

bad:
tifdef HOWFAR
printf ("cvrw: %s error unit=%d blkno-%d n-%d buf=Ox%x\n U ,
flag=B_READZ"read":"write U, punit, blkno, n, buff);
tendif HOWFAR
return -1;

(

/*

register struct buf *bp;
register lunit, offset, bn;
register struct device_d *addr;

VARARGS3

*1

cvop(unit, na, a)
{

tifdef INTSON
register s;
tendif INTSON
register int *ap;
register struct device_ d *addr

loop:
if «bp = cvtab.b actf) = (struct buf *)NULL)
return; if (cvtab.b active == 0) {
bp->b resid - bp->b bcount;
cvtab~b_active = 1;-

addr->d ddra = Oxff;
addr->d=irb &- -OxOS;

lunit = logical (bp->b dev);
blkacty 1= (1«CV2);
offset - bp->b bcount - bp->b resid;
bn - bp->b blkno + btod(offset);
/* logical block number */
if (bp->b ~esid < BSIZE 1 I bn >- cv sizes [lunit] . sz size)
next:
- Hfdef HOWFAR
if (bp->b resid !- 0)
p~intf ("Unix cvstart: blkno=%d resid=%d bn=%d\n",
bp->b_blkno, bp->b_resid, bn);
tendif HOWFAR
blkacty &= - (1 «CV2) ;
cvtab.b active = 0;
if (cvtab.b errent) {
logberr(&cvtab, 0); /* errlog non-fatal errors */
cvtab. b_ errent - 0;

=

cv_ addr (uni t) ;

1* port A to output *1
/* bidirectional driver to output *1

ap - &a;
if (na-- > 0) {
tifdef INTSON
s = spl7 ();
tendif INTSON
cvwait (addr) ;
addr->d_ira - "ap++;
tifdef INTSON
sp1x(s) ;
tendif INTSON
}

for (; na > 0; na--, ap++)
cvwait (addr) ;
addr->~ira = *ap;
return 0;

I * reset intr

*/

}

if !cvrw(minor!bp->b dev) , bn ... cv sizes [lunitJ. sz offset, BSIZ!,
bp->b flags&B READ~ bp->b un.b add~ + offset) < 0)
bp->b flags 1-= B ERROR;
-logbe~r (&cvtab, 1);
/ * log fatal error * /
goto next;
return;

Oxf) +1,

if (flag ~ B WRITE && cvw(punit, buff, n) < 0)
goto bad;
addr - cv_addr(punit);
addr->d ddra - OxOO;
/" data direction port A bits to input */
addr->()rb 1- OxOS;
/" bidirectional driver to input ,,/
return 0;

cvstart()

addr - ev addr (physical (bp->b dev»;
addr->d ifr - addr->d ifr;
cvtab.b-aetf - bp->av-forw;
iodone (bp) ;
goto loop;

&

cvint (punit)
int punit;
{

register struct device d *addr;
register struct buf *bp;
register char status;
(void) spl6 () ;
addr - cv addr (punit) ;
if (cvtab~b active -- 0)
tifdef HOWFAR
printf(lIcvint: b_active

~

O\n"l;

cv.c

Fri Sep

5 19:08:37 1986

3
register n;

tendif HOWFAR
if (addr

~

PPADDR)
addr->d_ifr

(
=

addr->d_ifr;

1* reset intr *1

register char *ira;
register struct device_d "addr - cv_addr(unit);

return;

if «bp .... c\rtab.b_actf) =

ira - li (addr->d ira);
cvwait (addr) ; for ( ; n > 0; n--) {
i f «addr->d_irb & ST_HTOC) ==
break;
*ira = *buff++;

(struct buf *)HULL)

Hfdef HOWFAR
printf("cvint: b_actf -

NULL\n");

tendif HOWFAR
i f (addr - PPADDR)
addr->d_ifr - addr->d_ifr;
return;

I" reset intr ,,/

cvwait (addr) ;
if (addr - PPADDR)
/* reset intr *1
addr->d ifr - addr->d ifr;
if (status = addr->d_ira) { err:
printf("%s error: Idev/c%d%c blkno=%d\n",
bp->b flags&B READ'? "read H : "write", punit,
, a' +logical (bp->b dev), bp->b blkno);
cvlog(status);
cv count = 0;
if- (++cvtab.b errcnt > NRETRY) {
bp->b-flags I ~ B ERROR;
logberr(&cvtab, 1);
1* log fatal error *1
blkacty &= -(1«CV2);
cvtab.b errcnt - 0;
cvtab.b-actf = bp->av forw;
cvtab.b-active - 0; iodone (bp) ;
} else if (bp->b flags&B READ)
if (cvr(punit, (Char *)cv_buf, cv_count) < 0)
goto err;

for (;;) {
cvwait (addr);
i f «addr->d irb & ST_HTOC)
break;
"ira - 0;

0)

~ 0)

cv count -- n;
if-(n> 0) (
Hfdef HOWFAR
printf("cvw: %d bytes short\n", n);
tendif HOWFAR
cvlog(O) ;
return -1;
return 0;

cvr (unit, buff, n)
register char "buff;
register n;
(

register char *ira;
register struct device_ d *addr - cv_ addr (unit) ;

1*
* because a single buffer can take several io operations,
* we leave it to cvstart () to figure out when it's done

*1
bp->b_resid -- cv_count;
cvstart ();

cvlog (status)
register status;
{

register struct buf *bp;
register struct device d *addr;
register bn, punit, lunit;
struct deverreg cvreg[2];
bp = cvtab.b actf;
punit - physIcal (bp->b dev);
lunit = logical (bp->b dev);
cvtab.io stp = &cvstat[lunit];
addr = cv addr (punit);
cvreg[O] .draddr - (long) &(addr->d ira);
cvreg[O] .drvalue = status;
cvreg[O] .drname = "cv status";
cvreg[O] .drbits - "Corvus disk status code";
cvreg[l] .draddr = (long) 0;
cvreg[l].drvalue = cv count;
cvreg [1] . drname - "coUnt";
cvreg[l].drbits - "byte count of transfer";
bn - bp->b_blkno + btod(bp->b_bcount - bp->b_resid) + cv_sizes [lunit] . sz_offset;
fmtberr (&cvtab,
(unsigned) punit,
(unsigned) 0,
1* cylinder *1
(unsigned) 0,
/* track */
(unsigned)bn,
1* sector *1
(long) (sizeof(cvreg) Isizeof(cvreg[O]», 1* regcnt *1
&cvreg [0), &cvreg [1) ) ;
cvw (unit, buff, n)
register char xbuff:

cvwait (addr) ;
ira = &(addr->d ira);
for ( ; n > 0; n--) {
i f (addr->d irb & ST_HTOC)
break;
*OOff++ - *ira;
cv count -- n;
if-(n> 0) {
tifdef HOWFAR
printf("cvr: %d bytes short\n", n);
tendif HOWFAR
return -1;
for (;;) {
cvwait (addr) ;
i f (addr->d_irb
break;
n - "ira;

&

ST_HTOC)

return 0;

1"*******
tifdef INTSON
felse
INTSON
1* wait for controller to host direction or timeout *1 I"
cvctoh(a)
register struct device_d *a;
I
register i;
for

(i -

i

100000;

=

20;

i-- > 0;);

do
while (--i > 0 U «a->d irb&ST BUSY) -- 0»:
while (i > 0 " (a->d irb & ST HTOC»);
i f (i <- D) {
printf ("cvctoh: timeout\n");
return -1;

E'ri Sep

cv.c

5 19:08:37 1986

4

return 0;
tendif

INTSON

********1
cvread (dev)
dey t dey;
{ physio (cvstrategy, &cvrbuf, dey, B_READ);

cvwrite (dev)
dey t dey;
{ physio (cvstrategy, &cvrbuf, dey, B_WRITE);

cvprint (dev, str)
char *str;
{

printf("%s on cv drive %d, slice %d\n", str, (dev»4)&OxF, dev&7);

Fri Sep

cxureg.c
+include
+include
tinclude
tinclude
+include
tinclude
+include
+include
tinclude
tinclude
+include
!include
tinclude
+include
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
+include

5 19:08:17 1986

1
page = p->p addr + v. v usize + segoff:
1* map a max of NPAGEPERsEG (256) 512-byte pages per segment *1
for (i = up->uJXisize; i > 0; i -= a) (
a = min (NPAGEPERSEG, (unsigned) i) ;
setmmu«short *) «int)addr I ACCSEG), page);

"sys/param.h"
"sys/config . hI!
"sys/mmu.h"
·sys/types .h"
"sys/sysmacros .h"
IIsyS/SySt.i'n..h"
"sys/sysinfo.h"
·sys/callo.h"

setmmu«short *) «int)addr I ACCLIM), ASRW I

page += a;
addr - (short *) «long) addr + (1 «

«256=a)

GAFF» ;

SEGSHIFT»);

"sys/dir.h"
·sys/signal.h"
"sys/user. hOI
·sys/proc.h"
"sys/text .h"
"syslipc. hOI
"sys/shm.h"
"sys/psl.h"
"sys/var.h"

I * set up stack segment * I
addr = (short *) (vtoseg (v. v_ uend) ) ;
page +- up->uyssize;
1* stack is right after data "I
for (i = up->uyssize; i > 0; i -- a) (
addr - (short ") «long)addr - (1 « SEGSHIFT»:
a - min(NPAGEPERSEG, (unsigned)i);
page -- NPAGEPERSEG;
setmmu short *) « int) addr
ACCSEG), page);
setmmu ( (short *) « int) addr
ACCLIM), ASRWS I (a -1)) ;

«

"sys/seg.h"
"sys/context. hOI
"sys/map.h"

"sys/errno.h"
1* set up phys() *1
for (ph = &u.uyhys[O]; ph < &u.uyhys[v.vyhys]; ph++)
if (ph->uyhsize) {
page - (ph->uyhpaddr » PAGESHIFT) + segoff;
addr - (short *) vtoseg Iph->uyhladdr) ;
for Ii = ph->uyhsize; i > 0; i -= a) {
a - min (NPAGEPERSEG, (unsigned) i) ;
1* if «getmmu(vtoseg(addr) I ACCLIM) &PROTMASK) ~ ASINVAL) { *1
if (getmmu ( I short ") ( (int) addr I ACCLIM» &PROTMASK) ~ ASINVAL)
setmmu {(short *) ( (int) addr I ACCSEG), page);
setmmu( (short ") «int) addr I ACCLIM), ASRW I «256-a) & OxFF»;

"sys/scat.h"

typedef int
mem_t;
short
segoff;
extern struct shmid ds
extern struct shmpt- ds
extern struct shminfo

I" mmu segment offset *1
*shm shmem[];
1* ptrs to attached segments "I
shmyte [];
/* segment attach points *1
shminfo;
1* shared memory info structure *1

/ * tdefine DUMPMM * I
/ * tdefine HOWFAR * /
/" tdefine TRACEALL * I

page +- a;
addr - (short *) «long)addr +

/*
" Load the user hardware page map.
*1
sureg()

I
/"dumpmm1 (1);

/"*""

DEBUG

(1

«

SEGSHIFT»;

*"""1

(

register struct user "up:
register struct phys "ph;
register struct shmid_ds *sp;
register short "addr;
register a, i, j, page;
struct text *tp;
struct proc *p;

I" set up shared memory * I
for

up = &u;
p - up->uyrocp;
tp - p->p textp;
tifdef HOWFAR
printf(Hsureg:p addr=Ox%x, tsize=%d dsize=%d ssize=%d\n",
p->p_addr, up->uytsize, up->uydsize, up->uyssize);
tendif
SEG1 1 - 1;
/ * SEG2_ 0 = 1; * /
clearmmu () :
addr = (short *)vtoseg(v.v ustart);
if (tp !- NULL) {
page = tp->x caddr + segoff;
1* map a max-of NPAGEPERSEG (256) 512-byte pages per segment */
for (i - up->uytsize; i > 0; i -- a) {
a - min (NPAGEPERSEG, (unsigned) i) ;
setmmu ( (short *) ( (int) addr I ACCSEG), page);
setmmu ( (short *) ( (int) addr I ACCLIM),
( (up->u_xrw--RO) ?ASRO:ASRW) I «256-a) & OxFF»;
page +- a;
addr - (short *) «long) addr + (1 « SEGSHIFT»;

(p - proc) " shminfo.shmseg; /* index of first shm_shmem[] ,,/
i < «p - proc) + 1) * shminfo.shmseg; i++) {
sp = shm shmem[i];
if (sp ...:: NULL)
/* no more shared mem segments this process */
continue;
I" shm scat is starting physical click number */
page --sp->shm scat + segoff;
addr - (short *)vtoseg(shmyte[i].shm_segbeg);
for (j - btoc(sp->shm segsz); j > 0; j -= a) {
a - min (NPAGEPERSEG, (unsigned) j) ;
if «getmmu«short *) «int)addr I ACCLIM»&PROTMASK) -- ASINVAL) (
setmmu«short *) «int)addr I ACCSEG), page);
setmmu ( (short *) ( (int) addr I ACCLIM),
ASRW I «256-a) & OxFF»;

{i =

page += a;
addr - (short *) «long)addr + (1 «

SEGSHIFT»;

setmmu(addr, data)
register short "addr;
register data;
(

int s;
addr-(short *)vtoseg(ctob(stoc(ctos(btoc(v.v_ustart)+up->uytsize»»;
} else
if (up->u ptsize !- 0)
addr - (short ") «long)addr +
ctob(stoc (ctos (Up->u_ptsize) ));

I * set up data segment */

iifdef TRACEALL
iifdef HOWFAR
i f (data !- ASINVAL)
i f « (int) addr & ACCSEG) -- .~.CCSEG)
printf ("setmmu: addr-Oxlx, data-Oxlx (Oxlx) \n", addr, data, data«9);
else

cxureg.c

Fri Sep

5 19:08:17 1986

printf (nsetmmu:addr-Ox%x prot-Ox%x, lenqth-Ox%x (%d) \n",
addr, data & PROTMASK, data, 2S6 - (data & OxFF»;
tendif
tendif
s

~

sp17 ();

SET~JP_l

=

1;

2
* are used by sureg to set up the page map.
*/
/* ARGSUSED */
estabur(nt, nd, ns, sep, xrw)
unsigned nt, nd, ns;
{

tifdef H~AR
printf("estabur:nt=%d nd=%d ns-%d rw-%d\n", nt, nd, ns, xrw);
tendif
if (verureg (nt, nd, ns, xrw»
return (-1) ;
suregO;
return (0) ;

*addr - data;
SETUP_O - 1;
splx(s) ;

qet..'!'.!nu(addr)

register short *addr;
{

register data;
int s;

/*

s = sp17();
SETUP_1 = 1;
data - *addr;
SETUP_O - 1;
splx(s) ;
data &= OxFFF;
tifdef TRACEALL
tifdef HOWFAR
if « (int) addr & ACCSEGI - ACCSEG)
printf(ngetmmu:addr-Ox%x, data=Ox%x (Ox%x) \nn, addr, data, data«9);
else
printf ("getmmu: addr-Ox%x prot-Ox%x, lenqth-Ox%x (%dl \nn,
addr, data & PROTMASK, data, 2S6 - (data & OxFF»;
tendif
iendif
return (data) ;

* verify user registers can be set up
*/
verureg(nt, nd, ns, xrw)
register unsigned nt;
unsigned nd, ns;
{

register int s;

/*

* check for sufficient number of segment registers
*/
if (ctos(nt) + ctos(nd) + ctos(ns) > ctos(btoc(v.v_uend-v.v_ustart»)
goto bad;
s = nd + ns + v.v usize;
if (nt -- 0) {
if (s > maxmem)
goto bad;
I else
if (nt + s <- maxmem)
goto ok;
goto bad;

clearmmu()
{

register
register
register
register
register

data - OxCOO;
/* ASINVAL (d7) */
inc = Ox20000;
/* address increment (d6) */
s - 0;
/* saved priority (dS) */
short i = 32-1;
/* loop counter (d4) */
char *addr = (char *)Ox8000;
/* address ACCLIM (as) */

tifdef lint
*addr = (char) i;
*addr = (char) inc;
*addr = (char) data;
tendif
s - sp17 ();
SETUP 1 = 1;
asm("loop:") ;
d7,aS@n);
asm("
movw
asm("
addl
d6,aS") ;
asm(H
d7,aS@") ;
movw
asm("
addl
d6,aS") ;
asm("
movw
d7,aS@") ;
asm(R
addl
d6,aS") ;
d7,aS@n) ;
movw
asm("
asm("
addl
d6,aS") ;
dbra
d4,loop") ;
asm("
SETUP_o - 1;
sp1x(s) ;

/* shared text *1
/* text+data can fit in largest hole */

ok:
u. uytsize = nt;
u.uyctsize - nd;
u.uyssize - ns;
u.u xrw = xrw;
return (0) ;
bad:
tifdef HOWFAR
printf("verureg failure:nt-%d
tendif
u. u error = ENOMEM;
return (-1) ;

ix essentially these pass args to sureg wi

nd-%d

ns=%d\n", nt, nd, ns);

tifdef DUMPMM
char *mmu_codes [1 = {
"UNPREDICT-O" ,
"UNPREDICT-1" ,
"UNPREDICT-2 u ,
"UNDEFINED" ,
"RO stack",
"RO",
"RW stack",
"RW",
"UNPREDICT-S" ,
"IO",
"UNPREDICT-A" ,
"UNPREDICT-B" ,

/*

* In V7, Set up software prototype segmentation
" registers to implement the 3 pseudo
text, data, stack segment sizes passed
* as arguments.
* The argument sep specifies if the
" text and data+stack secpnents are to
* be separated.
* The last argument determines whether the text
* segment is read-wr:i.te or read-only.

*

* u. uytsize etc replace the proto entries on the pdpll.

/* non shared text *1

"INVALID",

"UNPREOICT-O" ,
"UNPREDICT-E" ,
"SPIO",
};

They

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

*/
1 */
2 */
*/
*/
*/
6 */
*/
*/

*1
A *1
B */
c */
0 */
E */
F */

cx:ureg.c

Fri Sep

5 19:08:17 1986

dump the memory management registers
if system is non-zero, also dump system registers

*/
dumpmm(system)
int system;
!
printf (Op addr-Ox%x tsize=Ox%x dsize-Ox%x ssize=Ox%x\n",
u-:-uyrocp->p_addr, u.uytsize, u.uydsize, u.1lJ)ssize);
i f (system)
dumpmml (0) ;

dumpmml (1) ;

dumpmml (space)
(

register i, addr, prot, j, len;
printf("Context %d mmu registers\n", space);
printf(lIseg logical physical (clicks) permission\n");
for (i - 0; i < 128; iff) (
i f (space - 0)
SEGl_0 - 1;
else
SEGl_l = 1;
/* SEG2 0 - 1; */
addr = getmmu «i «SEGSHIFT) I ACCSEG);
prot = getmmu «i «SEGSHIFT) I ACCLIM);
if «prot & PROTMASK) ~ ASINVAL)
continue;
addr -= segoff;
len = prot & OxFF;
if (prot & Oxl00) (
/* data or stack segment */
j = i « SEGSHIFT;
len = 256 - len;
printf ("0X%X Ox%x-Ox%x Ox%x-Ox%x (%d) %s\n", i, j,
j+ctob(len), addr, addr+len, len,
mmu_codes [ (prot&PROTMASK) »8] ) ;
J else
len++;
j = (i+1) « SEGSHIFT;
addr +- NPAGEPERSEG:
printf ("Ox%x Ox%x-Ox%x Ox%x-Ox%x (%d) %s\n", i,
j-ctob(len), j, addr-len, addr, len,
mmu_codes [ (prot &PROTMASK) »8] ) ;

tendif DUMPMM
/*
* check the size of a process
*/
chksize (nt, nd. ns)
register unsigned nt, nd, ns;
(

if (nt + nd + ns + v.v usize < maxmem )
return (0);
u.u_error - ENOMEM;
return (1) ;

3

dsort.c

Fri Sep

1

5 19:07:48 1986

1*
* generalized seek sort for disk

*1
finclude
tinclude
tinclude
finclude
tinclude
finclude
finclude
finclude
tinclude
finclude
tinclude
tinclude
finclude
finclude

"sys/param.h"
"sys/config .h"
"sys/types.h"
"sys/sysmacros.h"
"sys/systm.h"
"sys/dir.h"
·sys/signal.h"
·sys/user .h Ol
·sys/errno.h·
·sys/utsname. hOI
·sys/buf . hOI
·sys/elog.h Ol
·sys/erec.h Ol
·sys/iobuf .h"

disksort (dp, bpJ
register struct iobuf "'dp:
register struct buf *bp:
{

register struct buf *ap:
struct buf *tp:
ap - dp->b actf:

i f (ap ~ NULL)

{

dp->b actf = bp:
dp->b:::actl - bp:
bp->av_forw - NULL:
return;
tp = NULL:
for (; ap != NULL: ap - ap->av forw)
i f «bp->b flags&B READ) && (ap->b_flags&B_READ)
i f- (tp ~ NuLL)
tp - ap;
break:

=

0)

i f «bp->b flags&B READ) = 0 && (ap->b_flagS&B_READ»
co~tinue; i f (ap->b cylin <= bp->b cylin)

if(tp -

NULL

tp
}

i f (tp

~

NULL)

tp - dp->b actl;
bp->av forw - tp->av forw;
tp->av- forw - bp;
i f (tp
dp->b_ actl)
dp->b_actl - bp;

==

=

II

ap;

ap->b_cylin >= tp->b_cylin)

{

err.c

Fri Sep

5 19:07:49 1986

1* @(t)err.c
1.1 *1
tinclude "sys/param.h"
tinclude "sys/types .hn
tinclude "sys/buf. h"
tinclude "sys/dir.h"
tinclude usys/signal.h"
tinclude Usys/user .h"
tinclude "syslerrno.hll
tinclude "sys/file .h"
finclude "sys/utsname.h"
tinclude "sysl elog. h"
tinclude "sys/erec,h"
static

short

logging;

erropen (dev, fIg)
(

if (logging)
u.u_error
return;

=

EBUSY;

)

if( (flg&FWRlTE) II dev != 0)
u.u_error = ENXIO;
return;
}

if (suser ()
(
logstart () ;
logging++;

1* ARGSUSED *1
errclose (dev, fIg)
{

logging

~

0;

1* ARGSUSED * I
errread (dev)
(

register struct errhdr *eu;:;
register n;
struct errhdr
*geterec () ;
if(logging ~ 0)
return;
eup = geterec () ;
n = min «unsigned) eup->e len, u. u count);
if (copyout«caddr_t)eup~ uou_base, n»
u.u_error - EFAULT;
else
u.u count -- n;
freeslot (eup);

1

errlog.c
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

Fri Sep

5 19:07:49 1986

"sys!param.h"
·sys!types.h"
• sys! sysmacros. h"
"sys!systm.h"
·sys!buf .h"
·sys/ccnf.h ll
·sys!map.h ll
"sys!utsname.h"
·sys!elog.h ll
·sys!erec.h"
·sys!err.h"
·sys/iobuf .h tl
·sys!var.h tl

1
while ("errp->e org - NULL)
(void) -sleep ( (caddr_t) &errp->e_org,PZERO+l);
ep = "errp->e org;
"errp->e org++ - NULL;
if(errp->e_org >- &errp->eytrs [errp->e_nslotj)
errp->e_orq = errp->eytrs;
splx(sps) ;
return (ep) ;

puterec(ep, type)
register struct errhdr *epi
register sps;
register struct err *errp;

typedef int
int

errp = &err;
(--ep) ->e type = type;
ep->e time = time;
sps = - sp17 () ;
"errp->e nxt++ - ep;
if(errp->e_nxt >= &errp->eytrs [errp->e_nslotj)
errp->e_nxt = errp->eytrs;
splx(sps) ;
wakeup ( (caddr_t) &errp->e_org);

blkacty;

errinit()
{

register struct err *errp;
errp = &err;
if (errp->e nslot) {
mapinit (errp->e map, (errp->e nslot+31 /21;
mfree (errp->e_map, (mem_ t) errp->e_ nslot, (mem_ tl 1 I ;
errp->e_org - errp->eytrs;
errp->e_nxt = errp->eytrs;

logstart ()
(

register sps;
register struct estart "ep;
register struct bdevsw "bdp;
register struct err *errp;
extern nodev () ;

struct errhdr *
geteslot (size)
{

register ns, *p;
register struct errhdr "ep;
int n, sps;

errp - &err;
sps - sp17 () ;
for (errp->e_org

ns - (size+sizeof(struct errhdr)+sizeof(struct errslot)-I)
/sizeof(struct errslot);
sps - sp17 () ;
n = malloc(err.e map, (me~t)ns);
splx(sps):
if(n ~ 0)
return (NULL) ;
ep - (struct errhdr ") (&err. e slot [--nj ) ;
ns *- sizeof(struct errslot)/sizeof(int);
p - (int *) ep;
do {
"p++ = 0;
I while (--ns) ;
ep->e_len = size + sizeof (struct errhdr);
return (++ep) ;

= &errp->eytrs [errp->e_nslot-lj;
errp->e_org >= errp->eytrs; errp->e_org--)
if(*errp->e_org := WuLL) {
freeslot (*errp->e org);
*errp->e_org = NULL;

errp->e_org = errp->eytrs;
errp->e_nxt = errp->eytrs;
ep = (struct estart *) geteslot (sizeof (struct estart»;
splx (sps) ;
i f (ep = NULL)
return;
ep->e name = utsname;
for(Mp = &bdevsw[bdevcnt-lj; bdp >= bdevsw; bdp--)
if (bdp->d_ strategy ! - nodev)
ep->e beonf I- 1 « (&bdevsw[Oj-bdpl;
ep->e_bconf = blkacty~
puterec( (struct errhdr *1 ep, E_GOTS);

freeslot (ep)
register struct errhdr *ep;
{

register ns, sps;

logtchg (nt)
time_t nt;

ns - (ep->e len+sizeof (struct errslot) -1) Isizeof (struct errslot);
sps - sp17 (T;
mfree(err.e map, (mem tIns,
(mem t) ««struct errslot *)ep)-err.e_slot)+I»;
splx(sps); -

{

register struct etimchg *ep;
if«ep

=

(struct etimchg *)geteslot(sizeof(struct etimchg»)) !- NULL) {
ep->e_ ntime ~ nt;
puterec ( (struct errhdr ") ep, E_ TCHG) ;

struct errhdr ..
qeterec I)
(

register sps;
register struct errhdr *ep;
register struct err *errp;
errp - &err;
sps - sp17 () ;

logstray (addr)
physadr addr;
{

register struct estray *ep;
if (lap -

(struct estray *)qeteslot (sizeof (struct estray))) !- NULL) {
ep->e_saddr = addr;

errloq.c

Fri Sep

5 19:07:49 1986

2
return;

ep->e_sbacty * blkacty;
puterec «struct errhdr *) ep,E_STRAY);

nn - major (dp->b dev);
bp - dp->b aetf;ep->e_dev -: makedev(nn, (bp-NULL) 1minor (dp->b_dev) : minor (bp->b_dev» ;
ep=>e bacty = blkacty;
ep->e::::stats.io_ops = iosp->io_ops;
ep->e stats. io misc ~ iosp->io mise;
ep->e- stats. io- unlog - iosp->i-;; unlog;
ep->e~s.unit-- unit;
ep->eJ>Os.eyl = eyl;
ep->eJ'''''Os. trk = trk:
ep->eJ>Os. sector = sector;
if(bp !- NULL) {
ep->e bflags - (bp->b flags'B READ)
E_READ
E_WRlTE:
if(bp=>b_flags , B_PHYS)
ep->e bflags 1- E PHYS;
if(bp->b flag~ , B MAP) ep->e bflags 1- E MAP;
ep->e bnum - bp->b blkno;ep->e-bytes = bp->b bcount;
ep->e::::memadd - paddr(bp);

logparity (addr)
register paddr t addr;
{
-

register struct eparity *ep;
if«ep

=

(struct eparity *)geteslot(sizeof(struct eparity») != NULL) {
ep->eyarreg - addr;
puterec ( (struct errhdr *) ep, E_PRTY) ;

/*
fmtberr () is used by block device drivers to build up a valid
eblock structure to be sent to the error log.
dp
unit
cyl
trk
sector
regcnt
regs

the address of the io queue item.
the Physical Device error report field
the Logical Device field is the minor device number
the cylinder number
the track number
the sector number
the number of following register structures
is the address of an array of structures each of which
contain the elements described in struct deverreg.

else
ep->e bflags = E NOlO;
ep->e nreg - regcnt;
pp - &«(struet br *)ep)->eregs[Oll;
dr - 'regs;
while (--regent >- 0) {
/* copy out the number values "/
pp - longcopy( (char *)' «"dr)->draddr),pp);
pp = longeopy( (char ")' «*dr)->drvalue) ,pp);
/* copy out the strings themselves */
strl - (*dr)->drname;
while (* str1) {
*pp++ - "str1++;

*I
/* VARARGS7 */
fmtberr (dp, unit, cyl, trk, sector, regcnt, regs)
register struct iobuf *dp;
unsigned unit;
unsigned cyl;
unsigned trk;
unsigned sector;
long regent;
struct deverreg *regs;

/* copy the terminating null too ,,/
*pp++ - , \0' ;
str1 - (*dr)->drbits;
while (*strl) {
"pp++ - "str1++;

register struct eblock *ep;
register struct buf *bp;
register struct deverreg **dr;
register char *str1;
register char *pp;
register short argc;
register short nn;
struct br {
/* just used to generate addr after eblock */
struct eblock eb;
char cregs[l);

logberr (dp, error)
register struct iobuf "dp;

);

{

*pp++
dr++;
dp->io_ erec

struct iostat *iosp;
extern char * longcopy () ;

ios~->io_unlog++;

\0' ;

ep;

dp->io erec) ~ NULL)
return;
if (error)
ep->e bflags 1- E ERROR;
puterec ( (stru~t errhdr *) ep, E_ BLK) ;
dp->io_ eree = NULL;
if «ep

iosp - dp->io stp;
/* want sizeo! ebloek to the next long address */
if I lep - Istruet eb10ek *1
geteslot (sizeof I struct ebloek) + nn» -- NULL)

,

register struct eblock *ep;

if (dp->io erec != NULL) {
dp-> io_ erec->e_ rtry++;
return;
/" count the length of the values and strings */
nn - 0;
argc - regent;
dr = 'regs;
while (arge--)
nn +- sizeof( ("dr)->draddr);
nn +- sizeof « *dr) ->drvalue) ;
nn +- str1en ( ("dr) ->drname) + 1;
/* + null * /
nn +- strlen « *dr)->drbits) + 1;
/* + null * /
nn +.. (nn & 1); /* round to e,"er: :'.::n'ber of bytes .. /
dr++;

=

=

=

I" may not be on long address boundary when copied to b2,
avoiding any alignment problems on some maehines1 */
char"
longcopy (b1, b2)
register char "bl, "b2;
{

register int ii;
for (ii=O; ii < sizeof(long); ii++) {
*b2++ - "bl ++;
return (b2) ;

fio.c

Fri Sep

5 19:07:50 1986

1
if «unsigned) fp->f count> 1) (
tifdef UCB_NET
fp->f_flag &= -FISUSER;
tendif
fp->f_count--:
return:

I" @(f)fio.c
1.4 *1
'include ·sys/param.h"
tinclude "sys/types.h H
finclude "sys/sysmacros.h"
tinclude ·sys/systJn.h"
.. include "sys/dir .h"
tinclude ·sys/signal.h"
tinclude ·sys/user.h"
tinclude ·sys/errno.h"
tinclude ·sys/filsys .h"
tinclude "sys/file.h"
tinclude ·sys/conf.h"
tinclude ·sys/inode.h"
tinclude ·sys/mount.h"
tinclude ·sys/var.h"
tinclude ·sys/acct.h"
finclude ·sys/sysinfo.h"
fifdef UCB NET
tinclude "net/misc.h lt
tinclude "netl socketvar. h"
fendif

fifdef UCB NET
if-(flag & FSOCKET) {
int nouser ~ « flag & FISUSER) -

I"

1*
" Convert a user supplied file descriptor into a pointer
" to a file structure.
" Only task is to check range of the descriptor.
"I
struct file *
getf(f)
register int f:

" the next line was in the 11 code. Dont quite understand it,
.. but it cant hurt ... (billn)
"I
u. u_error = 0;
I" so u. u_ofile always gets 0' d .. I
return:
tendif
ip = fp->f inode;
plOck(ip);dey = (dev t) ip->i rdev;
fmt - ip->I mode&IFMT:
fp->f count- ~ 0;
fp->f-next - ffreelist;
ffreelist - fp:
switch (fmt) (

{

register struct file "fp:
if

(0

<- f
fp

0):

u.u error" 0;
l* XXX *1
fp->f flag &= -FISUSER:
soclose«struct socket ")fp->f socket, nouser);
if (nouser ~ 0 && u.u_error) return:
fp->f_socket - 0:
fp->f count = 0;
fp->f-next - ffreelist;
ffreelist - fp:

f < NOFILE) {
u.u ofile[fl:
i f (fp !: NULL)
&&

=

case IFCHR:
cfunc = cdevsw[ (short)major(dev) l.d close:
break:
-

1* Mainly for net reset .. I
if (fp->f_count ~ 0) (
u.u error - ENETDOWN:
return (NULL);

case IFBLK:
cfunc = bdevsw[bmajor(dev) l.d close:
break:
-

else
tendif
return (fp) :

case IFIFO:
closep(ip, flag):

u. u_error = EBADF:
return (NULL) ;

default:
iput(ip) :
return;

1*

*

Internal form of close.
* Decrement reference count on file structure.
* Also make sure the pipe protocol does not constipate.

for (fp

* Decrement reference count on the inode following
* removal to the referencing file structure.
" On the last close switch out to the device handler for
.. special files. Note that the handler is called
* on every open but only the last close.

if (fp->f flag & FSOCKET)
c~ntinue:
fendif
if (fp->f count) {
tIp = fp->f inode;
if (tip->i rdev - dey &&
(tip->i iode&IFMT) -- fmt)
g~to out;

*1
closef(fp)
register struct file *fp;
{

register struct inode Kip:
int flag, fmt:
dev t dey:
regIster int (*cfunc) () :
if (fp -- NULL)
return:
flag - fp->f_flag;
Hfdef UCB NET
if- «flag' FSOCKET) - 0)
tendif
unlock (fp-> f _ inode) :

file; fp < (struct file ")v.ve file; fp++) {
register struct inode *tip;

=

}

i f (fmt

I" file lockinq hook "/

IFBLK) {
register struct mount *mp:

for (mp - mount; mp < (struct mount *)v.ve mount: mp++)
if (mp->m_flags - MINUSE " mp->m=:dev =- dey)
goto out:
bflush (dev):
(*cfunc) (minor (dev), flaq):
binYal (deY):
} else {

Fri Sep

fio.c

5 19:07:50 1986

2

prele(ip) :
I *cfunc) (minor (dev), flag);

return (0) ;
i f (up->u uid != ip->i uid)
m-»= 3:
i f (up->u gid !- ip->i gid)

out:

m-»=

iput(ip) :

3;

-

)

/*
.. openi called to allow handler of special files to initialize and
.. validate before actual 10.
*/
openi (ip, flag)
register struct inode *ip:
I
dey t dey:
regIster unsigned int maj:

dey = (dev t) ip->i rdev:
switch (ip->i_mode&IFMT) I
case IFCHR:
maj - major (dev):
i f (maj >- cdevcnt)
goto bad;
i f (u.u ttyp = NULL)
-u.u ttyd - dey;
("cdevsw[ (short)maj].d open) (minor (dev), flag);
break;
-

i f «ip->i mode&m) != 0)
return (0) ;

up->u error
return (1) ;

=

EACCES;

/*
* Look up a pathname and test if the resultant inode is owned by the
* current user. If not, try for super-user.
* If permission is granted, return inode pointer.
*/
struct inode *
owner()
{

register struct inode *ip;
ip - namei (uchar, 0);
i f (ip == NULL)
return (NULL) ;
i f (u. u uid = ip->i uid II suser () )
- i f (getfs(ip=>i_deV)->s_ronly)
u.u_error = EROFS;
if (!u.u error)
return (ip) ;
iput(ip) ;
return (NULL) ;

case IFBLK:
maj - bmajor (dev) ;
if (maj >- bdevcnt)
goto bad;
(*bdevsw [maj] . d open) (minor (dev), flag);
break;
-

/*
case IFIFO:
openp(ip, flag);
break;

.. Test if the current user is the super user.
*/
suser ()
(

return;
i f lu.u uid = 0) {
-u.u_acflag 1= ASU;
return (1);

bad:
u.u_error - ENXIO;

/*
* Check mode permission on inode pointer .
.. Mode is READ, WRITE or EXEC.
* In the case of WRITE, the read-only status of the file
* system is checked. Also in WRITE, prototype text
.. segments cannot be written.
* The mode is shifted to select the owner/group/other fields.
* The super user is granted all permissions.
*/
access (ip, mode)
register struct inode *ip;
(

register struct user *up;
register m;
up - &u;
m - mode;
i f 1m = IWRITE) (
i f (getfs(ip->i_dev)->s_ronly)
up->u error = EROFS;
return(1) ;

u.u_error - EPERM:
return (0) ;

/*
.. Allocate a user file descriptor .
*/
ufallocli)
register i;
(

register struct user *up;
up = &u;
fort; iu ofile til -- NULL) {
up->u rvall - i;
up->u-pofile[i] = 0;
return(i) ;
up->u_error - EMFILE;
return (-1);

}

i f (ip->i flaqUTEXT)

xrele(ip) ;
i f (ip->i_flag & ITEXT)
up->u_error - ETXTBSY;
return (1) ;

/*
.. Allocate a user file descriptor and a file structure.
.. Initialize the descriptor to point at the file structure.

.. no file -- if there are no available file structures.
*/
struct file *
falloc lip, flag)

fio.c

Fri Sep

struct inode *ip;
(

register struct file *fp;
register i;
i - ufalloc(O);
i f Ii < 0)
return (NULL) ;
i f Ilfp-ffreelist) = NULL)
printf("no file\n");
syserr. fileovf++;
u.u error - ENFlLE;
return (NULL) ;
ffreelist - fp->f next;
u.u ofile[i] ~ fp7
fp->f count++;
fp->f-inode = ip;
fp->f- flag = flag;
fp->f-offset - 0;
return (fp) ;

struct file *ffreelist;
finit()
{

register struct file *fp;
register short i;
ffreelist - fp - & file [01 ;
i = v. v file - 1 - 1;
do {
fp->f next = fp+l;
fp++;I while (--i !~ -1);

5 19:07:50 1986

3

fnet.c

Fri Sep

5 19:09:51 1986

1

1* data and code stubs for loading wit out network *1
netisr
finclude
tinclude
tinclude
tinclude
finclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
-#include
tinclude
tinclude

"sys/param.h"
"sys/config.h"
"sys/types.h"
"sys/mmu.h"
·sys/sysmacros.h"
"sys/dir.h"
·sys/proc.h"
·sys/seg.h"
·sys/signal.h"
"sys/errno.h"
"sys/user.h"
"sys/systm.h"
"sys/inode.h"
"sys/ino.h"
"sys/file .h"
"sys/conf.h"
"net/misc.h"
"net/protosw.h"
"net/ socket. h"
"net/ socketvar. h"
"sys/stat.h"
"sys/ioctl.h"
"net/ubavar .h"
"sys/map.h"
"net/if .h"
"net/in.h"
"net/in systm.h"
"net/ip~h"
"net/ip var.h"
"sys/var.h"

=

0:

}

I*ARGSUSED*/
soclose (so, exiting) struct socket *so; int exiting;
u.u_error - ENETDOWN;
/*ARGSUSED* I
soreceive (so, asa) struct socket *50; struct sockaddr *asa;
(

returneD) ;

1*ARGSUSED* I
sosend (so, asa) struct socket * so; struct sockaddr *asa;
(

return (0) :
/*ARGSUSED* 1
so stat (so, sb) struct socket *so; struct stat *sb;
(

return (0)

;

I*ARGSUSED*I

soioctl (so, cmd, cmdp) struct socket "so: int cmd; caddr_ t cmdp;
(

u.u_error = ENETDOWN;
sconnect()
(

u.u_error = ENETDOWN;
ssend()

1* data *1
struct protosw protosw [1] :
char netstak[3000]:
char * svstak;
int ifnetslow;
int protofast;
int proto slow ;
short netoff;
int netisr;
extern int ptc dev;
extern int selwait;
extern u short ip id;
extern struct ipq-ipq;
extern struct ipstat ipstat;
extern struct ifqueue rawintrq;
extern struct uba device ubdinit [J ;
extern struct protosw *protoswLAST;
tifdef INET
extern struct ifqueue ipintrq;
tendif

(

u.u_error - ENETDOWN:
ssockad()
(

u.u_error - ENETDOWN:
saccept()
{

u.u_error - ENETDOWN;
netreset ()
{
}

sethostname ()
(

u.u_error - ENETDOWN;
gethostname ()
{

u.u_error = ENETDOWN:

1* routines *1
ssocket ()

select ()

{

{

tifdef lint
ifnet++;
ifnetslow++:
protofast++;
protoslow++ ;
ptc dev++;
selwait++;
ip id++;
iM.iw.....ttl++;
·protoswLAST++ ;
ubdinit[O].ui unit++;
ipintrq. i fC!... 1;n++;
rawintrq. ifC!... len++;
protosw[O].pr type++;
ipstat. ips_ to~small ++;
tendif
u.u_error - ENETDOWN;
netintr ()

u.u_error

=

ENETDOWN;

sreceive ()
{

u. u_error - ENETDOWN;
}

I "ARGSUSED* I
ptswrite(dev) dev_t dey;
{

u. u_error

=

ENETDOWN;

}

/'ARGSUSED*I
ptcwrite(dev) dev_t dey:
{

u. u_error - ENETDOWN:
}

I*ARGSUSED* I
ptsioctl (dev, c:md, addr, flag) caddr_ t addr: dey _ t dev:
{

Fri Sep

fnet.c

5 19:09:51 1986

uou_error - ENETDOWN;
)

I*ARGSUSED* I

ptcioctl(dev, cmd, addr, flag) caddr_t addr; dev_t dev;
{
)

1* ARGSUSED* I
ptsopen (dev, flag) dev_ t dev;
{

I *ARGSUSED* I
ptcopen (dev, flag) dev_ t dev; int flag;
(

uou_error

=

ENETDOWN;

1* ARGSUSED* I
ptsread(dev) dev t dev;
{
uou_error - ENETDOWN;
)

I*ARGSUSED*I

ptcread(dev) dev t dev;
{
uou_error - ENETDOWN;

1* ARGSUSED* I
ptsclose(dev) dev_t dev;
{

uou_error - ENETDOWN;
I*ARGSUSED* I

ptcclose(dev) dev_t dev;
(

uou_error

=

ENETDOWN;

netinit()
{

I
tifdef NOTDEF
1* reference fnetlocal.c for inserting null interrupt associated stuff */
FAKE ()
{

fnetlocal ( ) ;
tendif _NOTDEF

2

fnetlocal.t;

Fri Sep

5 19:08:56 1986

I" local defs for no network "I
'include
.include
.include
tinclude
.include

"sys/param. h"
"sys/types. h"
"sysl sysmacros .h"
"sys/var.h"
"ermo. h-

'include
'include
'include
• include
'include

"net/misc.h"
"net/mbuf. h"
"net/protosw.h"
"net I socket. h"
"net/ubavar. h"

I" causes make to complain so this module gets included. "Called" from fnet.c *1
fnetlocal () { )

1* .. driver structure *1
struct uba_driver ebdriver;

1* interrupt routine *1
ebintr() {)

1

if.c

E'ri Sep

5 19:09:25 1986

/*
if.c
4.25
83/02/10
tinclude "sys/param.h H
tinclude "sys/config.h"
tinclude "sys/errno.h"
tinclude "sys/types.h"
tinclude "sys/syst!!!.h H
tinclude "net/misc.h"
t incl ude "net / socket. h"
tinclude "net/mbuf .h"
tinclude "net/protosw. h"
tinclude "net/if .h"
tinclude "net/af .h"

1
(bcmp«caddr t) «al) ->sa data), (caddr t) «a2) ->sa data), 14)
for (ifp = {fnet: ifp; ifp - ifp->if n~xt) {
if (ifp->if addr. sa family!:: addr->sa family)
continue; if (equal(&ifp->if_addr, addr»

*1

int

break;

if «ifp->if flags & IFF BROADCAST)
equal (&ifp->if_broadaddr, addr»
break;

&&

return (ifp);

/"
* Find an interface on a specific network.
* is first found.

/*
* Network interface utility routines.
* Routines with if ifwith" names take sockaddr .' s as
• parameters. oth~r routines take value parameters,
* e.g. if_ifwithnet takes the network number.
"/

If many, choice

,,/
struct ifnet *
if ifwithnet (addr)
register struct sockaddr "addr;
register struct ifnet *ifp;
register u int af = addr->sa family;
register i~t (*netmatch) (); -

ifinit ()
{

if (af >- AF MAX)
return (0);
netmatch - afswitch [af) .af netmatch;
for (ifp = ifnet; ifp; ifp-- ifp->if next)
if (af !- ifp->if addr.sa faiily )
continue; if «*netmatch) (addr, &ifp->if_addr»
break;

register struct ifnet "ifp;
for (ifp

ifnet; ifp; ifp - ifp->if_next)
if (ifp->if init) {
("ifp->if init) (ifp->if unit);
if (ifp->If_snd.ifif_snd.ifif_next)
if (ifp->if reset)
(*ifp->if_reset) (uban);

for (ifp

= ifnet; ifp; ifp = ifp->if next)
if (ifp->if net = net)
break;
return (ifp);

tendif

/"
* Attach an interface to the
" list of "active" interfaces.

"I
if_attach (ifp)
struct ifnet "ifp;

/*
" Find an interface using a specific address family
*/
struct ifnet *
if ifwithaf (af)
register int af;

register struct ifnet **p - &ifnet;
register struct ifnet *ifp;
while ("p)
p - '( ("p) ->if_next) ;
"p - ifp;

/"
" Locate an interface based on a complete address.
*/
I *ARGSUSED* /
struct ifnet "
if_ifwithaddr (addr)
struct sockaddr "addr:
register struct ifnet "ifp:
tdefine equal(al, a21 \

for (ifp - ifnet; ifp; ifp - ifp->if next)
if (ifp->if addr. sa family =-: af)
break;
return (ifp);

Hfdef notdef

!*
" Mark an interface down and notify protocols of
" the transition.
" NOTE: must be called at spInet or eqivalent.
*/
if down(ifpl
register struct ifnet *ifp;

~

0)

if.c

5 19:09:25 1986

E'ri Sep

ifp->if flags &- -IFF UP;
pfctlinput (PRC_IFDOWli; (caddr_t) &ifp->if addr);
tendif

1*

* Handle interface watchdog timer routines. Called
* from softclock, we decrement timers (if set) and
* call the appropriate interface routine on expiration.

*1
if_ slowtimo ()
{

register struct ifnet *ifp;
for (ifp

ifnet; ifp; ifp - ifp->if next) {
0 I I --Ifp->if timer)
continue;
i f (ifp->if watchdog)
(*ifp->if_watchdog) (ifp->if_unit);
=

i f (ifp->if timer =

)

1* billn -- clock calls us in old ...
timeout (if slowtimo, (caddr t) 0, hz 1 IFNET_SLOWHZ);
*1

-

-

2

if eb.c

Fri Sep

5 19:08:50 1986

1* 3com etherbox driver *1
finclude
tinclude
tinclude
finclude
tinclude
finclude

"sys/param. h U
"sys/types .h"
"sys/sysmacros .h"
"sys/var.h"
"errno.h"
"sys/config .h"

finclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

"net/misc.h"
"net/mbuf. h"
"net/protosw. h"
"net / socket. h"
"net/ubavar. h"
"net/if .h"
"net/route.h"
"net/in.h"
"net/in_systm.h"
"net/ip.h"
"net/ip_var.h"
"net/if_ether.h"

'define EBPUP PUPTYPE
tdefine EBPUP= IPTYPE

1
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

EB STABROAD
EB-PROMIS
EB- ANYGOOD
EB- ANY
EB-SHORT
EB-DRIBBLE
EB- CRC
EB- OVFLO
EB=RCVNORM

Ox80
Ox40
Ox20
Ox10
Ox8
4
2

match all packets * /
enable detection of any good frame */
enable detection of any frame */
enable decection of short frames */
Ix enable dectection of dribble error *i
/* enable dectection of CRC error *1
/* enable detection of overflow error */
(EB_STABROAD I EB_ANYGOOD I EB_DRIBBLE I EB_CRC I EB_OVFLO I EB_SHORT)

/*
* Receive status reg bits
*/
Ox80
tdefine EB STALE
tdefine EB-SHORTERR
Ox40
tdefine EB-DRlBERR
Ox20
tdefine EB-CRCERR
OxlO
tdefine EB- OVFLERR
Ox8
tdefine EB-RCVERR
Oxf8
Ox7
tdefine EB=RBUF

Ox0400
OxO 8 0 0

/* PUP protocol *1
1* IP protocol * /

1*
" The EBPUP NTRAILER packet types starting at EBPUP TRAIL have
(type-EBPUP TRAIL) *512 bytes of data followed
* by a PUP tyPe (as given above) and then the (variable-length) header.

*

1* match station, broadcast *1

/*
* Auxiliary command reg bits
*/
tdefine EB EDLCRES
Ox80
tdefine EB-SYSEI
Ox40
tdefine EB- RBBSW
Ox20
tdefine EB- RBASW
Ox10
tdefine EB- XBUFSW
Ox8
tdefine EB- XEOFDIS
2
tdefine EB=POWINTR

/*
/*
/*
/*

/*
/*
/*
/*
/*
/*
/*

invalid packet here */
short frame * /
dribble error */
crc error *1
overflow error * /
error mask * /
buffer pointer mask */

/*
/*
/*
/*
/*

reset EDLC chip * /
enable system interrupts *1
talk to receive buffer b */
talk to receive buffer a */
talk to transmit buffer */
1* create underflow for testing
/* clear power-on interrupt */

*/

*1
tdefine EBPUP TRAIL
'define EBPUP=NTRAlLER

/*
* 3Com
*1
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
'define
'define
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

Ox1000
16

/* Trailer PUP */

/*

* Auxiliary status reg bits
*/
'define EB XCVRUP
Ox8D
'define EB- BBASW
4
tdefine EB=IMASK
Ox70

Ethernet controller registers.
EB ACTADDRO
EB- ACTADDR1
EB- ACTADDR2
EB-ACTADDR3
EB-ACTADDR4
EB- ACTADDR5
EB- RCVCMD
EB-XCSR
EB-XBP HI
EB-XBP-LO
EB-BBPCLEAR
EB-PROM
EB- AUXCSR
EB- COLLCNTR
EB-XMTBUF
EB- RCVBUFA
EB= RCVBUFB

1* actual address byte
1* actual address byte

8
9
10
10
11

12
13
14
15

*1
*1

/* actual address byte
*/
1* actual address byte
*/
*/
1* actual address byte
1* actual address byte
*1
1* receive command * /
1* transmit csr * /
1* transmit buffer pointer high byte *1
1* transmit buffer pointer low byte */
/* buffer pointer clear (w) */
/* address prom (r) *1
1* auxiliary commandlstatus *1
1* collision counter * I
/* transmit buffer *1
1* receive buffer a *1
1* receive buffer b *1

1*

*

tdefine EBRDOFF
tdefine EBMAXTDOFF

/* the integral transceiver is enabled */
/* receive buf b before a switch */
/* interesting bits for rcv. into routine */

2
/* packet offset in read buffer "/
(2048-512)
/* max packet offset (min size) *1

tdefine NEB

/*
* 3Com Ethernet controller interface
*/
tdefine EBMTU

1500

int nulldev (), ebattach (), ebintr (), ebpoll () ;
struct uba_device *ebinfo [NEB];

struct

uba_driver ebdriver = {
nulldev, ebattach, (u_short * )0, ebinfo

I;
Transmit cmd reg bits

*1
tdefine
tdefine
tdefine
tdefine

tdefine EBUNIT (x)
EB EIEOF
EB- EIl6COLL
EB=EICOLL
EB_EIUNDER

Ox8
4

1* enable ints on end of frame * /
1* enable ints on 16 collisions * /
/* enable ints on collisions * I

minor (x)

int
ebini t () , eboutput () , ebwatch () ;
struct mbuf *ebget () ;

/* enable ints on underflow * /

1*
* Transmit status reg bits
*/
tdefine EB XREADY
Ox8
tdefine E9- ooLL16
4
'define EB- COLL
2
tdefine EB=UNDERFLOif
1

extern struct ifnet loif;
/*
/*
/*
/*

ready for new frame * /
16 collisions detected on last x.,.it */
collision occurred * I
force underflow */

/*

* Receive command reg bits
*1
'define EB_MULTI
Oxc

/* match st.ation, multi"

broadcast */

/*

* Ethernet software status per interface.

* Each interface is referenced by a network interface structure,
" es if, which the routing code uses to locate the interface.
* ThIs structure contains the output queue for the interface, its address,
*I
struct eb_softc {
st~,u,ct
arpcqIll e,s_ac;
/* COlllIl\on Eth~rnet structures */

if eb.c

Fri Sep

tdefine es_if
es_ac.ac_if
tdefine es enaddr es ac. ac enaddr
sh~rt
es_o;ctive:
) eb_softc[NEB];

2

5 19:08:50 1986
/* network-visible interface */
/* hardware Ethernet address ,,/
/* is output active? */

ebwatch()

1* te.i'np receive buffer '* /
char ebrbuf [EBMTU] ;

{}

/*

1* for polling */
short ebok

=

0;

1* set low 3 bytes to, eg, DEC manu!. nu.."'nber for us to pretend to be DEC */
long eb_masq = 0;

* Initialization of interface; clear recorded pending
* operations.
*/
abinit ('l.L"'lit)
int unit;
struct eb softc Xes = &eb softc[unit];
register -;truct ifnet *ifp - &es->es if;
register struct sockaddr_in *sin;
register pport;
int i, s;
char ebuf[6];

I"

* Interface exists: make available by filling in network interface
* record. System will initialize the interface when it is ready

" to accept packets.
*/
ebattach(md)
struct uba_device "md;

sin = (struct sockaddr in *) &ifp->if addr;
if (sin->sin_addr.s_addr ~ 0)
/* address still unknown */
return;
if «es->es if.if flags & IFF RUNNING)
0) {
pport - - (int) - ebinfo [unit]->ui_addr;
s - splimp{);

struct eb softc xes - &eb softc[md->ui unit];
register -;truct ifnet "ifp - &es->es if;
register pport - (int)md->ui addr; struct sockaddr_in *sin;
ifp->if unit = md->ui unit;
ifp->if-name = "eb"; ifp->if-mtu - EBMTU;
ifp->if=:net - md->ui_flags & OxFFOOOOOO;

/* reset EDLC chip by toggeling reset bit */
ebwr reg(pport, EB AUXCSR, EB EDLCRES);
ebwr=:reg(pport, EB=:AUXCSR, 0):

if

(! appleinit (pport) )
return;
ebreset (pport);
/*
* Read the ethernet address from the box.
*I
ebwr reg(pport, EB BBPCLEAR, 0);
1* reset bus-buffer pointer */
ebrd-setup (pport, EB PROM);
/* setup for read from prom *1
ebrd-data !pport, es->es enaddr, 6);
/* h;ck to change the ~nufacturer */
if (eb masq) {
- char *mp;

/* Initialize the address RAM "/
ebwr reg(pport, EB BBPCLEAR, 0);
/* reset bus-buffer pointer */
ebrd-setup (pport, EB PROM);
ebrd-data(pport, ebuf, 6);
for (i - 0; i < 6; i++)
ebwr_reg(pport, EB_ACTADDRO+i, ebuf[i]);
/* Hang receive buffers and start any pending writes. */
ebwr_reg(pport, EB_RCVCMD, EB_RCVNORMl;
/" normal bits ,,/
ebwr reg(pport, EB AUXCSR, (EB RBASWIEB RBBSWIEB SYSEI»;
es->es oactive - 0:
es->es-if.if flags 1- IFF UPIIFF RUNNING;
if (es=>es_ii.if_snd.ifcchead) ebstart (unit);
ebok - pport;
ebpoll(pport) ;
splx(s) ;

mp -(char *) &eb_masq;
mp++;
bcopy (mp, es->es_ enaddr, 3);
printf("Ethernet address - ");

}

{

if rtinit (&es->es if, RTF_UP);
arPattach(&es->es=:ac) ;
arpwhohas(&es->es_ac, &sin->sin_addr);

char * p = &es->es enaddr [0] ;
int i, j = 0;
char buf[H];
for (i - 0; i < 6; i ++) {
buf[j++] = "0123456789ABCDEF" [( !*p » 4) &Oxf)];
buf [j++] - "0123456789ABCDEF" [ ( (*p++) &Oxf) ] ;

/*

* Start or restart output on interface.
* If interface is already active, then this is a retransmit
* after a collision, and just restuff registers.
* If interface is not already active, get another datagram
* to send off of the interface queue, and map it to the interface
* before starting the output.
*/
ebstart (dev)
register dev_t dev;

buf[j++] = '\n';
buf[j] ~ 0;
printf (buf) ;
sin - (struct sockaddr in *) &es->es if. if addr;
sin->sin family - AF_INET;
/*
sin->sin addr = arpmyaddr( (struct arpcom *) 0);
*/
/ * this is a way to set addresses for now (without an ioctl (»
sin->sin addr.s addr - (u long)md->ui flags;
ebsetadd~ (ifp, -;in);
ifp-> f _ ini t - ebini t:
ifp-> f output - eboutput;
ifp-:> (~watchdoq - ebwatch;

"/

register
register
register
register
register
register

int unit - EBUNIT (dev) ;
struct eb softc *es - &eb_softc [unit];
int pport:
struct mbuf *m;
unsigned char csr;
x - sp16 () ;

pport - (int) ebinfo [unit] ->ui_addr;
if (es->es oactive)
gO~p re,st,art;

if eb.c

Fri Sep

5 19:08:50 1986

3

IF DEQUEUE (&es->es if. if snd, m);
if- (m ~ 0) (
es->es oactive = 0;
splx(x);

case EB_RBASWIEB_RBBSW:
case EB RBASWIEB RBBSWIEB BBASW:
-I * no input packets * I
nopkt++;

return;
break;
ebput (pport, m);
ebwr reg(pport, EB XCSR, (EB EIEOFIEB EI16COLL»;
csr ;: ebrd reg(pport, EB AUXCSR) & EB=:IMASK;
ebwr_reg (pport, EB_ AUXCSR, csr I (EB_ SYSEI IEB_ XBUFSW) ) :

default:
panic ("ebintr: impossible value");
I * NOT REACHED * I

restart:
splx(x) ;
es->es_ oactive

int
int
int
int
int

xcsr = ebrd_reg(pport, EB_AUXCSR);
if (xcsr !- csr) {
csr = xcsr;
goto again;

1:

bbuf;
abuf;
bbabuf;
abbbuf;
nopkt;

ebwr_reg(pport, EB_AUXCSR,

if (es->es oactive) {
if- «csr & EB XBUFSW) ~ 0) {
es->e; iLif opackets++;
es->es=:oactive = 0;
csr - ebrd reg (pport, EB XCSR):
i f (csr&Oxff -= Oxff)
csr - ebrd reg(pport, EB_XCSR);
if (csr&OXff -- Oxff) (
printf("eb%d xmit status reg. botch\n",
unit);
goto cont:

1*

*
*
*
*
*

(int) «csrlbits)&EB_IMASK));

Ethernet interface interrupt. If received packet examine
packet to determine type. If can't determine length
from type, then have to drop packet. othewise decapsulate
packet based on type and pass to type specific higher-level
input routine.

*1
1* ARGSUSED *1
ebintr (pport)
(

i f (csr & EB COLLI
1* clear counter *1
ebwr reg(pport, EB COLLCNTR, 0);
if (csr & EB- COLL16) (
printf("eb%d: 16 collisions; resetting ... \n"
, unit);
ebreset (pport);
ebinit (unit) ;

register struct eb softc xes:
register int unit;register bits - 0;
register unsigned char csr, xcsr;
extern short netoff;
i f (netoff)
return;
for (unit - 0; lL'!it < NEB; lL'!it++) (
es - &eb_softc[unit];
csr = ebrd_reg(pport, EB_AUXCSR);

,~

(es->es_if.if_snd.ifes if. if ipackets++;
ebwr reg(pport, EB BBPCLEAR, 0);
1* clear bus buffer pointer
bytel - ebrd_reg(pPort, buf);
1* first byte of buffer * I
if (byte1 & EB RCVERR) (
printf("ebrcv error %x\n", bytel&Oxff) ;
es->es_if. if_ierrors++;
return;

case 0:

/* RBASW -= 0, RBBSW ~ 0, BBASW =- 0, receive A, then B */
abbbuf++;
ebread(es, pport, EB RCVBUFA);
ebread (es, pport, EB-RCVBUFB);
bits 1- (EB_RBBSWIEB=:RBASWIEB_SYSEI);
break;

byte2
ehoff

=

ebr~reQ(pport,

=

« (byte1&EB_RBUF) «8) 1byte2)

buf);

1* qet data *1
ebrd setup(pport, buf);
ebr(~data (pport. ebrbuf, eboff);

/* second byte of buffer */
- EBRDOFF;

*I

if eb.c
/*
"
"
"
*

*

Fri Sep

5 19:08:50 1986

Get input data length.
Get pointer to ethernet header (in input buffer).
Deal with trailer protocol: if type is PUP trailer
qet true type from first 16-bit word past data.
Reebmber that type was trailer by setting off.

*/
len = eboff - sizeof (struct ether header):
eb = (struct ether header *) ebrbut";
tdefine ebdataaddr{eb, off~ type)
({type) « (caddr_t) «eb)+l)+(off) I»
if (eb->ether type >- EBPUP TRAIL &&
eb->ether-type < EBPUP TRAIL+EBPUP NTRAILERI {
off -- {eb->ether tyPe - EBPUP TRAIL I " 512:
i f (off >= EBMTU)
return:
/* sanity * /
eb->ether type = *ebdataaddr (eb, off, u short *):
resid = "(ebdataaddr(eb, off+2, u short-"»:
if {off + resid > lenl
return:
/" sanity */
len - off + resid:
I else
off = 0;
if (len = 0)
return;

/*
" Put packet into mbufs. Off is nonzero if packet
" has trailing header; ebget will then force this header
* information to be at the front, but we still have to drop
* the type and length which are at the front of any trailer data.
*/
m = ebget (ebrbuf, len, off);
if (m = 0)
return;
if (off) {
m->m_off +- 2 " sizeof (u short);
m->m_len -= 2 " sizeof (u::::short);

4
* If destination is this address or broadcast, send packet to
* loop device to kludge around the fact that 3com interfaces can't
" talk to themselves.
*/
eboutput (ifp, mO, dst)
reqister struct ifnet *ifp:
register struct mbuf "mO:
register struct sockaddr "dst:
int type, s, error:
u char edst [6];
struct i..."'l._addr idst:
register struct eb softc "es - &eb softc[ifp->if unit]:
register struct mbuf "m = mO:
register struct ether header *eb;
register int i:
struct mbuf "mcopy - (struct mbuf *) 0;
/" Null */
s = splnet () :
switch (dst->sa_fam1ly)
tifdef INET
case AF_INET:
idst = «struct sockaddr in ")dst)->sin addr;
if (!arpresolve (&es->es ac, m, &idst, edst»
return (0);
-/" if not yet resolved
i f (in lnaof (idst) - INADDR ANY)
- mcopy - m copy(m, O,-{int)M_COPYALL);
type = EBPUP_IPTYFE:
goto gottype:
tendif

case AF_UNSPEC:
eb = (struct ether header ") dst->sa data:
bcopy( (caddr_t)eb->ether_dhost, (caddr_t)edst, sizeof (edst»;
type - eb->ether type;
goto gottype:
default:
printf{"eb%d: can't handle af%d\n", ifp->if_unit,
dst->sa_fam11y) ;
error - EAFNOSUPPORT;
goto bad;

x - spl6!l:

switch (eb->ether_type)
tifdef INET
case EBPUP_IPTYPE:
schednetisr (NETISR IP);
inq - &ipintrq:
break;
case ETHERPUP ARPTYPE:
arpinput (&es->es ac, m):
splx{x):
return;

gottype:

/*
" Add local net header. If no space in first mbuf,
* allocate another.
*/
if {m->m off > MMAXOFF I I
MMINOFF + sizeof (struct ether header) > m->m_off)
m - m_get{M_DONTWAIT);

tendif

i f (m -

default:
m_freem(m) ;
splx(x) ;
return;

i f (IF QFULL(inq»
{
- IF DROP (inq) ;
splx(x) :
m_freem(m) ;
return;

IF_ENQUEUE(inq, m);
splx (x);

*/

0)

{

error = ENOBUFS;
goto bad;
m->m_next - mO;
m->m off = MMINOFF;
m->m::::len - sizeof (struct ether_header);
I else {
m->m_off
sizeof Istruct ether header);
m->m_len +- sizeof (struct ether::::header);
eb = mtod (m, struct ether header *);
bcopy I (caddr t) edst, (caddr t) eb->ether dhost, sizeof (edst»;
eb->ether tYPe - htons I lu short) type); bcopy «caddr_t) es->es_enaddr, (caddr_tl eb->ether_shost, 6);
/*

*

"
"
..
"

Queue message on interface, and start output if interface

* not yet active.

/*

Ethernet output routine.
Encapsulate a packet of type family for the local net.
Use trailer local net encapsulation if enough data in first
packet. leaves a multiple of 512 bytes of dat.a in remainder.

*/
s - splimp () ;
if (IF QFULL('ifp->if snd»
{
- IY_DRPP "i,fp->if_sndl;

if eb.c

Fri Sep

5 19:08:50 1986

error - ENOBUFS;
goto qfull;

cp - ebrbuf + sizeof (struct ether header);
Hfdef DUMPIN
{char *cp = ebrbuf; int i; int j; printf(lIebget:\nll) ;for(j-0;j<6;j++) {for(i=0;i<16;i++)printf(
tendif
wr.tila (totlen > 0) {

}

IF ENQUEUE (&ifp->if snd, m);
if- (es->es oactive -:... 0)
eb"itart (ifp->if unit):
splx(s);
gotlocal:
return (mcopy

looutput (&loif, mcopy, dst)

5

MGET(m, 0);
if (m 0) {
goto bad;

0) ;

qfull:
mO

=

i f (off) {
len - totlen - off;
cp - ebrbuf + sizeof (struct ether_header) + off;
} else
len = totlen;
m->m len = len = MIN (MLEN, len);
m->m-off - MMINOFF;
mcp :: mtod (m, u char ");
bcopy(cp, mcp, len);
cp += len;
"mp = m;
mp - &m->m next;
i f (off --0) {
tot len -= len;
continue;

m;

bad:
m_freem(mO) ;
splx(s) ;
return (error) ;

/*
" Routine to copy from mbuf chain to transmitter
* buffer in Multibus ebmory.
*/
ebput (pport, m)
register int pport;
register struct mbuf *m;

register
register
register
register
register

struct mbuf "mp;
short off;
flag - 0;
unsigned len;
u_char *p;

for (off - 2048, mp - m; mp; mp - mp->m_next)
off -= mp->m_len;
if (off> EBMAXTDOFF)
/* enforce minimum packet size */
off = EBMAXTDOFF;

off +- len;
i f (off ~ totlen)
cp = ebrbuf + sizeof (struct ether_header);
off = 0;
totlen = off 0 ;

return (top);
bad:
m freem(top);
return (0);

i f (off & 01) {
off--;
flag++;

/* load xmit buffer pointer */
ebwr reg(pport, EB XBP LO, off&Oxff);
ebwr-reg(pport, EB-XBP-HI, «off»8)&7»;
ebwr-setup(pport, BB xMTBUF);
for Imp = m; mp; mp :; mp->m next)
len - mp->m len;
i f (len = 0)
continue;
p = mtod (mp, u char*);
ebwr_data(pport, p, (short) len) ;

tifdef notdef
1* ebdelay -- wait about tim secs *1
ebdelay (tim)
register tim;
{

register i;
while (tim--) {
i - 100000;
while (i--)

I
tendif
if (flag)
ebwr_data(pport, "", 1);
/* re-load xmit buffer pointer */
ebwr reg(pport, EB XBP LO, off&Oxff);
ebwr:=reg(pport, EB:=XBP:=HI, «off»8) &7»;

I * stuff for apple * I
tinclude
tinclude
tinclude
tinclude






m_ freem (m) ;

/*
" Routine to copy from memory into mbufs.

"I
struct mbuf "
ebget (ebrbuf, totlen, offOl
register u char "ebrbuf;
register int totlen, off a;
register struct mbuf *m;
struct mbuf "top - 0, **mp - ,top.:
register int off - off 0, len;
reg-ister u_char *cp;

'define
'define
tdefine
tdefine
'define
'define

RC
WC
RD
WI)

INPUT
OUTPUT

Oxa8
OxaO
Oxb8
OxbO
OxOO
OxFF

1*
1*
1*
1*
1*
1*

read cmd *1
write cmd * I
read data *1
write data *1
ddra input *1
ddra output */

I * sometime, put the parallel port data somewhere besides the in disk driver * I
extern struct device_ d *pro_ da [ 1;
ebreset (pport)
register pport:

1* parallel port nU!!\ber * I

{

reqister struct device_d *dp -

pro_~a

(pportl;

Fri Sep

if eb.c

5 19:08:50 1986

6
dp->d ddra ~ OUTPUT:
dp->d-ira = regno;
dp->d-irb - WD:
dp->d::::ira - byte;

tdefine THISISMAGIC
tifdef THISISMAGIC
/* reset 6522. */
dp->d ddra - INPUT;
ctp->d::::irb = Ox1!!;
dp->d ddrb - Dxbc;
dp->d-irb = RC;
dp->dycr = Dxb;
dp->d ier - FIRQ I FCA1;
tendif THISISMAGIC

/* read a reqister *1
ebrd_ req (pport, regno)
int pport, regno;
/* enable interrupts (I guess) */

(

register struct device_d *dp

ebwr reg(pport, EB AUXCSR, 1);
ebportreset (pport)-;

=

pro_da [pport] ;

dp->d irb = WC;
dp->d- ddra - OUTPUT;
dp->d-ira = regno;
dp->d-irb = RD;
dp->d- ddra - INPUT;
retur; (dp->d_ira & Oxff);

1* clear power-on interrupt */

1* setup a register to write to it *1
ebwr setup(pport, regno)
int pport, regno;
(

register struct device_d *dp

=

pro_da [pport];

1* ebportreset - reset port to normal state after xmit command */
ebportreset (pport)
int pport;

dp->d_irb = WC;
dp->d ddra - OUTPUT;
dp->d-ira - regno;
dp->d~)rb - WD;

register struct device_d *dp -

pro_da [pport];

dp->d irb - RC;
dp->d::::ddra - INPUT;
/* setup a register to read from it *1
ebrd setup(pport, regno)
int pport, regno;

appleinit (i)

(

(

register struct device_d *dp

=

pro_da [pport];

register struct device_d *devp;
int ebintr () ;
extern char slot [] ;

dp->~irb =

WC;
dp->d ddra - OUTPUT;
dp->d-ira - regno;
dp->d-irb - RD;
dp->d::::ddra - INPUT;

i f (!PPOK(i) II (slot[PPSLOT(i)] !- PRO»
(/* check slot t and type */
printf(Uethernet init: port %d, ", i ) ;
i f (slot[PPSLOT(i)] = PM3)
printf(HPriam card\n");
else
printf("card ID Dx%x\n", slot[PPSLOT(i)]);
goto fail;

1* write data to box. must have done a ebwr_setupO first *1
ebwr data (pport, p, nbytes)
int pport;
register short nbytes;
register char *p;

}

devp = pro da til ;
if (iocheck(&devp->d ifr»
/* board there '2 */
( asm(" nap P); }
if (prodata [i] . pd. da ! = devp) ( / * not already setup * /
if (setpplnt «prodata til .pd_da = devp) ,ebintr»
qoto fail;

(

register struct device_d *dp

=

pro_da [pport];

if (nbytes )
do (
dp->d ira = *p++;
} while (--nbytes);

return 1;
} else
fail:
printf("Can't find port for etherbox %d\n", i);
return 0;

1* read data from box.

must have done a ebrd_setupO first *1
ebrd data (pport, p, nbytes)
int pport;
register short nbytes;
register char *p;

1* applereset -- reset apple interrupt hware * /

(

applereset (pport)
register struct device_d *dp -

pro_da [pport];

tifdef doneinppintr

{

reqister struct device d *dp dp->d_ifr - dp->d_ifr;-

if (nbytes
do
*p++ = dp->d ira;
} while (--nbytes); -

tendif
/* siqh

I * write a reqister * I
ebwr req(pport, regno, byte)
int pport, reqno, byte;

*/

short polleb - 1;
/* •.. as opposed to pollcat ... */
ebpoll (pport)
{

register struct device_d *dp -

pro_da [pport];

extern time_t lbolt:
i f (polleb). {

pro_da [pport] ;
/* reset interrupt trap */

Fri Sep

if eb.c

5 19:08:50 1986

7

char ebuf[6);
int i;

1*
ebintr (pport) ;

*/
ebreset (pport) ;
I" reset EDLC chip by toggeling reset bit "I
ebwr reg(pport, EB AUXCSR, EB EDLCRES);
ebwr reg (pport, EB AUXCSR, 0);-

=:

=:

I" Initialize the address RAM "I
ebwr reg (pport, EB BBPCLEAR, 0);
I" reset bus-buffer pointer "I
ebrd-setup (pport, BB PROM);
ebrd-data(pport, ebuf, 6);
for (i - 0; i < 6; i++)
ebwr_reg(pport, EB_ACTADDRO+i, ebuf[i);
I" Hang receive
ebwr reg(pport,
ebwr-reg(pport,
time~ut(ebpoll,

buffers and start any pending writes. "I
EB RCVCMD, EB RCVNORM); 1* normal bits "I
EB-AUXCSR, (EB RBASWIEB RBBSWIEB SYSEI»);
pp~rt, v.v_hz*lO);
-

ebsetaddr (ifp, sin)
register struct ifnet "ifp;
register struct sockaddr_in "sin;

ifp->if addr ~ "(struct sockaddr ") sin;
ifp->if-net - in netof(sin->sin addr);
ifp->if-host[O) :: in Inaof(sin->sin addr);
sin - ('itruct sockaddr in ") &ifp->if broadaddr;
sin->sin family = AF INET;
sin->sin- addr = if m;keaddr (ifp->if net, INADDR_ ANY);
ifp->if_flags 1- IFF_BROADCAST;
-

if ec.c

Fri Sep

1*

82/07/21

5 19:08:55 1986

1
register caddr_t ecbuf -

*1

(caddr_t) &umem[numuba] [ECMEM);

fifdef lint
br - 0; cvec - br; br = cvec;
ecrint(O); ecxint(O); eccollide(O);
tendif

finclude "ec.h"

1*
* 3Com Ethernet Controller interface

1*

*1

* Make sure memory is turned on
tinclude
#include
finclude
finclude
finclude
finclude
finclude
finclude
finclude
finclude
finclude
tinclude
finclude
tinclude
tinclude
tinclude
tinclude
tinclude
#include
tinclude
finclude

*1

"sys/param.h"
"sys/config.h"
"sys/errno. h"
"svs/tvoes .h"

addr->ec rcr - EC MOM;

1*

"sYs/sY~tm.h"

-

!!la.p registers for ec unibus space,

* but don' t allocate yet.

*I

"net/mbuf .h"
"sys/buf .h"
"net/protosw. h II
"net I socket. h"
"net/ubavar.h"
"netl ecreg . h"
Hnet/in.h"
"net/in_systm.h"
"net/if.h"
"net/if ec.h"
"net/if-uba. h"
"net/ip-:-h"
"net/ip_var.h"
"net/pup.h"
"netl route. h II
"errno.h"

tdefine ECMTU
tdefine ECMe:M

-

* Disable.

ubamem(numuba, ECMEM, 32*2, 0);

1*
* Check for existence of buffers on Unibus.

*1
if (badaddr«caddr_t) ecbuf, 2» {
bad1:
printf(Hec: buffer mem not found\n");
bad2:
ubamem(numuba, 0, 0, 0);
/* reenable map (780 only) *1
addr->ec rcr - EC_ MDISAB;
1* disable memory *1
return (0);
fif VAX780
if (cpu -- VAX_780 && uba_hd[numuba).uh_uba->uba_sr) {
uba_hd[numuba).uh_uba->uba_sr = uba_hd[numuba].uh_uba->uba_sr;
goto bad1;

1500
0000000

tendif

int
struct
u_short
struct

ecprobe (), ecattach (), ecrint (), ecxint (), eccollide () ;
uba_device *ecinfo [NEC] ;
ecstd [] - ! 0 );
uba driver ecdriver =
{ ecprobe, 0, ecattach, 0, ecstd, "ec ll , ecinfo );
u char ec iltop[3] - ! Ox02, Ox07, OxOl );
fdefine ECUNIT (x)
minor (x)

/*
* Tell the system that the board has memory here, so it won't
* attempt to allocate the addresses later.
*1
if (ubamem(numuba, ECMEM, 32*2, 1) ~ 0) {
printf("ecprobe: cannot reserve uba addresses\n");
goto bad2;

int
ecinit () , ecoutput () , ecreset () ;
struct mbuf *ecget () ;

1*
*
*
*
*

extern struct ifnet loif;

1*

*

Ethernet software status per interface.

*1
*(u short *)ecbuf - (u short) 03777;
ecbuf[03777) = '\0'; addr->ec xcr = EC XINTENIEC XWBN;
DELAY(lOOOOO);
-

* Each interface is referenced by a network interface structure,

*

es_if, which the routing code uses to locate the interface.
This structure contains the output queue for the interface, its address,
We also have, for each interface, a UBA interface structure, which
contains information about the UNIBUS resources held by the interface:
map registers, buffered data paths, etc. Information is cached in this
structure for use by the if_uba. c routines in running the interface
* efficiently.

*
*
*
*
*

if (cvec > 0 && cvec !- Ox200) {
if (cvec & 04) {
1* collision interrupt *1
cvec -= 04;
1* rcv is xmit + 1 *1
br += 1;
} else {
1* xmit interrupt *1
cvec -- 010;
1* rcv is xmit + 2 *1
br +- 2;

*1
ec_ softc
struct ifnet es if;
struct ifuba es:::ifuba;
short
es mask;
short
es:::oactive;
caddr_t es_buf[16];
u_char es_enaddr [6];
I ec_softc[NEC];

struct

1*
1*
1*
1*
1*
1*

Make a one byte packet in what should be buffer to.
submit it for sending. This whould cause an xmit interrupt.
The xmit interrupt vector is 8 bytes after the receive vector,
so adjust for this before returning.

network-visible interface *1
UNIBUS resources *1
mask for current output delay *1
is output active'? *1
virtual addresses of buffers *1
board's ethernet address *1

return (1);

/*
Interface exists: make available by filling in network interface
record. System will initialize the interface when it is ready
to accept packets.

1<

1*

1<

* Do output DMA to determine interface presence and
* interrupt vector. DMA is too short to disturb other hosts.

*I

ecprobe (reg)
caddr_t req;
register int br, cvec;
1* rll, rIO value-result *1
register struct ecdevice *addr - (struct ecdevice *) reg;

*
1<

I

ecattach (ui)
struct uba_device *ui;
struct ec_softc *es - &ec softc[ui->ui unit];
reqister struct ifnet *ifp - &es->es if;
reqister struct ecdevice *addr - (struct ecdevice *)ui->ui_addr:

if ec.c

Fri Sep

5 19:08:55 1986

2

struct sockaddr_in *sin;
int i, j;
u_char *cp;

/*
* Hang receive buffers and start any pending writes.
* writing into the rcr also makes sure the memory
* is turned on.
*1
addr = (struct ecdevice *)ecinfo[unit)->ui_addr;
s - splimp () ;
for (i-ECRHBF; i>-ECRLBF; i--)
addr->ec rcr - EC_READli;
es->es_oactive =-0;
es->es mask = -0;
es->es-if.if flags 1= IFF UP;
if (es=>es_lf.if_snd.ifq.)iead)
ecstart (unit);
splx(s) ;
if_rtinit (&es->es_if, RTF_UP);

ifp->if unit - ui->ui_unit;
ifp->if-name - "ec";
ifp->if-mtu - ECMTU;
ifp->if=:net = ui->ui_flags;

/*
* Read the ethernet address off the board, one nibble at a time.

*/
addr->ec xcr - EC UECLR;
addr->ec=:rcr = EC=:AROM;
cp - es->es enaddr;
tdefine NEXTBIT addr->ec rcr - EC AROM I EC ASTEP; addr->ec_ rcr = EC_ AROM
for (i=O; i<6; l++) { *cp = 0;
for (j=O; j<-4; j+-4)
*cp 1= «addr->ec_rcr » 8) & Oxf) « j;
NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;
cp++;
}

tifdef notdef
printf("ec%d: addr=%x:%x:%x:%x:%x:%x\n", ui->ui unit,
es->es enaddr[O)&Oxff, es->es enaddr[I]&Oxff,
es->es-enaddr [2) &Oxff, es->es-enaddr [3) &Oxff,
es->es=:enaddr [4) &Oxff, es->es=:enaddr [5) &Oxff);
tendif
ifp->if host[O) - «es->es enaddr[3)&Oxff)«16) I
«es->es enaddr[4)&Oxif)«8) I (es->es enaddr[5)&Oxff);
sin - (struct sockaddr in *) &es->es if. if ;ddr;
sin->sin family = AF liET;
-sin->sin=:addr - if_makeaddr (ifp->if_net, ifp->if_host [0);

/*
" Start or restart output on interface.
* If interface is already active, then this is a retransmit
* after a collision, and just restuff registers.
" If interface is not already active, get another datagram
" to send off of the interface queue, and map it to the interface
* before starting the output.
*1
ecstart (dev)

int unit - ECUNIT (dev), dest;
struct ec softe xes - &ee softe[unit);
struet eecteviee "addr;
struct mbuf *m;
eaddr_t eehuf;

sin = (struct sockaddr in *) &ifp->if broadaddr;
sin->sin family - AF liET;
sin->sin=:addr = if_m;keaddr (ifp->if_net, INADDR_ANY);
ifp->if_flags = IFF_BROADCAST;
ifp->if init = ecinit;
ifp->if=:output = ecoutput;
ifp->if ubareset = ecreset;
for (i=O; i<16; i++)
es->es buf[i) = &umem[ui->ui_ubanum) [ECMEM+2048*i];
if_attach (ifp)-:

I"
" Reset of interface after UNIBUS reset.
* If interface is on specified uba, reset its state.
*/
ecreset (unit, uban)
int unit, uban;
register struct uba_device *ui;
if (unit >= NEC I I (ui - ecinfo [unit) =- 0 I I ui->ui_alive =- 0 II
ui->ui_ubanum !- uban)
return;
printf(" ec'lrd", unit);
ubamem(uban, ECMEM, 32*2, 0);
/* map register disable (no alloc) * /
ecinit (unit) ;

1*
* Initialization of interface; clear recorded pending
* operations, and reinitialize UNIBUS usage.

*I
ecinit (unit)
int unit;
struct ec softc xes - &ec softc[unitj;
struct ecctevice * addr;
int i, s;

if (es->es oactive)
goto restart;
IF DEQUEUE (&es->es if. if snd, m);

item

=

0)

{

-

-

es->es_oactive - 0;
return;
eeput (es->es_buf [ECTBF], m);
restart:
addr - (struct ecdeviee *)ecinfo[unit)->ui addr;
addr->ec xcr = EC WRITE I ECTBF;
es->es_oactive - 1;

/*
* Ethernet interface transmitter interrupt.
* Start another output if more data to send.
*1
ecxint (unit)
int unit;
register struct ec softc xes ~ &ec softe[unit);
register struct ecctevice *addr - (struct eedeviee *) ecinfo [unit )->ui_addr;
if (es->es_oaetive = 0)
return;
if «addr->ee xer&EC XDONE) - 0 II (addr->ec xcr&EC XBN) !~ ECTBF)
printf(lIec'lsd~ stray xmit interrupt, xcr-'lsb\n", unit,
addr->ee xer, EC XBITS);
es->es_oactive --0;
addr->ec_xcr - EC_XCLR;
return;
es->es if. if opackets++;
es->es=:oactive - 0;
es->es_mask - -0;
addr->ec_xcr - EC_XCLR;

if ec.c

Fri Sep

5 19:08:55 1986

if (es->es_if.if_snd.ifCLhead)
ecstart (unit);

3
* input routine.
*1
ecrint (unit)
int unit:

1*

* Collision on ethernet interface, Do exponential
* backoff, and retransmit. If have backed off all
* the way print warning diagnostic, and drop packet.
*1
eccollide (unit)
int unit;
struct ec_softc xes

~

&ec_softc[unit];

struct ecdevice *addr -

ecread (unit)
int unit:

es->es if. if collisions++;
if (es=>es oactive)
ecdocoll (unit);

register struct ec softc xes = &ec softc[unit];
struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
register struct ec_header *ec;
struct mbuf *m;
int len, off, resid, ecoff, buf;
register struct ifqueue *inq;
caddr_ t ecbuf;

ecdocoll (unit)
int unit;
register struct ec_softc xes = &ec_softc[unit];
register struct ecdevice *addr =
(struct ecdevice *1 ecinfo [unit]->ui_addr;
register i;
int delay;

1*
" Es mask is a 16 bit number with n low zero bits, with
" n the number of backoffs. When es mask is 0 we have
* backed off 16 times, and give up. *1
if (es->es mask ~ 0) {
es=>es if.if oerrors++;
printf(tleC%d-;- send error\n tl , unit);
1*
* Reset interface, then requeue rcv buffers.
* Some incoming packets may be lost, but that
* can't be helped.
*1
addr->ec xcr = EC UECLR;
for (i=ECRHBF: i>::ECRLBF: i --)
addr->ec rcr = EC_ READ Ii;
I"
* Reset and transmit next packet (if any).

"I
es->es_oactive - 0;
es->es mask = -0;
if (es=>es_if . if_snd.ifCLhead)
ecstart (unit);
return:

1*
* Do exponential backoff. Compute delay based on low bits
* of the interval timer. Then delay for that number of
* slot times. A slot time is 51. 2 microseconds (rounded to 51).
* This does not take into account the time already used to
* process the interrupt.
"I
es->es mask «- 1;
delay:: mfpr (ICR) &- es->es_mask:
DELAY(delay " 51);
I"
" Clear the controller's collision flag, thus enabling retransmit.
"I
addr->ec_ xcr - EC_CLEAR;
/"
"
"
"
"
"
"

Ethernet interface receiver interrupt.
If input error just drop packet.
Otherwise purge input buffered data path and examine
packet to determine type. If can't determine length
from type, then have to drop packet. othewise decapsulate
packet based on type and pass to type specific higher-level

(stru.ct ecdevice *)ecinfo[w"lit]=>ui_addr;

while (addr->ec rcr & EC_ROONE)
ecread<'imit) ;

es->es_if. if_ ipackets++;
buf - addr->ec rcr & EC RBN;
if (buf < ECRLBF II buf-> ECRHBF)
panic (Uecrint") ;
ecbuf = es->es buf [buf] ;
ecoff - * (short ") ecbuf;
if (ecoff <= ECROOFF II ecoff > 2046) {
fifdef notdef
if (es->es if.if ierrors % 100 = 0)
prIntf("ec%d: +- 100 input errors\n", unit);
fendif
goto setup;

1*
* Get input data length.
" Get pointer to ethernet header (in input buffer).
* Deal with trailer protocol: if type is PUP trailer
" get true type from first 16-bit word past data.
* Remember that type was trailer by setting off.
*1
len - ecoff - ECROOFF - sizeof (struct ec header);
ec - (struct ec_header *) (ecbuf + ECRDOFF);
fdefine ecdataaddr (ec, off, type)
«type) « (caddr t) «ec) +1) + (off»»
if (ec->ec type >- ECPUP TRAIL &&
ec->ec-type < ECPUP TRAIL+ECPUP NTRAILER) {
off = (ec->ec type - ECPUP TRAIL) * 512;
i f (off >= EcMTU)
goto setup;
1* sanity *1
ec->ec type - *ecdataaddr (ec, off, u short ");
resid :: * (ecdataaddr (ec, off+2, u sh~rt "»;
if (off + resid > len)
goto setup;
1* sanity *1
len = off + resid;
} else
off - 0;
if (len -- 0)
goto setup;
1*
* Pull packet off interface. Off is nonzero if packet
* has trailing header; ecget will then force this header
" information to be at the front, but we still have to drop
* the type and length which are at the front of any trailer data.
*/
m = ecget (ecbuf, len, off);
if (m -- 0)
goto setup;
if (off) {
m->m_off +- 2 • sizeof (u short);
m->m_len -- 2 • sizeof (u:=short):
switch (ec->ec_type) (

if ec.c

Fri Sep

5 19:08:55 1986

tifdef lNET
case ECPUP IPTYPE:
schednetisr (NETISR IP);
inq = &ipintrq;
break;
tendif
default:
m freem(m);
gato setup;

4
dst->sa_family) ;
error = EAFNOSUPPORT;
goto bad;

qcttrailertype :

/*

* Packet to be sent as trailer: move first packet
* (control information) to end of chain.

*/
while (m->m_next)

if (IF QFULL(inq» {
- IF DROP (inq) ;
m_freem(m) ;
goto setup;
IF_ENQUEUE (inq, m);

m->m_next - mO;
m - mO->~next;
mO->m next = 0;
mO - Iii;
gottype:
/*

*
*

setup:

1*

*

Reset for next packet.

*1
addr->ec_ rcr

=

EC_READ I EC_ RCLR I buf;

1*
" Ethernet output routine.
" Encapsulate a packet of type family for the local net.
* Use trailer local net encapsulation if enough data in first
" packet leaves a multiple of 512 bytes of data in remainder.
* If destination is this address or broadcast, send packet to
" loop device to kludge around the fact that 3com interfaces can't
" talk to themselves.

*1
ecoutput (ifp, mO, dst)
struct ifnet "ifp;
struct mbuf *mO:
struct sockaddr *dst;
int type, dest, s, error;
register struct ec softc *es = &ec_softc[ifp->if_unit];
register struct mbuf *m - mO;
register struct ec header *ec;
register int off, i;
struct mbuf *mcopy = (struct mbuf *) 0;
/* Null */
switch (dst->sa_family)
tifdef lNET
case AF_lNET:
dest = «struct sockaddr in *)dst)->sin addr.s addr;
i f «dest &- Oxff) = 0)-mcopy - m copy (m, 0, M COPYALL);
else if (dest - «struct sockaddr_in *)&es->es_if.if_addr)->
sin_addr.s_addr) {
mcopy - m;
goto gotlocal;
off = ntohs «u short)mtod (m, struct ip *) ->ip len) - m->m_len;
i f (off> 0 ,,- (off & Oxlff) = 0 "
m->m off >- MMINOFF + 2 * sizeof (u short»
type - ECPUP TRAIL + (off»9); m->m off -- "2 * sizeof (u short);
m->m::::len +- 2 * sizeof (u::::short);
*mtod (m, u short *) = ECPUP IPTYPE;
*(mtod(m, u short .o) + 1) --m->m_Ien;
goto gottrailertype;
type - ECPUP IPTYPE;
off - 0;
goto gottype;
tendif
default:
printf(IIec\d: can't handle af\d\n", ifp->if_unit,

Add local net header.
allocate another.

If no space in first mbuf,

*/
if (m->m off > MMAXOFF I I
MMINOFF + sizeof (struct ec header) > m->~off)
m - m get (M DONTWAIT);
if (m-= O)-{
error = ENOBUFS;
goto bad;
m->m next = mO;
m->m-off - MMINOFF;
m->m::::len - sizeof (struct ec_header);
} else {
m->m_off -= sizeof (struct ec header);
m->m_len += sizeof (struct ec::::header);
ec = mtod (m, struct ec header *);
for (i-O: i<6; itt)
ec->ec shost [i] = es->es enaddr [i];
if «dest &- Oxff) = 0)
1* broadcast address */
for (i=O; i<6; itt)
ec->ec_dhost [i] ~ Oxff;
else {
if (dest & Ox8000) {
ec->ec_dhost[O] = ec iltop[O];
ec->ec_dhost[l] - ec-iltop[l];
ec->ec_dhost[2] = ec::::iltop[2];
} else {
ec->ec_ dhost [0] - es->es enaddr [0] ;
ec->ec_dhost [1] - es->es-enaddr [1];
ec->ec_dhost [2] = es->es::::enaddr [2];
ec->ec dhost[3] = (dest»8) & Ox?f;
ec->ec-dhost[4]
(dest»16) & Oxff;
ec->ec::::dhost[5] - (dest»24) & Oxff;
ec->ec_type

=

type;

/*

* Queue message on interface, and start output if interface
* not yet active.
*/
s - splimp () ;
if (IF QFULL(&ifp->if snd»
{
- IF_DROP (&ifp->if_snd) ;
error - ENOBUFS;
goto qfull;
IF ENQUEUE (&ifp->if snd, m);
if- (es->es oactive -:.. 0)
ecstart (ifp->if unit);
splx(s);
gotlocal:
return (mcopy

loou~put(&loif,

mcopy, dst)

0) ;

Fri Sep

if ec.c

5 19:08:55 1986

5
register int words;
u_char "mcp;

qfull:
mO - m;

MGET (m, 0);
i f (m 0)
goto bad;
i f (off) {
len = totlen - off;
cp - ecbuf + ECRDOFF + sizeof (struct ec_header) + off;
I else
len = totlen;
i f (len >= CLBYTES)
struct mbuf *p;

splx(s) ;
bad:
rn freern (rnO) ;
return (error);

/"
" Routine to copy from mbuf chain to transmitter
" buffer in UNIBUS memory.
,,/
ecput (ecbuf, m)
u char "ecbuf;
struct mbuf "m;

MCLGET (p, 1);
i f (p !- 0) {
m->m_len
m->m off
) else {
m->m len
m->m=:off

register struct mbuf *mp;
register int off;
u_char *bp;
for (off

=

2048, mp - m; mp; mp = mp->m_next)

) else {
m->m len = len = MIN (HLEN, len);
m->m=:off - MMINOFF;
mcp = mtod (m, u char *);
if (words - (len » 1» {
register u_short "to, * from;

i f (len - 0)
continue;
mcp - mtod(mp, u char *);
i f «unsigned)bp-' 01) {
*bp++ = *mcp++;
len--;

to - (u short *)mcp;
from = (u short ") cp;
do
*to++ = *from++;
while (--words> 0);
mop - (u char *)to;
cp = (u_Char *) from;

1» {

if (off - (len»
register u_short *to, *from;

i f (len' OIl
"mcp++ = "cp++;

to = lu short ") bpI
from = (u_short ")mcp:
do
*to++ - * from++ ;
while (--off> 0);
bp = lu char *)to,
mcp - (u_char ") from;

*mp = m;

mp - &m->m next;
i f (off =-0) {
totlen -= len;
continue;
off +- len;
i f (off - totlen)
cp - ecbuf + ECRDOFF + sizeof (struct ec_header);
off = 0;
totlen = off 0 ;

i f (len & 01)
.obp++ - *mcp++;
)

return (top);
bad:
m freem(top);
return (0);

/*
" Routine to copy from UNIBUS memory into mbufs.
" Similar in spirit to if_rubaget.
" Warning: This makes the fairly safe assumption that
" mbufs have even lengths.
*/
struct mbuf "
ecget (ecbuf, totlen, off a)
u char *ecbuf;
int totlen, offD;
register struct mbuf .om;
struct mbuf "top - 0, *.omp - ⊤
register int off - off 0, len;
u_char *cp;
cp - ecbuf + ECRDOFF + sizeof (struct ec_header):
while (totlen > 0) {

= len = MIN (HLEN, len);
= MMINOFF;

)

off -- mp->m_len;
* (u short ")ecbuf - off;
bp -: (u char *) (ecbuf + off);
for (mp-~ m; mp; mp - mp->m next)
register unsigned len - mp->m_len;
u_char *mcp;

Hfdef notdef
i f (bp - ecbuf != 2048)
printf(IIec: bad ecput, diff=%d\n", bp-ecbuf);
fendif
m_ freem (m) ;

- len = CLBYTES;
- (int)p - (int)m;

Fri Sep

if ether.c
6.2

1*

5 19:09:03 1986

1

*1

83/08/28

1*
* Attach an ethernet interface to the list "arpcom" where
* arptimer () can find it. I f fir st time
* initialization, start arptimer () .
/
arpattach (ac)
register struct arpcom wac;

/*

* Ethernet address resolution protocol.

*1

..

tinclude
tinclude
tinclude
#include
#include
#include
tinclude
tinclude

"sys/param. h"
"sys/types .h"
"sys/systlll..h"
"sys/var.h"
"net/misc. h"
"net/mbuf .hu
"net I socket. h"
"sys/errno.h"

register struct arpcom *acp;
for (acp =- arpcom; acp !""" (struct arpcom *) 0; acp = acp->ac_ac)
1* if already on list */
i f (acp - ac)
return;
ac->ac_ac - arpcom;
arpcom = ac;
/* very first time */
if (arpcom->ac ac ~ 0)
arptim-;r () ;

tinclude "net/if.h"
tinclude "net/in.h"
tinclude "net/if_ether. hOI

1*

* Internet to ethernet address resolution table.

*/
struct

arptab
struct
u_char
struct
u_char
u_char

in addr at iaddr;
at-enaddr[6] ;
mbuf Kat hold;
at timer;
a<)lags;

/*
/*
/*
1*

internet address */
ethernet address */
last packet until resolved/timeout *1
minutes since last reference */
1* flags */

};

1* at flags field values */
/* entry in use */
/* completed entry (enaddr valid) */

Mefine ATF INUSE
tdefine AT(::COM
tdefine
tdefine
tdefine
struct

register struct arptab Kat;
register i;
timeout (arptimer, (caddr_t)O, v.v_hz);
#ifdef notdef
i f (++arpt sanity> ARPT SANITY) {
register struct arpcom wac;

/*
* Randomize sanity timer based on my host address.
* Ask who has my own address; if someone else replies,
.. then they are impersonating me.
*/
arpt sanity - arpcom->ac enaddr[5] & Ox3f;
for lac = arpcom; ac !- lstruct arpcom *)-1; ac - ac->ac_ac)
arpwhohas{ac, & «struct sockaddr_in *l
&ac->ac_if.if_addr)->sin_addr) ;

... Ox?fff) % A.1U'T~.B_NB)

tdefine ARPTAB LOOK (at, addr) { \
regist;r n; \
at = &arptab[ARPTAB HASH(addr) * ARPTAB BSIZ];
for (n = 0 ; n < ARPTAB BSIZ ; n++,at++) \
i f (at->at iaddr. s addr = addr) \
br;ak; \ if In >- ARPTAB BSIZ) \
at = 0;-'

/* timer values * /
tdefine ARPT AGE
tdefine ARPT- KILLC
tdefine ARPT~)ILLI

tendif
if (++arpt age > ARPT AGE)
arpt age = 0;at =-&arptab[O];
for (i - 0; i < ARPTAB SIZE; i++, at++) {
if (at->at flags ~ 0)
continue;
if (++at->at timer < «at->at flags&ATF_COM)
ARPT KILLe : ARPT KILLI»continue;
/* timer has expired, clear entry */
arptfree (at) ;

1* chain of active ether interfaces *1
1* aging timer */

arpcom *arpcom;
arpt_age;

(60*1)
20

Age arp_tab entries once a minute.

{

ARPTAB BSIZ
/* bucket size */
ARPTAB-NB
19
1* number of buckets *1
ARPTAB-SIZE
(ARPTAB BSIZ * ARPTAB_NB)
arptab-arptab[ARPTAB_SIZE];

tdefine ARPTAB HASH (a)
«short) (!!!a) »16) ~ (a»

struct
int

/*
* Timeout routine.
*/
arptimer()

/* aging timer, 1 min. */
/* kill completed entry in 20 mins. * I
/* kill incomplete entry in 3 minutes */

u_char etherbroadcastaddr[6] - { Oxff, Oxff, Oxff, Oxff, Oxff, Oxff );
extern struct ifnet loif;

/*
* Broadcast an ARP packet, asking who has addr on interface ac.

1*
*
*
*
..
*
*
*

arpwhohas (ac, addr)
register struct arpcom wac;
struct in_addr *addr;

.. I

*

Local addresses in the range oldmap to infinity are
mapped according to the old mapping scheme. That is,
mapping of Internet to Ethernet addresses is performed
by taking the high three bytes of the network interface's
address and the low three bytes of the local address part.
This only allows boards from the same manufacturer to
communicate unless the on-board address is overridden
(not possible in many manufacture's hardware).

* NB: setting oldmap to zero completely disables ARP
(i.e. identical to setting IFF_NOARP with an ioctl).
*1
in"t

o1dmap

=

Oxffffff;

register struct
register struct
register struct
struct sockaddr

mbuf "m;
ether header *eh;
ether::::arp "ea;
sa;

i f «m - m get (M DONTWAIT»

- NULL)
return: m->m len - sizeof Rea + sizeof *eh:
m->m::::off - MMAXOFF - m->m_len;
ea - mtod (m, struct ether_arp ");

Fri Sep

5 19:09:03 1986

2

eh - (struct ether header *)sa.sa data;
bzero( (caddr t)ea, -sizeof (*ea»;bcopy( (caddr-t) etherbroadcastaddr, (caddr_t) eh->ether_dhost,
sizeof (etherbroadcastaddr»;
/* if_output will swap */
eh->ether_type - ETHERPUP_ARPTYPE;
ea ->arp_ hrd = htons (]I..RPF..P.D_ ET!IER) ;
ea->arp-pro - htons(ETHERPUP_IPTYPE);
ea->arp hln - sizeof ea->arp sha;
I" hardware address length" /
ea->arpyln = sizeof ea->arp:=spa;
/* protocol address length */
ea->arp op - htons (ARPOP REQUEST);
bcopy «caddr t) ac->ac enaddr, (caddr t) ea->arp sha,
sizeof (ea->arp_sha»;
bcopy«caddr t)&«struct sockaddr in ")&ac->ac if.if addr)->sin addr,
(caddr t) ea->arp spa, sizeof (ea->arp spa» -;
bcopy( (caddr t)addr; (caddr t)ea->arp tpa, sizeof (ea->arp tpal);
sa.sa family-= AF UNSPEC; (void) (*ac->ac_if.if_output) (&ac->ac_if, m, &sa);

I"
" Resolve an IP address into an ethernet address. If success,
" desten is filled in and 1 is returned. If there is no entry
" in arptab, set one up and broadcast a request
" for the IP address; return o. Hold onto this mbuf and
" resend i t once the address is finally resolved.

* We do some (conservative) locking here at splimp, since
" arptab is also altered from input interrupt service (ecintr/ilintr
* calls arpinput when ETHERPUP ARPTYPE packets come in).
*/
arpresolve lac, m, destip, desten)
register struct arpcom "ac;
struct mbuf "m;
register struct in addr "destip;
register u_char "desten;

at->at_timer - 0;
1* restart the timer */
if (at->at flags & ATF COM) {
/* entry IS complete */
bcopy( (Caddr_t)at->at_enaddr, (caddr_t)desten, 6);
splx(s) ;

return

(1);

}

/"
* There is an arptab entry, but no ethernet address
* response yet. Replace the held mbuf with this
" latest one.

*/
if (at->at hold)
m_freem(at->at_hold) ;
at->at hold - m;
arpwhohas (ac, destip);
splx(s) ;
return (0);

I"
* Find my own IP address. It will either be waiting for us in
* monitor RAM, or can be obtained via broadcast to the file/boot
" server (not necessarily using the ARP packet format).
" Unimplemented at present, return 0 and assume that the host
will set his own IP address via the SIOCSIFADDR ioctl.

*

*/
/"ARGSUSED* /
struct in addr
arpmyaddr(ac)
register struct arpcom "ac;
static struct in_ addr addr;

register struct arptab "at;
register struct ifnet *ifp;
struct sockaddr_in sin;
int s, Ina;

Hfdef lint
ac - ac;
.Jendif
addr. s addr = 0;
return- (addr);

Ina - in lnaof (*destip) ;
i f (Ina::" INADDR_ANY) {

/"

/* broadcast address */
bcopy I (caddr t) etherbroadcastaddr, (caddr t) desten,
sizeof (etherbroadcastaddr»;
return (1);

ifp

=

&ac->ac_if;

/* i f for us, then use software loopback driver */
i f (destip->s addr -( (struct 'iockaddr in *) &ifp->if addr) -> sin addr. s addr)
sin. sin family - AF INET; -sin. sin- addr - "destip;
return (looutput (&loif, m, (struct sockaddr *) &sin»;
/* billn: temp ...
if «ifp->if_flags & IFF_NOARP)
*/

II Ina >- oldmap) {

{

extern iff noarp;
if (iff noarp) {
-bcopy( (caddr t)ac->ac enaddr, (caddr t)desten, 3);
desten[3] - (Ina» 16) & Ox?f;
desten[4] - (Ina» 8) & Oxff;
desten [5] - Ina & Oxff;
return (1);

/* ask again "/

" Called from ecintr/ilintr when ether packet type ETHERPUP_ARP
* is received. Algorithm is exactly that given in RFC 826.
* In addition, a sanity check is performed on the sender
" protocol address, to catch impersonators.
*/
arpinput (ac, ml
register struct arpcom "ac;
struct mbuf "m;
register struct ether_arp "ea;
struct ether_header *eh;
register struct arptab "at = 0; 1* same as "merge" flag "/
struct sockaddr_in sin;
struct sockaddr sa;
struct mbuf "mhold;
struct in_addr isaddr,itaddr,myaddr;
if (m->m_Ien < sizeof "ea) {
goto out;
myaddr - «struct sockaddr_in *) &ac->ac_if. if_addr) ->sin_addr;
ea - mtod (m, struct ether_ arp *);
if (ntohs (ea->arp-pro) !- ETHERPUP_IPTYPE)
goto out;
}

spHIIIp () ;
ARPTAB LOOK (at, destip->s addr);
if (at-- 0) {
1* not found */
at - arptnelo' (destip) ;
at->at hold - m;
arpwhohas (ac, destip);
splx(s):
return (0);
If -

isaddr.s addr = (struct in addr *)ea->arp spa)->s_add::;
itaddr.s-addr - «struct in-addr *)ea->arp-tpa)->s_addr;
i f (!bcmP( (caddr_t) ea->arp_'iha, (caddr_t) ac->ac_enaddr,
sizeof (ac->ac enaddr») I
goto out;
/* it' If from me, iqnore it. */
}

i f (isaddr.s addr - myaddr.s addr) I
p:r;intf ('~duplicate IP add;r:ess!! sent from ethernet address: .. );

Fri Sep

5 19:09:03 1986

printf("%x %x %x %x %x %x\n", ea->arp sha[O], ea->arp_sha[l],
ea->arp_sha[2], ea->arp_sha[3], ea->arp sha['l], ea->arp sha[S]);
i f (ntohs (ea->arp op) ~ ARPOP REQUEST)
goto reply;
goto out;
ARPTAB LOOK (at, isaddr. s addr);
i f (atl {
bcopy( (caddr t)ea->arp sha, (caddr_t)at->at_enaddr,
sizeof (ea->arp shal);
at->at flags 1= ATF COM;
i f (at=>at hold) { mh-;;ld ~ at->at hold;
at->at hold - 0;
sin. sin family = AF lNET;
sin. sin- addr = isaddr;
(*ac->a~ iLif output) (&ac->ac if,
mhold, (struct sockaddr ")&sin);
if (itaddr.s_addr !- myaddr.s addr) {
goto out;
1* if-I am not the target */
}

if (at = 0) (
I" ensure we have a table entry *1
at = arptnew (&isaddr) ;
bcopy{ (caddr t)ea->arp sha, (caddr_t)at->at_enaddr,
sizeof (ea->arp shal);
at->at_flags 1- ATF_COM;
i f (ntohs (ea->arp op) !- ARPOP_REQUEST)
goto out;-

reply:
bcopy«caddr t)ea->arp sha, (caddr_t)ea->arp_tha,
sizeof (ea->arp shal);
bcopy( (caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa,
sizeof (ea->arp spa»;
bcopy( (caddr_tJ ac->ac_enaddr, (caddr_t) ea->arp_sha,
sizeof (ea->arp sha) J;
bcopy( (caddr_t) &myaddr, (caddr_tJea->arp_spa,
sizeof (ea->arp_spa»;
ea->arp op = htons (ARPOP REPLY);
eh = (struct ether header ")sa.sa data;
bcopy ( (caddr_ t J ea ->arp_ tha, (caddr_ t J eh->ether_dhost,
sizeof (eh->ether dhostJ);
eh->ether type - ETHERPUP ARPTYPE;
sa.sa family = AF UNSPEC;(*ac->ac iLif output) (&ac->ac if, m, &sa);
return; out:
m_freem(m) ;
return;

I"
" Free an arptab entry.
"I
arptfree (at)
register struct arptab "at;
int s

=

splimp();

i f (at->at_hold)
m freem(at->at hold):
at->at hold = 0;
at->a(~timer - at->at_flags - 0:
at->at iaddr. s addr - 0;
splxlsl;
-

1*
* Enter a new address in arptab, pushing out the oldest entry
" from the bucket if there is no room.
"I

struct arptab "

3
arptnew(addr)
struct in_addr *addr;
register n;
int oldest = 0;
reqister struct arptab *at, *ato;
ato = at - &arptab[ARPTAB HASH(addr->s addr) * ARPTAB_BSIZ];
for (n - 0 ; n < ARPTAB BSIZ : n++,at++) {
i f (at->at flags - 0)
goto out;
1* found an empty entry */
if (at->at ti.'!!.er > oldest) {
oldest = at->at_timer;
ato - at;

at = ato;
arptfree (at);
out:
at->at_iaddr - *addr;
at->at flags = ATF_INUSE;
return- (at) ;

if il.c

Fri Sep
S2/08/25

/*

5 19:09:26 1986

1

*/
tifdef lint
br = 0; cvec - br; br - cvec;
ilrint(O); ilcint(O); ilwatch(O);
tendif

tinclude "iloh"

/*
* Interlan Etnernet Communications Controller interface

,,/
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
+include
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

addr->il csr - ILC OFFLINE IlL CIE;
DELAY (100000) ;
i = addr->il csr;
/* clear CDONE */
if Icvec > 0-&& cvec !- Ox200)
cvec -- 4;
return (1);

"sys/param.h H
·sys/config.h"
"sys/errno.h"
"sys/types.h"
"sys/systm.h"
"net/mbuLh"
"sys/buf .h"
"net/protosw.h"
"net/socket .h"
"net/ubavar. h"
"net/ilreg .h"
"net/in.h"
"net/in sys.h"
"net/if-:-h"
·net/if iloh u
"net/if-uba.h"
"net/ip-:-h ll
"net/ip var.h"
"net/pup.hll
"net/route.h"
"errno.h"

tdefine ILMTU
tdefine ILMIN

1500
(60-14)

/"
* Interface exists: make available by filling in network interface
* record. system will initialize the interface when it is ready
" to accept packets. A STATUS command is done to get the ethernet
* address and other interesting data.
*/
ilattach (ui)
struct uba_device *ui;
register struct il softc xis - &il softc[ui->ui unit];
register struct ifnet "ifp = &is->1s if;
register struct ildevice *addr = (struct ildevice *)ui->ui_addr;
struct sockaddr_ in "sin;

/" Maximum data size for Ethernet packet */
/* Minimum data size for Ethernet packet */

int
struct
u_short
struct

ilprobe (), ilattach (), ilrint (), ilcint () ;
uba device *ilinfo [NIL];
i1std[] = { 0 };
uba driver ildriver =
{ iiprobe, 0, ilattach, 0, ilstd, "il", ilinfo };
+define ILUNIT (x)
minor (x)
int
ilinit (), iloutput (), ilreset (), ilwatch () ;

u_char
u_char

il ectop[3] - { Ox02, Ox60, OxSc !;
ilbroadcastaddr[6] = { Oxff, Oxff, Oxff, Oxff, Oxff, Oxff };

1*
" Ethernet software status per interface.
*
*
*
*
*
"
"
*

Each interface is referenced by a network interface structure,
is_if, which the routing code uses to locate the interface.
This structure contains the output queue for the interface, its address,
life also have, for each interface, a UBA interface structure, which
contains information about the UNIBUS resources held by the interface:
map registers, buffered data paths, etc. Information is cached in this
structure for use by the if_ uba. c routines in running the interface
efficiently.

*I

struct

i1 softc {
struct ifnet is if;
struct ifuba is-ifuba;
int
is_flags7
tdefine ILF_ OACTIVE
Ox1
tdefine ILF_RCVPENDING Ox2
tdefine ILF_ STATPENDING Ox4
short
is 1astcmd;
short
is=:scaninterval;
tdefine ILIifATCHINTERVAL 60
struct il stats is stats;
struct i1-stats is-sum;
long
is- ubaddr; , il_softe[NIL); -

I" network-visible interface * /
/* UNIBUS resources ,,/
output is active "I
start rev in ilcint * 1
stat cmd pending "I
can't read csr, so must save it *1
interval of stat collection * /
once every 60 seconds "I
/" holds on-board statistics * /
/* summation over time */
/* mapping registers of is_stats */

Ix
I*
1*
1*
1*
1*

il probe (reg)
caddr_ t reg;
register int br, cvee;
/* rll, rlO value-result */
register struct ildevice "addr - (struct ildevice *)reg;
register i;

ifp->if_unit = ui->ui_unit;
ifp->if name - "il";
ifp-> if-mtu - ILMTU;
ifp->if=:net = htonl (ui->ui_flags);

/"
" Reset the board and map the statistics
" buffer onto the Unibus.

,,/
addr->il csr = ILC RESET;
while «addr->il_c"ir&IL_COONE) -

0)

i f (addr->il csr&IL STATUS)
printf("il%d: reset failed, csr=%b\n", ui->ui_unit,
addr->il_csr, IL_BITS);

is->is ubaddr - uballoc(ui->ui ubanum, &is->is_stats,
- sizeof (struct il stat"i), 0);
addr->il_bar = is->is_ubaddr & Oxffff;
addr->il_bcr = sizeof (struct il stats);
addr->il csr - «is->is ubaddr » 2) & IL EUA) IILC STAT;
while «addr->il_csr&IL=:COONE) == 0)
if (addr->il csr&IL STATUS)
printf("il%d: status failed, csr=%b\n", ui->ui unit,
addr->il csr, IL BITS);
ubarelse (ui->ui ubanum, &is->is Ubaddr);
printf (" il %d: addr-%x: %x: %x: %x: %x: %x module=% s firmware-%s \n",
ui->ui unit,
is->is-stats. ils addr [0] &Oxff, is->is stats.ils addr [1] &Oxff,
is->is- stats.ils-addr [2] &Oxff, is->is=:stats .ils=:addr [3] &Oxff,
is->is- stats .ils-addr [4] &Oxff, is->is stats.ils addr [5] &Oxff,
is->is-stats.ils-module, is->is stats-:-ils firmware);
ifp->if host[O] - «long) (is->is stats.ils addr[3]&Oxff)«16) I OxSOOOOO I
«is->is stats-:-ils addr(4]&Oxff)«S) I
(is->is "itats.ils addr[5]&Oxffl;
sin - (stru-;;t sockaddr in ") &ifp->if addr;
sin->sin family - AF lNET;
sin->sin=:addr - if_makeaddr(ifp->if_net, ifp->if_host[O]);
sin = (struct sockaddr in *)&ifp->if broadaddr;
sin->sin family - AF INET;
sin->sin-addr - if makeaddr(ifp->if net, INADDR_ANY);
ifp->if_flags - IFF_BROADCAST;
ifp->if init - ilinit;
ifp->if=:output - iloutput;

if il.c

Fri Sep

5 19:09:26 1986

2

ifp->if ubareset = ilreset;
ifp->if-watchdog - ilwatch;
is->is scaninterval - ILWATCHINTERVAL;
ifp->if timer - is->is scaninterval;
is->is 1fuba. ifu flags-= UBA CANTWAIT;
Hfdef notdef is->is_ifuba.ifu_flags 1= UBA_NEEDBDP;
tendif

splx(s) ;
if_rtinit(&is->is_if, RTF_UP);

/*
"* start output on interface.
" Get another datagram to send off of the interface queue,
" and map it to the interface before starting the output.

"I
ilstart (dev)
dev_t dey;

1*

*
*

Reset of interface after UNIBUS reset.
If interface is on specified uba, reset its state.

int unit - ILUNIT (dev), dest, len;
struct uba device "ui = ilinfo[unit];
register struct il softc "is = &il softc[unit];
register struct ildeviee *addr;
struet mbuf *m;
short csr;

*/
ilreset (unit, uban)
int unit, uban;
register struct uba_device "ui;
if (unit >- NIL II (ui - ilinfo [unit]) ~ 0 II ui->ui_alive ui->ui_ubanum != uban)
return;
printf(" il%d", unit);
ilinit (unit) ;

IF DEQUEUE (&is->is if. if snd, m);
addr = (struct ildeviee *)ui->ui addr;
if (m - 0) {
if «is->is_flags & ILF_STATPENDING)
0)
return;
addr->il bar = is->is ubaddr & Oxffff;
addr->il-bcr = sizeof- (struct il stats);
esr - «1s->is ubaddr » 2) & IL-EUA) I ILC STAT I IL RIE I IL CIE;
is->is flags &= -ILF STATPENDING-;goto startcmd;
-

0 II

/"

* Initialization of interface; clear recorded pending
* operations, and reinitialize UNIBUS usage.
,,/
ilinit (unit)
int unit;

len - if_wubaput (&is->is_ifuba, m):
/*
* Ensure minimum packet length.
" This makes the safe assumtion that there are no virtual holes
" after the data.
" For se=ity, it might be wise to zero out the added bytes,
" but we're mainly interested in speed at the moment.

register struct il softc xis - &il softc[unit];
register struct ub~ device "ui = ilinfo [unit];
register struct ildevice "addr;
int s;

if (if ubainit (&is->is ifuba, ui->ui ubanum,
sii"eof (st::::uct i l rheade::::), (int)btoc(ILMTU)
printf("il%d:-can't initialize\n", unit);
is->is if. if flags &= -IFF UP;
return-;-

0)

is->is_ubaddr - uballoc(ui->ui ubanum, &is->is_stats,
sizeof (struct il stats), 0);
= (struct ildevice ")ui->ui_ addr;

addr

/*

* Turn off source address insertion (it's faster this way),
" and set board online.
*/
s - splimp();
addr->il csr - ILC CISA;
while «addr->il_csr & IL_CDONE) - 0)
addr->il csr - ILC ONLINE;
while «~ddr->il_csr & IL_CDONE) =

startcmd:
is->is lastcmd - csr & IL_CMD;
addr->1l csr - csr:
is->is_flags 1- ILF_ OACTlVE;

I"
" Command done interrupt.
"I
ilcint (unit)
int unit;

0)

1*

*

*1
if (len - sizeof(struct il xheader) < ILMIN)
len = ILMIN + sizeof (struct il xheader);
i f (is->is ifuba.ifu flags & UBA NEEDBDP)
uBAPURGE (is->is_ifuba .if;:;:_uba, is->is_ifuba.ifu_w.ifrw_bdp);
addr->il bar - is->is ifuba. ifu w. ifrw info & Oxffff;
addr->il::::bcr - len; csr =
«is->is_ifuba.ifu_w.ifrw_info » 2) & IL_EUA) I ILC_XMITI IL_CIEI IL_RIE;

Hang receive buffer and start any pending
* writes by faking a transmit complete.
* Receive bcr is not a muliple of 4 so buffer
* chaining can't happen.
"I
addr->il bar - is->is ifuba. ifu r. ifrw info & Oxffff;
addr->il::::bcr - sizeof(struct il::::rheader) + ILMTU + 6;
addr->il csr «is->is ifuba.ifu r.ifrw info» 2) & IL_EUA) iILC_RCVIIL_RIE;
while «addr->il::::csr & IL_CDONE)
0)

register struct il softe "is - &il softc [unit];
struet uba device *ui = ilinfo [unit] ;
register struct ildevice "addr - (struct ildevice *jui->ui_addr:
short csr;
MAPSAVE() ;
if «is->is flags & ILF OACTlVE) - 0) {
pri;tf("il%d: stray xmit interrupt, csr-%b\n", unit,
addr->il_csr, IL_BITS);
gata out;

=-

is->is flags - ILF OACTlVE;
is->is-if.if flags-'- IFF UP:
is->is-lastcmd - 0;
ilcint(unit) ;

csr - addr->il_csr;
1*
" Hang receive buffer if it couldn't
" be done earlier (in ilrint) .
xl

if il.c

Fri Sep

5 19:09:26 1986

3

if (is->is flags & I LF_RCVPENDING)
addr->il bar - i3->is ifuba. ifu r. ifrw info .. Oxffff;
addr->il-bcr ~ sizeof(struct il-rheader) + ILMTU + 6;
addr->il-csr «is->1s ifuba.ifu r.ifrw info» 2) & IL_EUA) I ILe_RCVI IL_RIE;
while «(addr->il_CSr-& IL_CDONE) -- 0)
is->is_flags &= -ILF_RCVPENDING;
}

is->is_flags &- -ILF_OACTIVE:
csr &- IL STATUS;
switch Ct'i->is_lastcmd}
case ILC XMIT:
Is->is if. if opackets++;
if (csr > ILERR RETRIES)
is->is_If. if_oerrors++;
break;

*/

«

fdefine ildataaddr (il, off, type)
«type)
(caddr_t) ((il) +1) + (offll»
i f (il->ilr type >- ILPUP TRAIL &&
il->ilr-type < ILPUP TRAIL+ILPUP NTRAILER) {
off-- (11->ilr tyPe - ILPUP TRAIL) * 512:
if (off >= lla.'1TU)
goto setup:
/* sanity */
il->ilr type - *ildataaddr (il, off, u short *1;
resid = - . (ildataaddr (il, off+2, u_ short *»:
if (off + resid > len)
goto setup:
/* sanity */
len = off + resid;
) else
off - 0:
if (len - 0)
goto setup;
/*
•
*
"
•

case ILC STAT:
If (csr = lLERR SUCCESS)
iltotal (Is) :
break;

Pull packet off interface. Off is nonzero if packet
has trailing header; ilget will then force this header
information to be at the front, but we still have to drop
the type and length which are at the front of any trailer data.

*/

=-

m - if rubaget (&is->is ifuba, len, off);
if (m
0)
goto setup;
if (off) {
m->m_off += 2 * sizeof (u short);
m->m_len -= 2 " sizeof (u=short);

if (is->is ifuba.ifu xtofree)
m freem(is->Is ifuba.ifu xtofree);
is->is_ifuba.ifu_xtofree-= 0;
ilstart (unit) ;
out:
MAPREST() ;

/*

* Ethernet interface receiver interrupt.
• If input error just drop packet.
" otherwise purge input buffered data path and examine
" packet to determine type. If can't determine length
• from type, then have to drop packet. othewise decapsulate
" packet based on type and pass to type specific higher-level
" input routine.
*/
ilrint (unit)
int unit;
register struct il softc xis - &il softc [unit];
struct ildevice *addr - (struct ildevice *)ilinfo[unit]->ui_addr;
register struct il_rheader *il:
struct mbuf "m;
int len, off, resid;
register struct ifqueue *inq:
MAPSAVE() ;
is->is if. if ipackets++;
i f (is-=>is ifuba.ifu flags & UBA NEEDBDP)
UBAPURGE (is->is_ifuba.ifu_uba, is->is_ifuba. ifu_r. ifrwYdp);
fif !pdpll
il - (struct il_rheader *) (is->is_ifuba.ifu_r.ifrw_addr);
felse
*aka5 - is->is ifuba.ifu r.ifrw click;
il = (struct ll_rheader .)HEX; fendif
len - il->ilr length - sizeof(struct il rheader):
if «il->ilr status& (ILFSTAT AI ILFSTAT C»
II len < 46 I I len> ILMTU) (
is->Is_if.if_ierrors++;
Hfdef notdef
if (i3->is if.if ierror3
100 == 0)
prlntf("Il%d: +- 100 input errors\n", unit);
tendif
goto setup:

fifdef INET
case ILPUP_ IPTYPE:
schednetisr (NETISR IP):
inq ~ &ipintrq:
break;
fendif
default:
m_ freem (m) ;
gote setup;

if (IF QFULL(inq» {
- IF DROP (inq) ;
m freem(m);
goto setup;
)

IF_ENQUEUE(inq, m);
setup:
/*
* Reset for next packet if possible.
" If waiting for transmit command completion, set flag
* and wait until command completes.

*/
i f (is->is flags & ILF OACTIVE) {
is-=>is flags I:: ILF RCVPENDING:
goto out;
-

addr->il_bar ~ is->is_ifuba.ifu r.ifrw info & Oxffff;
addr->il bcr - sizeof(3truct il-rheader) + ILMTU + 6;
addr->il-csr «is->i3 ifuba.ifu r.ifrw info» 2) & IL EUA) iILC_RCViIL_RIE;
while «addr->il=csr , IL_COONE)
0)

=-

out:
MAPREST() ;

/*
/*

*

Deal with trailer protocol: if type is PUP trailer
* qet true type from first 16-bit word past data.
• Remember that ty'pe wa,s trailer by settinr;! of:f;.

• Ethernet output routine.
* Encapsulate a packet of type family for the local net.
* Use trailer local net encapsulation if enough data in first
* packet leaves a multiple of 512 bytes of data in remainder.
*/

if il.c

Fri Sep

5 19:09:26 1986

4
1*

iloutput (ifp, mO, dst)
struct ifnet *ifp;
struct mbuf *mO;
struct sockaddr *dst;

" this is a kludge to talk with other company's boards;
* instead 1 byte Inlllticast addresses should be used, and the
" physical board address will be unused.

*1
bcopy(to, il->ilx d...'lost, 3);
bcopy( «caddr t)&dest)+1, &il->ilx dhost[3], 3);
il->ilx_dhost [3] &- Ox7f;
-

int t:ype, Sr error i
long dest;
register struct il softc *is - &il softc [ifp->if unit];
register struct mbuf *m = mO;
register struct il_xheader *il;
register int off;

bcopy(is->is stats.ils addr, il->ilx_shost, 6);
il->ilx_type-- type; -

switch (dst-> sa_family)

1*
* Queue message on interface, and start output if interface
* not yet active.

tifdef INET
case AF_ INET:
dest = «struct sockaddr in *)dst)->sin addr.s addr;
off - ntohs( (u short)mtod(m, struct ip *)->ip len) - m->m_len;
if (off> 0 &&-(off & Oxlff) ~ 0 &&
m->m off >= MMINOFF + 2 * sizeof (u short»
type - ILPUP TRAIL + (off»9); m->m off -- "2 " sizeof (u short);
m->m:=len += 2 * sizeof (u:=short);
*rntod(m, u short *) = ILPUP IPTYPE;
* (mtod (m, u short *) + 1) =- m->m_len;
goto gottrallertype;

*1
s - splimp () ;
if (IF QFULL(&ifp->if snd»
(
- IF DROP (&ifp->if snd);
splx(s);
m_freem(m) ;
return (ENOBUFS);
IF ENQUEUE (&ifp->if snd, m);
if-«is->is flags &-ILF OACTIVE) =
ilstart (ifp->if:=unit);
splx(s) ;
return (0);

}

type = ILPUP IPTYFE;
off - 0;
goto gottype;

0)

bad:
m_freem(mO) ;
return (error);

tendif
default:
printf("il%d: can't handle af%d\n-, ifp->if_unit,
dst->sa_family) ;
error = EAFNOSUPPORT;
goto bad;

1*

* Watchdog
"I

routine, request statistics from board.

ilwatch (unit)
int unit;
gottrailertype :
1*
" Packet to be sent as trailer: move first packet
* (control information) to end of chain.
*/
while (m->m_next)
m = m->m next;
m->m_next - mO; m - mO->m next;
mo->m_next - 0;
mO - m;
gottype:

1*

* Add local net header.
" allocate another.

I f no space in first mbuf,

register struct i1 softc *is = &i1 softc[unit];
register struct ifii:et *ifp - &is->ls_if;
int s;
if (is->is flags & ILF STATPENDING)
ifp->if_timer - is->is_ scaninterval;
return;
s - splimp () ;
is->is flags 1= ILF STATPENDING;
if «is->is flags &-ILF OACTIVE) -- 0)
ilstart (ifp->if-unit);
splx(s);
ifp->if_timer
is->is_ scaninterval;

*1
if (m->m off > MMAXOFF I I
MMINOFF + sizeof (struct il xheader) > m->m_off)
m - m get (M DONTWAIT) ;
if (m- -- 0) - (
error = ENOBUFS;
goto bad;

/*
* Total up the on-board statistics.
*/
iltotal (is)
register struct il_softc *is;
register u_short *interval, "sum, *end;

m->m next - mO;
m->m:=off - MMINOFF;
m->m len - sizeof (struct il_xheader);
} else {
sizeof (struct il xheader);
m->m_off
:n->:n_len
sizeof (str'.lc:' !.l:=>:header);
}

il - mtod (m, struct il xheader .);
if (in Inaof(dest) -- 0)
- bcopy(ilbroadcastaddr, il->ilx_dhost, 6);
else {
u_char *to - ntohl (dest) , Ox800000 ?
is->is_stats . .ils_addr : il_ectop;

interval - &is->is stats.ils frames;
sum - &is->is sum. lIs frames7
end - is->is sum.ils fi112;
while ( sum <-end)
* sum++ +- *!.nterval ++;
is->is_if. if_collisions - is->is_sum. ils_collis;

Fri Sep
/*

4.13

82/06/20

5 19:09:27 1986
*1

1
m_freem(mO) ;
return (EAFNOSUPPORT);

/*
" Loopback interface driver for protocol testing and timing.

"I
#include
Hnclude
#include
finclude
Hnclude
Hnclude
finclude
#include
#include
#include
#include
finclude
tinclude
#include
finclude

"sys/param.h"
"sys/config .h"
"sys/errno.h"
"sys/types.h"
"sys/systm.h"
"net/mise, hOI
"net/mbuf. h"
"netl socket. h II
"net/in.h"
"net/in_systm.h"
"net/if.h"
"net/ip.h"
"net/ip_var. h"
"net/route.h"
"errno.h"

Me fine LONET
fdefine LOMTU
struct
int

Ox7fOOOOOO
(1024+512)

ifnet loif;
looutput () ;

loattach()
{

register struct ifnet *ifp - &loif;
register struct sockaddr_in *sin;
ifp->if name = "10";
ifp->if-mtu = LOMTU;
ifp->if-net - htonl«u 10ng)LONET);
sin = (struct sockaddr-in *) &ifp->if addr;
sin->sin family = AF INET;
/*
sin->sin addr = if_makeaddr (Iu_long) ifp->if_net, lu_long) 0);
*/
sin->sin_ addr ~ if makeaddr I (u long) ifp->if net, (u_long) 1) ;
ifp->if flags = IFF UP;
ifp->if-output = looutput;
if atta"Ch(ifp);
i(:rtinit(ifp, RTF_UP);
looutput (ifp, mO, dst)
register struct ifnet *ifp;
register struct mbuf *mO;
register struct sockaddr *dst;
register int s - splimp ( ) ;
register struct ifqueue *ifq;
ifp->if opackets++;
switch (dst->sa_family)
fifdef INET
case AF INET:
-ifq - &ipintrq;
if (IF QFULL(ifq»
{
- IF DROP (ifq) ;
m_freem(mO) ;
splxls);
return IENOBUFS);
I
IF ENQUEUE(ifq, mOl:
sChednetisr INETISR_IP) ;
break;
#endif
default:
splx(sl;
printf("10'l;d: can't handle af%d\n", ifp->if_uni",
dst->sa_family) ;

ifp->if_ipackets++;
splx(s) ;
return (0):

Fri Sep

if me.c

5 19:09:28 1986

1
Ox07ff
'define MERDOFF
.ifdef notdef
'define MEMAXTDOFF
fendif
'define MEMAXTDOFF

1*
* structure of an Ethernet header.

'include
'include
finclude
finclude
finclude
'include
finclude
finclude
finclude
finclude
'include
'include
'include
'include
'include

Rnet/misc.h"
Itsys/param. h"
"sys/config.h u
·sys/errno.h"
Rsys/types.h"
"sys/systm.h"
"net/mbuf.h"
"sys/buf .hu
"net/protosw.h"
"net/socket.h lt
"sys/config.h"
"sys/mmu.h"
Asys/sysmacros.h"
"net/ubavar. h"
Aerrno.h"

1* first free byte *1
1* packet offset in read buffer *1

(2048-60)

1* max packet offset (min size) *1

(2048-512)

1* max packet offset (min size) *1

'define NME 1

1*

* 3Co!!!. Ethernet Controller interface
*1
'define MEMTU

1500

int nulldev (), meattach (), meintr () ;
struct uba_device *meinfo[NME];

struct

uba driver medriver nuiidev, meattach, (u_short * )0, meinfo

};

'include
finclude
'include
finclude
Hnclude
finclude
'include
'include

Anet/if .h"
Anet/route .h"
"net/in.h"
Rnet/in systm.h"
"net/ip-:-h ll
"net/ip var .hU
"net/pup.h U
Anet/if_ether.h A

fdefine MEUNIT (x)

extern struct ifnet loif;
Hfdef HAS8259
Mefine ME_ EOI 2
int meeoi = ME_ EOI;
'endif

1*

* 3Com Ethernet controller registers.

*1
struct medevice
u_short
u short
u_char
u char
u=:char
u_char
u_char
u_char
u char
u=:char

[
me_csr;
1* control and status *1
me back;
1* backoff value *1
meJ>adl [Ox400-2*2];
me arom[6];
1* address ROM *1
meyad2[Ox200-6];
me aram[6];
1* address RAM *1
meyad3[OX200-6];
me tbuf[2048]; 1* transmit buffer *1
me-abuf[2048]; 1* rmeeive buffer A *1
me=:bbuf[2048]; 1* receive buffer B *1

};

1*
* Control and status bits

*1
fdefine
"define
fdefine
'define
'define
"define
'define
'define
'define
'define
tdefine
tdefine

ME BBSW
ME-ABSW
ME- TBSW
ME-JAM
ME-AMSW
ME- RBBA
ME-RESET
ME~)INT
ME AINT
ME-TINT
ME- JINT
ME:)AMASK

Ox8000
Ox4000
Ox2000
Oxl000
Ox0800
Ox0400
OxOl00
OxOO80
OxOO40
OxOO20
OxOOl0
OxOOOf

1*
1*
1*
1*
1*
1*
1*
1*
1*
1*
1*
1*

buffer B belongs to ether * I
buffer A belongs to ether * I
transmit buffer belongs to ether *1
Ethernet jammed (collision) *1
address RAM belongs to ether * I
buffer B older than A * I
reset controller *1
buffer B interrupt enable *1
buffer A interrupt enable *1
transmitter interrupt enable *1
jam interrupt enable */
PA field *1

1* with old VAX 4.la, keep range errors, since vax sends too-small packets. *1
tdefine ME PA OLDVAX
tdefine ME~)A-

Ox0008
Ox0002

/* receive mine+broadcast- (fcs+frame) * I
all- fcs and frame errors * I

1*

/*

* Receive status bits

*1
tdefine
tdefine
tdefine
'define
'define

ME FCSERR
ME-BROADCAST
ME- RGERR
ME-ADDRMATCH
ME::::FRERR

Ox8000
Ox4000
Ox2000
Oxl000
OxOSOO

minor (x)

int
meinit () , me output () ,mewatch () ;
struct mbuf *meget () ;

1*
1*
I·
I·
I*

FCS error *1
packet was broadcast packet *;
range error * I
address match *1
framing error * I

1*
* Ethernet software status per interface.

* Each interface is referenced by a network interface structure,
* es if, which the routing code uses to locate the interface.
* This structure contains the output queue for the interface, its address, ...
*1
struct

me softc [
struct arpcom es ac;
'define es if
es ac. ac if
'define es=:enaddr es_ac"~c_enaddr
short
es mask;
short
es-oactive;
me_softc[NME]; -

/* common Ethernet structures *1
network-visible interface *1
hardware Ethernet address *1
mask for current output delay *1
is output active? *1

1*
1*
1*
1*

/*
* Interface exists: make available by filling in network interface
* record. System will initialize the interface when it is ready
* to accept packets.
*1
meattach (md)
struct uba_device *md;
struct me softc *es = &me softc[md->ui unit];
register struct Hnet *Hp - &es->es_lf;
register struct medevice *addr;
struct sockaddr in * sin;
int i;
u char *cp, *ap;
char *memap () ;
/" map controller into kernel space for Uniso!t. mernap is in co::.:ig c
addr - (struct medevice *1 memap( (intlmd->ui addr, btoc(81921 I;
1* replace the value of ui addr for everyone-else. *1
md->ui_addr - (Caddr_tladdr;
ifp->if unit - md->ui unit;
ifp->if-name - "me"; ifp:->if::::mtu- MplTU;

*'

if me.c

Fri Sep

5 19:09:28 1986

ifp->if_net - md->ui_flags & OxffOOOOOO;

2
" Initialize the address RAM

"I
if (! iocheck «caddr t) addr» {
printf ("*"\nCould not find me%d; am not initializing network device ... **\n",
ifp->if_unit) ;
return;

addr->me csr 1= ME_RESET;
medelay (1") ;

cp - es->es_ enaddr;
ap - addr->me aram;
for (i - 0; i-< 6; i++)
*ap++ .. *cp++;
addr->me_csr 1- ME_AMSW;

I" reset the board "I
1* wait for it to reset (1 sec) *1

/*
.. Hang receive buffers and start any pending writes.
*/
addr->!!!e csr != ME ABSW I ME AINT! ME BBSW! ME BINT
T ME PA OLDVAX; *1
es->es oacti-;;:e ;;; 0;
cp ~ es->es enaddr;
es->es-mask - -0;
ap - addr->me_ arom;
es->es-if.if flags 1= IFF UPIIFF RUNNING;
/ * check for mem. board mistakenly mapped to same addr. as me "I
if (es=>es_lr.if_snd.ifcchead)
mestart (unit) ;
if «"ap - 'g') == 'g') {
printf (
splx(s) ;
"\n*"Able to write the rom on me%d; probable memory addressing confilct. "*\nNot initializing interface. \n\n", ifpt>if unit);
return;
if rtinit(&es->es if, RTF UP);
arpattach (&es->es- ac) ;
arpwhohas (&es->es ac, &sin->sin_ addr) ;
for (i = 0; i < 6; i++)
"cp++ = *ap++;
printf("Ethernet address = ");
I"
{
" Start or restart output on interface.
char * p = &es->es enaddr [0] ;
.. If interface is already active, then this is a retransmit
int i, j = 0;
.. after a collision, and just restuff registers.
char buf [14];
" If interface is not already active, get another datagram
" to send off of the interface queue, and map it to the interface
for (i = 0; i < 6; i ++) {
" before starting the output.
buf [j++] - "0123456789ABCDEF" [ «*p » 4) &Oxf)];
"I
buf [j++] - "0123456789ABCDEF" [ «*p++) &Oxf) ];
mestart (dev)
register dev_t dey;
buf[j++] = , \n';
buf[j] = 0;
register int unit = MEUNIT (dev) ;
printf (buf) ;
register struct me softc "es = &me_softc[unit];
register struct medevice .. addr;
sin = (struct sockaddr_in *)&es->es_if.if_addr;
register struct mbuf "m;
sin->sin_fam.ily = AF_INET:
addr = (struct medevice *)meinfo[unit]->ui_addr;
1* this is a way to set addresses for now (without an ioctl (» .. I
if (es->es oactive)
sin->sin_addr.s_addr = (u_Iong)md->ui_flags;
goto restart;
mesetaddr (ifp, sin);
IF DEQUEUE(&es->es if.if snd, m);
if- (m == 0) {
ifp->if init - meinit;
ifp->if-output = meoutput;
es->es_oactive - 0;
ifp->if-watchdog = mewatch;
return;
if_atta-;;h(ifp) ;
meput (addr->me tbuf, m);
addr->me_csr I;;; ME_TBSWIME_TINTIME JINT;
mewatch()
{}
restart:
es->es_oactive - 1;
1*
* Initialization of interface; clear recorded pending
* operations.
1*
" Ethernet interface interrupt.
*/
meinit (unit)
" If received packet examine
int unit;
* packet to determine type. If can't determine length
" from type, then have to drop packet. othewise decapsulate
struct me_softc "es = &me so ftc [unit] ;
" packet based on type and pass to type specific higher-level
register struct ifnet "ifp = &es->es if;
" input routine.
register struct sockaddr_in "sin;
"I
struct medevice "addr;
meintr()
int i, s;
{
u_char "cp, *ap;
register struct me softc "es:
register struct medevice *addr:
sin - (struct sockaddr in ")'ifp->if addr;
register int unit:
if (sin->sin_addr.s_addr -- 0)
/* address still unknown *1
extern short netoff:
return;
register unsigned short meenables = 0:
if «es->es if.if flags & IFF RUNNING) - 0) {
addr - (struct medevi-;;e ")meinfo[unit] ->ui addr:
if (netoff)
s - splimp () ;
return;
(void) spInet () ;
1*

I"
* Read the ethernet address off the board, one byte at a ti."n.e.

=

if me.c

Fri Sep

5 19:09:28 1986

for (unit = 0; unit < NME; unit++) (
es - &me softc[unit]:
addr - (struct medevice *)meinfo[unit]->ui addr;
switch (addr->me_csr & (ME_ABSKIME_BBSWIME=:RBBA»
case ME_ABSW:
case ME ABSWIME REBA:
-1* BBSW-= 0, receive B packet *1
addr->me csr &= -ME BINT;
meread(eS, addr->me-bbuf);
addr->me csr 1= ME BBSW 1ME BINT;
break; case ME_BBSW:
case ME BBSWIME REBA:
-1* ABSH- 0, rmeeive A packet *1
addr->me_ csr &- -ME_ AINT;
meread(es, addr->me abuf);
addr->me csr 1- ME AsSW 1ME AI NT ;
break; case ME RBBA:
-1* ABSW = 0, BBSW = 0, RBBA, receive B, then A *1
addr->me csr &= -(ME AINTIME BINT);
meread (es, addr->me bbuf); addr->me_csr 1- ME_BssWIME_BINT;
meread(es, addr->me abuf);
addr->me_csr 1= ME_AsSWIME_AINT;
break:
case 0:

1* ABSW ~ 0, BBSW = 0, REBA = 0, receive A, then B *1
addr->me csr &= - (ME AI NT 1ME BINT);
meread(es, addr->me abuf); addr->me csr 1= ME AssW 1ME AINT;
meread (es, addr->me bbuf):addr->me csr 1- ME BBSW 1ME BINT;
break; -

3
tifdef HAS8259
/* try to force level change by exciting current ints on bd *1
meenables - addr->me_csr & (ME_TINTIME_AINTIME_BINTIME_JINT);
addr->me_csr &- -meenables;
sendeoi (rneeoi) ;
addr->me_csr 1- meenables;
tendif
return

meread (es, mebuf)
register struct me_so ftc "es;
register caddr_ t mebuf;
register struct ether_header *me:
register struct mbuf *m:
register int len, off, meoff;
short resid;
register struct ifqueue *inq;

1*
int i:
printf ("mer. H) ;
me = (struct ether header *) (mebuf + MERDOFF):
printf("s:");
for (i = 0: i < 6; i++)
printf (H%x.",me->me_shost [i] &Oxff);
printf(" H);
printf("d:-) ;
for (i = 0; i < 6; i++)
printf(U%x.",me->me dhost[i] &Oxff);

*1
es->es iLif ipackets++;
meoff -: * (short *)mebuf;

case ME ABSWIME BBSW:
case ME-ABSWIME-BBSWIME RBBA:
-Ix no input packets *1
addr->me csr &- - (ME AINT IME BINT);
addr->me-csr I~ ME AINTIME BINT:
break; -

if(meoff & (ME_FRERRIME_RGERRIME_FCSERR»
goto err:
meoff &= ME_DOFF;
i f (meoff <- MERDOFF I I meoff > 2046) {

err:
default:

es->es if.if_ierrors++:
return;

panic ("meintr: impossible value");
I * NOT REACHED */

1* end of "for unit" *1
for (unit - 0; unit < NME; unit++) (
es = &me_softc[unit];
addr = (struct medevice *)meinfo[unit]->ui_addr;
if (es->es oactive ~ 0)
continue:
if (addr->me csr & ME JAM)

1*

-

-

1*
* Get input data length.
* Get pointer to ethernet header (in input buffer).
* Deal with trailer protocol: if type is PUP trailer
* get true type from first 16-bit word past data.
* Remember that type was trailer by setting off.

*1

len = meoff - MERDOFF - sizeof (struct ether_header) - 4; /* 4 == FCS *1
me - (struct ether header *) (mebuf + MERDOFF):
tdefine medataaddr(me, off-; type)
«type) «(caddr_t) «me)+l)+(off»»

*

Collision on ethernet interface. Do exponential
* backoff, and retransmit. If have backed off all
* the way print warning diagnostic, and drop packet.

*/
es->es if. if collisions++;
medocoll(unit) ;
continue:
if «addr->me csr , ME TBSK) -- 0) {
addr->me csr &-: - (ME TINT1ME :INT);
es->es if. if opackets++:
es->es=:oactt";e - 0;
es->es mask - -0;
if (es=>es_iLif_snd.if~head)
mestart (unit):
1* end of "for unit" -I

if (me->ether type >- ETHERPUP TRAIL &&
me->ether-type < ETHERPUP TRAIL+ETHERPUP NTRAILER)
off --(me->ether type-- ETHERPUP TRAIL) * 512;
if (off >- MEMTU)
return:
1* sanity */
me->ether type - *medataaddr (me, off, u short *);
resid - ..(medataaddr (me, off+2, u short- *) ) ;
if (off + resid > len)
1* sanity */
return:
len - off + resid;
I else
off - 0;
i f (len 0)
return;

if me.c

Fri Sep

5 19:09:28 1986

* Pull packet off interface.

Off is nonzero if packet
has trailing header; meget will then force this header
information to be at the front, but we still have to drop
* the type and length which are at the front of any trailer data.

*
*

*/
m = meqat (mebuf, len, off):

if (m = 0)
return;
if (off) {
m->m_off += 2
m->~len -- 2

4
1*
* Ethernet output routine.
* Encapsulate a packet of type family for the local net.
* Use trailer local net encapsulation if enough data in first
* packet leaves a multiple of 512 bytes of data in remainder.
* If destination is this address or broadcast, send packet to
* loop device to kludge around the fact that 3com interfaces can' t
* talk to themselves.

*1

*
*

sizeof (u_short);
sizeof (u_short);

switch (me->ether_type)

meoutput (ifp, mO, dst)
register struct ifnet *ifp;
register struct mbuf *mO;
register struct sockaddr *dst;
int type, s, error;
u char edst [6];
struct in_addr idst;
register struct me softc xes - &me softc[ifp->if unit];
register struct mb'llf *m = mO;
register struct ether header *me;
register int i;
struct mbuf *mcopy - (struct mbuf *) 0;
1* Null */

tifdef INET
case ETHERPUP IPTYFE:
schednetisr (NETISR IP);
inq - &ipintrq;
break;
case ETHERPUP ARPTYFE:
arpinput (&es->es ac, m);
return;
-

s = spInet () ;
switch (dst->sa_family)

tendif
default:
m_ freem (m) ;
return;

if (IF_QFULL(inq» {
IF_DROP (inq);
m_ freem (m) ;
return;
I
IF_ENQUEUE(inq, m);

tifdef INET
case AF_INET:
idst - «struct sockaddr in *)dst)->sin addr;
if (! arpresolve (&es->es :;c, m, &idst, edst»)
return (0);
-1* if not yet resolved *1
if (in lnaof(idst) -= INADDR ANY)
- mcopy - m_copy(m, 0,- (int)M_COPYALL);
type - ETHERPUP_IPTYPE;
goto gottype;
tendif
case AF_ UNSPEC:
me - (struct ether header *)dst->sa data;
bcopy«caddr_t)me->ether_dhost, (caddr_t)edst, sizeof (edst»;
type - !!!e->ether_type;
goto gottype;

medocoll (unit)
int unit;
register struct me seftc xes = &me softc[unit];
register struct medevice *addr =
(struct medevice *) meinfo [unit ]->ui addr;
int delay;
-

default:
printf(Ume%d: can't handle af%d\n", ifp->if_unit,
dst->sa_family) ;
error - EAFNOSUPPORT;
goto bad;

1*

* Es_mask is a

16 bit number with n low zero bits, with
* n the number of backoffs. When es_mask is 0 we have
* backed off 16 times, and give up.
*/
if (es->es mask -= 0) (
es=>es if.if oerrors++;
printi"(
"\nme%d: 16 collisions detected on ethernet. Dropping current packet ... \n\n",
unit) ;

1*

* Reset and transmit next packet (if any) .
*/
es->es_oactive = 0;
es->es mask = -0;
if (es=>es_if.if_snd.ifCLhead)
mestart (unit);
return;
/*

* Do exponential backoff.

Compute delay based on low bits
* of the time. A slot time is 51. 2 microseconds (rounded to 51).
* This does not take into account the time already used to
.. process the interrupt.

*1

es->es mask «- 1;
delay: (time&Oxffff) &- es->es_mask;
addr->me_back .. delay * 51;
addr->me_ csr 1- ME_JAM 1ME_ JINT;

gottype:

/*

* Add local net header.

If no space in first mbuf,
* allocate another.
*1
if (m->m off > MMAXOFF I I
MMINOFF + sizeof (struct ether header) > m->m_off)
m - m get(M DONTWAIT);
if (m-=- O)-{
error - ENOBUFS;
goto bad;
m->m next - mO;
m->m-off .. HMINOFF;
m->nClen - sizeof (struct ether_header);
} else {
m->m_off
sizeof (struct ether header);
m->m_Ien +- sizeof (struct ether=:header);
me - mtod (m, struct ether header *);
bcopy «caddr t) edst, (caddr t)me->ether dhost, sizeof (edst));
me->ether tyPe - htons «u short) type); bcopy( (caddr t)es->es enaddr, (caddr t)me->ether shost, 6);

1*

-

-

-

-

* Queue message on interface, and start output if interface
.. not yet active.

if me.c

Fri Sep

5 19:09:28 1986

5
struct mbuf *
meget (mebuf, totlen, off 0)
register u char *mebuf;
register int totlen, off 0 ;

*/
s - splimp () ;
if (IF QFULL(&ifp->if snd»
- IF_DROP (&ifp->if_snd);
error = ENOBUFS;
got a qfull;

register struct mbuf *m;
struct mbuf *top = 0, **mp - ⊤
register int off - off 0, len;
register u_char *cp;

}

IF ENQUEUE(&ifp->if snd, m);
if- (es->es oactive ::.. 0)
mestart (ifp->if unit);
splx(s);
gotlocal:
return (mcopy

looutput (&loif, mcopy, dst)

cp - mebuf + MEROOFF + sizeof (struct ether_header);
/*
lint i; int j; printf("meget:\n") ;for{j-0;j<6;j++) {for (i-0;i<16;i++)printf("%x ", « ichar *)cp)
*/
while (totlen > 0) (
u_char *mcp;

0) ;

qfull:
mO

~

m;
MGET (m, 0);
if (m ~ O){
goto bad;

bad:
m freem(mO);
splx(s) ;
return (error) ;

if (off) {
len - totlen - off;
cp = mebuf + MERDOFF + sizeof (struct ether_header) + off;
} else
len - totlen;
m->m len = len = MIN (MLEN, len);
m->m:=off = MMINOFF;
mcp = mtod(m, u_char *);
bcopy(cp, mcp, len):
cp +- len;

/*
* Routine to copy from mbuf chain to transmitter
* buffer in Multibus memory.
*/
meput (mebuf, m)
register u char *mebuf;
register struct mbuf *m;
register
register
register
register

struct mbuf *mp;
short off;
u char *bp;
flag - 0;

*mp - m;

mp = &m->m next;
if (off =-0) {
tot len -- len;
continue;

for (off - 2048, mp - m; mp; mp - mp->m_next)
off -= mp->m len;
if (off> MEMAXTDOFF)
/* enforce minimum packet size */
off - MEMAXTDOFF;

off +- len;
if (off = totlen)
cp = mebuf + MERDOFF + sizeaf (struct ether_header);
off = 0;
tot len = off 0 ;

if (off & 01) {
aff--;
flag++;

return (top);
bad:
m_freem{top) ;
return (0):

"(u_short ")mebuf = off;
bp = (u char ") (mebuf + off);
for (mp-= m; mp; mp - mp->m next)
register unsigned len = mp->m len;
u_char "mcp;
if (len

/* medelay -- wait about tim secs */
medelay (tim)
register tim;

0)
continue;
mcp = mtad(mp, u char ");
bcapy (mcp, bp, (Int) len) ;
bp +- len:
~

{

register i;
while (tim--) {
i = 100000;
while (i--)

I"
if «Off & 01) && (Off> (2048-70»)
lint i; int j; printf(IImeput(%x) :\n", Off) ;for(j-O;j<4;j++) {for (i-D;i<16;i++) printf ("'Ix ",
*I
if (flag)
"bp - 0;
~freem(m)

(char *) (aff+JjIebuf»

}
[i+16*j]) &Oxff) :printf("\n U ) ; } }

mesetaddr (ifp, sin)
register struct ifnet "ifp;
register struct sackaddr_in "sin;

;

I"
" Routine to copy from Multibus memory into mbufs.
" Warning: This makes the fairly safe assUlI\ptian that
" mbufs have even lengths.
"I

«

ifo->if addr - * (struct sockaddr ,,) sin:
ifp->if-net - in netaf(sin->sin addr);
Up-> U-ho st [0] :; in Inaof(sin->sin addr);
sin - (struct sackaddr in *) &ifp->if braadaddr;
sin->sin family - AF lNET;
sin->sin-addr - if makeaddr(ifp->if net, INADDR_AN'f);
ifp->U_flags 1- IFF_BROADCAST;
-

if me.c

Fri Sep

5 19:09:28 1986

6

iget.c

Fri Sep

5 19:07:51 1986

1
if( (ip->i flag&IMOUNT) != 0) {
ior(mp = &mount[O]; mp < (struct mount *)v.ve_mount; mp++)
if (mp->m inodp - ip) {
dey = mp->m dev:
ino - ROOTINO;
if (ip ..., mp->m mount)
goto found:
else
goto loop;

1* @( t I iget. c
1. 4 * 1
tinclude "sys!param.h"
tinclude "sys/types .h"
tinclude "sysl sysmacros. hOI
tinclude "sys/systm.h"
tinclude "sys/sysinfo.h"
tinclude "sys/mount .h"
tinclude "sys/dir.h"
tinclude "sys/signal.h"
tinclude "sys/user.h"
tinclude "sys/errno.h"
tinclude "sys/inode .h"
tinclude "sys/file.h"
tinclude ·sys/ino.h"
tinclude ·sys/filsys.h"
tinclude ·sys/buf.h"
tinclude ·sys/var.h n

panic("no imt");
}

ip->i count++;
ip->Cflag 1= ILOCK;
return (ip) ;

inoinit ()

1*
*
"
"
"
"

{

Look up an inode by device, inumber.
If it is in core (in the inode structure), honor the locking protocol.
If it is not in core, read it in from the specified device.
If the inode is mounted on, perform the indicated indirection.
In all cases, a pointer to a locked inode structure is returned.

" printf warning: no inodes -- if the inode structure is full
" panic: no imt -- if the mounted filesystem is not in the mount table.
"cannot happen u

"I
tdefine NHINO
128
1* must be power of 2 *1
(&hinode[ (int) (X) & (NHINO-1)])
tdefine ihash (X)
struct hinode {
struct inode
} hinode [NHINO] ;
struct inode *ifreelist;
struct inode "
iget (dev , ino)
dev_t dey;
ino_t inc;
register struct inode *ip;
register struct hinode *hip;
register struct mount *mp;
struct inode *iread () ;

register struct inode *ip;
register short i;
ifreelist - ip = &inode[O];
i = v. v inode - 1 - 1;
do {
ip->i forw - ip+1:
ip++;I while (--i != -1);
tifdef notdef
register i = v.v_inode;
while (--i)
inode [i-1] . i forw - &inode [i];
ifreelist - &inode[O);
tendif
)

struct inode *
iread(ip)
register struct inode *ip:
I
register char *p1, *p2:
register struct dinode "dp;
struct buf *bp:
register short i:
bp = bread(ip->i dey, FsITOD (ip->i_dev, ip->i_number»;

sysinfo.iget++;
loop:
hip = ihash(ino);
for (ip = hip->i forw; ip; ip = ip->i forw)
if (ino
ip->i number && dev ~ ip->i_dev)
goto· found;
if «ip = ifreelist) - NULL) {
printf("Inode table overflow\n");
syserr. inodeovf++;
u.u_error = ENFILE;
return (NULL) ;

==

ifreelist - ip->i forw;
if (ip->i forw - hip->i forw)
ip->i forw->i back - ip;
ip->i back - ("struct Inode *)hip;
hip->I forw - ip;
ip->i dey ~ dey;
ip-> i-number = ino;
ip->i-flag - I LOCK;
ip->i-count++;
ip->i-lastr - 0;
return(iread(ip)) ;

if (u.u error) {- brelse (bp) :
iput(ip) :
return (NULL) ;
I
dp - bp->b un.b dino;
dp += FSITOO(ip=>i dey, ip->i number);
ip->i mode = dp->dI mode;
ip->i-nlink = dp->dI nlink;
ip->Cuid - dp->di uId;
ip->i-gid - dp->dCgid;
ip->i-size = dp->dI size;
p1 - ("char *) ip->i addr;
p2 - (char *) dp->dI addr;
i - NADDR - 1;
do {
*p1++ - 0;
·p1 ++ - "p2++;
*p1 ++ - *p2++;
·p1 ++ - *p2++;
I while (--i !- -1);
brelse (bpJ ;
return (ip) ;

found:
if( (ip->i flag&ILOCK) !- 0) {
lp->i flag 1- I WANT ;
(void) sleep ( (caddr_t) ip, PINOD);
goto loop;

1*
" Decrement reference count of an inode structure.
" On the last reference, write the inode out and if necessary,
" truncate and deallocate the file.

iget.c

Fri Sep

5 19:07:51 1986

2
*pl++

*1

=

I while (--i !=

iput(ip)
register struct inode Kip;

0;
-1);

}

} else {

{

i - NADDR - 1;

if (ip=>i count = 1) {
ip->i flag 1- lLOCK;
if(ip=>i nlink <= 0)
itrunc(ip) ;
ip->i mode - 0;
ip->i-flag 1= IUPD 1 ICHG;
ifree(ip->i_dev, ip->i_nu.T!lber);
J
if(ip->i flag&(IACCIIUPDIICHG)
iupdat (ip, &time, &time):
prele(ip) :
if (ip->i back->i forw = ip->i forw)
ip->i for;->i back - ip->i back:
ip->i forw = ifreelist:
ifreelist = ip:
ip->i flag - 0:
ip->i-number = 0:
ip->i=count = 0;
return:
ip->i count--;
prele("ip) :

1*
* Update the inode with the current time.

*1
iupdat (ip, ta, tm)
register struct inode Kip:
time_t ·ta, *tm:
!
register struct buf ·bp;
struct dinode *dp;
register char *p1:
char *p2;
register short i;
if (getfs (ip->i dev) ->s ron1y) !
if (ip->i_flag&(" IUPD 1ICHG) )
u.u error = EROFS:
ip->i_flag &= - (lACe 1 IUPD 1 ICHG 1 ISYN);
return;
bp - bread(ip->i dev, FsITOD(ip->i dev, ip->i_number):
if (bp->b flags & B ERROR)
brelse {bpI : return:
dp = bp->b un.b dino;
dp += FSITOO(ip=>i de v, ip->i number);
dp->di mode = ip->i mode:
dp->di-nlink .. ip->i nlink;
dp->dCuid - ip->i uid;
dp->dCgid = ip->Cgid;
dp->di-size .. ip->i size;
p1 .. (Char .) dp->di- addr;
p2 = (char *) ip->i addr;
if «ip->i modeUFMT) --IFIFO)
i :; NFADDR - 1;
do {
if (*p2++ != 0)
printf("iaddress > 2"24\n");
"pI ++ - *p2++;
"pI+'" - "p2t+;
*pl ++ - *p2++;
} while (--i !- -1);
i - NADDR - NFADDR - 1;
i f (i >- 0) {
do I
*pl++
0;
'p1t+ .. 0:

do {

if(*p2++ != 0)
printf("iaddress > 2"24\n");
·p1++ = *p2++;
"p1 ++ - ·p2++;
*p1 ++ = "p2++;
} while (--1 !- -1):

J
if (ip->i flagUACC)
dp->di atime = *ta:
if (ip->i flag&IUPD)
dp->di mtime = *tm:
if (ip->i flag&ICHG)
dp->di ctime = time;
if (ip->i flag&ISYN)
b;rite(bp) :
else
bdwrite (bp) ;
ip->i_flag &= -(IACCI IUPDI ICHGI ISYN);

I"
" Free all the disk blocks associated with the specified inode structure.
• The blocks of the file are removed in reverse order. This FlLO
" algorithm will tend to maintain
* a contiguous free list much longer than FIFO.
*1
itrunc(ip)
register struct inode Kip;
!
register i;
dev t dev:
daddr_t bn;
i = ip->i mode & IFMT;
i f (i!=IFREG && i!-IFDIR)
return:
dev = ip->i dev:
for (i=NADDR=I: i>-O: i--) {
bn = ip->i addr[i]:
if(bn =
(daddr_t) 0)
continue:
ip->i_addr[i] = (daddr_t) 0:
switch (i) (
default:
free (dev, bn);
break;
case NADDR-3:
tloop(dev, bn, 0, 0);
break;
case NADDR-2:
tloop(dev, bn, 1,
break;

0);

case NADDR-1:
tloop(dev, bn, 1, 1);

ip->i size - 0;
ip->i=flag 1- IUPDIICHG;
tloop(dev, bn, fl, f21
dev t dev;
daddr t bn;
{
register i;
reqister st~uct pUf *bp:

Fri Sep

iget.c

5 19:07:51 1986

register daddr t *bap;
daddr_t 00;
bp - NULL;
for (i=FsNINDIR(dev)-I; i>=O; i--) {
if (bp -- NULL)
bp - bread(dev, bn);
if (bp->b flags & B ERROR)
brelse (bp) ;return;

}

00 - bap[i];
if(OO~ (daddrt)O)
continue;
if(fl)

(

brelse (bp) ;
bp = NULL;
tloop(dev, 00, f2, 0);
) else
free(dev, 00);
)

if(bp != NULL)
brelse (bp) ;
free(dev, bnl;

1*
* Make a new file.
*1
struct inode *
maknode (mode)
register mode;
{

register struct inode *ip;
if «mode&IFMT) - 0)
mode 1- IFREG;
mode &- -u. u cmask;
ip = ialloC(\l.uydir->i_dev, mode, 1);
if lip = NULL) !
iput(u.uydir) ;
return (NULL) ;
)

wdir(ip) ;
return (ip) ;

1*
* write a directory entry with parameters left as side effects
* to a call to namei.
*/
wdir (ip)
struct inode *ip;
(

register struct user *up;
up - &u;
up->u dent. d ino - ip->i number;
up->u=:count :: sizeof(struct direct);
up->u segflg - I;
up->u-base - (caddr t) &Up->u dent;
up->u-fmode - FWRITE;
writeI (up->u pdir);
iput (Up->u_pdir) ;

3

J!"'ri Sep

in.c
/*

in.c

4.3

5 19:09:29 1986

82/06/20

1

*/

1*
tinclude
tinclude
tinclude
Hnclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

* Return the local network address portion of an
internet address; handles class albIc network
number formats.

"sys/param.h"
·sys/config.h a
"sys/errno.h u
·sys/types .h ll
"sys/systm.h"
"net/misc. h M
"net/mbuf .h M
"net/protosw.h"
"netl socket. hOI
"net I socketvar. h"
"net/in.h"
"net/in_systm.h"
"net/if.h"
"net/route .h"
"net/af.h"

*
*

*1
u long
in_lnaof(in)
struct in_addr in;

return ! IN_ LNAOF (in) ) ;

I"
" Initialize an interface's routing
" table entry according to the network.
" INTERNET SPECIFIC.

"I

tifdef INET
inet hash(sin, hpj
register struct sockaddr in *sin;
struct afhash *hp;

if rtinit (ifp, flags)
register struct ifnet "ifp;
int flags;

tifdef ELEVEN
long 1;
1 ~ in netof(sin->sin addr);
hp->afh nethash ~ «int) 1 ~ (int) (1)>16)) & 077777;
1 - sin=>sin addr. s addr;
hp->afh hosthash = «int) 1 ~ (int) (1)>16)) & 077777:
i f (hp->afh hosthash < 0)
hp->afh_hosthash = -hp->afh_hosthash:
tendif
hp->afh nethash - in netof (sin->sin addr):
hp->afh=hosthash = ntohl (sin->sin_addr. s_addr);

inet_netmatch(sin1, sin2)
struct sockaddr_in "sin1, *sin2;

1*

* Formulate an Internet address from network + host.
* building addresses stored in the ifnet structure.

*1
struct in addr
if_mkaddr(net, host)
u_long net,host;

addr - htonl (host) I net;
return (" (struct in_addr *) &addr);
}

1* bi11n -- for transition * I
tundef if_makeaddr(x,y)
struct in addr
if makeaddr (n, h)
u_long n, h;
return (if_mkaddr (n, h»);

1*
* Return the network number from an internet
* address; handles class albIc network t' s .

.,

u long
in_netof(in)
struct in_addr in;
return (IN_NETOF (in»);

Used in

struct sockaddr_in sin;
if (ifp->if_flags & IFF_ROUTE)
return;
bzero «caddr t) &sin, sizeof (sin);'
sin. sin family - AF INET;
sin.sin-addr = if makeaddr«u long)ifp->if net, (u long)O);
rtinit«struct sockaddr *)&sin, &ifp->if_addr, flags);
)

tendif

in cksum.c
tinclude
tinclude
tinclude
tinclude
tinclude
'include
tinclude
tinclude
tinclude

Fri Sep

5 19:09:29 1986

1
if (mlen) {
w. wchar [1] = *cptr++;
result +- w.wword;

"sys/param.h"
"sys/config .h"
"sys/errno.h"
"sys/types .h"
"sys/systm.h"
"net/misc.h"
Rnet/mbuf .h"
"net/in.h"
"net/in_systm.h"

tdefine M68000
fdefine bswap (x)

else

1* note wasodd still set */
goto nextbuf;
/* next mbuf *1
wasodd - 0;
goto nextbuf;

1* next mbuf */

« « (int) (x» »8) &Oxff) ! « «int) (x!) &Oxff) «8)!
1* main line ... check odd byte count *1
if(mlen & 01) {
thisodd++;
mlen--;
if (mlen = 0)
goto lastbyte;

1*
* Checksum routine for Internet Protocol family headers.
* This routine is very heavily used in the network
* code and should be rewritten for each CPU to be as fast as possible.
* billn: This shows the main outline for a prospective algorithm on
a prospective machine.
I suppose one could try to outline
general guidelines for writing this routine, ie, if the machine
is byte-swapped, etc, etc. In practice, what one does is find
a machine which is known to conform to the "standard" and
beat on the code of the new machine till it works with the
known ok machine.
*1
in ckodd;
/* int
1* number of calls on odd start add *1
/* int
in:::ckprint - 0;
1* print sums */
1* 68k */
union 101 {
unsigned short wword;
unsigned char wchar [2] ;

1* make wc a word count *1
mlen »= 1;
1*
" this is the main loop of the algorithm.

*1
mlen -- 1;
do {
result += *ptr++;
) while(--mlen !- -1);
i f (thisodd) {
lastbyte:
wasodd++;
cptr - (char *) ptr;
w.wchar[O] - *cptr++;

);

else
in_ cksum (m, len)
register struct mbuf *m;
register short len;

wasodd - 0;
nextbuf:
i f (len <- 0)
break;
m = m->m next;

{

register unsigned short *ptr;
1* "unsigned" is important... *1
register short rolen - 0;
register long result = 0;
register unsigned short r;
register char " cptr;
register unsigned short wasodd;
register unsigned short thisodd;
union 101 101;
extern short tcpcksum;
extern short ipcksum;

1*

-

* Locate the next block with some data.

*1
for

(;;l

{

i f (m -

0)

{

printf("cksum: out of data\n");
goto done;
if (m->m len)
break;
= m->m_next;

1*

m

if (in_ckprint) printf("ck m%o l%o",m,len);

*1
if (!tcpcksum) Ii< not checksumming? *1
if (! ipcksum)
return 0;
wasodd - 0;
for (;;) {

1*
" Each trip around loop adds in
" words from one mbuf segment.

*1
thisodd - 0;
ptr = mtod (m, unsigned short *);
mlen - m->m len;
if (len < mIen)
mIen - len;
len -- mlen;
if (mIen> 0) !
if (wasodd)
1* "last mbuf odd" code ... */
cptr = (char ")ptr;
w. wchar [1] - "cptr++;
result +- w.wword;
while (--mIen) 1
w.wchar [0] - -cptr++;
mlen--;

)

i f (wasodd)
101 .wchar [1] = 0;
result +- w. wword;

done:
i f (r - (result» 16»
{
result &- Oxffff;
result +- (unsigned) r;
goto done;

1*
if (in_ckprint) printf(" s%o\n",-result);
*/
ret'.lrn «- ({unsigned short I result II & Oxffff);

Fri Sep

in.....pcb.c
1*
1*

inycb.c

"8/27/84

4.28

82/06/20

5 19:09:30 1986

1

*1

if (ifnet = 0)
return (EADDRNOTAVAIL);
if (sin) {
if (sin->sin_family != AF_INET)
return (BAFNOSL'PPORT);
if (sin->sin addr.s addr) {
int tport =-sin->sinyort;

wrn In inycbattach, protection check excludes case where port - 20
thus allowing ftp to create data sockets. This is a hack, but
the decision was made not to put in the setreuid system call for
now.

*1
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

"sys/param.h"
"sys/config .h"
"sys/errno.h"
Usys/types. h"
"sys/sysmacros.h"
"sysl systm.h"
"sys/sysmacros.h u
"sys/dir.h"
·sys/signal.h"
"sys/user. h n
"net/misc.h"
"net/mbuf.h"
"net 1 socket. h"
"netl socketvar. h"
·net/in.h"
anet/in_systm.h u
"net/if .h"
"net/route .h lO
"net/inycb.h"
"net/protosw. h"

sin->sinJX>rt - 0;
1* yech ... *1
if (if_ifwithaddr «struct sockaddr ") sin) - 0)
return (EADDRNOTAVAIL);
sin->sinJX>rt - tport;
lport = sin->sinJX>rt;
if (lport) {
u short aport = lport;
ii;:t wild - 0;
Hfndef WATCHOUT
aport = htons (aport) :
tend if

1* GROSS *1
if (aport < IPPORT RESERVED && u.u_uid !-

" Routines to manage internet protocol control blocks.

* At PRU_ATTACH time a protocol control block is allocated in
" inycballoc() and inserted on a doubly-linked list of such blocks
* for the protocol. A port address is either requested (and verified
" to not be in use) or assigned at this time. We also allocate
* space in the socket sockbuf structures here, although this is
" not a clearly correct place to put this function.

MSGET(inp, struct inpcb ,1);
if (inp = 0)
return (ENOBUFS);
if (sbreserve (&So->so_snd, sndcc)
0)
goto bad;
if (sbreserve(&so->so_rcv, rcvcc)
0)
goto bad2:
inp->inp head = head:
if (sin)inp->inp laddr - sin->sin_addr;
if (lport -- 0) do {
if (head->inp lport++ < IPPORT RESERVED)
head->inp lport - IPPORT RESERVED;
lport - htons (head->inp lport); ) while (in pcblookup(head,
-zeroin addr, 0, inp->inp laddr, lport, 0»;
inp->inp lport - lport:
inp->inp-socket = so:
insque (inp, head):
so->soycb ~ (caddr_t) inp;
return (0);

" A connectionless protocol will have its protocol control block
* removed at PRU_DETACH time, when the socket will be freed (freeing
" the space reserved) and the block will be removed from the list of
" blocks for its protocol.
" A connection-based protocol may be connected to a remote peer at
* PRU_CONNECT time through the routine inycbconnect II . In the normal
* case a PRU_DISCONNECT occurs causing a in pcbdisconnect () .
* It is also possible that higher-level routines will opt out of the
* relationship with the connection before the connection shut down
" is complete. This often occurs in protocols like TCP where we must
* hold on to the protocol control block for a unreasonably long time
" after the connection is used up to avoid races in later connection
" establishment. To handle this we allow higher-level routines to
" disassociate themselves from the socket, marking it ss USERGONE while
" the disconnect is in progress. We notice that this has happened
* when the disconnect is complete, and perform the PRU DETACH operation,
" freeing the socket.
bad2:

sbrelease(&so->so_snd) :

" TODO:
bad:

MSFREE (inp):
return (ENOBUFS):

"I
I"
" Allocate a protocol control block, space
" for send and receive data, and local host information.
" Return error. I f no error make socket point at pcb.
"I
in_pcbattach(so, head, sndcc, rcvcc, sin)
struct socket "so;
struct inpcb "head;
int sndcc, rcvcc;
struct sockaddr_in "sin;
register struct inpcb "inp;
u_short lport - 0;

{

if «so->soyroto->pr_flags & PR_CONNREQUIRED) =
(so->so options & SO ACCEPTCONN) = 0)
wild = INPLOOKUP-WILDCARD:
if (inycblookup(head, zero in addr, 0, sin->sin addr, lport, wild»
return (EADDRINUSE):-

1*

use hashing

0)

if (aport T- 20)
return (EACCES);

1*
" Connect from a socket to a specified address.
" Both address and port must be specified in argument sin.
" If don't have a local address for this socket yet,
" then pick one.
*1
inycbconnect (inp, sin)
., struct inpcb "inp;
struct sockaddr_in "sin;
struct ifnet "ifp;
struct sockaddr_in *ifaddr;

0 II

Fri Sep

inycb.c

5 19:09:30 1986

2

i f (sin->sin family != AF IHET)
return (EAFNOSUPPORT);
if (sin->sin addr.s addr - a II sin->sin_port ~ 0)
return (EADDRNOTAVAIL);
.:~ (inp->inp laddr.s addr =
0) {
ifp -: if ifonnetof«int) (in netof(sin->sin addr»);
if (ifp::" 0) {
-

/*
" We should select the interface based on
* the route to be used, but for udp this would
* result in two calls to rtalloc for each packet
" sent; hardly worthwhile .•.
,,/
ifp - if ifwithaf (AF IHET);
if (ifp
0)
return (EADDRNOTAVAIL);

" protocol specific routine to clean up the
" mess afterwards.

"/
inycbnotify (head, dst, errno, abort)
struct inpcb "head;
reqister struct in addr *dst;
int errno, ("abort) () ;
register struct inpcb *inp, "oinp;
int s - splimp();
for (inp" head->inp next: inp !- head:) {
if (inp->inp::::faddr.s_addr !- dst->s_addr)
next:
inp = inp->inp next;
continue;
-

=-

if (inp->inp socket ~ 0)
gotonext;
inp->inp_socket->so_error - errno;
oinp = inp;
inp .. inp->inp next;
(*abort) (oinp)-;-

)

ifaddr

(struct sockaddr_in *) &ifp->if_addr;

if (inycblookup(inp->inp_head,
sin->sin addr,
sin->sin::Yort,
/* c will pass a structure.
inp->inp laddr. s addr
inp->inp_laddr. s _ addr : ifaddr->sin_addr. s _ addr,
*/
inp->inp laddr. s addr
inp->inp_laddr
ifaddr->sin_ addr,
inp->inp-lport, -

0» { -

return (EADDRINUSE);
}

if (inp->inp laddr.s addr - 0)
inp->inp laddr .. ifaddr->sin addr;
inp->inp faddr = - sin->sin addr;
inp->inp::::fport = sin->sin~rt;
return (0);

splx(s) ;

/"
* SHOULD ALLOW MATCH ON MULTI-HOMING ONLY
*/
struct inpcb "
in pcblookup(head, faddr, fport, laddr, lport, flags)
struct inpcb "head;
struct in addr faddr, laddr;
u short f"Port, lport;
i~t flags;
register struct inpcb *inp, "match .. 0;
int matchwild = 3, wildcard;

inycbdisconnect (inp)
struct inpcb "inp;

for (inp
inp->inp_faddr.s_addr = 0;
inp->inp fport = 0;
if (inp->inp socket->so state & SS_USERGOHE)
in~bdetach (inp) ;
inyCbdetach (inp)
struct inpcb *inp;
struct socket *so

eo

inp->inp_socket;

so->soycb .. 0;
so free (so);
if (inp->inp route.ro rt)
rtfr;e (inp->i~p route. ro rt);
remque(inp);
MSFREE (inp) ;

in_setsockaddr(sin, inp)
register struct sockaddr in * sin;
register struct inpcb *i~p;

a

II inp - 0)
panic ("setsockaddr in");
bzero( (caddr t) sin, sizeof- ("sin»;
sin->sin famIly - AF !NET;
sin->sin~ort .. inp->inp lport;
sin->sin_addr .. inp->inp::::laddr;
if (sin

=eo

= head->inp next; inp != head; inp = inp->inp_next) {
if (inp->inp-lport != lport) .
contInue;
wildcard = 0;
if (inp->inp laddr.s addr != 0)
if (laddr. s ~ddr = 0)
wildcard++ ;
else if (inp->inp laddr. s addr !- laddr. s_addr)
continue; } else
if (laddr.s addr !- 0)
wildcard++;

if (inp->inp faddr.s addr !- 0)
i f (faddr. s ~ddr -= 0)
wildcard++ ;
else if (inp->inp faddr.s addr != faddr.s_addr II
inp->inp fport !- fport)
contInue;
} else
if (faddr. s addr ! - 0)
wildcard++ ;
if (wildcard && (flags & INPLOOKUP WILDCARD) -- 0)
continue;
if (wildcard < matchwild) (
match - inp;
matchwild .. wildcard;
i f fmatchWild == 0)
break;
return (match);

1*

" Pass an error to all internet connections
• associated with address sin. Call the

Fri Sep
/*
ip icmp.c
4.28
tinclude ";ys/param.h"
tinclude "sys/config .hu
tinclude "sys/errno.h"
tinclude "sys/types.h"
tinclude ·sys/systm.h"
tinclude "net/misc.h"
tinclude "net/mbuf .h"
tinclude "net/protosw.h"
tinclude "net/socket.h"
tinclude "net/in. hOI
tinclude -net/in syst.'Tu h U
tinclude "net/ip-:h"
tinclude "net/ip_icmp.h"
tinclude "net/route.h"

5 19:09:31 1986

83/02/22

1
nip->ip len - m->m len + oiplen;
nip->ipy - IPPROro_ICMP:
1* icmp send adds ip header to m_off and m_Ien, so we deduct here *1
m->m off +- oiplen:
icmp::::reflect (nip);

*/

free:
m_freem (dtom (oip) );

static char icmpmap []
-1,

=

{

-1,

-1,

PRC_ UNREACH_ NET, PRC QUENCH,
-1,
-1,-1,

/*
" ICMP routines: error generation, receive packet processing, and
* routines to turnaround packets back to the originator, and
* host table maintenance routines.
*/
int
icmpprintfs - 0;
1*

PRC PARAMPROB,
-1,-

-1,
-1,
-1

PRC REDIRECT NET,
-1,PRC TIMXCEED INTRANS,
-1,-

};

static struct sockproto icmproto = { AF INET, IPPROTO_ICMP };
static struct sockaddr in icmpsrc = { Ai INET };
static struct sockaddr::::in icmpdst - { AF:::: lNET };

1*
* Process a received ICMP message.
*1
icmp input (m)
struct mbuf *m;

*

Generate an error packet of type error
.. in response to bad packet ip.
*/
icmp error (oip, type, code)
struct ip *oip;
int type, code;
register unsigned oiplen = oip->ip_hl «
register struct icmp *icp;
struct mbuf *m;
struct ip "nip;

2;

register struct icmp *icp;
register struct ip *ip = mtod(m, struct ip *1;
int icmplen - ip->ip len, hlen - ip->ip_hl « 2;
int i, (*ctlfunc) () , -type;
extern u_char ipJ)rotox[]:

1*
i f (icmpprintfs)
printf("icmp_error (%x, %d, %d) \n N , oip, type, code);

/*

* Make sure that the old IP packet had 8 bytes of data to return;
.. if not, don't bother. Also don't EVER error if the old
" packet protocol was ICMP.
*/
i f (oip->ip len < 8 II oip->ip_p ~ IPPROTO_ICMP)
goto free;
/*
* First, formulate icmp message
m - m get 1M DONTWAIT, MT HEADER);
*1 m - m get (M DONTWAIT);
i f (m-- 0)goto free;
m->m len = oiplen + 8 + ICMP MINLEN;
m->m-off = MMAXOFF - m->m leii:;
icp :: mtod (m, struct icmp- *) :
icp->icmp type - type;
icp->icmp-void - 0;
i f (type:': ICMP PARAMPROB)
icp->icmp_pptr - code;
code - 0;

icp->icmp code - code;
bcopy( (caddr t)oip, (caddr t) &icp->icmp ip, (int) (oiplen + 8»;
nip - &icp->Icmp ip:
nip->ip len +- oIplen;
nip->ip::::len - htons «u_short) nip->ip_len) ;

* Locate icmp structure in mbuf, and check
* that not corrupted and of at least minimum length.

*1
i f (icmpprintfs)
printf("icmp input from %x, len %d\n", ip->ip_src, icmplen);
if (icmplen < ICMP MINLEN)
goto free;m->m_Ien -= hlen;
m->m off += hlen:
/* need routine to make sure header is in this mbuf here *1
icp - mtod (m, struct icmp ");
i = icp->icmp cksum;
icp->icmp cksUm - 0;
i f (i ! = In cksum (m, icmplen»
priii:tf("icmp: cksum %x\n", i);
goto free;

1*
* Message type specific processing.

*1
i f (icmpprintfs)
printf("icmp input, type %d code %d\n", icp->icmp_type,
icp->icmp code);
switch (i = icp->icmp_typeI (

case
case
case
case
case

ICMP_UNREACH:
ICMP_TIMXCEED:
ICMP_PARAMPROB:
ICMP_REDIRECT:
ICMP SOURCEQUENCH:

1*
/*

* Now, copy old ip header in front of icmp

.. Problem with previous datagram: advise
* higher level routines.

* message. This allows us to reuse any source
* routing info present.

*1

*1
m->m off -- oiplen;
nip :: mtod (m, struct ip *);
bcopy ( (caddr_t) oip, (caddr..-t) nip,

lint) oiplen) ;

icp->icmp ip.ip len - ntohs«u short)icp->icmp ip.ip len);
if (icmplen <
ADVLENMIN II icmplen < ICMP-ADVLEH(lcp»
goto free; i f (icmpprintfs)
printf("deliver to protocol %d\n", icp->icmp_ip.ipJ)J;

roo

Fri Sep

5 19:09:31 1986

2
i f (icrnpprintfs)
printf(lIicrnp send dst %x src %x\n", ip->ip dst, ip->ip src);
(void) ip_output(m, (struct mbuf *)0, (struct rout; *)0, 0); -

type - i - ICMP_PARAMPROB '? 0 : icp->icmp_code;
i f (ctlfunc - inetsw[ipyrotox[icp->icmp_ip.ipy]].pr_ctlinput)
(*ctlfunc) (icmpmap [i] + type, (caddr t) icp);
goto free;
case rCM? ECHO:
icp->icmp type
goto refl;ct;

=

n tLue
iptirne()

I CMP_ECHOREPLY;

{

case ICMP TSTAMP:
if (icmplen < ICMP_TSLEN)
gata free;
icp->icmp_type - ICMP_TSTAMPREPLY;
icp->icmp rtime = iptime();
icp->icmp-ttime = icp->icmp rtime;
goto refl;ct;
-

int s - spl6();
u_long t;

1* systelll 3 ...
t -

*1
1* bogus, do later! */

case ICMP IREQ:
/* fill in source address zero fields! * I
goto reflect;
case ICMP_ ECHOREPLY:
case ICMP_TSTAMPREPLY:
case ICMP IREQREPLY:
if (icmplen < ICMP ADVLENMIN II icmplen < ICMP_ADVLEN(icp»
goto free;icmpsrc. sin addr - ip->ip src;
icmpdst.sin-addr - ip->ip-dst;
raw input (dtom(icp), &icmproto, (struct sockaddr *) &icmpsrc,
("itruct sockaddr *) &icmpdst);
goto free;
default:
goto free;
reflect:
ip->ip len += hlen;
icmp_r;flect(ip) ;
return;

1* since ip_input deducts this */

free:
m_freem{dtom(ip)} :

/*

* Reflect the ip packet back to the source
" TODO: rearrange ip source routing options.

"I
icmp reflect (ip)
struct ip Kip;
struct in_ addr t;
t ~ ip->ip dst;
ip->ip dst- - ip->ip src;
ip->ip- src - t;
icmp_s;nd(ip) ;

1*

* Send an icmp packet back to the ip level,
* after supplying a checksum.
*1
icmp_send(ip)
struct ip "ip;
register int hlen;
register struct icmp *icp;
register struct mbuf *m;
m - dtom(ip);
hlen - ip->ip hl « 2;
icp - mtod (m, - struct icmp ");
icp->icmp cksum - 0;
icp->icrnp-cksurn - in_cksu-'I'.(!!'., :'.p->ip_len - !lIen):
m->m_off
hlen;
m->m_Ien +- hlen;

-=-

(time.tv sec % (24*60*60»

-

*

1000 + time.tv_usec I 1000;

t = (time % SECDAY) * 1000 + lbolt
splx(s) ;
return (htonl (t) ) ;

*

hz;

Fri Sep
1*
ip input.c
1. 6S
tinclude "sys/param.h"
tinclude Hsys/config.h"
tinclude "sys/errno.h"
tinclude "sys/types.h"
tinclude ·sys!syst.'1l.h H
tinclude "net/misc.h"
tinclude Hnet/mbuf . hOI
tinclude "net/protosw.h"
tinclude "net/socket.h Ol
tinclude "net/in.htinclude "net/in systm, hOI
+include "net/ip-:-htinclude "net/ip_icmp.h"

5 19:09:32 1986

next:

1*

*

Get next datagram off input queue and get IP header

* in first !!lbuf.
*1
s = splimp () :
IF_DEQUEUE (&ipintrq, m);
splx(s) ;
if (m = 0)
return;
if (Im->m off> MMAXOFF II m->m len < sizeof (struct ip»
1m - myulluPlm, sizeof (struct ipl» = OJ {
ipstat. ips too small ++;
goto next;-

&&

ip - mtod (m, struct ip *);
if «hlen - ip->ip_hl « 2) > m->m_Ien) {
i f I (m - myullup(m, hlen» = 0)
ipstat .ips_badhlen++;
goto next;

tinclude "net/inycb.h"
tinclude "net/ip var .h"
tinclude "net/tcp.h"
ip protox[IPPROTO MAX];
ip~xlen - IFQ_MAxLEN;
ifnet *ifinet;

int hlen, s;

*/

83/02/23

tinclude "net/if .h"
tinclude "net/route.h"

u char
iii:t
struct

1

ip

=

mtod(m, struct ip *1;

1* first inet interface * I

1*

* IP initialization: fill in IP protocol switch table.
* All protocols not implemented in kernel go to raw IP protocol handler.

i f lipcksum)
if (ip->ip sum - in cksum(m, hlenJ)
ipstat. ips badsum++;
goto bad; -

(

*1
ip init ()
{

-

1*

register struct protosw *pr;
register int i;
pr - pffindproto (PF lNET, IPPROTO_RAW);
if (pr -- 0)
panic("ip init");
for (i = 0; i < IPPROTO MAX; i++)
ip protox[i] - pr - inetsw;
1* billn -= meld with old code
for (pr - inetdomain. domyrotosw:
pr <- inetdomain. domyrotoswNPROTOSW; pr++)
if (pr->pr family - PF lNET &&
pr->pr~rotocol && pr->pryrotocol != IPPROTO_RAW)
ipyrotox[pr->pryrotocol] - pr - inetsw;

*1
for (pr - protosw; pr <- protoswLAST; pr++)
if (pr->pr family - PF lNET &&
pr->pr~rotocol && pr->pryrotocol != IPPROTO_RAW)
ipyrotox[pr->pryrotocol] = pr - protosw;
ipq.next - ipq.prev = &ipq;
1* billn .•.
ip id = time. tv sec & Oxffff;
*1ip id - time & Oxffff;
iplntrq. if~maxlen = ipqmaxlen;
ifinet = if_ifwithaf(AF_INET):

short
struct
struct

ipcksum - 1;
ip * ip reass (I ;
sockaddr_in ipaddr - { AF_INET };

* Convert fields to host representation.
*1
ip->ip_Ien = ntohs «u_short) ip->ip_Ien);
i f (ip->ip len < hlen) {
ipstat.ips badlen++;
goto bad; }

ip->ip_id = ntohs (ip->ip_id) ;
ip->ip_off = ntohs «u_short) ip->ip_off);

1*

*
*

Check that the amount of data in the buffers
is as at least much as the IP header would have us expect.
* Trim mbufs if longer than we expect.
* Drop packet if shorter than we expect.
*1
i = -ip->ip_Ien;
mO - m;
for (;;) {
i +- m->m len;
i f (m->mjiext == 0)
break;

i f (i != 0)

if

< 0)

ipstat.ips tooshort++;
printf(" [iptooshort by 'lid]", i); goto bad;
}

if (i <- m->m len)
m->m_len -= i;
else

1*

* Ip input routine. Checksum and byte swap header. If fragmented
* try to reassamble. If complete and fragment queue exists, discard.
* Process options. Pass to next level.

(
(i

m - mO;

*1
ipintr (I

1*

{

register struct ip Kip;
register struct mbuf Om;
struct mbuf *mO.:
register int i:
register struct ipq • fp;

*
*

Process options and, if not destined for us,
ship it on. ip dooptions returns 1 when an
* error was detected (causing an iemp message
* to be sent).

*1

if (hlen > sizeof (struct ipl

&&

ip_dooptions (ip»

Fri Sep

5 19:09:32 1986

2

goto next;

/*
* Switch out to protocol's input routine.
*/
(*inetsw[ipyrotox[ip->ipyl1 .pr_inputl (m);
goto next;

/*
* Fast check on the first internet
* interface in the list.
*1
if lifinet) {
struct sockaddr_in * sin;

bad:
m_ freem (m) ;
goto next;

sin - (struct sockaddr in *1 &ifinet->if addr;
if (sin->sin_addr.s_addr = ip->ip_dst.s_addr)
goto ours;
sin - (struct sockaddr in *)&ifinet->if broadaddr:
if (Iifinet->if flags & IFF BROADCAST) &&
sin->sin_addr .s_addr ==-ip->ip_dst. s_addrl
goto ours:
/* BEGIN GROT * /
tif NND > 0
tinclude "nd.h"
/*
* Diskless machines don't initially know
* their address, so take packets from them
* if we're acting as a network disk server.
*/
if (ip->ip dst. s addr ~ INADDR ANY &&
(in netoflip-=>ip srcl
INAnDR ANY &&
in-lnaof(ip->ip-src) != INADDR=:ANYI)
- goto ours: fendif
/* END GROT */
ipaddr. sin addr - ip->ip dst;
if (if ifwIthaddrl (struct sockaddr *1 &ipaddr) =
- ip_forward(ip);
goto next;

1*
* Take incoming datagram fraqment and try to
* reassemble it into whole datagram. If a chain for
* reassembly of this datagram already exists, then it
* is given as fp; otherwise have to make a chain.
*/
struct ip *
ip reass lip, fp)
register struct ipasfrag *ip;
register struct ipq *fp;
register struct mbuf *m - dtom (ipl :
register struct ipasfrag *q;
struct mbuf *t;
int hlen - ip->ip hl « 2:
int i, next:
-

/*

0)

{

ours:
/*
" Look for queue of fraqments
" of this datagral:t.
*/
for (fp = ipq.next; fp 1- &ipq: fp = fp->next)
if (ip->ip_id - fp->iIXLid &&
ip->ip_src.s_addr = fp->ipip_dst.s_addr ~ fp->iPipy == fp-> iPip len -= hlen:
( (struct ipasfrag *) ipl->ipf mff - 0:
if (ip->ip off & IP MF)
«struct ip-;;sfrag *)ip)->ipf_mff = 1;
ip->ip_off «- 3:
/*
* If datagram marked as having more fraqments
* or if this is not the first fragment,
* attempt reassembly; if it succeeds, proceed.
*/
i f «(struct ipasfrag ")ip)->ipf mff II ip->ip offl
ip - ip_reass «struct ip-;;sfraq *1 ip, fpl;
if lip -- 01
goto next;
hlen - ip->ip hl « 2;
m - dtom(ip);} else
i f (fpl
ip_fre,ef Ifp) ;

* Presence of header sizes in mbufs
* would confuse code below.
*/
m->m_off += hlen:
m->m_len -= hlen;
/*
* If first fraqment to arrive, create a reassembly queue.
*/
if (fp = 0) {
/* billn -- meld with old
i f «t = m_get (M_WAIT, MT_FTABLEI I == NULL)
*/
if «t - m get (M WAIT» = NULL)
goto dropfrag;
fp - mtod (t, struct ipq *):
insque (fp, &ipql:
fp->iIXLttl = IPFRAGTTL;
fp->iIXLP - ip->ipy:
fp->iIXLid = ip->ip_id:
fp->iIXLnext = fp->iIXLPrev - (struct ipasfrag *1 fp;
fp->iIXL src = « struct ip * 1ipl ->ip_src:
fp->iIXLdst - «struct ip *1 ipl->ip_dst;
q = (struct ipasfrag ") fp:
gato insert;

1*
* Find a seqment which begins after this one does.
*/
for (q - fp->iIXLnext: q !- (struct ipasfrag ") fp; q - q->ipf_nextl
if (q->ip_off > ip->ip_off)
break;

/"

* If there is a preceding seqment, it may provide some of
" our data already. If so, drop the data from the incoming
* seqment. If it provides all of our data, drop us.
"/
i f (q->ipf prev != (struct ipasfraq *) fp) !
i -= q->ipfyrev->ip_off + q->ipfyrev->ip_len - ip->ip_off;
i f (i > 01 (
i f (i >- ip->ip lenl
goto dropfrag;
m adj (dtom(ip), i);
ip->ip off +- i;
ip->i.P::::'len -- i;

Fri Sep

5 19:09:32 1986

3
ip freef(fp)
struct ipq *fp;

/*
" While we overlap succeeding segments trim them or,
+: if they are completel~t covered, dequeue them.
*1
while (q != (struct ipasfrag *) fp && ip->ip off + ip->ip len> q->ip_off) {
i - (ip->ip off + ip->ip len) - q->Ip off;
if Ii < q->Ip len) { q->ip-Ien -- i;
q->ip-off +- i;
m adj(dtom(q), i);
break;

register struct ipasfrag *q, *p;
fp->iP"'"~next;

for (q -

q != (struct ipasfrag *) fp: q

p = q->ipf_next;
ip deq(q);
m_freem(dtorn(q)) :
rernque (fp);
(void) rn_free(dtorn(fp»;

/*
* Put an ip fragment on a reassembly chain.
* Like insque, but pointers in middle of structure.
*/
ip enq (p, prey)
register struct ipasfrag *p, *prev:

q = q->ipf next;
m_freemldt;mlq->ipfyrev» ;
ip_deq(q->ipf_prev) ;
insert:

/*
" stick new segment in its place;
* check for complete reassembly.
*/
ip_enq(ip, q->ipfyrev);
next - 0;
for (q - fp->iPCLnext; q != (struct ipasfrag *) fp; q
if (q->ip_off !- next)
return (0);
next += q->ip_Ien;
i f (q->ipfyrev->ipf_mff)

return

p->ipfyrev = prev;
p->ipf_next - prev->ipf_next:
prev->ipf_next->ipfyrev = p:
prev->ipf_next - p;
=

q->ipf_next) {

/*
* To ip enq as remque is to insque.
*/
ip deq(p)
register struct ipasfrag *p;

(0);

/*

p->ipfyrev->ipf_next - p->ipf_next:
p->ipf_next->ipfyrev - p->ipfyrev;

* Reassembly is complete; concatenate fragments.
*/
q = fp->iPCLnext;
m - dtom(q);
t

=

m->m_next;

m->m_next = 0;
m cat(m, t);
q-- q->ipf next;
while (q
(struct ipasfrag *)fp) {
t - dtom(q):
q = q->ipf_next:
m_cat (m, t):

!=

/*
* Create header for new ip packet by
* modifying header of first packet:
* dequeue and discard fragment reassembly header.
* Make header visible.
*/
ip = fp->ipip len = next;
«struct ip *)ip)->ip src - fp->iPip-dst = fp->iPm_Ien +- sizeof (struct ipasfrag);
m->~off -- sizeof (struct ipasfrag);
return «struct ip *) ip):

/*

* IP ti.lller processing:
* if a timer expires on a reassembly
" queue, discard it.
*/
ip_ slowtimo ()
{

register struct ipq *fp;
int s = splnet();
fp - ipq.next;
0) {
splx(s) ;
return;

i f (fp =

while (fp != &ipq) {
--fp->iPnext;
i f (fp->prev->ipprev) ;
splx(s) ;

Ix
* Drain off all datagram fragments.

dropfrag:
rn_!reem(m) ;
return (0);

while (ipq.next !- ,ipq)
ip_freef(ipq.next) ;

/*

* Free a fragment reassembly header and all
* associated datagrams.
*1

1*

* Do option processing on a dataqram,
* possibly discardinq it i f bad ~ptions

=:

p)

Fri Sep

5 19:09:32 1986

4

" are encountered.

case IPOPT TS TSANDADDR:
if- (ipt->iptytr + 8 > ipt->ipt_Ien)
goto bad;
if (ifinet ~ 0)
goto bad;
1* ??"l *1
* sin++ - « struct sockaddr_in *l&ifinet->if_addrl->sin addr;
break;

*1
ip dooptions (ip)
struct ip *ip;
register u char *cp:
int opt, optlen, cnt, code, type;
struct in addr *sin;
register struct ip_timestamp *ipt;
register struct ifnet *ifp;
struct in_addr t;

case IPOPT TS PRESPEC:
ipiddr. sin addr - * sin;
if (if_ifwIthaddr( (struct sockaddr *) &ipaddr) =
continue;
if (ipt->iptytr + 8 > ipt->ipt_Ien)
goto bad;
ipt->iptytr +- 4;
break;

cp = (u char *) (ip + 1);
cnt ~ (Ip->ip_hl « 2) - sizeof (struct ip);
for (; cnt > 0; cnt -= opt len, cp +- optlen)
opt = cp[O];
i f (opt - IPOPT_EOL)
break;
if (opt - IPOPT NOP)
optlen --1;
else
optlen = cp[l);
switch (opt) {

default:
goto bad;
}

* (n time *) sin = iptime ();
ipt=>iptytr += 4;

default:

return
break;

(0);

bad:

1*
* Source routing with record.
* Find interface with current destination address.
* If none on this machine then drop if strictly routed,
* or do nothing if loosely routed.
* Record interface address and bring up next address
"component. If strictly routed make sure next
* address on directly accessible net.
*1
case IPOPT_LSRR:
case IPOPT SSRR:
if- (cp[2] < 4 II cp[2] > optlen - (sizeof (long) - 1»
break;
sin = (struct in addr *) (cp + cp[2]);
ipaddr.sin addr : "sin;
ifp = if iiwithaddr( (struct sockaddr ") &ipaddr);
type - IeM? UNREACH, code - IeM? UNREACH SRCFAIL;
if (ifp = Ii> {
-if (opt = IPOPT SSRR)
goto bad;
break;
t
ip->ip dst; ip->ip_dst - *sin; *sin = t;
cp[2] +i f (cp[2] > optlen - (sizeof (long) - 1»
break;
ip->ip dst ~ sin[l];
i f (opt IPOPT SSRR &&
if ifonnetof«int) (in netof(ip->ip dst») =
- goto bad;
break;

icmp error (ip, type, code);
return (1);

1*

* strip out IP options, at higher
* level protocol in the kernel.
* Second argument is buffer to which options
* will be moved, and return value is their length.

"I
ip stripoptions (ip, mopt)
struct ip *ip;
struct mbuf *mopt;
register int i;
register struct mbuf "m;
int olen;
olen = (ip->ip hl«2) - sizeof (struct ip);
m - dtom(ip); ip++;
if (mopt) {
mopt->m len - olen;
mopt->moff - MMINOFF;
bcopy«caddr_t)ip, mtod(m, caddr_t), (int)olen);

4;

case IPOPT_TS:
code - cp - (u char *) ip;
type - ICMP PAAAHPROB;
ipt = (struct ip timestamp *) cp;
i f (ipt->ipt_Ien-< 5)
goto bad;
i f (ipt->iptytr > ipt->ipt_Ien - sizeof (long»
i f (++ipt->ipt oflw - 0)
goto bid;
break:
I
sin - (struct in addr *) (cp+cp[2]);
switch (ipt->ipt=:flg) {
case IPOPT_TS_TSONLY:
break;

}

i = m->m len - (sizeof (struct ip) + olen);
bcopy( (ca:ddr_t) ip+olen, (caddr_t) ip, (int) i);
m->m_Ien -- olen;
0)

u_char inetctlerrmap [ ]
ECONNABORTED,

~

{

ECONNABORTED,

0,

0,

0,

0,

EHOSTDOWN,
ECONNREFUSED,

EHOSTUNREACH,
ECONNREFUSED,

ENETUNREACH,
EHSGSIZE,

EHOSTUNREACH,
0,

0,

0,

0,

o

};

{

tifdef notdef
ip ctlinput (cmd, arq)
int cmd;
caddr_t arq:
struct in addr "in;
int tcp abort ( ), udp abort () ;
extern struct inpcb tcb, udb;
if (cmd < 0 I I cmd > PRC_NCMDSI
return;

0)

Fri Sep

5 19:09:32 1986

5

i f (inetctlerrmap[cmd] - 0)
return:
/ * XXX * I
=
PRC IFOOVIN)
in - &«struct sockaddr in *)arg)->sin addr:
else i f (cmd ~ PRC HOSTDEAD 11-cmd - PRC_HOSTUNREACH)
in = (strnct in_addr *)arq;
else
in = &«struct icmp *)arg)->icmp ip.ip dst:
1* THIS IS VERY QUESTIONABLE, SHOULD HIT ALL PROTOCOLS- * /
inJ>Cbnotify(&tcb, in, (int)inetctlerrmap[cmd], tcp abort):
inycbnotify(&udb, in, (int)inetctlerrmap[cmd], udp::::abort):

1* billn - meld with old
case EPERM:
code - ICMP_UNREACH_PORT;
break:

i f (cmd

*1
case ENOBUFS:
type = ICMP_SOURCEQUENCH;
break:
case EHOSTDOWN:
case EHOSTUNREACH:
code = ICMP_ UNREACH HOST;
break;

tendif
int
ipprintfs = 0:
int
ipforwarding - 1;
1*
" Forward a packet. If some error occurs return the sender
" and icmp packet. Note we can' t always generate a meaningful
" icmp message because icmp doesn't have a large enough repetoire
" of codes and types.

sendicmp:
icmp_error(ip, type, code);

"I
ip forward (ip)
register struct ip "ip:
register int error, type, code:
struct mbuf *mopt, *mcopy;
i f (ipprintfs)
printf("forward: src %x dst %x ttl %x\n", ip->ip src,
ip->ip dst, ip->ip ttl):
i f (ipforwarding = O)-{
1* can't tell difference between net and host */
type - ICMP UNREACH, code = ICMP UNREACH NET;
goto sendicliip;
-i f (ip->ip ttl < IPTTLDEC)
tYPe = ICMP TIMXCEED, code - ICMP_TIMXCEED_INTRlINS;
goto sendicliip ;

ip->ip_ttl -- IPTTLDEC;
/* billn -- meld with old
mopt = m get (M DONTWAIT, MT DATA);

*1

-

-

-

mopt = m get (M DONTWAIT);
if (mopt--- NULL) {
m_freem(dtom(ip» :
return:

/*

*
*

Save at most 64 bytes of the packet in case
we need to generate an ICMP message to the src.

*1
1* billn -- imin -> MIN *1
mcopy - m copy (dtom(ip) , 0, MIN(ip->ip_len, 64»;
ip_stripoptions (ip, mopt);

1* last 0 here means no directed broadcast */
if «error - ip output (dtom(ip), mopt, (struct route
i f (mcopy)
m_freem(mcopy) ;
return;
ip - mtod (mcopy, struct ip *);
type - ICMP UNREACH, code = 0;
switch (err-;)r) {
ca se ENETUNREACH:
case ENETDOWN:
code - ICMP_UNREACH_NET;
break;
case EMSGSIZE:
code - ICMP_UNREACH_NEEDFRAG;
break;

*) 0,

0»

1* need "undefined"

-- 0)

*I

{

Fri Sep
1*
ip output.c
1.46
'include "sys/param. hOI
'include "sys/config.h"
'include "sys/errno.h"
'include "sys/types. hOI
finclude ·sys/systa-u..h-'
tinclude "net/misc.h"
tinclude "net/mbuf .h"
tinclude "net / proto sw . h"
tinclude "net/socket.hu
tinclude "net/socketvar .h"
tinclude -errno.h u
tinclude "net/in.h"
tinclude "net/in_systm.h"
tinclude "net/ip.h"
#include "net/ip_icmp. h"

83/02/10

5 19:09:33 1986

1
/*

*/

" If source address not specified yet, use address
* of outgoing interface.
*/
if (in lnaof(ip->ip src) ~ INADDR_ANY)
- ip->ip src.s addr =
«struct- sockaddr_in *) &ifp->if_addrl->sin_addr. s _addr;
tendif

/*
* Look for broadcast address and
* and verify user is allowed to send
* such a packet.
*/
if (in lnaof«(struct sockaddr in *)dst)->sin addrl
- i f «ifp->if_flags & IFF_BROADCAST) ,,;;;;. 0) {
error - EADDRNOTAVAIL;
goto bad;

tinclude "net/iLh"
'include "net/route .h"

if (!allowbroad=st)
error = EACCES;
goto bad;

tinclude "net/ip_var.h"
int

ipnorouteprint - 0;
/* don't allow broadcast messages to be fragmented */
if (ip->ip_len > ifp->if_mtul {
error = EMSGSIZE;
goto bad;

ip_output (m, opt, ro, allowbroadcast)
struct mbuf ,om;
struct mbuf *opt;
struct route "ro;
int allowbroadcast;
register struct ip *ip = mtod(m, struct ip *);
register struct ifnet "ifp;
int len, hlen - sizeof (struct ip), off, error - 0;
struct route iproute;
struct sockaddr "dst;
if (opt)
(void) m_free(opt);

/*
/*

XXX
XXX

/*
* If small enough for interface, can just send directly.

*/
if (ip->ip len <= ifp->if mtu) {
ip=>ip len = htons «u short) ip->ip len);
ip->ip-off - htons ( (u-short) ip->ip- offl ;
ip->ip-sum - 0;
ip->ip-sum = in cksum (m, hlen);
error:; (*ifp->If output) (ifp, m, dst);
goto done;
-

*/
*/

/*
" Fill in IP header.
*/
ip->ip v = IPVERSION;
ip->ip-hl = hlen » 2;
ip->ip-off &- IP DF;
ip->iP=:id = htons (ip_id++);

/*

* Too large for interface; fragment if possible.

*

Must be able to put at least 8 bytes per fragment.
*/
if (ip->ip_off & IP_DF) {
error - EMSGSIZE;
goto bad;

/*
* Route packet.
"/
if (ro = 0) {
ro = &iproute;
bzero( (caddr_t)ro, sizeof (,oro»;
dst ~ &ro->ro dst;
if (ro->ro rt-~ 0)
ro=>ro dst. sa family = AF INET;
«stru~t sockaddr in *) &ro->ro dst) ->sin addr
/*
-

len = (ifp->if mtu - hlen)
if (len < 8) {error = EMSGSIZE;
goto bad;

=

ip->ip dst;
-

" If routing to interface only, short circuit routing lookup.

"/
if (ro -- &routetoif) {
/* check ifp is AF INET1?? */
ifp = if ifonnetof{ (int) (in netof (ip->ip dst»);
if (ifp -:- 0)
goto unreachable;
goto gotif;
rtalloc(ro) ;
J
if (ro->ro rt - 0 II (ifp - ro->ro rt->rt ifp) -- 0)
qoto unreachable;
-ro->ro rt->rt use++;
if (ro=>ro rt=>rt flags & RTF GATEWAY)
dst - &ro=>ro_rt->rt_gateway;
qotif:
fifndef notdef

&-

7;

/*
* Discard IP header from logical mbuf for m copy's sake.
* Loop through length of segment, make a copy of each
* part and output.
*/
m->m_len -- sizeof (struct ip);
m->m off +- sizeof (struct ip);
for (off - 0; off < ip->ip len-hlen; off +- len) {
/* billn - meld with old
struct mbuf *mh - m get (M DONTWAIT, MT HEADER);
"/
struct mbuf *mh - m get (M DONTWAIT);
struct ip "mhip;
i f (mh -- 0) {
error - ENOBUFS;
got a bad;

mh->m_off - MMAXOFF - hlen;
mhip - mtod (mh, struct ip .);

Fri Sep

5 19:09:33 1986

"mhip = *ip;
i f (hlen > sizeof Istruct ip»
{
int olen = ip optcopy (ip, mhip, off);
mh->m_len - sIzeof (struct ip) + olen;
} else
mh->m len = sizeof (struct ip);
mhip->ip off:: off» 3;
i f (off +" len >= ip->ip len-hlen)
len - mhip->ip_len - ip->ip_len - hlen - off;
else {
mhip->ip len = len;
mhip->ip=off I- IP_MF;
mhip->ip len +- sizeof (struct ip);
mhip->ip-len - htons( (u short)mhip->ip len);
mh->m next = m copy(m, off, len);
i f (mh->m next-= 0) {
(;oid) m_free(mh);
error = ENOBUFS;
/* 111 */
goto bad;
mhip->ip off - htons «u short)mhip->ip off);
mhip->ip-sum = 0;
mhip->ip-sum - in cksum(mh, hlen);
i f (error - ("ifp=>if_output) (ifp, mh, dst»
break;
m_ freem (m) ;
goto done;
unreachable:
if (ipnorouteprint)
printf (Hno route to %x (from %x, len %d) \n",
ip->ip dst.s addr, ip->ip_src.s_addr, ip->ip_len);
error - ENETUNREACH;
bad:
done:
if (ro = &iproute && ro->ro rt)
RTFREE(ro->ro_rt) ;
return (error);

/"
* Copy options from ip to jp.
* If off is 0 all options are copied
* otherwise copy selectively.
*1
ip optcopy lip, jp, off)
struct ip Kip, *jp;
int off;
register u char "cp, "dp;
int opt, optlen, cnt;
cp - lu char *) lip + I);
dp = (u-char *) (jp + 1);
cnt - (Ip->ip hI « 2) - sizeof (struct ip);
for (; cnt > (); cnt -- optlen, cp += optlen)
opt = cp[O);
i f (opt - IPOPT_EOL)
break;
i f (opt IPOPT NOP)
optlen =-1;
else
optlen - cp [1);
if loptlen > cnt)
1* xxx *1
optlen - cnt;
1* xxx *1
i f (off = 0 II IPOPT :OP:::ED (opt) )
bcapy«caddr t)Cp, (caddr t)dp, (int)aptlen);
dp +- aptlen7
for (apt1en - dp - lu char *)ljp+l); optlen
*dp++ - IPOPT-EOL;
return (optlen);
-

&

Ox3; optlen++)

2

ipc.c

Fri Sep

5 19:07:52 1986

1
register struct ipcyerm
register int

1* I!!t)ipc.c

1.1 *1
tinclude "sysl errno. h"
tinclude "sys/types .h"
tinclude "sys/param.h"
tinclude "sys/seg.h"
tinclude "sysl signal.hl!
tinclude ·sys/proc.h"
tinclude "sys/dir.h"
tifdef u3b
tinclude "sys/istk.h"
tendif
iinclude "sys/user .hl.
tinclude "sys/ipc.h u

if (key

*a;

i;

~

IPC PRIVATE) {
for(i-- O;i++ < cnt;
base - (struct ipcyerm "l « (char *)base) + size»
if(base->mode & IPC_ALLOC)
continue;
goto init;

u.~error - ENOSPC;
return (NULL) ;
) else {
forti - 0, a = NULL;i++ < cnt;
base - (struct ipcyerm ") « (char *)base) + size»
if (base->mode & IPC ALLOC) {
if (base->key = key) {
iff (flag & (IPC_CREAT
IPC_EXCL»
(IPC_CREAT I IPC_EXCL»
u. u error = EEXIST;
return (NULL) ;

1*
Common IPC routines.

*1
1*
Check message, semaphore, or shared memory access permissions.
This routine verifies the requested access permission for the current
process. Super-user is always given permission. otherwise, the
appropriate bits are checked corresponding to owner, group, or
everyone. Zero is returned on success. On failure, u. u error is
set to EACCES and one is returned.
The arguments must be set up as follows:
p - Pointer to permission structure to verify
mode - Desired access permissions

)

iff (flag

continue;
)

if(a
*p;
mode;

if(u.u_uid - 0)
return(O) ;
if(u.u_uid != p->uid && u.u_uid != p->cuid) (
mode »= 3;
if(u.u gid != p->gid && u.u_gid != p->cgid)
- mode »= 3:

1*
Get message, semaphore, or shared memory structure.
This routine searches for a matching key based on the given flags
and returns a pointer to the appropriate entry. A structure is
allocated if the key doesn't exist and the flags call for it.
The arguments must be set up as follows:
key - Key to be used
flag - creation flags and access modes
base - Base address of appropriate facility structure array
cnt - t of entries in facility structure array
size - sizeof (facility structure)
status - Pointer to status word: set on successful completion
only:
0 -> existing entry found
1 -> new entry created
Ipcget returns NULL with u.u error set to an appropriate value if
it fails, or a pointer to the initialized entry if it succeeds.

"I
struct ipc perm "
ipeget :key~ :laq, base, ent, size, staLl.s)
register struct ipcyerm
"base;
int
cnt,
flag,
size,
"status;
key t
key;
(

-

~

NULL)
a = base;

if (! (flag & IPC_CREAT»
(
u.u_error = ENOENT;
return (NULL) :

(

if (mode & p->mode)
return(O) ;
u.u_error - EACCES;
return(l) ;

& 0777) & -base->mode)
u. u error - EACCES;
retUrn (NULL) ;

"status - 0;
return (base) ;

*1
ipcaccess (p, mode)
register struct ipcJ>erm
register ushort

1* ptr to available entry */
I" loop control "I

if(a -- NULL) (
u.u_error - ENOSPC;
return (NULL) ;
base - a;
init:
*status = 1;
base->mode - IPC ALLOC I (flag .. 0777);
base->key - key;
base->cuid = base->uid - u. u uid;
base->cgid = base->gid = u. ~gid;
return (base) ;

leb.c

E'ri Sep

5 19:09:10 1986

1
kb chrbuf = Esc:
cointr(O) ;
kb chrbuf - , 0' :
cointr(O):
kb chrbuf - a:
cointr(O) :
goto out:

/"
" (e) 1984 UniSoft Corp. of Berkeley CA
" UniPlus Source Code. This program is proprietary
* with Unisoft Corporation and is not to be reproduced
* or used in any manner except as authorized in
* writing by Unisoft.
" Interrupt handler for level 2 interrupts.
keyboard, mouse, real time clock, on/off switch

}

*1

if

=

(a

>=

0)

kb_keytab[i
(

&

/ * send 3-char sequence * /

Ox7F):I* reset to ascii "/

/* ascii '1 *1

kb keycount++;

tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

if-(kb ctrl) a &- Ox1F:
else if (kb keycount - 1) (
kb reptrap = kb repwait:
kb-lastc - a; ) else kb_reptrap = 0;
kb chrbuf = a;
cointr(O) :
goto out;

"sys/param.h"
·sys/types.h"
·sys/mmu.h"
·sys/reg. h"
"sys/local.h"
·sys/cops .h"
·sys/keyboard.h"
·sys/mouse.h"
·sys/ms. h"
·sys/12.h"
·sys/kb.h"

}

} else {

extern struct rtime rtime;
char *kb keytab - ToLA;
char kb_-;;ltkp:

1* are we in alternate keypad mode'1 (set in vt100.c) ,,/

char pportplug;
char msylg, ms_btn;
short ms_row, ms_col;
kbintr ()
{

register char i;
register struct device_e "p - COPSADDR;
register char a, ud;
register int tmp;
extern time_t lbolt:
tifdef SUNIX
extern char kb_getchr: I" flag for polling keyboard "I
tendif SUNIX
a = p->e ifr;
/" Read and save reason for interrupt * /
i f (a & FCAl)
/" keyboard input * /
i - p->e ira;
/" get keyboard/mouse input "/
if (a & PTIMERI)
a = COPSADDR->e tIcl;
/* prime timer */
-/* no character input * /
} else
a = COPSADDR->e tIcl:
/* prime timer */
if (--kb reptrap = 0)
kbrepeat () :
/* possible char repeat */
return;

switch (kb_state) {
case NORMALWAIT:
I" IDLE LOOP *1
/" whether up or down keycode ,,/
ud - i & Ox80:
12 dtrap = lbolt + 12 dtime;
1* reset dim delay */
if- (12 dimmed)
- 1* restore screen intensity */
- l2undim () ;
a - kb keytab[i & Ox7F]:I" convert to ascii "I
i f (ud) (
1* "key went down" bit *1
/* click (); 1* key click *1
if (ARROW(i,a))
/" check arrow keys * /
kb chrbuf = Esc;
I * send 3-char sequence
colntr(O) ;
kb chrbuf =
colntr(O) :
kb_chrbuf - a;
cointr (0) ;
goto out;

*/

}

if (kb altkp) { /" send special sequence for keypad chars *1
- if (a - altkpad[i & Ox7F]) V* is it in the keypad2 *;

/* key went up *1
kb reptrap - 0:
if-(a >- 0) {
if (kb keycount-- < 0) {
- kb_keycount - 0:
goto out;

switch (a & OxF) {
case KB_CTRL:
kb_ctrl - ud: kb reptrap - 0; msintr(M CTL);
goto out;
kb_shft = ud; kbsetcvtab(); msintr(M_SFT);
case KB_SHFT:
goto out:
goto out;
kb lock = ud: kbsetcvtab () ;
case KB_LOCK:
goto out;
printf("[SOFT OFF %x)\n",i):
case KB_OFF:
goto out;
msylg = ud; msintr(M_PLUG);
ms btn ~ ud: msintr(M BUT);
goto out;
case KB_MSB:
goto out;
case KB_PPORT: pportplug = ud:
printf{"[disk1button %xJ\n",i); goto out;
case KB_D2B:
goto out:
printf("[diski %x]\n",i);
printf(" [disk2button %x] \n",i); goto out:
goto out;
printf{"[disk2 %x]\n",i):
if (ud == 0) (
kb_state = MOUSERD;
} else
kb_state - RESETCODE;
goto out;
printf(Hinvalid key [Ox%x] ",i) ;
default:
)

goto out:
case MOUSERD:
/* PICKUP Y axis change in mouse pos */
kb state - YMOUSE;
ms-col- (short)i;
goto out;
case YMOUSE:
/* PICKUP Y axis change in mouse pos "/
kb state - NORMALWAIT:
ms-row - (short) i;
msintr(M_MOVE) :
goto out;
case RESETCODE:
/* special condition */
switch (i & OxFF) {
case KB KBCOPS: /* keyboard cops failure detected */
-printf("KEYBOARD COPS FAILURE\n");
break;
case KB IOCOPS: / * 10 board cops failure detected "/
- printf ("10 BOARD COPS FAILURE\n"):
break:
case KB UNPLUG: /* keyboard unplugged */
- kb chrbuf - , s' &OxIF;
/* cntl S "/
colntr{O) ;
break;
case KB CLOCKT: 1* clock timer interrupt *1
- printf ("Real Time Clock interrupt \n") ;
break;

E'ri Sep

kb.c

5 19:09:10 1986

2

case KB SFTOFF: 1* soft power switch *1
-kb state = SHUTDOw'"N:
prlntf(IIShutting down •.• \nH);
update() :
for (tmp ~ 0: tmp < 500000; tmp++);
12 crate - 2:
12-desired = TOTALDIM: 1* completely blacken screen *1
12ramp(0) :
12ramp(0) ;
1* extreme priority *1
SPL7 ();
12copscmd(SHUTOFF) :
rom monO;
1* return to the ROM l'rtonitor *1
1*NOTREACHED* 1
default: switch (i & OxFO) {
case KB RESERV:
- printf (" [Reserved keycode Ox%x] \n", i);
break:
case KB RDCLK:
-rtime.rtyear = (i & OxF) + 10;
kb_state - CLKREAD;
goto out:
default:
kb_idcode = i;
kb chrbuf - 'q' &Ox1F:
1* cntl Q *1
colntr(O) :
printf(IIKeyboard type Ox%x\nH,i):
}

case

case

case

case

case

case

kb_state = NORMALWAIT:
goto out:
CLKREAD:
rtime.rt_day - «(i&OxFO)>>4)*10 + (i&OxF»*10;
kb_state++:
goto out;
CLKREAD+1:
rtime.rt day +- (i&OxFO) » 4:
rtime.rt:=hour - (i & OxF) * 10;
kb_ state++:
goto out:
CLKREAD+2:
rtL"'lle.rt hour += (i & OxFO) » 4;
rtime.rt:=min - (i & OxOF) * 10:
kb_ state++:
goto out:
CLKREAD+3:
rtime.rt min += (i & OxFO) » 4:
rtime.rt:=sec = (i & OxOF) * 10;
kb_ state++:
goto out;
CLKREAD+4:
rtime.rt sec +~ (i & OxFO) » 4:
rtime . rt:=tenth = i & OxOF:
kb_state = NORMALWAIT:
rtcsettod () ;
goto out;
SHUTDOWN:
goto out:

out:
tifdef SUNIX
if (!ud)
kb_getchr - 0;
tendif SUNIX
I
kbrepeat I)
{

1* reset repeat timeout * 1
if Ikb_keycount -- 1) {
kb chrbuf - kb 1astc;
f* click!); 1* key-click *f
cointr(O) ;
I else

1* reset repeat timeout */

kbsetcvtab ()
(

kb keytab = ccvtab[(kb shft'22:0)+(kb lock'?l:O)];
kb:=reptrap = 0:
-

11.c

5 19:09:10 1986

1

/"

clock (ap) ;

" IC) 1984 Unisoft Corp. of Berkeley CA
* UniPlus Source Code. This program is proprietary
* with Unisoft Corporation and is not to be reproduced
* or used in any rnanJ'J.er except as authorized in
" writing by Unisoft.
" Interrupt handler for level 1 interrupts.
parallel port 0, sony, and video circuit controller

* Since the Parallel Port hard disk interrupt comes in at this level
* as well as the Sony and vertical retrace (clockl we have included
'" this so we may only call the actual interrupt routine when really
* necessary.
*1
finclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
finclude
tinclude
Hnclude
Hnclude
finclude
tinclude
finclude
tinclude
tinclude
tinclude
tinclude
tinclude
finclude
tinclude

"sys/param.h"
"sys/config .h"
"sys/types. h"
"sys/systm.h"
"sys/dir.h"
"sys/signal.h"
"sys/user .h"
"sys/proc.h"
"sys/errno .h"
"sys/file.h"
"sys/tty.h"
"sys/termio.h u
Hsys/conf .h"
·sys/sysinfo.h"
"sys/var.h"
"sys/reg.h"
"setjmp.h"
·sys/mmu.h"




unsigned char msvrcnt;
extern struct msparms mparm;
extern struct proc *msproc;
extern char msblkd;
extern char msvrmsk;
llintr(ap)
struct args "ap;
unsigned char a;
register struct device d "'devp = PPADDR;
register struct device::::e "f = COPSADDR;

I'" read intr flag register *1

a - devp->d ifr;
i f (a & (FCA1 I FTIMER1»

1* set to port number instead of clock value "I
1* built in parallel port xl

ap->a dey - 0;
ppintr(ap);
} else!

i f «f->e irb & FDIR) != 0)
snintr () ;
I" sony interrupt * I
else !
/" verticle retrace interrupt * /
i f {(mparm.mp_flags & MF_VRT) !- 0) !
VROFF - 1;
if (msvrcnt++ >- msvrmsk)
msvrcnt - 0;
i f (msblkd) (
msblkd - 0;
wakeup { (caddr_t) &msblkd);

psignal (msproc, SIGMOUS) ;
VRON
} else {
do {

=

1;

VROFF - 1:
VRON - 1;
} while {(STATUS & S_VRJ -- 0);

Jrri Sep

12.c

5 19:08:40 1986

1

/* tdefine HOWFAR "I
/x

* UniPlus Source Code. This program is proprietary
with Unisoft Corporation and is not to be reproduced
* or used in any manner except as authorized in
* writing by Unisoft.

p->e_irb - 12_bvol «
p->eycr
OxA9;

*

p->e ier - Ox7F;

Level 2 special functions handler
* Used to drive keyboard, speaker, mouse, real time clock, screen contrast,
* and soft on/off circuitry.
* All processing is done through the Keyboard SY6522 (@addr DCOO) with the
* exception of the screen contrast which is sent through the Hard disk 6522.
*1
tinclude
tinclude
tinclude
+include
+include
+include
tinclude
+include
+include
tinclude
+include
tinclude
tinclude
tinclude
tinclude
+include
tinclude
+include
tinclude
+include
tinclude
tinclude

I" bytewide bus connecting to Ilo cops*1

p->e ddra ~ 0;
p->e=:ddrb ~ Ox2E;

* (C) 1984 Unisoft Corp. of Berkeley CA

"sys/param.h"
"sys/config .hu
"sys/types.h"
Usys/systm.h"
"sys/dir.h"
"sys/signal.h"
"sys/user .h"
"sys/errno.h"
·sys/file.h"
"sys/tty.h"
"sys/termio .h"
"sys/conf .h"
"sys/sysinfo.h"
·sys/var.h"
·sys/reg.h H
·setjmp.h"
·sys/mmu.h"
·sys/cops.h H
·sys/local.h"
·sys/12.h"
"sys/kb.h"
"sys/sony.h"

1:

1*
1*
/*
1*
/*
1*
1*
1*

PP parity and speaker are outputs *1
PP reset, CRDY, FDIR, , KBIN: input*1
init moderate speaker volumn *1
Pulse speaker output, handshake */
COPS line, and enable leading edge*1
Make Timer1 continous (i.e. self- *1
reset), enable latching of COPS bus"l
disable all interrupts *1

romid = SNIOB->rol!! id & RQ!of.RlI..5K;

i f «romid (ROMTWIROMSLOW»
II «romid&ROMTW)-O» { 1* slow timer */
p->e t1cl - OxCA:
p->e-tlch - 0x27:
p->e- tlll - OxCA:
p->e- t1lh = Ox27;
} else {
1* fast timer (includes undefined romid-EO) *1
p->e t1cl = Ox7B:
p->e- tlch - Ox63:
p->e- t1l1 - Ox7B:
p->e=:t1lh = Ox63:

I" Enable timerl and COPS bus intr */
1* clear pending interrupt flags ,,/
/* bring to user selected contrast *1

p->e ier - OxC2;
p->e-ifr = Ox7F;
12ramp(0) :

1* This procedure is used to send commands to the Keyboard COPS.
It is VERY timing-dependent. In particular, nothing can be changed
in the part which sets the data direction to out, since this must
happen WHILE CRDY drops to the low state. Interrupts are enabled while
waiting for this because the line can stay high for as long as 2 ms,
although it's typically about 800 microseconds while the mouse is in
use. It only stays in the low state for about 4 microseconds before
returning to Hnot ready".

*1
12copscmd (c)
register char c;

tdefine DIMSCREEN

/* d7 *1

(

1* The contrast control latch is hanging off the Parallel Port VIA but

register
register
register
register
register
int pI;

* is only changed in response to a leve12 timer interrupt. Syncronization
* with the hard disk is necessary since they both use the parallel port data
* bus. This is done by having the disk driver maintain a variable called
* 'ppinuse'. When this variable is zero we can ramp the console contrast.
* otherwise we set ppcontchg and the disk driver will call 12ramp as soon
* as it's convenient.

*1

struct device e *p = COPSADDR:
char *ddra - &p->e ddra:
unsigned short dir-- OxFFFF;
short crdy = 6:
char i:

pI = sp17 ():
p->e aira = c;
asm("
btst
asm("
beq
tdefine chkrdy()

1*
1*
1*
/*
/*

as
a4
d6
d5
d4

*1
*1
data direction (out) */
CRDY bit for btst *1

*1

try:

+include 
extern ppinuse:

1* flag preventing us from setting contrast */

/*

* Setup Keyboard 6522 VIA appropriately. This is mostly magic dependant on
* how the chip is connected to its environment in hardware. This procedure
• is only called once to initialize the interface.

*/

12init ()
{

register struct device_e .p
register char romid;
extern int 12dim () ;

=

COPSADDR;

12_dtime - Ox4650;
12 crate - 1;
12-dtrap - 12 dtime;
12-dimcont - (Ox32 « 2);
12-desired - (ONCONT « 2);
12-defcont = 12 desired & OxF::;
12-contrast - (ONCONT« 2);
tiiiieout(12dim, (caddr tIl, 1);
12 bvol - 4;
12-bpitch - 1000;
12-btime - 6;
kb=:repdlay - 0x20;
kb_repwait - Ox30;

/* power on contrast */

se:'!::! :

chkrdy() ;
chkrdy() ;
chkrdy() ;
chkrdyO;
chkrdyO;
chkrdy() ;
chkrdyO;
chkrdy() ;
chkrdy() ;
chkrdy() ;
chkrdy() ;
chkrdy() ;
chkrdy() ;
chkrdy() ;
chkrdy() ;
chkrdy() ;
asm(".Ll:") ;
splx (pI);
goto try;
asmC".L2:") ;
*ddra - dir;
i - QxlO;

/* load cmd into lORA (no handshake) *1
d5,a5@(1)"):
.L1") :
asm("
btst
asm("
beq

1* wait 'til not ready *1
1* if already low we're too late "I
d5,a5@(1)"); \
.L2")
1* as soon as it's ready (low), go to send */

1* i f still high give up, try again later -f
1* again: *1

/ * restore intr s cause this may take a while -/

*'

1* send:
1* switch dir 68K -> cops (send command) */

.t!'ri Sep

12.c

2

5 19:08:40 1986

do i--; while(i>O);
dir = 0;
*ddra - dir;
splx(pl) ;
tifdef lint
if (crdy) goto send;
tendif lint

/* wait a bit */
/.. reset dir to cops -> 68K

if (c < 12_contrast) 12_contrast -= 4; else 12_contrast += 4;
c - 12 contrast;
12 rcflag - 1;
tiliieout(12ramp, (caddr_t) 1, 12_crate);

*/

skip:
pI = sp17 ();
pp - PPADDR;
tifdef lint
c - (int)pp;
tendif
asm(" bset
asm(U bset
asm(" movb
asm(H movb
asm(" bset
asm(" bclr
asm(" bset
asm(" heIr
asm(" heIr
splx(pl) ;
return;

}

/* ARGSUSED * /
12dim(flg)
extern time_t lbolt;

/* time in ticks */

tifdef DIMSCREEN
if (12_dimmed - 01 {
/* not dimmed already */
if (12 dtrap > Iboltl {
- timeout (12dim, (caddr_tIO, (int) (12_dtrap - Ibolt»;
return;
}

12_desired = 12_dimcont;
12 dimmed = 1;
12ramp(0) ;
tifdef HOWFAR
else printf (lI\nWHAT!! -- 12dim called while screen was dim\n"l;
tendif HOWFAR
tendif DIMSCREEN
}

12undim()
{

tifdef DIMSCREEN
if (12 dimmed !- 0) {
- 12 dtrap = Ibolt + 12 dtime;
ti;;eout (12dim, (caddr- t) 0, 12_dtime) ;
12 desired = 12 defcont;
12-dimmed = 0; 12ramp(O) ;
tifdef HOWFAR
else printf (lI\nWHAT!! -- 12undim called while screen was bright\n");
tendif HOWFAR
tendif DIMSCREEN
}

12 ramp (tflag)
{

register struct device_d *pp;
register int c;
int pI;

/* as */
/* d7 */

switch (tflag)
case 0:

I * who called us * I
1* somebody starting a ramp *1
return;

break;

I" timeout (continue ramp) *;

case 1:
12_rcflag - 0;
break;

1* profile driver (kludge) *1

case 2:
c - 12 desired;
if (c :... l2_contrastl
return;
goto skip;

c - 12_desired;
i'" ,~ == 12_contrastl
return;
if (ppinuse) {
12 rcflaq - 1;
tlmeout(l2ramp,
return;

/*

contrast desired

*/

/ * finished "I

I * contrast desired * I
/* finished * I
1* port busy, try again in 50 ms *1
(cadd!'_-:n, 1); /* try again next clock tick

.1

t2,aS@(Oxll) II);
t2,aS@(l) II);
tOxff,aS@(Ox19) It);
d7,aS@(9) ");
t7,aS@(Oxll) H);
t7,aS@(l) H);
t7,aS@(l) It);
t7,aS@(Oxll) ");
t2,aS@(l) II);

linesw.c

Fri Sep

5 19:08:59 1986

/*
" Line Discipline switch table
*/
finclude ·sys/conf .h"
extern nulldev () ;
extern ttopen (), ttclose (), ttread (), ttwrite (), ttin (), ttout () ;
struct linesw linesw [1 = {
/* 0 *1 ttopen, ttclose, ttread, ttwrite, nulldev, ttin, ttout, nulldev,
};

int

linecnt

=

1;

1

Fri Sep

1ock.c

5 19:07:52 1986

1
return (1) ;

1* @(t) lock. c
1. 2 "I
tinclude "sys/param.h"
tinclude "sys/types .h"
tinclude "sys/mrnu.h"
tinclude "sys/proc.h"
tinclude "sysidir .h Oi
.include ·sysl siqna1. hOI
tinclude "sys/user.h"
.include "sys/errno.h"
.include ·sys/text. hOI
tinclude ·sys/lock.h H
lock()
{

struct a {
long oper;
);

i f (! suser () I
return;
switch! «struct a *)u.u_ap)->oper) {
case TXTLOCK:
if ! (u.u_lock& (PROCLOCKITXTLOCK»
II textlock() goto bad:
break:
case PROCLOCK:
if (u. u lock& (PROCLOCK I TXTLOCK»
-goto bad;
(void) textlock();
proclock () ;
break;
case DATLOCK:
i f (u.u_lock& (PROCLOCKIDATLOCK»
goto bad;
u.u_lock 1- DATLOCK;
I" NOP for VAX *1
break:
case UNLOCK:
i f (punlock() = 0)
goto bad;
break;

default:
bad:
u.u_error

= EINVAL;

textlock()
{

if (u.uyrocp->p_textp == NULL)
return(O) ;
u. u_lock 1= TXTLOCK;
return (1) ;

tunlock()
{

i f (u.uyrocp->p_textp return;
u. u_lock &- -TXTLOCK;

NULL II

(u.u_lock&TXTLOCK) ==

proclock()
(

u.u_procp->p_flag !- SSYS;
u. u_lock 1- PROCLOCK;
punlocil.( )
{

i f «u.u_lock, (PROCLOCKI TXT LOCK IDATLOCK) ) -return(O) ;
u. u_procp->p_flag ,- -SSYS;
u. u lock &- -PROCLOCK;
u. u-loCk ,- -DATLOCK;
tllniockl);

0)

0)

0)

Fri Sep

locking.c
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

5 19:07:53 1986

1
* for locks in the range by
,. this process

"sys/param.h"
"sys/types. hOI
"sys/sysmacros .h"
·sys/systm.h"
"sys/sysinfo.h"
IIsys/mount .h"
"sys/dir .h"
"sys/signal.h"
"sys/user.h"
"sys/errno.h"
·sys/inode.h"
"sys/file.h"
·sys/ino.h"
·sys/filsys.h"
"sys/buf .h"
·sys/var .h"
"sys/proc.h"
"sys/locking.h n

*1
cl - (struct locklist *)&ip->i locklist;l* addr is pointer *1
while(nl - cl->ll_link) {

1*

*

1*

* check for locks in proper range
*1

if ( UB <= nl-> 11_start
break;
if( nl->ll_end <= LB )
cl - nl;
continue;

1*

* file lock routines
* John Bass, PO Box 1223, San Luis Obispo, CA 93401
* Original design spring 1976, CalPoly, San Luis Obispo
* Deadlock idea from Ed Grudzien at Basys April 1980
* Extensions Fall 1980, Onyx Systems Inc., San Jose
* Linted and ported to System V by UniSoft Systems, Berkeley, CA.
*/

tdefine MAXSIZE (long) (lL«30)

if not by this process skip to next lock

*1
if(nl->llyroc != u.u_procp)
cl - nl;
continue;

1*

* for locks fully contained within

*

requested range, just delete the item
*/
if( LB <- nl->ll start && nl->ll end <= UB)
Cl->ll_lInk = nl->ll_link;
lock free (nl);
continue;
I

/* number larger than any request *1

struct locklist *deadlock!);
/*
,. locking -- handles syscall requests

1*
* if some one is Sleeping on this lock
* do a wakeup, we may free the region
* being slept on

*1
locking!) (
struct file *fp;
struct inode "'ip;

*1
if(nl->ll flags & IWANT) {
nl->ll flags &= -IWANT;
wakeup! (caddr_t)nl);

1*
" define order and type of syscall args

*1

1*
*
*
*
*

register struct a
int fdes;
int flag;
off t size;
*uap - (struct a *)u.u ap;
register struct locklist-*cl, *nl;
off_t LB, UB;

middle section is being removed
add new lock for last section
modify existing lock for first section.
if no locks, return in error

*1
if ( nl->ll start < LB && UB < nl->ll end) {
if! lOCkadd(nl,UB,nl->ll_end) ) return;
nl->ll_end - LB;
break;
I

1*
'" check for valid open file
*/
fp - getf(uap->fdes);
if(fp - NULL) return;
ip = fp->f inode;
if «ip->i:::mode&IFMT) == IFDIR)
u. u_error - EACCES;
return;

/*
* first section is being deleted
* just move starting point up
*/
if( LB <- nl->ll_start && UB < nl->ll_end)
nl->ll_start = UB;
break;
I

1*

* must be deleting last part of this section

/*

* validate ranges
* kludge for zero length

* move ending point down
* continue looking for locks covered by upper
* limit of unlock range

*/
LB = fp->f offset;
if ( uap->sIze ) {
UB ~ LB + uap->size;
if (UB <- 0) UB - MAXSIZE;

*1
nl->ll_end
cl - nl;

=

LB;

1*
else UB

=

MAXSIZE;

1*

,. e:1.d of scan for '.mlock
*1
return;

~equest

* test for unlock request

*1
if(uap->flag - 0)
1*
* starting at list head scan

1*
" request must be a lock of some kind
* check to see if the region is lockable by this
" process

Fri Sep

locking.c

5 19:07:53 1986

2
J
/*

*1
if (locked (uap->flag, ip, LB, UBI) return;
cl - (struct locklist *)&ip->i 10cklist;l* note addr is pointer *1

1*

* end point set above may overlap later entries

*

-

* simple case, no existing locks, simply add new lock

while { (nl=cl=->ll_link) != }.TTJLL) {

*1
if(

/*

(nl~cl->ll

link) - NULL) {
(void) -lockadd(cl, LB, UB);
return;

* if we found lock by another process we must
* be done since we validated the range above
*/
if(u.uyrocp !~ nl->llyroc) return;
/*
* if the new endpoint no longer overlaps were done
*/
if(cl->ll end < nl->ll_start) return;
/*
" if the new range overlaps the first part of the
* next lock, take its end point
1< and delete the next lock
* we should be done
*/
i f (cl->l1 end <= nl->ll end) {
cl->ll end = nl=>l1 end;
CI->ll~)ink - nl->ll_link;
lock free (nl) ;
return;

/*

* simple case, lock is before existing locks,
* simply insert at head of list

*1
if ( UB < nl->ll start ) {
(void) 10ckadd(cl,LB,UB);
return;
/*

*

if so delete or modify them to perform the compaction

*1

ending range of lock is same as start of lock by

* another process, simply insert at head of list
*/
if( UB <- nl->ll_start && u.uyrocp != nl->llyroc ) {
(void) lockadd(cl, LB, UB);
return;

1*

* request range overlaps with begining of first request
* modify starting point in lock to include requested region

/*

* the next lock is fully included in the new range
* so it may be deleted

*1
if( UB >= nl->ll_start && LB < nl->ll_start ) {
nl->ll_start = LB;

*1
cl->l1 link = nl->ll link:
lockfree (nl);
-

1*
* scan thru remaining locklist

*1
cl = nl;
for (;;) {

/*
* locked -- routine to scan locks and check for a locked condition

*1

1*

* actions for requests at end of list
"I
if ( ( nl = cl->ll link ) == NULL ) (

1*

-

locked(flag, ip, LB, UBI
register struct inode *ip;
off t LB, UB;
{

-

* request overlaps tail of last entry
* extend end point

register struct locklist *nl

"I

1*

if! LB <= cl->ll_end && u.uyrocp = cl->llyroc ) (
if( UB > cl->ll_end ) cl->l1_end = UB;
return;
* otherwise add new entry
*/
(void) lockadd (cl, LB, UB);
return;

J
/*

* if more locks in range skip to next
* otherwise stop scan

*1
if( nl->l1_start < LB )
cl - nl;
else
break;

*/
&&

nl->ll start < UB)

-

* skip locks for this process
* and those out of range

*1
if( nl->ll_proc - u.uyrocp II nl->l1_end <= LB) {
nl = nl->ll link;
if (nl ~ NULL) return (NULL) ;
continue;
J

/*
.. must have found lock by another process
* if request is to test only, then exit with
* error code
*/
if (flag>l) {
u.u_error - EACCES:
return (1) ;
/*

/"

• ;:.r upper bOund is ful:;'y reso:;'ved were done
.. otherwise fix end of last entry or add new entry
.. 1
if(UB <- cl->ll end) return;
if(LB <- cl->ll-end " u.u procp -- cl->ll_proc) cl->ll_end - UBi
else [

ip->i_locklist;

* scan list while locks are in requested range

while (nl != NULL

1*
1*

=

-

-

if ( lockadd (cl, LB, UB) ) return;
c;J.. - c.l->ll...liIlk;

*
*

will need to sleep on lock, check for deadlock f::c:-st
abort on error

*/
if (deadlock (nl) !- NULL) return (1) ;
1*
* post want flag to get awoken
* then sleep till lock is released
*1

Fri Sep

locking.c

5 19:07:53 1986

nl->11 flags 1- IWANT;
!void)-sleep( (caddr t)nl, PSLEP);
/*
* set scan back to begining to catch
* any new areas locked
* or a partial delete
*/
nl - ip->i locklist;
/*
* abort if any errors

*1
if (u.u_error)

3
/*
* lockalloc -- allocates free list, returns free lock items
*/
struct locklist *
lockalloc () {
register struct locklist *fl - &locklist [0] :
register struct locklist *nl:
/*
* if first entry has never been used
* link the locklist table into the freelist
*/
if(fl->11yroc ~ NULL) (
fl->llyroc - &proc[O];
for(nl- &locklist[l]; nl < &locklist[(short)v.v_flock]; nl++) {
lock free (nl) :

r~turn'l);

return (NULL) ;

1*
* deadlock -- routine to follow chain of locks and proc table entries
to find deadlocks on file locks.

}

*1

1*

register struct locklist *nl:

* if all the locks are used error exit
*/
if( (nl=fl->11_link) - NULL) (
u. u error = EDEADLOCK:
return (NULL) ;

1*

/*

struct locklist *
deadlock (lp)
register struct locklist *lp;
(

* return the next lock on the list
*/
fl->11 link - nl->11 link;
nl->11:)ink - NULL; return (nl) ;

* scan while the process owning the lock is sleeping

*1
while(lp->11yroc->p_stat - SSLEEP)
/*
* if the object the process is sleeping on is
* NOT in the locktable every thing is ok
* fallout of loop and return NULL

*1

/*

nl ~ Ip->llyroc->p_wlock:
if( nl < &locklist[O] II nl >= &locklist[!short)v.v_flock]
break;

1*

*

the object was a locklist entry

* lockfree -- returns a lock item to the free list
*/
lock free (lp)
register struct locklist *lp:
(

* if the owner of that entry is this

register struct locklist *fl = &locklist [0] :

process then a deadlock would occur
* set error exit and return

/*

*

* if some process is sleeping on this lock
* wake them up
*/
if(lp->11_flags & IWANT) {
Ip->11 flags &~ -IWANT:
wakeup! (caddr_t)lp);

*1
if(nl->11yroc -- u.uyrocp)
u.u_error - EDEADLOCK:
return (nl) ;

/*
* the object was a locklist entry
* owned by some other process
* continue the scan with that process
*1
Ip = nl;

}

1*

* add the lock into the free list
*1

lp->11 link - fl->11_link;
fl->ll::)ink - Ip;

return (NULL);

1*
1*

* lockadd -- routine to add item to list

* unlock -- called by close to release all locks for this process
*/
unlock (ip)
struct inode Kip;

*1

{

register struct locklist *n1;
register struct locklist *cl;

lockadd (cl, LB, UBI
register struct locklist *cl;
off t LB, UBI
( register struct locklist *nl;

1*
cl - (struct locklist *1 &ip->i locklist;
wh:'1e( (n1 = c1->l1link) := N"JLL) {
if(nl->llyroc -- u.uyrocp) (
cl->ll_link = nl->ll_link;
lockfree(nll;

* get a lock, return if none available

*1
nl - lockalloc () ;
if (n1 ~ NULL) (
return(l) ;
}

else cl - n1:

1*
.. link the new entry into list at current spot
.. fill in the data from the args

locking.c

Fri Sep

*1
nl->11 link - cl->11 link;
cl->11=:link = nl;
nl->ll--'proc = u.u--'procp;
nl->ll_start - LB;
nl->ll_t!nd - UBi
return (0) ;

5 19:07:53 1986

4

,t1ri Sep

lp.c

1

5 19:08:41 1986

1* check expansion slot number and type (must be 2-port card) *1
i f (!PPOK(unit) II (slot[PPSLOT(unit)] !- PRO)
{
err:
u.u_error - EIO;
fini:

1*

* (C) 1984 UniSoft Corp. of Berkeley CA

* UniPlus Source Code. This program is proprietary
* with Unisoft Corporation and is not to be reproduced
* or used in any llianner except as authorized in

*

SPLC ();

return:

writing by Unisoft.
}

*

i f «lp

Driver for Centronix Citoh Dot Matrix Printer

*1

&lp_dt[unit])->flag)
goto err;

=

}

tinclude
tinclude
+include
+include
+include
tinclude
+include
+include
+include
tinclude
+include
+include
tinclude
tinclude
tinclude
+include
+include
tinclude

i f (setppint (pro_da [unit], lpintr»
u. u error = ENODEV;
goto fini;

Usys/paral1l.h"
Hsys/config .h"
·sys/types .h"
·sys/sysmacros.h"
·sys/systm.h"
·sys/dir.h"
·sys/signal.h"
·sys/user.h"
·sys/errno.h"
·sys/file.h"
"sys/tty.h"
"sys/termio.h"
"sys/conf.h"
"sysl sysinfo .h"
·sys/var .h"
·sys/reg.h u
"setjmp.h"
·sys/mmu.h"

}

p = pro da [unit] ;
zero = 0;
p->d acr - 0;
/* no output latching */
NO_OP;
p->dycr = Ox6B;
1* set controller CA2 pulse mode strobe */
NO OP;
p->d ddra - -1; /* set port A bits to output *1
NO OP;
I*if (p ~-PPADDR)
from system III
set BSY and OCD to input
p->d ddrb &= Ox5C;
else-xl
p->d_ddrb &- OxDC:
/* two or four port cards *1
NO OP;
p->d_ddrb 1= Ox9C;
1* set port B bits 2,3,4,7 to out *1
NO OP;
p->d irb &- -(DENIDRW);
1* disable buffers */
NO OP;
p->d_irb 1= WCNT;
/* set direction to output * /
NO OP;
p->d_ier = FIRQIFCAl;
1* enable interrupt on busy *1
NO OP;
zero = p->d_irb;

tinclude "sys/cops.h"
tinclude ·sys/pport. h"
extern struct device_d *pro_da [] :
tdefine
tdefine
tdefine
tdefine

LPPRI
LPLOWAT
LPRIWAT
LPMAX

struct Ip {
struct
char
int
int
int
1p_dt[LPMAX] :

1* port is already busy *1

(PZERO+8)
40
100
NPPDEVS

if (zero & oeD) (
1* out of paper'?'? */
printf(lIlpopen: cable disconnect or out of paper\n");
out:

freeppin(p) ;
goto err;

clist 1 outq:
flag, ind:
ccc, mcc, mlc;
line, col;
dey:

if «zero & PCRK) = 0)
/* online?'? */
printf(lIlpopen: (ddrb - %x) offline\n", zero);
goto out;

1*
Ip->flag = (dev & (PORT I CAP I NOCR»
Ip->ind - 4;
Ip->col - 80;
Ip->line = 66;
Ip->dev - dey;
lpoutput (lp, FORM);
SPLO () ;

flag values - PORT, CAP and NOCR bits from minor device

*1
tdefine
tdefine
tdefine
tdefine
tdefine

PORT
CAP
NOCR
ASLP
OPEN

1* which port - 1,2,4,5,7,8 */

OxOF
OxlO
Ox20
Ox40
Ox80

1* only set within driver */
1* only set within driver *1

tdefine physical (d)

«minor (d»

tdefine FORM
014
tdefine NO OP asm(If
char lpflg[LPMAX];

nop If)

I OPEN:

& PORT)
lpclose (dev)
register dev_t dev:
(

/* whether we expect another interrupt

/* ARGSUSED *1
lpopen(dev, mode)
register dey t dey;
(
register unit:
register struct Ip *lp;
register unsigned char zero;
register struct device d *p;
int Ipintr () :
extern char slot [ ] ;

unit - physical (dev);
SPL5 () ;

w/

register unit;
register struct Ip

*Ip;

unit - physical (dev) :
lp - &lp dt [unit] ;
IpoutputIIp, FORM);
SPL5 () ;
while (lpflg [unit])
Ip->flag 1- ASLP:
(void) sleep ( (caddr_t) Ip, LPPRI);
}

freeppin (pro da [unit] ) :
Ip->flag - 0:SPLO ();

Eri Sep

lp.c

5 19:08:41 1986

2
SPL5 () ;
lpintr (lp->dev) ;
SPLO ():
return;
case 010:
i f (lp->ccc > lp->ind)
lp->ccc--;
return;
case' ,.
lp->ccc++;
return;
default:
if (lp->ccc < lp->rncc) {
i f (lp->flag&NOCR)
lp->ccc++;
return;

lpwrite (dev)
register dev_t dev;
{

register unit;
register c;
register struct lp *lp;
unit - physical (dev):
lp - &lp dt [unit] ;
while (u-:-u_count) {
SPL5 ();

while(lp->l_outq.c_cc > LPHIWAT)
lpintr (unit);
lp->flag 1- ASLP;
(void) sleep ( (caddr_t)lp, LPPRI);

(void) putc (' \r', &lp->l_outq);
lp->mcc = 0;

SPLO ();
c = fubyte (u. u base++);
if Ic < 0) { u. u error = EFAULT;
break;

}

i f (lp->ccc < lp->col) {
while (lp->ccc > lp->rncc)
(void) putc("
&lp->l_outq);
lp->rncc++ ;

u.u_count--;
lpoutput (lp, c);

}

(void) putc(c, &lp->l_outq);
lp->rncc++;

SPL5 () ;
lpintr(unit) ;
SPLO () ;

lp->ccc++;

lpoutput(lp, c)
register struct lp *lp;
register c;

lpintr (dev)
register dev;

(

{

register struct lp *lp;
register struct device_ d *p;
register c;

if (lp->flag&CAP)
if(c>-' a' && c<-' z')
c += 'A'-'a'; else
switch (c)
case 'I':
c = '(':
goto esc;
case 'l':
c
'I';
goto esc;
case ",.
c = , \";
goto esc;
case '1':
c
'!';
goto esc;
case '-' .
c = ,"",.
esc:
lpoutput (lp, c) ;
lp->ccc--;
I_I.
c

dev - physical (dev);
i f (lpflg[dev]) return;
lp = &lp dt [dev];
p - pro da [dev];
while (Ic - getc(&lp->l outq»
lpflg[dev] - 1;p->d ira - c;

-

c

=

0) {

}

lpflg[dev] - 0;

i f (lp->l outq.c cc <= LPLOWAT && lp->flag&ASLP) (
lp->flag-&- -ASLP;
wakeup «caddr_t) lp) ;

-

case' \r':
lp->ccc - Ip->i,nd;

30;

while «p->d ifr & FCAl)
i f (=-c <- 0)
return;

-

switch (c)
case ' \t' :
lp->ccc - «lp->ccc+8-lp->ind) & -7) + lp->ind;
return;
case '\n':
lp->mlc++;
if(lp->mlc >= lp->line
c - FORM;
case FORM:
Ip->mcc - 0;
i f (lp->rnlc) {
(void) putc (c, Hp->l outq);
i f (c -- FORM)
lp->mlc - 0;

=

>- 0) {

1* ARGSUSED *1
lpioctl(dev, crnd, arg, mode)
{
}

Fri Sep

machdep.c
I*fdefine HOWFAR
finclude
tinclude
tinclude
tinclude
tinclude
tinclude
-#include
tinclude
tinclude
tinclude
-#include
tinclude
tinclude
tinclude
-#include
-#include
tinclude
tinclude
-#include
finclude
-#include
tinclude

5 19:08:49 1986

1
cp - (caddr_t) (ctob(btoc( (unsigned) &end) +v. v_usize» ;
limit = (caddr_t) «(*«long *)MEMEND» & OxFFFFFEOO)-ctobCl»;

*1

"sys/param.h"
"sys/config.h"
Asys/mmu.h"
·sys/types.h"
"sys/sysmacros.h"
"sys/systm.h"
"sys/dir.h"
"sys/signal.h"
"sys/user.h"
·sys/errno.h H
"sys/proc.h"
"sys/context .h"
·sys/seg.h"
"sys/map.h"
·sys/reg.h"
"sys/psl.h"
·sys/utsname.h"
·sys/ipc.h"
·sys/shm.h"
·sys/var.h"
·sys/scat.h"
·setjmp.h"

-#ifdef HOWFAR
printf("Segment offset - Ox%x, first click at %d(Ox%x) \n\r",
segoff,. keroff, keroff);
printf ("First free memory - Ox%x\n", cp);
printf("Last free memory = Ox%x\n", limit);
printfC"%d clicks available\n",btoc( (int) limit) -keroff);
tendif
for ( ; cp < limit; cp +- ctob(l»
(
clearseg( (int)btoc( (int)cp»;
maxmem++;
cp = (caddr_t) (btoc( (unsigned) &end)+v.v_usize);
mfree (coremap, maxmem, (int) cp) ;
printf (HAvailable user memory is %d bytes\n\r", ctobC (long)maxmem»;
if Cmaxmem> dtocCnswap*MEMFACT»
(
maxmem - dtoc(nswap*MEMFACT);
printf C"Insufficient swap space for available memory. \n") ;
printf ("Largest runnable process is %d. \n", ctob (maxmem) ) ;
if (MAXMEM < maxmem) maxmem

=

MAXMEM;

typedef int
tdefine LOW
(USTART&OxFFFF)
/* Low user starting address *1
tdefine HIGH
«USTART»16) &OxFFFF)
1* High user starting address *1
tdefine MEMFACT 8/10
/* swap space to free memory minimum ratio *1
int

keroff;

/* kernel memory offset *1

segoff; 1* mmu segment offset *1

extern short

1*
* iocheck - check for an 1/0 device at given address
*/
iocheck (addr)
caddr t addr;
(
register int "saved jb;
register int i;
jmp_buf jb;

1*

* Icode is the bootstrap program used to exec init.
*1
short icode [] - {
.=USTART
1*
*1
Ox2E7C, HIGH, LOW+Oxl00,1*
movl
tUSTART+Oxl0 0, sp* I
Ox227C, HIGH, LOW+Ox26, /*
movl
tenvp,al
*1
Ox223C, HIGH, LOW+Ox22, 1*
movl
tarqp,dl
*/
Ox207C, HIGH, LOW+Ox2A, 1*
movl
tname,aO
*1
Ox42A7,
sp@clrl
1*
*1
Ox303C, Ox3B,
movw
t59.,dO
1*
*1
Ox4E40,
trap
to
1*
*1
Ox60FE,
bra
1*
*1
HIGH,
LOW+Ox2A,
1* argp: . long name
*1
0,
0,
1* envp: . long
*1
Ox2F65, Ox7463, Ox2F69, 1* name: .asciz "/etc/init"
*1
Ox6E69, Ox7400

* usraccess - Check a virtual address for user accessibility.
*1
usraccess (virt, access)
long virt;

);

{

int szicode

=

saved jb = nofault;
if (!setjmp(jb» {
nofault = jb;
i - *addr;
i
1;
} else
i - 0;
no fault - saved jb;
return (i) ;
-

/*

sizeof (icode) ;

register prot;

/*

*

SEGl 1 - 1;
/* SEG2_0 - 1;

startup code

/* user context */
/ * user context .. /

1< /

/ * ARGSUSED * I
startup (cudot)

prot - getmmu( (short *) (vtoseg(virt) I ACCLIM» & PROTMASK;
/* printf(Husraccess at Ox%x is Ox%x\n", virt, prot); */
if (prot ~ ASRW II prot - ASRWS II (prot - ASRO && access -- RO»
return(l) ;
return(O) ;

(

extern int nsysseg, dispatch [] :
extern caddr_t end, etext;
extern struct var v;
register caddr t cp, limit;
register long *ip;
for (ip - & «long *) 0) [0]; ip < & «long
*ip = (lon<;) dispatch + (::"on<;) ip;

/*

*)

/*

* free swap memory
*/

0) [NlVEC]; ip++)

* vtop - Convert virtual address to physical.
*/
caddr t
vtop(virt)
register caddr_t virt;
{

long segbase, phys;

rnfree (swapmap, nswap, 1);
keroff - bt,oc, (unsigned) &end) + v. v_usize;

SEG1 1 - 1;
/,* SEG2~0 - 1;

/.. user context * I
1* user context */

machdep.c

Fri Sep

5 19:08:49 1986

2
no fault = saved jb;
return (val) ;
-

segbase - getmmu( (short ") (vtoseg(virt) I ACCSEG» & SEGBASE;
phys - (segbase « VIRTSHIFT) + «long)virt & OFFMASK);
return ( (caddr_t) (phys - ctob(segoff»);

I"
" subyte - store byte into user space.

*1

1*
* fuword - Fetch word from user space.

*1
fuword (addr)
register caddr_ t addr;

subyte (addr, byte)
register caddr t addr;
char byte;
(

jmp buf jb;
int-val, "saved_jb;

{

int val;
jmp buf jb;
int-" saved_jb;

if (addr < (caddr t)v.v ustart II addr >- (caddr_t) v. v_uend)
return (-1);
if «addr - (char ,,) vtop (addr» = (char *) -1)
return(-I);
saved jb = nofault;
if (!setjmp(jb» {
no fault = jb;
*addr - byte;
val = 0;
) else
val - -1;
no fault - saved_jb;
return (val) ;

if (addr < (caddr_tlv.v_ustart II addr+3 >- (caddr_t)v.v_uend)
return (-1);
if «addr = (caddr t)vtop(addr»
(caddr_t)-l)
return (-1);saved jb - nofault;
if (!setjmp(jb» {
no fault - jb;
val = "( int ") addr ;
} else
val - -1;
no fault ~ saved jb;
return (val) ;
-

1*
" copyout - Move bytes out of the system into user's address space.

1*

* fubyte - Fetch byte from user space.

*1
fubyte (addr)
register caddr t addr;
{
register int val;
jmp buf jb;
int-" saved_jb;
if (addr < (caddr t)v.v ustart II addr >- (caddr_t)v.v_uend)
return (-1);
if ((addr = (caddr t) vtop (addr) )
(caddr_ t) -1)
return (-1);saved jb - nofault;
if (!setjmp(jb»
{
no fault - jb;
val - *addr & 0377;
} else
val = -1;
nofau1t = saved_jb;
return (val) ;

"I
copyout (from, to, nbytes)
caddr t from, to;
int nbytes;
int val;
jmp buf jb;
int- * saved_jb;
Hfdef DGETPliT
printf(-copyout:copying %d bytes to user space Ox%x (p=Ox%x) from Ox%x\n",
nbytes, to, vtop(to), from);
tendif
if «int) to+nbytes > v. v uend I I usraccess «long) to, RW) - 0 I I
(to - (char *)vtop(t;» =
(char *)-1) (
printf(Hcopyout fai1ed\n"):
return (-1) ;
saved jb - nofault;
if (!setjmp(jb»
{
no fault - jb;
bIt (to, from, nbytes);
val - 0;
) else
val = -1;
nofault - saved_jb;
return (val) ;

1*

* suword - store word into user space.
*1

suword (addr, word)
register caddr t addr;
int word;
-

1*
* copyin - Move bytes into the system space out of user's address space.

{

jmp buf jb;
int-val, "saved_jb;
if (addr < (caddr t)v.v ustart II addr+3 >- (caddr_t)v.v_uend)
return (-1);
if «addr - (caddr t)vtop(addr»
(caddr_t)-I)
return (-1);saved jb - nofault;
if (!setjmp(jb» {
no fault - jb;
·(int *)addr - word;
val - 0;
) else
val = ,-1;

*1
copyin (from, to, nbytes)
caddr t from, to;
int nbytes:
(

int val:
jmp buf jb:
int- * saved_jb;
Hfdef DGETPUT
printf("copyin:copying 'ld bytes from user space Ox'lx (p-Ox%x) to Ox%x\n",
nbytes, from, vtop(from), to):
tendif
if "int)frp,m+nbytes > v. v_ uend II usraccess ((long) from# RO) --0 I I

Fri Sep

machdep.c

(from - (char *)vtop(from» printf ("copyin failed\n");
return (-1) ;

5 19:08:49 1986
(char *)-1) {

saved jb - nofault;
i f (!-;etjmp(jbli i
no fault - jb;
blt (to, from, nbytes);
val - 0;
} else
val ~ -1;
nofault ~ saved_jb;
return (val);

3
if (bcount ~ 0)
return;
1* valid logical address
*1
addr - laddr;
if (addr & (-SEGMASK»
goto bad;
i - ctos (btoc (bcount) ) ;
while (i-- > 0) {
if «getmmu«short *1 (vtoseg(addrl I ACCLIM» & PROTMASK) !=
ASINVAL) {
tifdef HOWFAR
printf (Uaddr-Ox%x prot-Ox%x\n",
addr, * (short ")vtoseg(addr»;
tendif
goto bad;

1*
" copyseg - Copy one click's worth of data.
*/
copyseg(from, to)
int from, to;

addr += 11«SEGSHIFT);
if «ctos (btoc(v. v_uend» -ctos (btoc Iv. v_ustart» -ctos (up->uytsize)ctos (up->uydsize) -ctos (Up->u_pssize) -ctos (btoc (bcount) » < 0)
goto bad;
ph->u phladdr - laddr;
ph->uyhsize = btoc (bcount) ;
ph->u-Phpaddr - phaddr;
goto out;

if (from ~= to)
return;
blt512(ctob(to), ctob(from), ctob(1»>9);
bad:

1*
* clearseg - Clear one click's worth of data.
*/
clearseg (where)
int where;

1*
printf (llclearseg Ox%x (Ox%x) \nn, where, ctob (where) ) ;
*/
clear I (caddr_ t) ctob (where), ctob (1) ) ;

up->u_error

=

EINVAL;

out:

/* cxrelse(up->uyrocp->p_context); *1
suregO;

1*
* Scan phys array for physical Ilo (raw I/o) transfer verification
*1
chkphys (base, limit)
{

register struct phys *ph;
register i;

1*

*

busaddr - Save the info from a bus or address error.

*/
/* VARARGS *1
busaddr (frame)
struct {
long regs [4];
int baddr;
short fcode;
int aaddr;
short ireg;
frame;

0, ph = ;;u.uyhys[OJ; i < v.v-Phys; i++, ph++)
if (ph->uyhsize !- 0 && base >- ph->u-Phladdr &&
limit < ph->uyhladdr+ctob (ph->u_phsize) )
return (1) ;
return(D) ;

for (i

1*
1*
1*
/*

dO,d1,aD,a1 *1
bsr return address */
fault code *1
fault address *1
I" instruction register * I

u.u_fcode = frame.fcode;
u.u aaddr - frame.aaddr;
u.u=:ireg = frame.ireg;

1*
* dophys - machine dependent set up portion of the phys system call
*1
dophys Iphnum, laddr, bcount, phaddr)
unsigned phnum, laddr, phaddr;
register unsigned bcount;
I
register struct phys *ph;
register struct user *up:
reqi ster unsigned addr:
reqister i;
up - &u;
if (phnum >- v.vyhys)
qoto bad;
ph - &Up->u phys [(short) phnum]:
ph->u phladdr - 0;
ph->uyhsize - 0;
ph->uJ)hpaddr - 0:
s,"regU;

=

/*
* addupc - Take a profile sample.
*1
addupc(pc, p, incr)
unsigned pc;
register struct (
short
*pr base;
unsigned pr-size;
unsigned pr-off;
unsigned pr=:scale;
*p;
union
int w form;
short-s_form[2] ;
1 word;
register short * slot;

1* this is 32 bits on 68000 "/

slot - &p->pr_base[((((pc - p->pr_off) * p->pr_scale) »16) + 1»>1J;
if (Icaddr t) slot >~ (caddr t) (p->pr base) &&
Icaddr-t) slot < (caddr t) I (unsig1led) p->pr base + p->pr size»
if-I (word. II form --fuword«caddr t) slot)) ~- -1) u.u=:prof.pr_scale - 0; ;* turn off */
else (
word. s form [D 1 +- (short) incr;
(void) - BUllord ( (caddr_t) slot, lIord.lI_form):

machdep.c

Fri Sep

5 19:08:49 1986

1*
" backup - Prepare for restart on a bus error.

*1
backup (ap)
register int *ap;
{

register caddr_t pc;
register ins;
extern int tstb;
pc -

(caddr_t)ap[PC] -

2;

ins = fuword( (caddr t)pc);
tifdef HOWFAR
printf("backup: pc, ins, tstb - %x, %x, %x.
", pc, ins, tstb);
tendif
if (ins & Ox8000 && (tstb & OxFFFFOOOO) (ins & OxFFFFOOOO)) {
ap[PC] = (int)pc;
return(ins I OxFFFFOOOO);
return (0);

1* signify we could not back up *1

1*
* sendsig - Simulate an interrupt.

*1
/ * ARGSUSED "I
sendsig (p, signo)
caddr_t p;
{

register unsigned long n;
register int "regp;
short ps;
regp - u.u_arO;
n = regp[SP] - 6;
ps = (short)regp[RPs];
(void) subyte( (caddr tin, ps » 8);
1* high order byte of ps *1
(void) subyte«caddr-t) (n+1), psi;
/* low order byte of ps *1
(void) suword«caddr::::t) (n+2), regp[PC]);
regp(SP] = n;
regp[RPS] &- -PS T;
regp[PC] = (int)p;

I*ARGSUSED* /
clkset (oldtime)
time t oldtime;

-

{

/* use real time clock value instead of oldtime wI
time = rtcdoread ( ) ;

1*
" create a duplicate copy of a process

*1
procdup(p)
register struct proc *p;
{

register aI, a2, n;
n - p->p size;
if «a2 :; malloc(coremap, n»
return (NULL) ;
al = p->p_addr;
p->p addr - a2;
whil; (n--)
copyseg(a1++, a2++);
return (1);

-

NULL)

4

main.c

Fri Sep

5 19:08:18 1986

1

/* tdefine HOWFAR *1

up->uyrocp = p;
up->u cmask = cmask;
up->u-limit - cdlimi t;
up->u::::stack[O) - STKMAGIC;

/* @(t)main.c
1.7 */
tinclude "sys/param.h"
tinclude Hsys/mmu.h H
tinclude "sys/types.h"
tinclude "sysl sysmacros. hOI
tinclude "sys/systm.h"
tinclude "sys/dir.h"
tinclude Hsys/signal.h"
tinclude "sys/user.h"
tinclude ·sys/filsys.h'·
tinclude ·sys/mount.h"
tinclude ·sys/proc.h"
tinclude ·sys/inode.h"
tinclude ·sys/seg.h·
tinclude ·sys/conf .h"
tinclude ·sys/buf.h"
tinclude ·sys/iobuf .h"
tinclude ·sys/tty.h"
tinclude ·sys/var.h"
+include


startupicudot) :

/*
* initialize system tables at priority ?
,,/
for (initp - &init? tbl[O); initp->init_func; initp++)
tifdef HOWFAR

-

printfC"main calling %s\n", initp->init_msg);
tendif
(*initp->init_func) ();

tifdef HOWFAR
printf(nabout to splO\nH);
tendif HOWFAR
SPLO ();
tifdef HOWFAR
printf(-now at level O\n");
tendif HOWFAR

1*

* Initialization code.
* Called from cold start routine as
* soon as a stack and segmentation
* have been established.
* Functions:
clear and free user core
turn on clock
hand craft Oth process
call all initialization routines
fork - process 0 to schedule
- process 1 execute bootstrap

I"

* initialize system tables at priority 0

*1
for (initp - &initO_tbl[O); initp->init_func; initp++)
tifdef HOWFAR
printf("main calling %s\n", initp->init_msg);
tendif
("initp->init_func) ();

tifdef HOWFAR
printf(·main calling iget\n");
tendif
rootdir = iget (rootdev, ROOTINO);
rootdir->i flag &- -ILOCK;
up->u cdir- = iget (rootdev I ROOTINO);
up->u- cdir->i flag &= -ILOCK;
up->u- rdir - NuLL;
up->u::::start = time;

* loop at low address in user mode -- letc/init
cannot be executed.

*1
int
maxmem;
int
minmem;
int
physmem;
int
cputype;
int
"nofault;
struct inode *rootdir;

/*

* create initial processes
* start scheduling task

main (cudot)
(

*1
register struct user *up;
register struct proc *p;
register struct init tbl *initp;
extern char oemmsg [)-: timestamp [ ) ;
extern int cmask, cdlimit;
printf(" (C) Copyright 1983 - UniSoft Corporation\n
printf("%d", cputype '? cputype : 68000);
printfC" Unix System V - August 1983\n\n");
printf("Created %s\n\n", timestamp);
printfC"%s\n", oemmsg);
/*

*

set up system process

"I
up -

&u;

P - &proc [0) ;

t':"f:-_de: NONSCATLOAD

tendif
p->p addr
p->p-size
p->p- stat
p->p-flag
p->p::::nice

- cudot;
- v.v usize;
- SRuN;
1- SLOADISSYS;
- NZER,O;

");

tifdef HOWFAR
printf("main calling newproc\n");
t endif
if (newproc (0»
(
tifdef HOWFAR
printf(lImain calling expand\n");
t endif
expand ( (int) (v.v_usize + btoc(szicode»);
tifdef HOWFAR
printf("main calling estabur\n");
t endif
(void) estabur «unsigned) 0, (unsigned) btoc (szicode),
(unsigned) 0, 0, RO);
tifdef HOWFAR
print f ("main calling copyout \n") ;
t endif
(void) copyout «caddr t) icode,
(caddr_t) (v. v::::ustart+v. v_doffset), szicode);
/*
* Return goes to loco 0 of user init
* code just copied out.
*1
Hfdef HOtfFAR
printf ("main returning to icode\n lt ) ;
t endif
ret~.n;

main.c

Fri Sep

5 19:08:18 1986

2
/*
* Initialize the buffer I/O system by freeing
* all buffers and setting all device hash buffer lists to empty.
*/
binit ()

Hfdef HOWFAR
printf(IImain calling sched\n");
endif
sched() ;

/*
" iinit is called once (from main) very early in initialization.
* It reads the root's super block and initializes the current date
* from the last modified date.

* panic: iinit -- cannot read the super block.

*

Usually because of an 10 error.

*/
iinit ()
{

register struct user *up;
register struct buf *cp;
register struct filsys *fp;
struct inode iinode;
up = &u;
(*bdevsw[bmajor(rootdev) ].d open) (minor (rootdev), FREAD
(*bdevsw [bmajor (pipedev) ].d-open) (minor(pipedev), FREAD
("bdevsw [bmajor (swapdev) ] .d-open) (minor (swapdev), FREAD
cp - geteblk();
fp = cp->b un.b filsys;
iinode. i mode - - IFBLK;
iinode . i - rdev = rootdev;
up->u offset - SUPERBOFF;
up->u-count - sizeof(struct filsys);
up->u=:base - (caddr_t) fp;
up->u segflg = 1;
readi(&iinode) ;
if (up->u error)
pi"nic("iinit a ) ;
mount[O].m bufp = cp;
mount[O].m-flags - MINUSE;
mount[O].m-dev = brdev(rootdev);
i f (fp->sjnagic 1- FsMAGIC)
fp->s type = Fslb;
/* assume old file system
if (fp->s type = Fs2b)
mount[O].m_dev 1= Fs2BLK;
tif FsTYPE == 4
if (fp->s_type =- Fs4b)
mount[O].m_dev 1- Fs4BLK;
tendif
rootdev = mount[Oj.m dey;
if (brdev (pipedev)
brdev (rootdev) )
pipedev - rootdev;
fp->s flock = 0;
fp->s=:iloCk = 0;
fp->s ronly - 0;
fp->s-ninode = 0;
fp->s=:inOde[Oj = 0;

-=

clkset (fp-> s _time) ;

/*
" Initialize clist by freeing all character blocks.
*/
struct chead cfreelist;
cinit ()
{

register n;
register struct cblock *cp;
for(n - 0, cp - 'cfree[Oj; n < v.v clist; n++, cp++l {
cp->c next - cfreelist.c next;
cfreelist.c_next - cp; cfreelist.c_size

=

CLSIZE;

FWRITE)
FWRITE)
FWRITE)

register
register
register
register

struct buf *bp;
struct buf *dp;
unsigned i;
long b;

dp = &bfreelist;
dp->b forw - dp; dp->b back = dp;
dp->av forw = dp; dp->av back = dp;
b - «(long)buffers + (sIzeof(int) - 1» & (-sizeof(int»);
for (i-O, bp-buf; ib_dev = NODEV;
bp->b un.b addr - (caddr t)b;
b += SBUFSIZE;
bp->b back = dp;
bp->b-forw = dp->b forw;
dp->b-forw->b back-= bp;
dp->b=:forw - bp:
bp->b flags - B BUSY:
bp->b-bcount - Q;
brelse (bp) ;

pfreelist.av forw = bp = pbuf;
for (; bp < &pbuf[ (short) (v.vybuf-l)]: bp++)
bp->av forw - bp+l;
bp->av forw - NuLL;
for (i-:O; i < v.v hbuf; i++)
hbUf[(short)i].b_forw - hbuf[(short)i].b_back

*/

=

(struct buf *)&hbuf[(short)i];

malloc.c

Fri Sep

5 19:08:19 1986

1

1*

@(t)malloc. c 1.1 *1
tinclude "sys/param.h"
tinclude "sys/types.h"
tinclude ·sys/systm.h H
tinclude ·sys/map.h"
iinclude "'sysivar.h"
tinclude ·sys/scat.h u

mapsize Imp) ++;
}

) else {
if (a+size = bp->m addr && bp->m_size) {
bp->m addr -== size;
bp->m-size +- size;
} else if (size) {
if (mapsize Imp) - 0) (
printf("\nDANGER: mfree map overflow at map Ox%x\n", mp);
printf!n lost %d items starting at Ox%x\n", size, a);
return;

I"
* Allocate' size' units from the given map.
" Return the base of the allocated space.
,. In a map, the addresses are increasing and the
" list is terminated by a 0 size.
* The swap map unit is 512 bytes.
* Algorithm is first-fit.
*1
malloc (mp, size)
register struct map *mp;

do
t - bp->m addr;
bp->m_addr = a;
a = t;
t - bp->m size;
bp->~size - size;
bp++;
1 while (size = t);
mapsize (mp)--;

(

int n;
if (mp != coremap)
return(domall(mp, size»;
do
if «n

domall (mp, size»
return(n) ;
while (xmrelseO != 0);
return (0) ;
=

!-

0)

tifdef NONSCATLOAD

1*
* Wake scheduler when freeing core

*1
if (mp--coremap) (
if (runin) (
runin = 0;
wakeup ( (caddr_t) &runin);

domall (mp, size)
struct map *mp;
register size;
(

register struct map *bp;
register a;

) else
telse
if (mp != coremap)

for (bp

mapstart (mp); bp->m size; bp++) {
if (bp->m size >= size) (
a- - bp->m addr;
bp->m addr +- size;
if (6;p->m_size -~ size) = 0)
do (
bp++;
(bp-l)->m addr = bp->m addr;
) while «bp-1) ->m size = bp->m size);
mapsize (mp) ++;
-

=

tendif

1*
" wakeup anyone waiting for a map

"I
if (mapwant (mp) i i
mapwant (mp) = 0;
wakeup ( (caddr_t)mp);

1*
return(a) ;

* return the largest size in the given map structure

*1
return (0)

;

mallocl (mp)
struct map *mp;
(

register struct map *bp;
register a;

1*
* Free the previously allocated space aa
* of size units into the specified map.
* Sort aa into map and combine on
* one or both ends if possible.
*I
mfree (mp, size, a)
struct map "mp;
register a;
{

register struct map *bp;
register t;

a - 0;
for (bp-mapstart (mp); bp->m size; bp++)
if (bp->m size > a)a-= bp->m_size;
return(a) ;

tifdef NONSCATLOAD
/*
* malloc size clicks starting at address 'start'

*1
bp - mapstart (mp) ;
for (; bp->m addr<=a && bp->m size!-O; bp++);
if (bp>mapstart Imp) && Ibp-l J -=>m addr+ (bp-l) ->rr. si.ze
(bp-l) ->m size +- size; if (a+size -- bp->m addr) (
(bp-l) ->m sIze +- bp->m size;
while (bp-=>m size) (
bp++;
(bp-l) ->m addr - bp->m addr;
tbp-ll.->:uLsize - .bp->m=size;

mallocat (mp, size, start)
struct map *mp;
reqister start;
{

register struct map *bp;
register a;
for (bp-mapstart (mp); bp->m size; bp++) {
if (bp->m addr - start && bp->m size >- size) {
a-~ .bp->JIl_ad,dr;
-

Fri Sep

malloc.c

5 19:08:19 1986

bp->m addr += size;
i f (m_size -- size) = 0) {
do {
bp++;
(bp-l) ->m_addr ~ bp->m_addr;
1 whHe «bp-l)->m size ~ bp->m size;;
mapsize(mp)++:
-

2
register size;
{

register struct scatter *s, "ss;
register short i;
register aI, a2, n;
i f (size <= 0) {
printf("cmemalloc error: tried to allocate %d units\n", size);
return (NULL) ;

return (a) ;

}

if (size> nscatfree)
return (trULL) ;
s - scatmap;
ss = &scatfreelist;
al - ss->sc index;
for (:;) { n = memcontig (aI, size):
i f (n >- size)
break:
i f (n > 1) {
i = n - 2:
do
al - s [all. sc_index:
while (--i != -1):

returniO) ;
telse
extern int nscatfree;

I"
" allocate size units from the memory map
xl
memalloc(size)
{

int n;
while «n = domemalloc(size»
if (xmrelse () = 0)
break;
return(n) ;

-

NULL)
ss~&s[all:

if (ss->sc index ~ SCATEND)
return (NULL) ;
al = ss->sc_index;

domemalloc (size)
register size;

a2 = al:
i f (size> 1) {
i = size - 2;
do
al = s[all.sc_index:
while (--i != -1);

{

register struct scatter *s;
register short i;
register al, a2;
i f (size <= 0) {
printf("memalloc error: tried to allocate %d units\n", size);
return (NULL) ;

ss->sc index = s [all. se index;
s [a 11 ."ic index = SCATEND:
nscatfree -= size:
1* printf("cmemalloc: found %d free pages starting at index %d\n",
size, a2); *1
if (countscat(a2) !- size)
printf ("cmemalloc: improper allocation countscat-%d size=%d\n",
countscat (a2), size);
return (a2) ;

if (size> nscatfree)
1* printf(''memalloc: less than %d free pages at present\n",
size); *1
return (NULL) ;
s - scatmap;
al = a2 = scatfreelist. sc index;
i f (size> 1) {
-

i = size - 2;
do {
al = s[all.sc_index;
} while (--i !- -1);

Ix
* free memory map chain
*/
memfree(a)
register a:
{

scatfreelist. sc index = s [all. sc index;
s[all.sc index;;;; SCATEND;
nscatfree -= size;
1* printf("memalloc: found 'lsd free pages starting at index 'lsd\n",
size, a2); *1
return(a2) ;

register struct scatter *s;
register i, aI, a2;
if (a <= 0 II a >- v.v nscatload)
printf("memfree: illegal index %d (Ox'lsx) \n", a, a);
return;
=

1*
" allocate size contiguous units from the memory map

*I
cmemalloc (size)
{

1;

s - scatmap;
al - a;
while «a2-s[al].sc_index) !-SCATEND) {
al - a2;
i++;

int n;
do
scat sort 0 ;
while «n - docmema 11 oc (size) )--NULL && xmrelse();
1* printf (lIcmemalloc: size-\d starting address-Ox\x\n", size, n); *!
return (n):
doc.memalloe (size)

i* printf("memfree:'Isd units freed starti.'1g
s[all.sc index - scatfreelist.sc index;
scatfreelist. sc_index - a;
nscatfree +- i;
/*
• Wake scheduler when !:reeinq memory
*/
i f (runin) {

a~

'iid\n", :.., a):

*:

malloc.c

Fri Sep

5 19:08:19 1986

runin = 0;
wakeup ( (caddr_t) &runin);

}

tendif

/*
* find number of contiguous memory pages
*/
memcontiq (sindex, ct)
register sindex, ct;
{

register struct scatter *s;
register al, n;

if I sindex - SCATEND 1 1 ct <- 0) {
printf ("memcontiq: sindex=Ox%x ct=%d\n", sindex, ct);
return (0) ;
n = 1;

s = scatmap;
a 1 = ixtoc ( sindex) ;
while (--ct > 0) {
if «sindex = s[sindex] .sc_index)
break;
if (++al != ixtoclsindex»
break;
n++;

~ SCATEND)

return(n) ;

/*
* sort the scatter load map
*/
scat sort I)
{

register struct scatter *s, *sf;
register int j, k, n, *ip, *jp;
register short i;

1*

* clear scatter sort array
*/
ip - scsortmap;
i = I (v.v_nscatload+31) » 5) - 1;
do
*ip++ = 0;
while (--i !- -1);
1*
* build bit map of free pages

*1
s - scatmap;
sf = &scatfreelist;
ip - scsortmap;
for (j = sf->sc index; j !- SCATEND; j
ip[j»5] 1= 1 « (j&31);

=

s [j] . sc_index)

1*
* rebuild freelist

*1
n - 0;
sf->sc index - SCATEND;
j - I (v.v nscatload+31) » 5) - 1;
jp - &scs;rtmap[jl;
for ( ; j >- 0; j--, jp--) {
if (*jp -- 0)
continue;
for (k-31; k>-O; k--) {
if (*jp&(l«k»)
n++;

i - sf->sc_index;
sf->sc index - (j « 5) + k;
s[(j« 5) + kl.sc_index - i;

nscatfree - n;

3

mbuf.c
1*

mbuf.c

tinclude
+include
tinclude
:include
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

Fri Sep
1.36

5 19:09:17 1986

1

"sys/param.h"
"sys/config.h ft
·sys/types.h"
"syslllllli.u. h"
·sys/sysmacros .hu
·sys/dir .h"
·sysl signal. h"
·sys/errno.h"
"sys/user.h"
"sys!proc.h ll
·net/misc.h"
"net/mbuf .h"
"sys/map.h"
·net/in_ systm.h"

frmptr;
raddr;

long
long

*1

82/06/20

};

int i;
register struct call * cp - &i;
extern dogJ>r;
register olddogpr - dogJ>r;
if (dog_prj (printf("",cp->raddr); dogJ>r - O;}
tendif
(m., canwait):
PRMDEF
if (olddogpr)
dogJ>r = 1;

MGET

tifdef

/*

XXX

*/

tendif
return (m);

/* some random constants, ints */
/.. THIS SHOULD BE AN EVEN CLrCK NUMBER OF BYTES !!! .. I
/*
tdefine rOSIZE 8192
/* area for DMA buffers */
tdefine rOSIZE
/* no space for DMA buffers for multibus */

struct mbuf *
m free(m)
struct mbuf *m;
register struct mbuf *n;
MFREE (m, n);

/* unsigned int
miosize
unsigned int
miobase;

~

rOSIZE; */

/*
* Initialize the buffer pool.
*/
mbinit ()

return (n);
/* loc of DMA area. */
m freem(m)
register struct mbuf *m;

Called from netinit/main.
register struct mbuf *n;
register int s;

{

register i;
register struct mbuf *m;
extern struct mbuf * mballoc () ;

if

(m NULL)
return;
s = splilnp () ;
do {

'*

/* allocate mbuf io area. iomalloc is machine-dependent. .. */
miobase = mbioalloc (btoc (miosize) ); "/
miobase = mbioalloc () ;
/* link the mbufs */
m = mballoc();
/*
printf("mbufs at %x\n", m);
*/
mbstat.m_mbufs = NMBUFS;
for(i-O ; im_off - 0;
bzero( (char *)m, MSIZE);
(void) ~free(m);
m++;

/ .. NEED SOME WAY TO RELEASE SPACE

1*

*'

* Space allocation routines.
* These are also available as macros
* for critical paths.
*/

/* ARGSUSED */
struct ll'.buf *
m get (canwait)
int canwait;

register struct mbuf Om;
Hfdef

=

nl;

/*
* Mbuffer utility routines.

*'

struct mbuf *
m copy(m, off, len)
register struct mbuf *m;
int off;
register int len;
register struct mbuf *n, **np;
struct mbuf *top;
if (len = 0)
return (0);
if (off < 0 II len < 0)
panic ("m copyl");
while (off> 0) T
if (m ~ 0)
panic (Um copy2");
if (off < m->m_len)
break;
off -- m->m_len;
m - m->m_next;
MAPSAVE() ;
np - ⊤
top - 0;
while (len> 0)
i f 1m -

{
0)

i f (len

PRMDEF

struct call {
long

MFREE (m, n);

} while 1m
splx(s) ;

!~

Y. CCFYALL)

paniC(Hm_copy3") ;
local;

Fri Sep

mbuf.c

5 19:09:17 1986

2
m - mp:
) else {
n->m_Ien
break:

MGET(n, 1);
*np - n:
i f (n = 0)
go to nospace:
n->m_len = MIN (len, m->m_len - off);

-=

len:

n->m off = MMINOFF:
MBCOPY (m, off,n, 0, (unsigned) n->m_Ien):
)

i f (len !- M_COPYALL)
len -= n->m_len;
off = 0:
m - m->m_next:
np = &n->m_next:

struct mbuf "
myullup(mO, len)
struct mbuf
int len:
register struct mbuf *m, *n:
int count:

goto out:
nospace:

n = mO:

i f (len > MLEN)
goto bad:
MGET(m, 0):
i f (m = 0)
goto bad:
m->m off = MMINOFF:
m->m-Ien = 0:
do (count - MIN (HLEN - m->m len, len):
if (count> n->m len) count = n->m_Ien;
MBCOPY(n, 0, m, m->m_Ien, (u_int) count) ;
len -- count:
m->m_len += count
n->m_off += count
n->m len -= count
i f (n->m_Ien)
break;
n - m free(n):
) while (n): i f (len) (
(void) m free (m);
goto bad7

m_freem(top) :
top - 0:
out:
MAPREST() :
return (top):

m_cat(m, n)
register struct mbuf "m, *n;

while (m->m_next)
m - m->m next:
while In) {
i f (m->m off >= MMAXOFF I I
m->m-off + m->m len + n->m len> MMAXOFF)
1* just join the two chains ,,/
return:
/* splat the data from one into the other */
MBCOPY(n, 0, m, m->m len, (u_int)n->m_Ien);
m->m_Ien += n->m_Ien7
n = m_free(n):

m->m next - n:
return (m):
bad:
m_adj (mp, len)
struct mbuf "mp;
register int len;

m freem(n):
return (0):

register struct mbuf *m, *n;

tifdef notdef

/*

* Allocate a contiguous buffer for DMA 10. Called from if ubainit () .
" TOoo: fix net device drivers to handle scatter/gather to-mbufs
" on their own: thus avoiding the copy to/from this area.

mp) = NULL)
return:
i f (len >= 0)
while (m !- NULL

i f «m

=

&& len> 0) {
<= len) (
len -= m->m len;
m->m_Ien = 0;
m = m->m_next:
) else {
m->m_Ien -= len:
m->m off +- len;
break:

if

(m->~len

*1
unsigned int
m ioget (size)
{-

unsigned int base:
size - «size + 077) & -077);
if (size> miosize) return(O);
miosize -- size;
base - miobase;
miobase +- size;
return (base);

}

} else {

1* a 2 pass algorithm might be better *;
len - -len;
while (len > 0 && m->m len ! - 0) ~
while 1m !- NULL && m->~len !- 0) {
n = m;

if (n->m_Ien <- len) {
len -- n->m_len;
n->m_len = 0;

}

tendif
tifdef debug
mbprint 1m, s)
register struct mbuf *m;
char *s;
{

extern enprint;
r,~i..s.ter char *ba.;

/* round up byte size ,,/

mbuf.c

Eri Sep

5 19:09:17 1986

3

int col, i, bc;
if (enprint - 0) return;
MAPSAVE() ;
nprintf("MB %s\n",s);
for i;;) i
if (m = 0) break;
ba = mtod (m, char "');
col = 0; be - m->m len;
nprintf ("m%o next%o- off%o len%o actio free%o \n",
m, m->m_next, m->m_off, m->~len, m->m_click,
m->m free):
fori; bc ; bC--) {
i - *ba++ & 0377;
nprintf(lI%o ·,i);
if(++col > 31) {
col ~ 0;
nprintf(lI\n ");

nprintfIU\n") :
m - m->m_next;
MAPREST ():

telse
mbprint 1m, s)
register struct mbuf *m:
char 'ks;
{

tifdef lint
mbprint (m, s):
tendif
)

tendif debug
tifdef notdef
mcheck (m, msg)
struct mbuf *m:
char * msg;
extern char mbufbufs [] ;
extern struct mbuf * mfreep;
register x, ret = 0;
x = sp17 ();

if ( (1m < (struct mbuf *)&mbufbufs[O]) && (m !- 0)) II
1m > (struct mbuf *) &mbufbufs [(NMBUFS+l) *MSIZEJ) II
«mfreep < (struct mbuf *)&mbufbufs[O]) && (mfreep !- 0»
II
(mfreep> (struct mbuf *)&mbufbufs[(NMBUFS+l)*MSIZEJ) ) {
printf ("mcheck fail; m, mfreep - %x, %x, from %s\n",
m,mfreep,msg) :
ret = 1;
splx(x) :
return ret;
tendif
tifdef PRMDEF
struct call {
long
long
long

local:
frmptr:
raddr;

);

int dogyr;
int dof_pr:
prmget()
{

int i;
reqiste!:' st=-uct ca:::l . . cp =

&i,'

if (dogJlr) print,fl"",cp,..>raddrl:

prmfree()
(

int i;
register struct call * cp

=

&i;

if (dof_pr) printf(" [MFREE from %xj",cp->raddr);

iendif

mem.c

Fri Sep

5 19:08:20 1986

1
u. u segflg = 0;
no fault - saved jb;
while(u.u_error .;;; 0 && u.u_count);
return;

1*
mem, kmem and null devices.
Memory special
minor device 0
~~or device 1
minor device 2

file
is physical memory
is kernel :memory
is EOF/RATHOLE

bad:

*1
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

"sys/param.h"
"sys/config.h"
"sys!!!!!!lu.h"
"sys!types.h"
"sys/sysmacros .h"
"sys/dir. hOI
Usys/signal.h"
"sys/user .h"
"sys/errno.h"
"sys/buf.h"
"sys/systm.h"
"setjmp.h"

1*
* mmread - read mem, kmem or null.

*1
mmread(dev)
(

i f (minor (dev) !- 2)

1* not Idev/null *1

mmmove(dev, B_READ);

1*
* mmwrite - write mem, kmem or null.

*1
mmwrite (dev)
{

i f (minor (dev) =

2) (
u.u count - 0;
return;

1* Idev/null, just gobble chars *1

mmmove(dev, B_WRITE);

1*

* mmmove - common routine for mmread and mmwrite
*1
mmmove(dev, flag)
dev t dev;
(

-

register int pageoffs, count, prot;
jmp bUf jb;
int-*saved jb;
int s;
i f (minor(dev)==1 [[

minor(dev)~=O)

{

1* kmem, mem *1

do {
s - spl7 ();
SEGl 0 - 1;
1* system context */
1* SEG2_0 = 1; 1* system context */
prot - getmmu( (short *) (vtoseg(u.u offset) [ ACCLIM» &PROTMASK;
SEG1 1 - 1;
1* user context *11* SEG2 0 - 1; 1* user context *1
Splx(s)7
1* printf(Uu base-Ox%x offset=Ox%x prot=Ox%x\n H , u.u base, u.u offset, prot); *1
if «unsigned)u.u_offset < (unsignedlsTDIO && prot !- ASRW)
goto bad;
pageoffs - u.u offset & (ctob(1)-1);
count - mini (unsigned) (ctob(l) - pageoffs), u.u count);
1* pri!'!tf("paqeoffs=%d count-%d u.u count=%d\n", paqeoffs, count, u.u_coum:); */
saved jb - nofault;i f (!setjmp(jb»
(
no fault - jb;
u.u segflg - 0;
iomOve«caddr_t)u.u_offset, count, flag);
) else
u.u_error - ENXIO;

mkfspm.c

Fri Sep

5 19:09:11 1986

1

I"
" mkfspm device
Get the size of the Priam disk "device" and make a root
file system in partition o. This makes a file system using the
entire disk except for the boot and swap areas.
The raw device is specified, but both the block and character
devices are expected to be available (created). The file system
is made on Idev/pm1a where Idev/rpm1a is the argument.

*1
iinclude
iinclude
iinclude
iinclude
iinclude
iinclude

"stdio.h"
"sys/types.h"
"sys/sysmacros.h"
"sys/uioctl.h"
"sys/stat.h n
"sys/swapsz .h"

main (argc, arqv)
char "*argv;
(

register fp;
register char "device;
register char *cp;
int pmsize;
char spmsize [101 :
device = * (argv+1):
i f Ilfp = openldevice, 2» < 0)
got a out;
if (ioctl(fp, UIOCSIZE, (caddr_t)&pmsize) < 0)
goto out;
cp = (char *1 strchr (device, , r'):
1* cp points to 'r' in /dev/rpm1a *1
for ( ; *cp: cp++)
1* change to Idev/pm1a *1
"cp = "lcp+1):
sprintf (spmsize, ""d", pmsize-PMNSWAP-101):
printf("%s: %s blocks\n", device, spmsize);
execl("letc/mkfs1b", "mkfs1bu , device, spmsize, 0) ;
out:
perror ("mkfspm") ;
exit (1);

5 19:08:42 1986

E'ri Sep

ms.c

1
i f (u.u_ttyd !- CONSOLE) {
u.u_error = EPERM;
return;

1*
* (C) 1984 UniSoft Corp. of Berkeley CA
* UniPlus Source Code. This program is proprietary
* with Unisoft Corporation and is not to be reproduced
~ or used in any manner except as authorized in
* writing by unisoft.

if (mouseopen++ > 0) { /* already opened *1
u.u_error = EBUSY;
return;
splms() ;
msproc - u.uyrocp;
mqhi = mqlo = mqbuf;
mqlen = 0;
mparm.mp irate ~ 28;
mparm.mp-fdlay ~ 300;
mparm.mp-flaqs - ME' BUT;
12copscrnd (MOUSEON) ;splO () ;

* Mouse Driver
*1
·sys/paralll.h M
"sys/config. hOI
"sys/types .h"
·sys/systm.h"
"sys/dir.h"
"sys/siqna1.h u
"sys/user.h"
"sys/proc.h"
·sys/errno.h"
·sys/file .h"
·sys/tty.h"
·sys/termio. h"
·sys/conf .h"
·sys/ sysinfo. hOI
·sys/var.h"
.sys/reg .hu
·sys/buf .h"
·setjmp.h"
·sys/cops .h"
·sys/loca1.h"
·sys/elog.h"
"sys/ms.h"
"sys/mouse.h"
"sys/mmu.h"
·sys/kb.h"
·sys/al_ioct1.h"

tinclude
#include
tinclude
#include
tinclude
#include
tinclude
#include
tinclude
#include
#include
# include
# include
#include
#include
#include
#include
#include
tinclude
tinclude
#include
tinclude
#include
#include
#include
#include

#define splms

/* controlling tty not bitmap */

1*
* Reset everything since code elsewhere (in 11. c) uses it.
*1
1* ARGSUSED *1
msclose (dev, flag)
{

if (mouseopen <= 0)
u.u_error = EINVAL;
else {
SPL60 ;
mouseopen - 0;
mqhi = mqlo - mqbuf;
mqlen = 0;
mparm.mp irate - 0;
mparm.mp-fdlay - 0;
mparm.mp::)lags - 0;
msvrmsk - 0;
12copscrnd (MOUSEOIT) ;
SPLO ();

/* only accessed in ms.c */

sp12

1* flags local to ms.c *1
/* active flag "I
/* flag to sleep on when blocked * I

char mouseopen;
char msblkd;

msstrategy (bp)
register struct buf *bp;
{

1* also used in 11. c (vertical retrace interrupt code) *1
struct msparms mparm;
1* place to save ioctl data */
struct proc "msproc;
/* controlling process for mouse */
char msvrmsk;
/* mask of low bits of retrace counter */

register mem t *rp;
register int-i:

/* Make sure the mouse is plugged in and the read request is for a

*
1* values set in kb.c */
extern char msylg, mS_btn;
1* mouse plugged-in and button state */
extern short ms row, ms col;
/* last received row and column *1
extern time_t Ibolt;
-

/* reciever buffer pointer */
/* record count * /

multiple of the record size.

*1
i f (msylg) {
u. u error - ENODEV;
goto fail;

/ * mouse unplugged * I

}

tdefine QUELEN 128
typedef unsigned long mem t;
int mqlen;
mem t *mqlo, *mqhi;
mem- t mqbuf [QUELEN] ;
mem:) mtim[QUELEN];

if (bp->b_bcount & 3) {
u.u_error - EINVAL;
fail:

1* high and low pointers into
1* ring buffer for mouse data */

msopen (dev, flag)
dev t dev;
{ if (dev !- 0) {
/* minor device number is wrong *1
u. u error - ENXIO;
return;

if (ms_plg) [
u.u_ error
return;

/* mO;.Jse is nct pl:.Jgged i:: *1

- ENODEV;

*/

bp->b resid - bp->b bcount;
iOdone (bp) ;
return;
if (mqlo - mqhi)
/* queue empty */
if «int)mparm.mp_irate <= 0)
/* mouse shutdown *1
u. u error = EIO;
splms ():
if (mparm.mp flags & MF BLK)
/* block till record avail */
msblkd - 1;
while (msblkd)
(void) sleep ( (ca:ldr_ t) &rnsblkd, TTIPRI);
goto ok;
splO () ;
goto fail;

}

i f (flaq !- 1) {

u. u_error
return;

-

/* count not multiple of record size */

1* open for writinq
EINVAL:

II

*1
splms ();

/* so msintr doesnt screw up que ptr s • /

E'ri Sep

ms.c

5 19:08:42 1986

2
msintr (M_FLUSH) ;

ok:
i f (lbolt - mtim[mqlo-mqbuf] >- mparm.mp fdlay)
if (mparm.mp fdlay)
msintr (M_FLUSH) ;

if (mqlen >- QUELEN)
return;
} else

rp = (meIil_t *)bp=>b_u.~.b_addr; /* start of receiver buffer *1
for (i=bp->b bcount; i>O && mqlo != mqhi; i -= 41
*rp++ = *mqlo++;
if (mqlo >- mqbuf + QUELEN) mqlo = mqbuf;

bp->b_resid = i;
mqlen -= (bp->b bcoun.t - i) »
splO ();
iodone (bpI;
return;

/* queue was empty */
i f (mparm.mp flags & MF SIG)
psigDal(msprOc,-SIGMOUSI;

mp->mr but ~ ms btn ? 1 : 0;
mp->mr-ctl - kb-ctrl ? 1 : 0;
mp->mr-sft - kb-shft ? 1 : 0;
mp->mr-time ~ ibolt & OxFFF;
if (kind ~ M_MOVE) (
mp->mr row - ms row;
mp->mr::::col = ms::::col;

2;

/* called from kbintr */

}

struct buf rmsbuf;
msread (dev)

1* Buffer for raw input-output */

mtim[mqhi - mqbuf] = lbolt;
*mqhi++ = msr.mf long;
mqlen++;
i f (mqhi >- mqbuf + QUELEN)
mqhi - mqbuf;
i f (msblkd) (
msblkd = 0;
wakeup ( (caddr_t) &msblkd);

{

if (msproc != u.uyrocp)
u.u_error = EIO;
return;
rmsbuf.b flags &= -B BUSY;
physio(m-;strateqy, &rmsbuf, deY, B_READ);

msintr (kind)

/" ARGSUSED * /
msioctl (dev, cmd, addr, flag)
dey t dey;
int-cmd;
caddr t addr;
int flag;

{

register struct msrecord "mp;
union {
struct msrecord mf rec;
unsigned long mf_ iong;
l msr;
if (!mouseopen II mparm.mp_irate
return;

{
~

0) {/* mouse not active *1

switch (cmd) {
case AL GMOUSE:
-if (mp->mp qlen = mqlen)
mp=>mp otime - Ibolt - mtim[mqlo-mqbuf];
mp->mp:=rtime - lbolt - mtim[mqhi-mqbuf-1];
} else {
mp->mp otime = 0;
mp->mp:=rtime = 0;

if (:nsylg) {
mqlo = mqhi - mqbuf;
mqlen = 0;
return;

msr.mf_Iong - 0;
mp - &msr .mf_rec;

register struct msparms "mp - &mparm;
int dlay, rate;

/* clear new record *1
1* get pointer to record structure */

switch (kind) {
/* kind of interrupt *1
/* auto flush (called from msintr,msstrategy) */
case M_FLUSH:
mp->mr_but = 1;
I" automatic reset (called from kbintr) ,,/
case M_PLUG:
mp->mr reset - 1;
mqlo --mqhi - mqbuf;
mqlen - 1;
mtim[O] = lbolt;
*mqhi++ = msr.mf_Iong;
return;
case M BUT:
1* mouse button changed (called from kbintr) *1
- if «mparm.mp_flags & MF_BUT) - 0)
return;
break;
case M CTL:
/* control key changed (called from kbintrl */
- i f «mparm.mp_flags & MF_CTLI - 01
return;
break;
case M SFT:
/* shift key changed (called from kbintr) */
- it' (fmparm.mp_flags & MF_SFT)
0)
return;
break;
if (mqlen)
/* check for invalid queue data */
i f (Tholt - mtim[mqlo-mqbuf] >- mparm.mp fdlay) (
i f (mparm.mp_fdlay)
-

if (copyout( (char *)mp, addr, sizeof(struct msparmsl) I
u.u_error = EFAULT;
break;
case AL_SMOUSE:
dlay = mp->mp fdlay;
rate = mp->mp-irate;
if (copyin(addr, (char *Imp, sizeof(struct msparms»))
u.u_error - EFAULT;
else {
i f (mp->mp fdlayl {
if-(mp->mp fdlay < 201 {
splms (I;
mp->mp fdlay = dlay;
/* restore" /
mqlen ;: 0;
mqhi - mqlo = mqbuf;
splO ();
l else i f (mp->mp fdlay > 4095)
mp->mp_fdlay - 4095;
if (mp->mp irate !- rate) {
1* did int rate chg */
mp=>mp irate - (mp->mp irate + 3) & -3;
i f (rnp=>mp irate > 28)mp=>mp irate = 28;
splms (I;
i f (mp->mp irate)
12copscmd( (charI «MOUSEON&-7) I (mp->mp_irate»2»);
else
l2copscmd(MOUSEOFF) ;
splO ();

Fri Sep

ms.c

5 19:08:42 1986

splms ();
i f (mp->mp flags & MF VRT)
msvrmsk = mp->mp_flags & MF_VRATE;
splO ();
break;

default:
u • u_error = ENOTTY;

3

Fri Sep

msg.c
1* @(t)msg.c
1*

5 19:07:55 1986

1
msgctl()

1.3 *1

{

register struct a {
int

Inter-Process communication Message Facility.

msgid,
cmd;
struct msqid cis "buf;
*uap-~ (struct a *)u.u ap;
ds;
- 1* queue work area *1
struct msqid ds
*qp;
1* ptr to associated q *1
register struct msqid_ds

*1
tinclude "sys/types .h"
tinclude "sys/param. h"
#include ·sys/dir.h"
#ifdef u3b
tinclude Hsys/istk.h"
tendif
tinclude "sys/signal.h"
tinclude IIsys/user: .hU
tinclude ·sys/seg.h"
tinclude ·sys/proc.h"
tinclude .. sys/buf. h"
tinclude "sys/errno .h"
#include ·sys/map.h"
tinclude ·sys/ipc.h"
.finclude "sys/msg.h"
tinclude "sys/systm.h"
Hfdef vax
tinclude "sys/page .h"
tendif
Hfdef u3b
tinclude "sys/macro. h"
telse
tinclude "sys/sysmacros.h"
tendif
extern struct
extern struct
extern struct
extern struct
extern char
struct msg
paddr t
extern time_ t

map
msqid_ds
msg
msginfo

if «qp

msgconv (uap->msgid» = NULL)
return:
u.u rvall ~ 0;
switch (uap->cmd)
case IPC RMID:
If(u.u_uid != qp->msgyerm.uid && u.u_uid != qp->msgyerm.cuid
&& ! suser () )
return:
while (qp->msg first)
msgfr;e(qp, (struct msg *)NULL, qp->msg_first):
qp->msg cbytes = 0;
if (uap->msgid + msginfo. msgmni < 0)
qp->msgJ)E!rm. seq - 0;
else
qp->msgyerm. seq++;
if(qp->msgJ)E!rm.mode & MSG_RWAIT)
wakeup ( (caddr_ t) &qp->msg_qnum) ;
if (qp->msgJ)E!rm.mode & MSG_WWAIT)
wakeup ( (caddr_t)qp);
qp->msgyerm.mode = 0;
return;
case IPC SET:
If(u.u_uid != qp->msgyerm.uid && u.u_uid !- qp,..>msgyerm.cuid
&& ! suser () )
return:
if (copyin( (caddr t)uap->buf, (caddr_t) &ds, sizeof(ds)) {
u.u_error = EFAULT;
return;

msgmap[] ;
1* msg allocation map * I
msgque[] :
1* msg queue headers *1
msgh[J ;
1* message headers *1
msginfo;
1* message parameters *1
msgspace [ ] ;
1* space for message buffers *1
*msgfp; /* ptr to head of free header list * /
msg;
1* base address of message buffer *1
time:
/* system idea of date *1

=

)

if (ds. msg qbytes > qp->msg_qbytes && ! suser () )
r;turn;
qp->msgyerm.uid = ds.msg_perm.uid;
qp->msgyerm.gid = ds.msgyerm.gid;
qp->msgyerm.mode = (qp->msgyerm.mode & -0777) I
(ds.msg perm.mode & 0777);
qp->msg_qbytes ;;; ds .msg_qbytes;
qp->msg_ctime = time;
return;
case IPC STAT:
If(ipcaccess(&qp->msgyerm, MSG_R»
return;
if (copyout «caddr_t) qp, (caddr_t) uap->buf, sizeof(*qp») (
u.~error = EFAULT;
return;

*ipcget() ;
*msgconv () ;

struct ipcyerm
struct msqid_ds

/* Convert bytes to msg segments. */
tdefine btoq(X) «X + msginfo.msgssz -

1)

I msginfo.msgssz)

1* Choose appropriate message copy routine. *1
tifdef pdpll
tdefine MOVE
telse
tdefine MOVE
tendif

msgpimove
iomove

1*
msgconv - Convert a user supplied message queue id into a ptr to a
msqid_ds structure.

return;
default:

struct msqid ds *
msgconv(id) register int
id;

u.u_error
return;

=

EINVAL;

(

register struct msqid_ds

*qp;

1* ptr to associated q slot * /

1*
qp - &msgque[(short) (id % msginfo.msgmni)];
if( (qp->msgyerm.mode & IPC_ALLOC) -- 0 II
id I msginfo.msgmni !- qp->msgyerm.seq)
u. u error = EINVAL;
return (NULL);
return (qp) ;

/*
msgctl - Msgctl system call.

"/

msgfree - Free up space and message header, reI ink pointers on q,
and wakeup anyone waiting for resources.

*1
msgfree (qp, pmp, mp)
register struct msqid ds
register struct msg -

*qp;
*mp,
*pmp;

1* ptr to q of

~es'1

beinq f=ee:l. ".I

I" ptr to msg being freed ,,/
/* ptr to mp's predecessor *1

I" Unlink message from the q. * I
if(pmp - NULL)
qp->msg_first - mp->msg_next;
else

Fri Sep

msg.c

5 19:07:55 1986

2

pmp->msq next - mp->msg next:
if (mp->msq next
NULL)
qp=>msg_last - prop:
qp->msq qnum--:
if(qp->msqyerm.mode & MSG_WWAIT)
qp->msqyerm.mode &= -MSG_WWAIT:
wakeup, (caddr_tiqp;:

fendif
fifdef u3b
iff (msg = (paddr_t)kseq(RW, btop(msginfo.msgseg * msqinfo.msgssz») NULL) {
fendif
fifndef mc68000
printf("Can't allocate message buffer. \n"):
msginfo.msgseg = 0:

1* Free up message text. *1

fendif

if (mp->msg_ts)
mfree (msgmap, btoq(mp->msg_ts), mp->msg_spot + 1):

mapinit (msgmap, msginfo .msgmap) ;
mfree(msgmap, (int)msginfo.msqseg, 1);
for(i = 0, mp = msgfp = msgh;++i < msqinfo.msgtql;mp++)
mp->msg_next - mp + 1;
Hfdef vax
maxmem -= bs:
fendif
Hfdef mc68000
return:
fendif
fifdef pdpll
return (bs) ;
fendif

=-

/* Free up header *1
mp->msg next - msqfp:
if (msgfp - NULL)
wakeup ( (caddr_ t) &msgfpJ :
msgfp - mp:

1*
msgqet - Msgget system call.

*1

)

msgget ()
fifdef pdpll

{

register struct a {
key t
key:
intmsqflg:
*uap = (struct a
register struct msqid ds
int
-

1*
msgpimove - PDP 11 pimove interface for possibly large copies.

*1
*)u.~ap:

*qp:
s:

1* ptr to associated q *1
1* ipcget status return *1

msgpimove (base, count, mode)
paddr t
base;
register unsigned
count:
int
mode:

ifl (qp - (struct msqid ds *)
ipcget(uap->key, uap->msgflg, (struct ipcyerm *)msgque,
msginfo .msqmni, sizeof (*qp), &s» ~ NULL)
return:

{

register unsigned

1* This is a new queue.

Finish initialization. */
qp->msg first - NULL: qp->msg last = NULL:
qp->msg-qnum = 0:
qp->msq-qbytes - msqinfo.msgmnb:
qp->msg-lspid = 0: qp->msg lrpid - 0:
qp->msg- stime - 0: qp->msg-rtime - 0:
qp->msg::::ctime - time:
=

qp->msgyerm. seq

*

tcount: 1* current transfer count *1

while(u.u error ~ 0 && count) {
tcount = count > 8064 '1 8064
pimove(base, tcount, mode):
base += tcount;
count -= tcount:

ifls) {

u.u_rvall

1* base address *1
1 * byte count * 1
1* transfer mode *1

count:

)

tendif

1*
msginfo.msqmni + (qp - msgque):

msgrcv - Msgrcv system call.

*1
msgrcvl)

1*
msginit - Called by main lmain. c) to initialize message queues.

{

register struct a {
int
msqid:
struct msgbuf
*msgp;
int
msgsz:
long
msgtyp:
int
msgflg:
*uap - (struct a *)u.u_ap:
register struct msg
*mp,
*pmp,
*smp,
*spmp;
.qp:
reqister struct msqid ds
int
sz;

*1
msginit ()
{

register int
register struct msg
Hfndef mc68000
register int
#end if

i:
*mp:

1* loop control *1
1* ptr to msg begin linked */

bs:

1* message buffer size * f

f* Allocate physical memory for message buffer. *f
Hfndef mc68000
bs - (long)msginfo.msgseg " msginfo.msgssz;
fendif
Hfdef mc68000
msg - (paddr_t) msgspace:
fendif
Hfdef pdpll
i f «msg - (paddr_t) ctob( (long) (unsigned)malloc (coremap,
bs=(int)btoc( (lonq)msginfo.msgseq • msginfo.msgssz»» -- 0)
tendlf
tifdef vax
If((msg - (paddr_t)sptalloc(bs=btoc(msqinfo.msgseg· msginfo.msgssz),
PG_V J PG_KIf, 0»
- NULL) {

i f I (qp - msgconv (uap->msqid» - NULL)
return:
if(ipcaccess('qp->msg_perm, MSG_RJ)
return;
if(uap->msgsz < 0) {
u.u_error - EINVAL:
return:

{

smp - NULL: sprop - NULL;
findInsg:

1*
1*
1*
1*
1*
1*

ptr to msg on q */
ptr to mp's predecessor *1
ptr to best msg on q ·1
ptr to smp's predecessor * f
ptr to associated q *1
transfer byte count * f

Fri Sep

msg.c

5 19:07:55 1986

3
"uap = (struct a ")u.u_ap;
register struct msqid ds
*qp;
register struct msg *mp;
register int
cnt,
spot;
long
type;

pmp = NULL:
mp - qp->msg_first:
if(uap->msgtyp - 0)
smp - mp;
else
for(;mp:pmp - mp, mp = mp->msg_nextj (
if(uap->msgtyp > 0) (
if(uap->msgtyp != mp->msg type)
continue;
smp = mp:
spmp = pmp:
break;
}

}

(void) copyin«caddr t)uap->msgp, (caddr_t)&type, sizeof(type»;
if (u.u_error)
return;
if(type < 1) {
u.u_error = EINVAL;
return;

if (smp)
getres:

I" Be sure that q has not been removed. */
if (msgconv(uap->msqid) == NULL) (
u. u_error = EIDRM;
return;
Ix Allocate space on q, message header, & buffer space. "I
if(cnt + qp->msg cbytes > qp->msg qbytes) {
if(uap->liisgflg & IPC_NOWAIT) {
u.u_error - EAGAIN;
return;
qp->msgyerm.mode 1= MSG_WWAIT;
if(sleep«caddr_t)qp, PMSG 1 PCATCH»
u.u error - EINTR;
qp->msgJ)E!rm.mode &= -MSG_WWAIT;
wakeup ( (caddr_ t) qp) ;
return;

if(u.~error)­

return;
u. u rvall - sz;
qp->msg cbytes -- smp->msg ts;
qp->msg::)rpid = u.uyrocp->pyid;
qp->msq rtime - time;
curpri :: PMSG;
msgfree (qp, spmp, smp):
return;

ptr to associated q "I
ptr to allocated msg hdr *1
byte count *1
msg pool allocation spot *1
msg type * I

if «qp = msgconv (uap->msqid» == NULL)
return;
if (ipcaccess (&qp->msgJ)E!rm, MSG_ W) )
return;
if (tent .. uap->msqsz) < 0 II cnt > msqinfc .msgroax)
u.u_error - EINVAL;
return;

if (mp->msg type <- -uap->msgtyp)
if(smp && smp->msg type <= mp->msg type)
continue; smp - mp;
spmp = pmp;

if (uap->msgsz < smp->msg ts)
if(! (uap->msgflg-& MSG_NOERROR»
u. ~error = E2BIG:
return;
} else
sz - uap->msgsz;
else
sz - smp->msg_ts;
(void) copyout «caddr t) &smp->msg type, (caddr_t) uap->msgp,
s1zeof (smp->msg type»; if(u.u_error)
return;
if(sz) {
u.u base - (caddr t)uap->msgp + sizeof(smp->msg type);
u.u-segflg = 0; MovE ( (caddr_t) (msg + msginfo.msgssz " smp->msg_spot),
sz, B READ);

1*
I"
1*
1*
/*

goto getres;
}

if(msgfp == NULL) {
if(uap->msgflg & IPC_NOWAITI
u.u_error = EAGAIN;
return;
}

if(uap->msgflg & IPC_NOWAIT)
u.u_error = ENOMSG:
return;
qp->msq perm.mode 1- MSG RWAIT;
if (sleep( (caddr_t) &qp->msg_qnum, PMSG 1 PCATCH»
u.u error - EINTR;
return:
if (msgconv (uap->msqid) ~ NULL)
u.u_error - EIDRM;
return;

if(sleep( (caddr_tl &msgfp, PMSG
u.u_error = EINTR;
return;

1

PCATCH»

{

goto getres;
(
if(cnt && (spot = malloc(msgmap, btoq(cnt) I) == NULL) {
if (uap->msgflg & IPC_NOWAIT) {
u. u_error = EAGAIN;
return;
mapwant (msgmap) ++;
if(sleep( (caddr_t)msgmap, PMSG 1 PCATCH)
u.u error = EINTR;
return;

goto findmsg;

{

goto getres;
msgsnd - Msgsnd system call.

"I

!* Ever:."thing is avai::'able, copy in tex;; a:ld pu;; msg

msgsnd ()

i f (cnt)

{

register struct a {
int
struct msgbuf
int
int

msqid;
*msgp;
msgsz;
msgflg:

0."1 q" ,;
{
u.u base = (caddr t)uap->msgp + sizeof(type);
u.u-segflg - 0; HOvE( (caddr t) (msg + msginfo.msgssz .. --spot), cnt, B_WRITE);
i f lu. u error) !
- mfree (msgmap, btoq (cnt), spot + 1);
return;

msg.c

Fri Sep

5 19:07:55 1986

qp->msg ,qnum++;
qp->msg-cl:lytes += cnt;
qp->msg=lspid = u.u-procp->p-pid;
qp->msg stime - time;
mp .. msqfp;
msgfp = mp->msg_next;
mp->msg next - NULL;
mp->msg-type = type;
mp->msg=ts = cnt;
mp->msg_spot = cnt "1 spot : -1;
if(qp->msg last = NULL) {
qp=>msg_first = mp; qp->msg_Iast = mp;
} else {
qp->msg last->msg next = mp:
qp->msg=last = mp~
& MSG_RWAIT) {
qp->msg~rm.mode &= -MSG_RWAIT:
curpri = PMSG;
wakeup( (caddr_t) &qp->msg_qnum):

if(qp->msg~rm.mode

/"
msgsys - System entry point for msgctl, msgget, msgrcv, and msgsnd
system calls.

*/
msgsys()
{

msgctl() ,
msgget() ,
msgrcv(),
msgsnd() ;
static int
("calls []) () = { msgget, msgctl, msgrcv, msgsnd };
register struct a {
unsigned
id;
/* function code id */
int
*ap;
/* arg pointer for recvmsg * /
*uap = (struct a *)u.u_ap;

int

if(uap->id > 3)
return;
u.u ap ~ &u.u arg[l]:
("calls [uap->Id] ) () ;

4

Fri Sep

name.c
1* @(t)name.c

1.1 *1
tinclude "sys/utsname.h"

tifdef lint
tdefine SYS
"sys"
tdefine NODE
"node"
tdefine REL
"reI"
tdefine VER
"ver"
tdefine MACH
"m68000"
tdefine TIMESTAMP "timestamp"
tendif
struct utsname utsname =
SYS,
NODE,
REL,
VER,

MACH,
};

char timestamp [1

=

TIMESTAMP;

5 19:09:00 1986

1

nami.c

Fri Sep

5 19:07:55 1986

1

1* tdefine HOWFAR *1
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
iinclude
tinclude
iinclude
iinclude

1.2 *1
"sys/param.h"
"sys/types.h"
"sys/systm.h"
"sys/sysinfo.h H
"sys/inode.h H
"sys/mount .h"
"sys/dir.hu
"sys/signal.h"
"sys/user. h"
"sysierrno.h"
"sys/buf.h"
"sys/var.h"

1*
* If there is another component,
* gather up name into users' dir buffer.

1* @(t)nami.c

*1
cp ~ &up->u dent.d name[O];
while(c != 'I' && C !- '\0' && up->u error =
if(cp < &Up->u_dent.d_name[DIRSIZ])
*cp++ - c;
c - (*func) ();

0) (

* an inode. Note that the inode is locked.

while(cp < &up->u_dent.d_name[DIRSIZ])
*cp++ = , \0' ;
iifdef HOWFAR
printf("nami: about to scan for' %s' \n", up->u_dent.d_name);
iendif
while (c ~ , I' )
c = (*func) ();

* func - function called to get next char of name

seloop:

1*

*

Convert a pathname into a pointer to

&uchar if name is in user space
&schar if name is in system space
* flag = 0 if name is sought
1 if name is to be created
2 if name is to be deleted

*1
struct inode *
namei (func, flag)
int ( .. func) () ;
(

register struct user "up;
register struct inode "dp;
register c;
register char *cp;
register struct buf *bp;
register i;
dev_t d;
off_t eo;

1*
* dp must be a directory and
* must have X permission.

*1
iifdef HOWFAR
1* printf("nami:directory mode = O%o\n", dp->i_mode&OxFFFF); *1
tendif
if «dp->l_mode&IFMT) != IFDIR II dp->i_nlink=O)
up->u_error = ENOTDIR;
else
(void) access (dp, IEXEC);
if (up->u_errorj
goto out;

1*
.. set up to search a directory

*1
up->u offset = 0;
up->u-count - dp->i size;
up->uJ>bsize = 0; eo - 0;
bp = NULL;
if (dp ~ up->u rdir)
if (up->u dent.d name[O]
if (up->u-dent.d-name[l]
if (up->u=dent.(~name[2]
goto cloop;

1*
.. If name starts with' I' start from
* root; otherwise start from current dir.

*1
up - &u;
sysinfo. namei ++;
c - ("func) ();
if (c =- '\0') {
up->u_error - ENOENT;
return (NULL) ;

'.')
'.')
, \0')

eloop:

1*
if

I') {
if «dp - up->u rdir) -- NULL)
dp = rootdir;
while (c - , I' )
c = (*func) ();
if(c ~ , \0' && flag !- 0) (
up->u_error = ENOENT;
return (NULL) ;

(c - - ,

) else
dp - up->u cdir;
(void) iget(dP->i_dev, dp->i_number);
cloop:

1*

* Here dp contains pointer

.

.. to last component matched .
/

if (up->u_error)
goto out;
If(c -- '\0')
return (dp) ;

* If at the end of the directory,
* the search failed. Report what
* is appropriate as per flag.
*1

if (up->u count -- 0) (
if(bp !- NULL)
brelse (bpI;
if (flag-l && c-' \ 0' )
if (access (dp, limITE»
goto out;
up->u pdir - dp;
if (eo)
up->u_offset = eo - sizeof (struct direct);
up->u count - sizeof(struct direct);
(void) OOtap(dp, B imITE);
if (up->u_error) goto out;
return (NULL) ;
up->u error - ENOENT;
goto out;

nami.c

Fri Sep

5 19:07:55 1986

2
iput(dp) ;
dp = iget (d, up->u dent. d ino):
if(dp = NULL)
return (NULL) :
goto cloop:

1*

*

If done with current block,
* read the next directory block.
* Release previous if it exists.

*/
if (Up->u_pbsize = 0) {
daddr_t bn:
if(bp !- NULL)
brelse (bp) ;
sysinfo. dirblk++;
bn - bmap(dp, B READ);
if (up->u_error)
goto out:
i f Ibn < 0) {
up->u_error = EIO;
goto out:

out:
iput(dp) ;
return (NULL) ;

1*
* Return the next character from the
* kernel string pointed at by dirp.

*1
schar()
{

return(*u.u_dirp++
bp ~ bread(dp->i dev, bn):
if (up->u error) - {
brelse (bp) ;
goto out;

& 0377):

1*

* Return the next character from the
* user string pointed at by dirp.

*1
uchar()

1*

{

*
*

Note first empty directory slot
in eo for possible creat.
* string compare the directory entry
* and the current component.
* If they do not match, go back to eloop.

*/
cp - bp->b_un.b_addr + up->u~ff;
up->u offset +- sizeof Istruct direct);
up->uyboff +- sizeof (struct direct):
up->uybsize -- sizeof(struct direct);
up->u count -- sizeof(struct direct);
up->u-dent. d ino = I (struct direct *) cp) ->d ino:
if(up=>u dent.d ina = 0) {
lfleo ,.;: 0)
eo = up->u offset;
goto eloop:
cp = & ( (struct direct *) cp) ->d name [0] ;
for (i=O; iu dent.d name[i])
goto eloop;
-

1*

*
*

Here a component matched in a directory.
If there is more pathname, go back to

* cloop, otherwise return.
*1
if(bp !- NULL)
brelse (bp) ;
if(flag~2 && c-~'\O')

if (access (dp, IWRITE»
goto out;
return (dp) ;
)

d = dp->i dev:
i f (up->u dent. d ina - ROOTINO)
if(dp->i-number--- ROOTINO)
if(up->u-dent.d name[l] - , .')
for(i-17 ii count++:
plock(dp) ;
goto seloop;

register c;
c - fubyte( (caddr t)u.u dirp++):
if(c - -1)
u.u_error = EFAULT;
return (c) ;

netipc.c
1*
tinclude
tinclude
#include
+include
#include
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
1*
tinclude

ipc.c

Fri Sep
4.20

82/06/20

5 19:09:18 1986

1

*1

"sys/param.h"
"sys/config .h"
"sys/types.h"
"sys/m.'D.u.h"
"sys/sysmacros.h"
"sys/systm.h"
"sys/signal.h"
·sys/errno. h"
"sys/dir.h"
"sys!useroh"
"sys/proc.h"
"sys/file.h"
"sys/inode.h"
"sys/buf .h"
"net/misc.h"

/*
.. Accept system call interface.
*1
saccept()
{

register struct a {
int
fdes:
struct sockaddr *asa:
*uap - (struct a *)u.u_ap:
struct sockaddr sa;
register struct file *fp:
struct socket *so;
int s:
if (uap->asa && useracc( (caddr t)uap->asa, sizeof (sa), B_WRITE) =0)
u.u_error - EFAULT:
return;

"net/mbuf.h"

*1
tinclude
+include
tinclude
#include
tinclude

Hnet/protosw.h"
"net I socket. h"
"net/socketvar .h"
"net/in.hu
"net/in_systm.h"

fp = getf (uap->fdes) :
i f (fp 0)
return;
i f «fp->f_flag & FSOCKET) ~ 0) {
u.u_error = ENOTSOCK;
return;

1*
* Socket system call interface.

s - spInet () :
so - (struct socket *1 fp->f_socket;
if ({so->so_state & SS NBIOI &&
(so->so_state & SS=:CONNAWAITINGI u.u error - EWOULDBLOCK:
splx(s) ;
return;

* These routines interface the socket routines to UNIX,
* isolating the system interface from the socket-protocol interface.
.. TODO:
So_ INTNOTIFY

0) (

*1
while «so->so state & ss CONNAWAITING) - 0 && so->so_error -- 0) {
if (so=>so_state
SS_CANTRCVMORE) {
so->so error - ECONNABORTED;
break;-

&

1*
* Socket system call interface. Copy sa arguments
* set up file descriptor and call internal socket
* creation routine.
*1
ssocket ()

(void) sleep ((caddr_tl &So->so_timeo, PZERO+l);
if (so->so_error)
u.u error
splx(s) ;
return;

{

register struct ua {
int
type;
struct sockproto *asp:
struct sockaddr *asa:
int
options:
*uap - (struct ua *)u.u ap:
struct sockproto sp:
struct sockaddr sa:
struct socket *so:
register struct file *fp:

=

so->so_error;

u.u error = soaccept(so, &sa):
i f (u.u error) {
-splx(s) ;
return;
if (uap->asa)
(void) copyout «caddr t) &sa, (caddr t) uap->asa, sizeof (sa»:
/* deal with new file descriptor case *1
/* u.u r.r vall - ... */
splx(s):

i f «fp

= falloc«struct inode *)0, FSOCKETIFREADIFWRITE»
- NULL)
return;
if (uap->asp && copyin «caddr t) uap->asp, (caddr t) &sP, sizeof (sp»
II
uap->asa && copy in ( (Caddr=:t)uap->asa, (caddr=:t) &sa, sizeof (sa») (
u. u error - EFAULT:
fp->f count = 0:
fp->f-next - ffreelist:
ffreelist - fp:
return:

1*
* Connect socket to foreign peer; system call
.. interface. Copy sa arguments and call internal routine.
*1
sconnect()
{

u.u_error - socreate(&so, uap->type,
uap->asp '? &sP : 0, uap->asa '? &sa
if (u. u error)
-qoto bad:
fp->f_socket - (off_t) so:
return:
bad:
u.u ofile[u.u rvalll - 0;
fp->f count --0:
fp->f-next - ffreelist:
ffreeiist = fp:

0, uap->options):

register struct ua {
int
fdes;
struct sockaddr *a;
*uap - (struct ua *)u.u ap:
struct sockaddr sa;
register struct file * fp:
register struct socket *so;
int s;
if (copyin( (caddr_t)uap->a, (caddr_t)&sa, sizeof (sa» I (
u.\Lerror - EFAULT;

2

5 19:09:18 1986

Fri Sep

netipc.c
return;

return:
i f «fp->f_flag & FSOCKET)

}

fp - getf (uap->fdes) ;
i f (fp -- 0)
return;
if «fp->f_flaq & FSOCKET) == 0)
u. u_error = ENOTSOCK;
return;

~

0) {

u.u_error - ENOTSOCK;
return;
u.u base - uap->cbuf;
u.u-count = uap->count;
u.u-segflg - 0;
if (useracc(uap->cbuf, uap->count, B WRITE) - 0 II
uap->asa && copyin( (caddr_t)Uap->asa, (caddr_t) &sa, sizeof (sa») {
u.u_error = EFAULT;
return:

so = (struct socket *) fp->f socket;
u . u error - soconnect (so, &sa) ;
if (u"u error)
-return;
s - spInet () ;
if «so->so_state & SS NEIO) &&
(so->so_state & SS:=ISCONNECTING»
u. u_error = EINPROGRESS;
splx(s);
return;
while «so->so state & SS ISCONNECTING) && so->so error
(void) - sleep ( (Caddr_tl &So->so_timeo, PZERO+l);
u. u_error - so->so_error;
so->so_error = 0;
splx(s);

u.u error - soreceive( (struct socket *) fp->f_socket, uap->asa
&sa
0);
if (u.u_error)
return;
if (uap->asa)
(void) copyout«caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa»:
u.u_rvall - uap->count - u.u_count:
=

0)

1*
" Get socket address.

*1
ssocketaddr ()
{

register struct a {
int
fdes;
struct sockaddr *asa;
*uap = (struct a *) u. u ap;
register struct file *fp;
register struct socket *so;
struct sockaddr addr;

1*
* Send data on socket.
*1
ssend()
{

register struct a {
int
fdes;
struct sockaddr *asa;
caddr t cbuf;
unsigned count;
"uap = (struct a ")u.u ap;
register struct file * fp;
struct sockaddr sa;
fp

=

fp - getf(uap->fdes);
i f (fp =

getf(uap->fdes);

i f (fp

~

0)

return;
i f «fp->f_flag & FSOCKET) -

u.u_error
return;

=

0)

{

ENOTSOCK;

u.u_base = uap->cbuf;
u.u_count = uap->count;
u. u segflg - 0;
if (useracc(uap->cbuf, uap->count, B READ) 0 II
uap->asa && copyin«Caddr_t)Uap->asa, (caddr_t)&sa, sizeof (sa») {
u.u_error - EFAULT;
return;
u.u_error - so send ( (struct socket *) fp->f_socket, uap->asa
u.u_rvall ~ uap->count - u.u_count;

/*
* Receive data on socket.
*I
sreceive ()
{

register struct a {
int
fdes;
struct sockaddr *asa;
caddr t ebUf;
u int- count;
*uap - (struct a *)u.u ap;
register struct file *fp;
struct sockaddr sa;
fp - qetf (uap->fdes) :
if (fp ~ 0)

0)

return:
i f «fp->f_flag & FSOCKET) 0) {
u.u_error - ENOTSOCK;
return;
l
so = (struct socket *) fp->f_socket:
u.u error =
(*so->soyroto->pr_usrreq) (so, PRU_SOCKADDR, 0, (caddr_t) &addr):
if (u.u error)
-return;
if (copyout«caddr_t)&addr, (caddr_t)uap->asa, sizeof (addr»))
u.u_error = EFAULT;

&sa

0);

partab.c

Fri Sep

5 19:07:56 1986

1* (Ht) partab. c 1.1 *1
char partab [1 = {
0001,0201,0201,0001,0201,0001,0001, 0201,
0202, 0004, 0003, 0205, 0007,0206,0201,0001,
0201,0001,0001,0201,0001,0201,0201,0001,
0001,0201,0201,0001, 0201, 0001, 0001, 0201,
0200,0000, 0000, 0200, 0000, 0200, 0200, 0000,
0000, 0200, 0200, 0000, 0200, 0000, 0000, 0200,
0000,0200, 0200, 0000, 0200, 0000, 0000, 0200,
0200, 0000, 0000, 0200, 0000, 0200, 0200, 0000,
0200, 0000, 0000, 0200, 0000, 0200, 0200, 0000,
0000, 0200, 0200, 0000, 0200, 0000, 0000, 0200,
0000, 0200, 0200, 0000, 0200, 0000, 0000, 0200,
0200, 0000, 0000, 0200, 0000, 0200, 0200, 0000,
0000, 0200, 0200, 0000, 0200, 0000, 0000, 0200,
0200, 0000, 0000, 0200, 0000, 0200, 0200, 0000,
0200, 0000, 0000, 0200, 0000, 0200, 0200, 0000,
0000, 0200, 0200, 0000, 0200, 0000, 0000, 0201,
0210,0210,0210, 0210, 0210, 0210, 0210, 0210,
0210,0210,0210, 0210, 0210, 0210, 0210, 0210,
0210, 0210, 0210, 0210, 0210, 0210, 0210, 0210,
0210,0210, 0210, 0210, 0210, 0210, 0210, 0210,
0210, 0210, 0210, 0210, 0210, 0210, 0210, 0210,
0210, 0210, 0210, 0210, 0210, 0210, 0210, 0210,
0210, 0210, 0210, 0210, 0210, 0210, 0210, 0210,
0210,0210, 0210, 0210, 0210, 0210, 0210, 0210,
0210, 0210, 0210, 0210, 0210, 0210, 0210, 0210,
0210,0210,0210, 0210, 0210, 0210, 0210, 0210,
0210, 0210, 0210, 0210, 0210, 0210, 0210, 0210,
0210,0210,0210,0210, 0210, 0210, 0210, 0210,
0210,0210, 0210, 0210, 0210, 0210, 0210, 0210,
0210,0210, 0210, 0210, 0210, 0210, 0210, 0210,
0210,0210, 0210, 0210, 0210, 0210, 0210, 0210,
0210, 0210, 0210, 0210, 0210, 0210, 0210, 0210
):

1

pipe.c

Fri Sep

5 19:07:57 1986

1* @(t)pipe.c
1.4 *1
tinclude "sys!param.h"
tinclude OIsys/types .h"
finclude IIsys/systm.h"
finclude "sys/dir .h"
tinclude "sys/signal.h"
finclude "sys/buf. hOI
tinclude OIsys/filsys . hOI
finclude OIsys/user . hOI
finclude ·sys!errno.h"
tinclude "sys!inode. hOI
tinclude ·sys!file.h"
tinclude "sys/mount . hOI
tinclude "sys/var.hll

1
if (mode&FREAD) {
while (ip->i fwcnt = 0) {
if (mode&FNDELAY II ip->i_size)
return:
(void) sleep ( (caddr_t) &ip->i_fwcnt, PPIPE):

if (mode&FWRITE)
while (ip->i frcnt = 0)
(void) sleep ( (caddr_t) &ip->i_frcnt, PPIPE):

/*

*
*

/*

*

The sys-pipe entry.
* Allocate an inode on the root device.
" Allocate 2 file structures.
* Put it all together with flags.
*/
pipet)

closep(ip, mode)
register struct inode * ip:
register mode:
{

{

register i:
daddr_t bn:

register struct inode "ip:
register struct file *rf, *wf:
int r:
register struct user "up:

if (mode&FREAD) {
if «--ip->i_frcnt ~ 0) && (ip->i_fflag&IFIW»
ip->i fflag &- -IFIW:
wakeup( (caddr_t) &ip->i_fwcnt):

up - &u:
ip = ialloc(getpdev(j, IFIFO, 0):
if(ip - NULL)
return:
rf = falloc (ip, FREAD):
if (rf ~ NULL) {
iput(ip) :
return:

if (mode&FWRITE) {
if «--ip->i fwcnt - 0) && (ip->i fflag&IFIR»
ip->i fflag &- -IFIR:
wakeup ( (caddr_tl &ip->i_frcnt):

r = up->u rval1:
wf = falloc (ip, FWRITE):
if (wf - NULL) {

if «ip->i_frcnt - 0) && (ip->i_fwcnt = 0»
for (i=NFADDR-1; i>-O; i--) {
bn = ip->i faddr [i] ;
i f (bn = (daddr t) 0)
continue7
ip->i_faddr[i] - (daddr_t) 0;
free (ip->i_dev, bn);

rf->f next - ffreelist:
ffreelist = rf;
up->u ofile[r] - NULL;
iput(ip) ;
return;
up->u rval2
up->u::::rval1
ip->i count
ip->i-frcnt
ip->i-fwcnt
prele(ip) ;

=
=
=

up->u_rval1;
r:
2;
1;

=

1;

=

Close a pipe
Update counts and cleanup

*1

ip->i size = 0;
ip->i-frptr = 0;
ip->i- fwptr - 0;
ip->i::::flag 1- IUPDIICHG:

/*

* Lock a pipe.

/*
" Open a pipe
* Check read and write counts, delay as necessary
*/

*
*

If its already locked,
set the WANT bit and sleep.

*1
plock (ip)
register struct inode *ip;
{

openp (ip, mode)
register struct inode *ip;
register mode;

while (ip->i flag&ILOCK)
ip->i flag 1- IWANT;
(void) sleep ( (caddr_tl ip, PINOD):

{

if (mode&FREAD)
if (ip->i frcnttt =~ 0)
wakeup ( (caddr_t) &ip->i_frcnt);

ip->i_flag 1- lLOCK;

}

i f (mode&FWRITE) {
i f (mode&FNDELAY && ip->i frcnt -- 0) {
u.~error - ENXIO:
return;

if (ip->i fwcnt++ -- 0)
wakeup ( (caddr_t)&ip->i_fwcnt):

/*

* Unlock a pipe.

*

If WANT bit is on,

* wakeup.
" This routine is also used
* to unlock inodes in general.
*1
prele(ip)

{

pipe.c

Fri Sep

5 19:07:57 1986

reqister struct inode *ip;
{

ip->i flaq &- -ILOCK;
if(ip=>i flag&IWANT) {
Ip->i flag &- -IWANT;
wakeup ( (caddr_t)ip):

1*

* Return the mounted pipe device

*1
dev_t
getpdev()
{

register struct mount *mp:
register dey_ t dev:
dey ~ pipedev:
for Imp - &mount [01; mp < (struct mount *) v. ve mount; mp++)
if (mp->m flags != MFREE && dey ~ mp->m dey &&
mp->m=:bufp->b_un.b_filsys->s_ronly=O)
return (dev) :
return (rootdev) ;

2

prf.c

Fri Sep

5 19:07:58 1986

1

1* @(t)prLc
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

1.2 *1
"sys/param.h"
"sys/types. hOI
·sys/sysmacros.h"
"sys/systm.h"
"sys/buf.h"
·sys/conf. h"

} else if (c == 'D') {
printn(* (long *)adx, 10);
adx +- (sizeof (long) / sizeof (int)

* In case console is off,
* panicstr contains argument to last call to panic.

printn (n, b)
long n;
register b;

*1

{

1*

char

kpanicstr;

register i, nd, c;
int
flag;
int
plmax;
char d[12];

1*
*
*
*
*
*
"
"

- 1;

adx++;
got a loop;

Scaled down version of C Library printf.
Only %c %s %u %d (-%u) %0 %x %D are recognized.
Used to print diagnostic information
directly on console tty.
Since it is not interrupt driven,
all system activities are pretty much suspended.
Printf should not be used for chit-chat.

c - 1;
flag - n < 0;
if (flag)
n =

(-n);

if (b=8)
plmax = 11;
else if (b=10)
plmax - 10;
else if (b=16)
plmax = 8;
if (flag && b=10)
flag = 0;
C'putchar) (' -');

*1
/* VARARGSI *1
printf(fmt, xl)
register char "fmt;
unsigned xl;
{

register c;
register unsigned int *adx;
register int b, i, any;
char *s;

for (i-O;i- b) {
nd -- b;
c = 1;
) else
c - 0;

tifdef PRINTFSTALL
for (c - 0; c < PRINTFSTALL; c++)
tendif PRINTFSTALL
adx - &xl;
loop:
while«c = *fmt++) !- '%')
if(c ~ '\0')
return;
(*putchar) (c);

}

c = *fmt++;
if(c == 'd' II c == 'u' II c ~ '0' II c - 'x')
printn«long)*adx, c-'o'? 8: (c--'x'? 16:10»;
else if(c = 'c')
(*putchar) (*adx);
else if (c ~ 'b') {
= "adx++;
b
s
= (char ") "adx;
printn«long) b, *s++);
any
= 0;
if (b) {
(*putchar) (' <' ) ;
while (i = ·s++) {
if (b & (1 « (i - 1») {
if (any)
(*putchar) (',');
any
= 1;
for (; (c - *s) > 32; s++)
(*putchar) (c);

d[i] - nd;
n = nib;
if «n=O) && (flag=O»
break;
if (i=plmax)

i--;
for (;i>-O;i--) {
(*putchar) ("0123456789ABCDEF" [d [i]]) ;

1*
" Panic is called on unresolvable fatal errors.
* It syncs, prints "panic: mesg" and then lOOps.

*1
panic(s)
char *s;
if (s && panicstr)
printf("Double panic: %s\n", s);
else {
i f (s)
panicstr - s;
update ();
printf(Hpanic: .'s\n", panicstr?panicstr:"'Z?'Z");

else
for (; *s > 32; s++)
i f (any)

for (:;,
idle () :

(*putchar) ('>');
else if(c == , s') {
s - (char *) *adx;
while (c - ·s++)
(*putchar) (e) ;

1*
" prdev prints a warning message.
" dev is a block special device argument.

*;

prf.c

Fri Sep

5 19:07:58 1986

prdev (str, dev)
char *str:
dev_t dev:
{

register maj:
ma] = bmajor (dev) :
i f (maj >- bdevcnt)
printf(lI%s on bad dev %0(8) \n", str, dev):
return:
(*bdevsw [ma j 1 • d'-print) (minor (dev), str):

/*
* prcom prints a diagnostic from a device driver.
* prt is device dependent print routine.
*/
prcom(prt, bp, erl, er2)
int (*prt) ():
register struct buf *bp:
{

(*prt) (bp->b dev, "'nDevice error");
printf(Ubn =-%D er = %o,%o\n", bp->b_blkno, erl, er2);

2

priam.c

Fri Sep

1* tdefine HOWFAR xl
I" tdefine UNISOFT
1*

*

5 19:09:08 1986

1* allow access to boot partition "I

Priam Datatower

" (C) 1984 Unisoft Corp. of Berkeley CA
" UniPlus Source Code. This program is proprietary
" with Unisoft Corporation and is not to be reproduced
* or used in any manner except as authorized in
" writing by unisoft.

*1
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
+include
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
+include
tinclude
tinclude
tinclude
Hnclude
tincll,;.de
tinclude
tinclude

"sys/param.h"
nsys/config .h"
"sys/mmu.h"
"sys/types .h"
·sys/sysmacros.h"
• sysl dir . h"
"sys/signal.h"
IIsys/user. h"
"sys/errno.h"
·sys/utsname.h"
"sys/buf.h"
"sys/elog.h"
·sys/erec.h"
IIsys/iobuf .h"
·sys/systm.h"
·sys/var.h"
"sys/uioctl.h"
"sys/al_ioctl.hu
• sysl diskformat. h"
"setjmp.h"
"sys/reg.h"
"sys/altblk.h"
·sys/cops.h"
II sysIpport . hOI
"sys/priam.h"
·sys/swapsz .h"

tdefine logical (x)
tdefine physical (x)
tdefine splpm
spl5

(minor (x) & 7)
«minor (x) & OxFO) »

1
char
pmresults[NPMRES];
1* result regs. for last command comp ack *1
int
pm..'lblks[NPM];
1* number of blocks on disk *1
int
pmcblkcnt;
1* current block count *1
struct pmfmtparms pmfmt;
Ix format parameters for packet-based format cmd *1
struct pmfmtstat pmfstat;
1* format status from packet-based format cmd xl
1* variables needed to share info for interrupt routines */
char
pmstate;
1* idling or waiting for interrupt xl
tdefine IDLING
tdefine INITING
Ix 1st intr while reading xl
tdefine READING1
tdefine READING2
3
1* 2nd intr while reading *1
tdefine WRITING1
4
1* 1st intr while writing *1
tdefine WRITING2
5
/* 2nd intr while writing xl
fdefine FMTINGl
6
I" 1st intr while formatting */
Me fine FMTING2
7
1* 2nd intr while formatting *1
tdefine FMTING3
1* 3rd intr while formatting *1
tdefine FMTING4
9
1* 4th intr while formatting xl
caddr t pmma;
1* current memory address * I
Ix error value from intr * I
char - pmierror;
pmopen (dev)
register dev;
{

register punit;
extern char slot [ ] ;
punit - physical (dev);
i f (punit >- NPM) (
u.u_error = ENXIO;
return(-1) ;
i f (slot [punitJ !- PM3)
printf(IIUnix pmopen: no Priam card in slot %d\n", punit);
u. u error = ENODEV;
return (-1);
i f (pmiflag[punit] ~ 0) {
i f (pmdinit (dev) I (
u. u error ~ EIO;
return (-1) ;

Ix eight logicals per phys "I
4)/* 10 physical devs *1

}

pmiflag[punit]++;
return(O) ;

Ix

*
*

When the disk is first opened its size is determined and pm_sizes is
initialized accordingly (in pmdinit).

*

" The first 100 blocks are reserved for the boot program and
" are inaccessible via unix.

"I
'define MAXBOOT 100
struct pm_sizes (
daddr_t sz_offset;
daddr t sz size;
) pm_sizes [NPM] [8]7
tdefine GETBUF (bpI
splpm (I; \
while (bp->b_flags & B_BUSY) ( \
bp->b flags 1- B WANTED;
(void)sleep( (Caddr_t)bp, PRIBIO+l);
I \
bp->b flags 1- B_BUSY;
spIO()
'define FREEBUF (bp)
splpm () ;
i f (bp->b flags & B HANTED) \
wakeup ( (caddr t)bp); \
bp->b flags - 0; \
splO ()
struct
struct
struct
struct
char

1*

iostat pmstat [NPM] ;
iobuf
pmtab - tabinit (PM3,pmstat);
1* active buffer header *1
buf
pmcbuf;
1* command buffer *1
buf
pmrbuf;
pmiflaq[NPMJ;

pmdinit - initialize device (sequence up)

*1
pmdinit (dev)
register dev_t dev;
{

register
register
register
register

struct buf *bp = &pmcbuf;
punit, ~;
struct pm sizes * sp;
daddr_t offset, size;

punit - physical (devl ;
GETBUF (bp) ;
bp->b dev = dev;
bp->b-resid - PMRDEVPMS;
pmnblks [punit] - 0;
pmstrategy (bpi;
iowait (bpi;
i - bp->b_flags & B_ERROR;
FREEBUF (bpi;
i f (i)

return (-1) ;
sp - pm sizes [punit] :
offset:: MAXBOOT + 1;
size - pmnblks [punit] - offset;
sp[7] .sz offset - offset;
sp[7].sz-size - size;
spell .sz-offset - offset;
sp [1] . sz-size - PMNSIfAP;
offset
PMNSHAP;

+=

/*

avoid boot area

1* h - entire *1
1* b - swap

*l

*/

priam.c

Fri Sep

5 19:09:08 1986

2

size -- PMNSWAP;
if (size < 0) {
printf("Unix pmdinit: disk size - %d (insufficient) \n", pmnblks [punit]);
return (-1) ;
sp[O].sz_offset - offset;
1* a = root *1
sp[O].sz size - size;
for (i --2; i < 7; i++) {
sp[i].sz offset - (daddr t)(O); /* c-g =spare */
sp[i].sz::::size - (daddr_tJO;
return (0) ;

pmstrategy (bp)
register struct buf *bp;
{

lunit - logical (bp->b dev);
punit ~ physical (bp->b dev);
offset - bp->b bcount :: bp->b resid;
bn = bp->b blkiio + btod(offset);
/* logical block number */
i f (bp->b_resid < BSIZE II bn >- pm_sizes [punit] [lunit].sz_size) {
next:
tifdef HOWFAR
if (bp->b resid ! - 0)
printf (·Unix pmstart: blkno-%d resid-%d bn=%d\n",
bp->b_blknO, bp->b_resid, bn);
tendif HOWFAR
pmtab.b active - 0;
pmtab.b-errcnt = 0;
blkacty- &= - (1 «PM3) ;
pmtab.b actf = bp->av forw;
iodone (bp) ;
goto loop;

register punit, lunit, bn;
punit = physical (bp->b dev);
if (bp - &pmcbuf) { /* if command */
pmstat[punit).io Misc++; /* errlog: */
splpm();
if (pmtab.b actf (struct buf *)NULL) /* set up links */
pmtab.b_actf - bp;
else
pmtab.b actl->av forw = bp;
pmtab.b actl = bp;
bp->av_forw = (struct buf *)NULL;
) else {
lunit = logical (bp->b dev);
bn = bp->b_blkno + pm::::sizes[punit] [lunit).sz_offset;
tifdef UNISOFT
if (bp->b_blkno <
) {
telse UNISOFT
if (bp->b_blkno <
II bn <= MAXBOOT)
tendif UNISOFT
tifdef HOWFAR
prdev("pmstrategy: illegal blkno", bp->b dev);
printf("blkno-%d bcount=%d\n", bp->b_blkiio, bp->b_bcount);
tendif HOWFAR
bp->b flags 1= B_ERROR;
iOdone (bp) ;
return;

bn +- pm sizes [punit] [lunit].sz offset; /* physical block number */
i f (pmrw(punit, bn, bp->b flagS&B READ, bp->b_un.b_addr+offset) != 0)
bp->b flags 1= B ERROR; goto next;
-

/ * ARGSUSED * /
pmioctl (dev, cmd, addr, flag)
dey t dey;
caddr_ t addr;
{

register punit;
register struct buf *bp;
punit - physical (dev);
i f (punit >- NPM) {
u.u_error = EINVAL;
return;
switch (cmd) {
case UIOCSIZE:
/* get size of Priam disk */
if (copyout t (caddr_t) &pmnblks [punit], (caddr_t) addr, 4»
u.u_error = EFAULT;
break;
case UIOCFORMAT:
i f (! suser () )
u.u_error - EPERM;
return;

pmstat[punit].io ops++; /* errlog: */
bp->b_resid = bn;
/* resid for disksort */
splpm() ;
disksort (&pmtab, bpJ;
if (pmtab.b_active
pmstart() ;

~

)

bp - &pmcbuf;
GETBUF (bp) ;
bp->b dey = dey;
bp->b- resid = PMPKTXFER;
pmstrategy (bp) ;
iowa it (bp) ;
if (bp->b_flags & B ERROR)
u.u_error --EIO;
FREEBUF (bp) ;
break;

0)

SPLO () ;

pmstart ()
{

register struct buf *bp;
register offset, bn, lunit, punit;

default:
u. u error
break;

loop:
if «bp

pmtab.b_actf) -- (struct buf *)NULL)
return;
i f (pmtab.b active == 0) {
pmtab.b active - 1;
if (bp ! = &pmcbuf)
bp->b_resid - bp->b_bcount;

1* stash the command in resid .. /

=

ENOTTY;

=

blkacty 1- (1«PM3);
~- &pmcbuf) {
if (pmcmd (bp) ! - 0)
/* b_resid holds the command */
bp->b_ flaqs 1- B_ERROR;
goto next;

i f (op

return;

pmcmd(bp)
register struct bUf *bp;
{

register
reqister
register
register

struct pm base *pmhwbase;
struct pm-base *addr;
punit;
struct pmfmtparms *fmtp = &pmfmt;

punit - physical (bp->b dev);
pmierror - 0;
switch (bp->b_resid)
case PMRDEVPMS:
/* read device parameters (spin up if necessary) wi

priam.c

Fri Sep

5 19:09:08 1986

3

pmhwbase = pmaddr(punit);
/" base address for this card */
addr - pmBWaddr(pmhwbase);
/" byte mode - waiting */
if (pmwaitrf (addr»
(
printf("Unix pmc:md: timeout before read dev parms\n");
return (-1) ;
addr->pO = 0;
/* device always 0 */
addr = pmBladdr (pmhwbase) ;
/* byte mode - intr enabled "/
pmstate = INITING;
addr->c:mdreg = PMRDEVPMS;
return (0) ;
case PMPKTXFER:
/* format disk (done with packet-based cOllll!!and) */
pmhwbase = pmaddr (punit);
/* base address for this card */
addr - pmBWaddr(pmhwbase);
/* byte mode - waiting */
if (pmwaitrf(addr» {
printf("Unix pmc:md: timeout before format\n");
return (-1);
fmtp->pm opcode - PMFMT; /" set up format parms packet * /
fmtp->pm-devsel - 0;
/* device select = 0 (no daisy chaining) * /
fmtp->pm-scntl - PMFBD; /* fill byte disabled, media type - 0 ,,/
fmtp->pm-fill - 0;
/* fill byte */
fmtp->pm-ssize - 536;
/* sector size */
fmtp->pm-dcntl = 0;
/" defect mapping enabled, 0 spares/track ,,/
fmtp->pm-ncyl = 10;
/* t cyls for alt tracks and alt sectors "/
fmtp->pm- cif = 0;
/" cyl interleave factor * /
fmtp->pm-hif = 1;
/* head interleave factor ,,/
fmtp->pm- sif - 1;
/* sector interleave factor */
fmtp->pm:=sitl - 0;
/* sector interleave table length */
addr->pO = 0;
/* device always 0 */
addr->p2 - 0;
/" MSB of packet length */
addr->p3 - sizeof(struct pmfmtparms);
/* LSB of packet length */
addr - prnBIaddr (pmhwbase);
/* byte mode - intr enabled * /
pmstate - FMTINGl;
addr->c:mdreg - PMPKTXFER;
return (0) ;
default:
return (-1)

;

pmrw (unit, bn, rflag, addr)
register unit;
register bn;
register rflag;
register caddr t addr;
{
register struct pm base "pmhwbase;
register struct pm:=base *hwaddr;
register tmp;
pmhwbase = pmaddr{unit);
I" base address for this card ,,/
hwaddr - prnBWaddr (pmhwbase) ;
/* byte mode - waiting */
if (pmwaitrf{hwaddr»
(
printf{"pmrw: timeout before setting %s parameters"
rflag?"read": "write");
printf("card %d, bn %d, addr Ox%x\n", unit, bn, addr):
return(-I) ;

pmintr(ap)
struct args *ap;
(

register struct pm base *pmhwbase;
register struct pm:=base *addr;
register struct buf *bp;
register char status;
dev_t punit;
(void) splpmO;
punit = ap->a dev;
pmhwbase - pmaddr(punit);
1* base address for this card *1
addr - pmBWaddr (pmhwbase);
/* byte mode - waiting */
if (pmtab.b active -- 0) {
tifdef HOWFAR
printf("Unix pmintr: b_active = O\n");
tendif HOWFAR
spurious:
addr->c:mdreg = 0:
/" clear spurious intr (clrb) */
return;
if «bp
Hfdef HOWFAR

pmtab.b actf) = (struct buf *)NULL) {
printf(UUnix pmintr: b_actf = NULL\n");

=

tendif HOWFAR
goto spurious:
if (bp

&pmcbuf) {
/* if command "I
switch (bp->b resid) {
case PMRDEVPMS: /" read device parameters (spin up i f necessary) */
i f (pmstate != INITING)
goto spurious:
i f (pmierror = pmackcc(addr»
(
printf(Herror on read dev parms: /dev/pm%d%c .. ,
punit, 'a'+logical(bp->b_dev»:
printf(Ustatus Ox%x\n", pmierror);
bp->b_flags 1- B_ERROR:
} else {
register nheads, ncyls, nsecs:
nheads - PMNH(pmresults [1);
ncyls = PMNC (pmresults [1), pmresults [2]) ;
nsecs = PMNS (pmresults [3)):
pmnblks [punit) = nheads " ncyls " nsecs;

==

break;
case PMPKTXFER: /* format disk (done with packet-based command) *1
switch (pmstate) {
case FMTINGl:
1* intr to transfer packet * /
i f «addr->status & DTREQI - 0)
goto ackcc:
/" i f not waiting for data */
/* send packet "I
register char *cp - {char "I &pmfmt:
register i - sizeof (struct pmfmtparmsl;
do (
addr->pdata - *cp++;
I while ( --i );
}

wait:
hwaddr->pO = 0;
/* device always 0 "I
tmp - bn;
hwaddr->p3 - tmp & OxFF;
1* most sig. byte *1
tmp - tmp » 8;
hwaddr->p2 - tmp & OxFF;
1* middle byte *1
tmp - tmp » 8;
hwaddr->pI - tmp & OxFF;
1* least sig. byte * 1
hwaddr->p4 - 1;
1 * operation count - 1 sector * I
pmcblkcnt - 1;
hwaddr - pmBIaddr(pmhwbasel;
I * byte mode - intr enabled * I
pmma = addr;
pmierror - 0;
pmstate - rflag ? READINGI : WRITINGI;
hwaddr->c:mdreg - rflaq ? PMREAD : PMWRITE;
1* start r/w "I
return (0) ;

(void) pmackdt (addr) :
/* Apple's code doesn't check * /
pmstate++;
1* not done yet - wait for next intr */
return;
case FMTING2:
1* intr after packet complete *1
(void) pmackcc (addr);
(void) pmwaitrf (addr);
addr->pO - 0:
/* packet ID - 0 *1
addr - prnBIaddr (pmhwbase) ;
addr->c:mdreg - PMPKTRST; 1* read packet status *1
goto wait;
case FMTING3:
/" intr when status can be read *1
if «(addr->status & DTREQ) =- OJ
goto ackcc;
1* i f not waiting for data *1
/* read packet status *1
register char *cp - (char *1 &pmfstat;
reqister i - sizeof(struct pmfmtstat);
do (
*cp++ - addr->pdata;
} while ( --i );

Fri Sep

priam.c

ackcc:

5 19:09:08 1986

4
printf("bn %d\n", bn);
} else printf(H\nH);

(void)pmackdt(addr);
1* Apple's code doesn't check *1
goto wait:
case FMTING4:
1* intr after read packet status *1
(void) pmackcc (addr) ;
i f «pmfstat.pmystate !- PMPKTCOMP)
i 1 pmfstat.pmyristat) {
pmierror - pmfstat .pmyristat;
bp->b_flags 1- B_ERROR;

1* error logging *1
pmtab.io stp = &pmstat[punit];
pmreg[O]-:-draddr ~ (long) 0;
pmreg [0] . drvalue = pmierror;
pmreg[O].drname = "pmierror";
pmreg[O].drbits - "Priam disk status code";
pmreg[I].draddr = (long) 0;
pmreg[l] .drvalue - pmstate;
pmreg [1] . drname = "pmstate";
pmreg[l].drbits - "Priam driver state";
fmtberr (&pmtab,
(unsigned) punit,
(unsigned) 0,
1* cylinder *1
(unsigned) 0,
1* track *1
(unsigned)bn,
1* sector *1
(long) (sizeof(pmreg) Isizeof(pmreg[O]», 1* regcnt *1
&pmreg[O], &pmreg[I]);

break:
goto out;
if «addr->status & CMD_DONE) = 0) (
1* block transfer interrupt *1
i f (!pmcblkcnt) (
I" 2nd interrupt *1
i f «pmstate~READING2) II (pmstate-WRITING2»
goto done;
printf(IIUnix pmintr: state-%d, expecting 2nd\n", pmstate);
bp->b_flags 1- B_ERROR;
goto out;

1* 1st interrupt

logberr (&pmtab, 1);
blkacty &- - (1«PMJ);
pmtab.b active = 0;
pmtab . b- errcnt - 0;
pmtab.b-actf = bp->av forw;
iodone (bp) ;
-

*I

i f «pmstate!-READINGl) && (pmstate!=WRITINGl»

(
printf("Unix pmintr: state-%d, expecting Ist\n", pmstate);
bp->b flags I- B ERROR;
goto out:
-

} else
bp->b_resid -- 512:
pmstate = IDLING;
pmstart{) ;

pmcblkcnt -- :
i f (pmstate

READINGl)
pmrsect (punit): 1* sets pmierror for parity *1
~

else
pmwsect (punit);
pmstate++;
1* set to READING2 or WRITING2 *1
addr->cmdreg = PMCBTI; 1* clear block transfer intr *1
addr = pmBWIaddr(pmhwbase);
1* setup for next intr *1
status = addr->status;
return:
} else (
1* cmd completed (error) *1
i f «pmstate!=READING2) && (pmstate!=WRITING2»
printf(IIUnix pmintr: command complete, state=%d\n", pmstate);

1*
* read block to memory at pmma

* from PRIAMASM. TEXT - READ SECT

*1

-

pmrsect (punit)
register punit;
(

register
register
register
register

done:
if (status - pmackcc{addr»
(
1* ack intr *1
i f «pmstate=READING2) && (pmresults [0] == PMECCERR»
1* ECC err requiring scavenger write *1
status = PMECCERR;
else i f (pmresults [0] ~ PMDTIMOUT)
1* dev timeout - they reissue read/write *1
status - PMDTIMOUT;

struct pm base *pmhwbase:
struct pm-base *hwaddr;
short *waddr;
i:

1* base address for this card *1
pmhwbase - pmaddr(punit);
hwaddr = pmBWaddr (pmhwbase) ;
1* byte mode - waiting *1
while «hwaddr->status & DTREQ) ~ 0)
1* parity checking enabled *1
hwaddr - pmPaddr (pmhwbase) ;
waddr - (short *) pmma;
1* start read of first word *1
*waddr = hwaddr->data:
i = 12;
1* read and throwaway header * 1
do (
*waddr - hwaddr->data:
} while ( --I );
1* read 24-byte header */
waddr - (short *)pmma;
i - 255;
do (
*waddr++ - hwaddr->data;
} while ( - - i ) ;
1* read 510 bytes *1
hwaddr - pmNaddr(hwaddr):
1* read last 2 avoiding device cycle *1
*waddr - hwaddr->data;
hwaddr - pmpaddr (punit) ;
1* parity in 10 select space * 1
pmierror 1- (hwaddr->parity & PMPERROR);

}

if (pmierror 1- status)
bp->b_flags 1- B_ERROR;
out:

1*
" because a single buffer can take several io operations,

* we leave it to pmstart () to figure out when it's done
*1
i f (bp->b flags&B ERROR 1 1 bp -- &pmcbuf)
if (bp->b-flags & B ERROR) (
(-

-

register bn - 0;
struct deverreg pmreg [2] ;
printf("Unix: HARD I/O ERROR on Idev/pm%d%c "
punit, logical (bp->b dey) +' a'):
i f (pmierror) {
i f (pmierror & PMPERROR)
printf("parity error ");
if (status - (pmierror & -PMPERROR»
printf("error code Ox%x H, status);

* write block from memory at pmma
" from PRIAMASH.TEXT - iffiITE_SECT
"I
pmwsect (punit)
register punit;

}

(

i f (bp !- &pmcbuf) (
bn - bp->b_blkno + btod (bp->b_bcou:lt - bp->b_resid)
+ pm_sizes [punit] [logical (bp->b_dev) J. sz_offset;

1* log hard (unrecovered) error *1

1*

register struct pm base *pmhwbase;
register struct pm-base *hwaddr;
register short "waddr;

priam.c

Fri Sep

register i;
register short tmp

5 19:09:08 1986

5
register struct pm_base *addr;

=

0;

/* pmBWaddr */

{

register i;
pmhwbase = pmaddr (punit) ;
/*
hwaddr ~ pmBWaddr (pmhwbase) ;
/*
while «hwaddr->status & DTREQ) hwaddr = pmhwbase;
i - 12;
do {
/*
hwaddr->data - tmp:
} while ( --i );
/*
waddr = (short *)pmma:
i = 256;
do {
hwaddr->data - *waddr++;
} while ( --i );
/*

base address for this card */
byte mode - waiting */

addr->cmdreg = PMCBTI;
/* clear block transfer intr */
i - TlMELIMIT;
while «addr->status & BTR_INTI !- 0) {
i f (--i)
continue;
printf("Unix pmackdt: timeout\n"):
return (-1) ;

0)

write dummy header */
write 24 bytes */

addr = pmladdr (addr) ;
i - addr->status & BTR_INT;
return (0) ;

/* pmBWladdr */
/* setup for next intr */

write 512 bytes */

1*
* pmcinit - initialize controller (turn on motor)
* called from oem7init (config. c)

1*
" wait for register file not busy
* from PRIAMASM. TEXT and PRIAMCARDASM. TEXT - WAITRF

*1
pmcinit (unit)
register unit;

*1
pmwaitrf (addr)
register struct pm_base *addr;

{

register struct pm_base *addr;
register i;

{

register i;
i = TlMELIMIT;
while «addr->status & ISR_BUSYj !- 0) {
i f (--i)
continue;
return (-11 :

addr - pmaddr(unit);
1* hwbase *1
addr = pmBWaddr (addr); 1* byte mode - waiting *1
if «addr->status & CMD DONE) != 0) {
/* cmd complete must be false */
i f (pmwaitrf (addr»
{
printf(Utimeout with status CMD_DONE\nll);
goto err;

return(O) ;

/*
* acknowledge command completion
* from PRIAMASM. TEXT and PRIAMCARDASM. TEXT - ACKCC
*/
pmackcc (addr)
register struct pm_base *addr; /* pmBWaddr */

addr->cmdreq = 0;
1* command ack power up (clrb) */
i - TlMELIMIT;
while «addr->status & CMD_DONE) = 0) {
if (--i)
continue;
printf (lltimeout wai tinq for power up\n");
goto err;

{

register i;
i = TlMELIMIT;
while «addr->status & CMD_DONE) ~ 0) {
/* wait for cmd done */
i f (--i)
continue;
printf (llpmackcc: timeout waiting for CMD_DONE\nll);
return (-11 :
pmresults[O] = addr->rO:
/* transaction status */
pmresults[l] - addr->r1;
pmresults[2] - addr->r2;
pmresults [3] - addr->r3:
pmresul ts [4] = addr->r4:
pmresults [5] = addr->r5;
addr->cmdreg - 0:
/* send command acknowledge (clrb) */
i = TlMELIMIT;
while «addr->status & CMD_DONE) !- 0) (
/* wait 'til reset */
i f (--i)
continue;
printf("pmackcc: timeout waiting for CMD_DONE reset\n");
return (-1) ;
return (pmresults [0]

&

PMCTYPE); /* error completion type */

1*

* acknowledge data transfer
* from PRIAMASM.TEXT - ACKDT
" Their code does not check the return value, so who knows what'll happen
" if it times out?

*I

pmackdt (addr)

i f (pmwaitrf (addr» {
printf(lItimeout before software reset\n");
goto err;

addr->cmdreg = PMRESET;
/* issue software reset */
i f «i=pmackcc(addr)
!- PMICOMP) {
printf (Usoftware reset error Ox%x\n", i);
goto err;
i f (pmwaitrf (addr) )
printf("timeout before read mode\n");
goto err:

addr->pO = 0;
/* (clrb) */
addr->cmdreg - PMRMODE;
i f (pmackcc (addr»
(
printf("read mode cmd ack failed\n"):
goto err;
I
i f (pmwaitrf(addr»
(
printf(ntimeout after read mode\n");
goto err;
addr->pO - 0;
/* (clrb) */
if (pmresults[3] -- 2) {
printfC-Smart E controller not implemented'.r."!;
goto err:

I * set mode "logical sector mode" * /
addr->pl - PMLOGSECT;
/* (clrb) */
addr->p2 - 0;
addr->cmdreg - PMSMODE;
if (pmackcc (addr»
(
printf("set mode cmd ack failed\n");

Fri Sep

priam.c

5 19:09:08 1986

gata err;
i f (pmwaitrf (addr) )
printf("timeaut after set made\n");
gata err;
addr->pO

=

Ox40;

addr->pl - PMPSELl;
addr->p2 - PMlPARMS;
addr->cmdreg - PMSETP;
i f (pmackcc(addr»
{
printf ("set parms 1 cmd ack failed\n");
goto err;
i f (pmwaitrf (addr») {
printf("timeaut after set parms l\n");
gata err;

addr->pO - Ox40;
addr->p1 = PMPSELO;
addr->p2 = PMOPARMS;
addr->cmdreg = PMSETP;
if (pmackcc (addr» {
printf("set parms 0 cmd ack failed\n");
gata err;

err:

return 0;
printf("Unix pmcinit: can't initialize cantra1ler\n Q ) ;
return (-1) ;

pmread (dev)
dev_t dev;
{

physia(pmstrategy, &pmrbuf, dev, B_READ);
pmwrite (devl
dev_t dev;
{

physio(pmstrategy, &pmrbuf, dev, B_WRITE);
pmprint (dev, str)
char *str;
printf(U%s on priam drive 'lid, slice %d\n", str, (dev»4) &OxF, dev&7);

6

pro.c

Fri Sep

5 19:08:33 1986

1
tdefine ERROR (x)
tdefine ASSERT (e, p, m, x)
tendif

I*tdefine NOERROR */
tdefine MOREASM

1*

*

SY6522 disk driver

1* contrast change ok flag.

Maintained by the disk driver. When 0 the
* parallel port is not in use and may be switched to allow console contrast
* changes. If the contrast is waiting for the disk then ' 12 rcflag' is one.
* When convenient and this is set the disk will call 12ramp.-

*1
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

"sys/pararn..h H
"sys/config .h"
"sys/mmu.h"
"sys/types. hOI
"sys/sysmacros .h"
.. sysl dir. hOI
"sys!signal.h"
"sys/user.h"
"sys/errno.h"
"sys/utsname .h"
"sys/buf .h"
"sys/elog.h"
"sys/erec.h ll
·sys/iobuf .h"
·sysl systm.h"
·sys/var.h u
·sys/ttold.h"
·setjmp.h"
·sys/profile .h"
"sys/pport.h"
"sys/dyrofile.h"
·sys/cops.h"
·sys/ swapsz. hIt

tifdef notdef
tdefine logical (x)
tdefine interleave (x)
tdefine physical (x)
tendif

*1
int ppinuse:
extern char 12_rcflag:

/*

*

proopen - check for existence of controller
*/
pro open (dev)
{

int i:
register struct device d *devp:
int prointr () :
extern char slot [] :
i-physical (dev) :
if (i) (
/* for expansion slot check slot number and type * /
if (!PPOK(i) II (slot[PPSLOT(i)] !-PRO)) {
u.u_error - ENXIO:
return 1;

devp = pro da [i] :
u. u error:; 0;
if (iocheck(&devp->d ifr»
( asm(U nop Ii): }
if (prodata[i].pd da !- devp) { /* not already setup */
if (setppInt ( (prodata [i] . pd da - devpl, prointr) )
goto fail:
if (proinit (&prodata [i]»
freeppin(devp) :
goto fail:

/* these are in dyrofile.h */
(minor (x) & 7)
/* eight logicals per phys * /
(minor (x) & Ox8)
/* interleave bit for swaping *1
«minor (x) & OxFO) » 4)/* 10 physical devs */

char pro secmap[NSEC] - {
/*11*/ 0, 15, 14, 13, 12, 11, 10,

9,

8,

7,

6,

5,

~,

3,

2,

};

1* Logical Units */
/* The first 100 blocks
are inaccessible via
*/
tdefine MAXBOOT 100
struct prlrnap {
daddr_ t pm beg;
daddr t pm-len;
prlrnap[] - {"
/* a */ (PRNSWAP+101,
16955),
1* b */ (l0!,
PRNSWAP),
/* c * / {PRNSWAP+101,
7227},
/* d */ {9728, 9728),
/* e */ to,
0),
/* f */ {O,
7168},
/* g */ {7168, 2496},
/* h */ (l01,
19355),

are reserved for the beot program and
unix.

return 0;
root filesystern on 10 Meg. disk * /
swap area (2400 blocks) "/
root filesystem on 5 Meg. disk ,,/
2nd filesystern on 10 Meg. disk */
unused ,,/
old root filesystern (old a) */
1* old swap (old b) * /
/* f. s. using entire 10 Meg. disk "I

/*
/*
/*
/*
/*
/*

/* THESE MAY REPLACE f AND g ABOVE */
/* f
(4101, 15355),
/* alternate root f.s. on 10 Meg. disk */
/* g
(101,
4000),
/* alternate swap * /
iostat prost at [NPPDEVS] ;
iobuf protab - tabini t (PRO, prostat) ;
buf rprobuf;
proheader rphbuf;
proheader phbuf;

/ * active buffer header * /
/* Raw input-output buffer */

tHndef NOERROR
tdefine ERROR (x) printf ("HARD DISK ERROR "); p:dnt.f x
char "pro lefmt - "ASSERTION (%s) FAILED IN PROC %s ".
tdefine ASSERT (e, p, m, x) if (! (e»
{\
printf(pro_lefmt, "e", "p"); \
printf m;\
printf ("\n"); \
x; };

felse

u. u error = ENXIO;
prodata[i].pd_da = (struct device_d *)0;
return 1;

/* Base address in blocks */
/* Number of blocks in logical device "I

};

struct
struct
struct
struct
struct

)

} else {
fail:

/*

*

prostrateqy - set up to start the transfer

*1
prostrateqy (bp)
register struct buf *bp;
{

int pun - physical (bp->b dev);
register struct prodata *p - &prodata [pun] ;
register struct buf *up;
if (!p->pd da) (
prIntf(HAttempt to read/write unopened profile device\n");
printf(Ubp-%x dev-%x (Unit %d) \n",bp,bp->b dev,pun);
p->pd err - "device not open";
goto haderr;
if (bp->b blkno >- 0 &&
(bp->b-blkno < prlmap[logical (bp->b dev)] .pm len»
bp->av fbrw - (struct buf *) NULL: 1* last of all bufs and *.'
bp->ul::::forw - (struct buf *)NULL; /* last of units bufs */
SPL6();
/* must be highest of all ints for this code*1
if (protab.b actf -- NULL)
protab.b_actf - bp;
1* empty - put on front */
else
protab.b_actl->av_forw - bp; ;* else put at end *;

Fri Sep

pro.c

5 19:08:33 1986

2
devp->d ddrb 1- OxIC;
/* set port B bits 2,3,4 to out */
devp->d-irb &- -DEN:
/* set enable = true */
devp->d-irb 1= CMDIDRW: /* set command = false set direction - in */
devp->d-t2cl - zero:
devp->d-t2ch = zero:
devp->d- ler = FIRQ I FCAI:
zero - devp->d irb:
i f (zero & OCD) (
p->pd_state = SERR:
splx(pl) ;
return 1:

protab. b_ actl - bp;
i f (p->pd actv ~ 0)
p=>pd_actv = bp;

I

=:

*

/* controller inactive */
/* start of unit blk list */

Since we might fail before ever getting an interrupt
we must be prepared to do the buffer cleanup here also.

*I
while (prostart (p»
(
/" start up the transfer * /
bp->b resid = bp->b bcount:
bp->b=flags 1= B_ERROR:
prorelse (p, bp) :
I
I else (
/* link onto unit list *1
up->ul_forw

=

p->pd state - SCMD:
splx(pl) ;
return 0;

bp:
/*
* proread - process read from disk
*/
proread (dev)
dey t dey:

SPLO ();
return;

-

(

p->pd_err = "invalid blkno";

physio (pro strategy, &rprobuf, dey, B_READ);

haderr:
bp->b resid - bp->b bcount;
bp->b-flags 1- B ERROR;
iOdone (bp) ;
return;

/*

*

prowrite - process write to disk

*1
/*
" Release finished buffer and unlink from list. Two lists are maintained.
* The av forw pointers are used to link all the buffers in use by the driver
" onto the protab iobuf header. The av back pointers (dubbed ul forw) are
* used to link together the buffers into unit lists (headed by the prodata
* entry for that unit) .
*/
prorelse (p, bpI
register struct prodata *p;
register struct buf *bp;

prowrite (dev)
dey t dey;

-

(

physio (prostrategy, &rprobuf, dey, B_WRITE);

/*

* prostart - initiate the next logical io operation
*/
prostart (p)
register struct prodata *p;
{

(

register struct buf "up;

register struct buf *bp - p->pd_actv;

if (protab.b actf ~ bpI
/* first buffer */
if «protab.b actf - bp->av forw) (struct buf *) 0)
protab.b actl (struct buf *) 0;
) else
/* middle or last buffer */
for (up-protab.b_actf; up->av_forw !- bp; up-up->av_forw)
if (! up->av forw) panic ("prorelse: buf list error");
up->av forw ~ bp->av forw;
if (!up->av forw && (protab.b actl = bp»
protab.b_actl = up; -

i f (!bp)

p->pd actv = bp->ul forw;
iOdone (bp) ;
-

/* next buf for this unit */

/*
* proinit - initialize drive first time or after severe error
*/
proinit (p)
struct prodata *p;

register char zero - 0;
register struct device_d *devp - p->pd_da;
int pI:
p1 - sp16();
devp->d acr - zero;
devp->dycr - Ox6B;
devp->d ddra - zero;
i f (devp -- PPADDR)
devp->d_ddrb
else
devp->d.-ddrb

/* set controller CAl pulse mode strobe */
/* set port A bits to input **/
&-

Ox5C:

1* set BSY and OCD to input */

&-

OxEC;

/* two o,r fO\lI port =.rds */

return 0;
ASSERT (bp&&p, prostart, (lIbp=x%x p=x%x", bp, p) , while (1) )
p->pd limit - prlmap[logical (bp->b dev)] .pm beg; /* logical offset */
p->pd-blkno - bp->b blkno + p->pd limit;
/* starting blk f */
tHndef UNISOFT
if (p->pd_blkno <= MAXBOOT)
1* don't allow access to boot */
return (-1) ;
tendif UNISOFT
p->pd limit +- prlmap[logical (bp->b dey) l.pm len: /* max blk t + 1*/
p->pd-bcount = bp->b bcount;
p->pd- addr = bp->b
b addr;
return procmd(bp->b_flags, bp->b_dev, p->pd_blkno, (unsigned)p->pd_bcount);

un.

/*
* ProCInd - initiate next physical io operation

*/
proCInd(func, dey, bn, ct)
register daddr t bn:
unsigned ct: register int pun - physical (dev) :
register struct prodata *p - &prodata [pun] :
register struct cmd ·pc;
ASSERT (ct!-O,Procmd, ("ct-%d", ct), while (1»
Hfndef UNISOFT
i f Ibn <- MAXBOOT)
return(-l) ;
lendif UNIS0;FT

I

* check again to be sure *!

pro.c

Fri Sep

5 19:08:33 1986

if (p->pd state = SERR) {
if (proinit (p) )
return -1;

3

1* initialize drive *1

I * Send command * I
1* set dir-out *1
1* set port A bits to output *1
1* Now send command *1
cp = (char *) (&p->pd cmdb);
if !*cp - PRORB}l..D) p->pd_nxtst - SRDBLK;
else
p->pd_nxtst - SWRTD;

if (p->pd state - SCMD) {
devp->d irb &- -DRW;
devp->c(ddra = OxFF;

1* controller should not be busy now *1
1* Build Command (ok to send extra bytes on write cmd) *1
pc - &p->pd cmdb;
pc->p cmd =- (func & B READ) '] PROREAD : PROWRITE;
pc->p-high - bn » l6""i"
pc->p-mid - bn » 8;
if (ii;:terleave (dev) - 0)
else
pc->p low - Ibn & OxFO)
pc->p retry --10;
pc->p=:thold - 3;
p->pd state - SCMD;
p->pd=:nxtst - SCMD;

devp->d ira - *cp++; devp->d_ira
devp->d=:ira - *cp++; devp->d_ira

return;

return 0;

prointr (pun)
int pun;
{

register struct device_d *devp; 1* as *1
register char *cp;
1* a4 *1
register char csum;
1* d7 *1
register char zero = 0;
1* d6 *1
register struct buf *bp;
register struct prodata *p - &prodata [pun] ;
register short i;
struct proheader *ph;
devp = p->pd_da;

I*NOTUSED*I

*cp++; devp->d ira
"cp++; devp->d=:ira

=

=

*cp++;
*cp;

devp->d irb 1= DRW;
devp->d-ddra - zero;
if (proChk(p,p->pd nxtst»
p->pd_err :;; "failed to issue cmd to disk";
goto haderr;

1 pro_secmap[bn&OxF];

if (prochk (p, SCMD) )
1* sync controller to cmd state *1
if (!prochk(p,SCMD)
1* if it failed it should work now *1
return 0;
p->pd_err - "cant force disk into CMD state";
p->pd state - SERR;
returi;: -1;

=
=

1* will send data or get status next *1

if (p->pd state - SRDBLK II p->pd_state - SFINI) {/* Read status word *1
devp->d irb 1- DRW;
devp->d-ddra - zero;
p->pd_ shUf - 0;
cp - (char *) (&p->pd sbuf);
*cp++ - devp->d ira;*cp++ = devp->d-ira;
*cp++ - devp->d-ira;
*cp - devp->d ira;
p->pd sbuf &=--STATMSK; 1* mask off redund stat bits *1
if (p=>pd sbuf) {
ERROR ( ("dev %d: state-%d status-x%x\n",p-prodata,p->pd_state,p->pd_sbuf);
p->pd_err - "bad status";
goto haderr;
if (p->pd state = SRDBLK) ! 1* Read successful so pickup data*1
ASSERT (p->pd_ bcount>O, prointr, ( .... ) , goto haderr)

(void) spl6 (); 1* added April 4/84 to prevent panic in prorelse *1
1* changed from spl5 August 30/84 to fix multi-user bug on 2110 *1
1* ASSERT ( (stats&BSY) ~BSY, prointr, (Oldisk %d busy: state=%d, irb=x%x H , pun, p->pd_state, stats) , return (devp->d_ifr

i = sizeof (rphbuf) - 1;
cp - (char *) (&rphbuf);
do *cp++ = devp->d ira;
while (--1 !- -1);=

1* sizeof header

*1

devp->d9fl!')j)-~Pd_ addr;

i - min(SECSIZE, (unsiqned)p->pd_bcount);
Hfdef lint
csum = 0;
i - csum;
tendif
if «bp - p->pd actv) -- 0) {
1* spurious interrupt *1
1* printf(IISpurious INT on profile dey %d [at %xj\n",pun,devp); *1
devp->d ddrb 1= Ox80;
1* setup for a reset *1
devp->d-irb 1- Ox80;
devp->d- ddrb &- Ox7F;
devp->d-ifr - devp->d ifr;
1* reset interrupt trap *1
1* proii;:it(p); *1
return;

tifdef MOREASM
if «i

& 3)

=

i - (i
do {

0)

{

»

2) - 1;

asm ( .. movb a5@(9),a4@+ .. );
asm ( .. movb a5@(9),a4@+ .. );
asm (" movb a5@(9),a4@+ .. );
asm ( .. movb a5@(9),a4@+ .. );
1* asm (H movb a5@(9),d6 H); *1
1* asm (H movb d6,a4@+ "); *1
1* asm (n eorb d6,d7 01); *1
1* asm (" movb a5@(9),d6 "I; *1
1* asm (" movb d6,a4@+ "); *1
1* asm (OI eorb d6,d7 "); *1
1* ASSERT (bp!-O,prointr, ("dsk-%d ier-x%x ifr-x%x state-%d",pun,devp->d ier&255,devp->d ifr&255,p->pd state),return devp->d_ifr=Ox7F) *1 1* asm (M movb a5@(9),d6 H); *1
ASSERT «p->pd state! -SERR& &p->pd state! -SSTOP) , prointr, (lib flags-Ox'lsx":-bp->b flags), whIle (1) )
1* asm (" movb d6,a4@+ "); *1
ASSERT (physical (bp->b_dev)--pun,prointr, ("dev-x%x unit-%dH:-bp->b_dev,pun), whIle (1) )
1* asm (n eorb d6,d7 H); *1
1* asm (n movb a5@(9),d6 01); *1
devp->d ifr = devp->d ifr;
1* reset interrupt trap *1
1* asm (01 movb d6,a4@+ "); "I
-1*
1* asm (to eorb d6,d7 "); *1
* Note that 10 operations fail when OCD.
1* optimizes to DBRA *1
J while (--i !- -1);
" This may result in a 'panic'. lIHowing it to
else
* block and be restarted has it problems also.
tendif
*1
i--;
if (devp->d_irb & OCD) {
1* cable disconnected
*1
do {
p->pd err - "Open Cable Disconnect ";
asm (H movb a5@(9),a4@+ H);
goto haderr;
1* asm ( .. movb a5@(9),d6 "J; *1
1* asm (" movb d6,a4@+ "); *1
/* asm (" eorb d6,d7 "); *1

Fri Sep

pro.c

5 19:08:33 1986

4

} while (--i !- -1);

p->pd err = "didn't get to perfrom state";
goto haderr;

tifdef MOREASM
tendif

1* will pick up status next intr *1

return;
p->pd_err

1* Determine if

10 operation is completed or spans another block.
*1
p->pd bcount -- min(SECSIZE, (unsigned)p->pd bcount):
i f (p=>pd bcount <- 0 II ++p->pd bllmo >- p->pd lilnit) {
bp->b_resid - p->pd_bcount:
prorelse (p, bpI :
i f (p-prodata = 0) ppinuse = 0:
1* contrast */

1* next op started or no next op * /

p->pd addr += SECSIZE: /* setup for next block of io trans */
if(procmd(bp->b flags,bp->b dev,p->pd bllmo, (unsignedlp->pd bcount» {
p->pd. err = "Procmd- failed to-continue operation"; goto haderr;

/* end of i/o or beg of next blk */

return;

if (p->pd_state ~ SWRTD) {
/* send data */
p->pd nxtst = SFINI:
ASSERT (p->pd bcount>O, prointr, ("") , while (1) )
devp->d irb &- -DRW:
/* set dir=out *1
devp->d=:ddra = OxFF:
/" set port A bits to output */

bp->b resid = p->pd bcount;
bp->b-flags 1- B ERROR;
ERROR( ("dev %d: %s\n",p-prodata,p->pd_err»;
prorelse (p,bp! ;
p->pd_state - SERR;
while (prostart (p) ) ;

/"
* Get in sync with disk.
" (subroutine FINDD2 & CHKRSP from' profrom. text' document)
" Expects enable=true and Direction-in at start.
" If disk response is ' state' then returns 0 (success)
" otherwise fails (returns -1 if timeout and cur state if bad state).
*/
prochk (p, state)
register struct prodata *p;
register struct device_d *devp = p->pd_da;
register zero - 0;
register i;
int resp:
/* while «devp->d irb&BSY)-O); */
ASSERT «devp->d irb&BSY) =BSY,prochk, ("state=%d [waiting]", state) ,goto err)
/* while «devp=>d_irb&BSY)=O); ,,/

ph = &phbuf;
ph->ph fileid = p->pd bllmo ?O :OxAAAA;
i = sizeof (phbuf) - 1~
cp - (char *) (ph);
do devp->d ira = *cp++:
while (--i-!= -1):
cp = (char *)p->pd_addr:
/* place to get data from ,,/
i

=

"invalid state";

do I

if (prostart (p»
1* startup next buf in chain "I
p->pd err = "prostart failed on next blk":
goto haderr:
return:

=

haderr:

0» {I" PP inuse ,,/
if (state - SCMD && (p-prodata
/* ramp in progress ,,/
i f (12 rcflag)
- 12ramp(2);
1* so help it along "/
ppinuse = 1;
devp->d irb 1= DRW;
devp->d- ddra - zero;
devp->d=:irb &= -CMD;

min(SECSIZE, (unsigned)p->pd_bcount);

/" set input mode * /
/" set port A bits to input ,,/
/* set cmd and enable bufs */

tifdef MOREASM
if «i

& 3)

~ 0)

i - (i
do {

»

asm (" movb a4@+,a5@(9) H) ;
asm (" movb a4@+,a5@(9) H) ;
asm (" movb a4@+,a5@(9) H) ;
asm (M movb a4@+,a5@(9) ");
/* asm (" movb a4@+,d6 H);
*1
*/
/" asm (" eorb d6,d7 ");
/" asm (" movb d6,a5@(9) ");
"I
/* asm (" movb a4@+,d6 H);
*/
*/
/* asm (" eorb d6,d7 ");
("
movb
d6,a5@(9)
")
;
asm
/*
*/
*/
/* asm (" movb a4@+,d6 H);
*/
/" asm (" eorb d6,d7 H);
/* asm (" movb d6,a5@(9) ") ;
*/
,,/
/* asm (H movb a4@+,d6 ");
(ft
eorb
d6,d7
");
asm
*/
/"
/* asm (" movb d6, a5@ (9) H) ;
*/
} while (--i !- -1);
/* optimizes to DBRA ,,/
}

i - RSPTIME;
while (devp->d_irb&BSY

{

2) - 1;

else {

tendif

i--:
do {
asm (" movb a4@+,a5@ (9) "):
/ " aSIII (M movb a4@+,d6 "); */
/" asm (" eorb d6,d7 "); */
/* asm (00 moyb d6,aSI!(9) "): ,,/
} while (--i !- -1):
tifdef MOREASM
tendif
i f (proeM; (p, SPERFORM»

I

resp = PIDL;
i f (i > 0) {

&&

/* about Ims * /
i--); /* wait sig that resp byte is ready*/

/"
/*
i = devp->d ira;
/*
i f (i st~te)
/*
resp - PGO;
/*
devp->d irb &- - (DRWI CMD);
devp->d- ddra = OxFF;
devp->d-ira = resp;
devp->d- ier - FIRQ IFCA1;
devp->d-irb 1- CMD;
p->pd state = p->pd nxtst;
return (i ~ state)-?O :i;

reply to use if resp byte wrong * /
didn't timeout */
get response from disk * /
got correct state * /
reply to use if resp byte correct*/
/" set dir=out cmd=true */
/* set port A bits to output */
/* send reply (GO or RESET) */
/* enable interrupts * /
/" sig disk to read resp ,,/
/" setup next state ,,/

err:
if (p-prodata - 0) ppinuse - 0;
/" reset ppinuse flag ,,/
p->pd state = SERR;
p->pd-err - "EXCESSIVE DISK DELAY -- (is the drive plugged in?'?) ";
ERROR( ("deY id: %s\n",p-prodata,p->pd err»;
devp->d ddra = zero;
/" set port A bits to input */
devp->d-irb 1- CMDIDRW;
/" set dir-in, disable buffers */
devp->d-ier - -FIRQ;
/" disable all interrupts */
return (-1);

1* ARGSUSED * /
proioctl (dev, cmd, addr, flag)
dey t dey;
int-cmd;
caddr t addr;
lnt flag;
/*NOTUSED*/

pro.c

Fri Sep

5 19:08:33 1986

5

struct prodata *p - &prodata [physical (dev) 1 ;
switch (cmd) {
case TIOCGETP:
i f (copyout( (caddr_t) &p->pd_flags, addr, sizeof(p->pd_flags»)
u.u_error = EFAULT;
break;
case TIOCSETP:
i f (copyin (addr, (caddr_t) &p->pd_flags, sizeof (p->pd_flags) »
u.u_error = EFAULT;
break;
default:
u. u_error ~ ENOTTY;

proprint (dev, strl
char *str;
printf("%s on pro drive %d, slice %d\n", str, (dev»41&OxF, dev&7);

Fri Sep

proto.c
proto.c 4.22

1*

tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

5 19:09:18 1986

SOCK STREAM,
tcp input,
tcp- usrreq,
tcp:::init,

*1

82/06/20

"sys/param.h"
"sys/config.h"
"sys/types. h"
·sys/mmu.h"
ItsYs/sysmacros.h"
"net/misc.h"
"net/socket.h"
"net/protosw.h"
"net/in.h"
"net/in_systm.h"

IPPROTO_ TCP,
tcp_ ctlinput,

PR_ CONNREQUIRED I PR_ WANTRCVD,

0,

tcp_ fasttimo,

tcp_ slowtimo,

tcp_drain,

0,
0,

0,

raw_ctlinput,

0,
0,

0,

0,

0,

PF INET,
rip_output,

15,
0,

0,

0,

PF INET,
rip_output,

0,

0,

0,

0,

PF IMP LINK,
riIilp_output,

0,
0,

PR_ATOMIC I PR_ ADDR,

0,

hostslowtimo,

0,

PF PUP,
rpup_output,

0,
0,

PR_ATOMIC I PR_ ADDR,

0,

0,

0,

PF_INET,

0,

},

{ 0,

raw_input,
raw usrreq,
raw-init,

-

),

tifdef SRI
{ SOCK RAW,
rip_Input,
raw_usrreq,

1*

*

1

Protocol configuration table and routines to search it.

0,

PR_ATOMIC I PR_ADDR,
0,

0,

},

*

SHOULD IHCLUDE A HEADER FILE GIVING DESIRED PROTOCOLS

*1
/*

tendif
( SOCK RAW,
rip_input,
raw usrreq,

* Local protocol handler.

0, -

IPPROTO_RAW,

PR_ATOMIC I PR_ ADDR,

0,

*/
tif NIMP > 0
/*
* TCP/IP protocol family: IP, rCMP, UDP, TCP.
*/
ip output () ;
int
ip- init () , ip slowtimo () , ip drain (l ;
int
icmp input ( ) -;
int
udp input () , udp ctlinput () ;
int
udp-usrreq(); int
udp-init ();
int
tcp:::input ( ) , tcp_ ctlinput () ;
int
tcp usrreq () ;
int
tcp:::init (), tcp_fasttimo (), tcp_slowtimo () ,tcp_drain();
int
rip_input () ,rip_output ();
int

SOCK_RAW,
0,

0,

raw usrreq,
0, )

tendif
tif NPUP > 0
SOCK_RAW,
0,

0,

raw_ usrreq,
0,
}

tendif

1*

* IMP protocol family: raw interface.

};

* Using the raw interface entry to get the timer routine
* in is a kludge.

tdefine NPROTOSW

(sizeof(protosw) I sizeof(protosw[O]»

*/
struct

tinclude "net/imp.h"
tif HIM? > 0
int
rimp_output (), hostslowtimo () ;
tendif

protosw *protoswLAST

=

&protosw [NPROTOSW-l];

1*
* Operations on protocol table and protocol families.

*1
/*

* PUP-I protocol family: raw interface
*/
tinclude "net/pup.h"
Hf NPUP > 0
int
rpup_output ();
tendif

1*

* Initialize all protocols.
*/
pfinit ()
{

register struct protosw *pr;
for (pr

1*
* Sundries.
*1
struct protosw protosw [1
0,

-

1*

0,
0,

ip_output,

0,
0,

ip_init,

0,

ip_slowtimo,

ip_drain,

PF_IHET,

IPPROTO_ ICMP,

0,

0,

0,
0,

0,

0,

0,

PF_INET,

IPPROTO_ UDP,
udp_ctlinput,

PR_ ATOMI C i PR_ ADDrt,

0,
0,

0,

0,

{ 0,

0,
0,

},

I 0,
icmp_input,

i f (family -

},

I SOCK DGRAM,
udp_Input,
udp usrreq,
udP:::init,
j,

* Find a standard protocol in a protocol family
* of a specific type.
*I
struct protosw *
pffindtype ( family, type)
int family, type;
register struct prot09w *pr;

0,

0,

protoswLAST; pr >= protosw; pr--)
if (pr->pr init)
(*pr->pr_init) ();

=

0,

0)

return (0);
for (pr - protosw; pr <~ protoswLAST; pr++J
if (pr->pr family -- family && pr->pr_type
return (pr);
return (0):

type)

proto.c

Fri Sep

2

5 19:09:18 1986

1*
* Find a specified protocol in a specified protocol family.
*1
struct protosw *
pffindproto (family, protocol)
int family, protocol;
register struct protosw *pr;
if (family ~ 0)
return (0);
for (pr - protosw; pr <= protoswLAST; pr++)
if (pr->pr family == family && pr->pr protocol =
return (pr);
return (0):

tifdef notdef
pfctlinput (cmd, arg)
int cmd;
caddr_t arg;
register struct protosw *pr;
for (pr

protosw; pr <= protoswLAST: pr++)
if (pr->pr ctlinput)
(*pr->pr_ctlinput) (cmd, arg);

=

tendif

1*

* Slow timeout on all protocols.
*1

pfslowtimo ()
{

register struct protosw "pr;
for (pr

protoswLAST; pr >- protosw; pr--)
if (or->or slowtimo)
-(*pr->pr_slowtimo) () ;

=

pffasttimo ()
(

register struct protosw *pr;
for (pr - protoswLAST; pr >- protosw; pr--)
if (pr->pr fasttimo)
(*pr->pr_fasttimO) ();

protocol)

pty.c

Fri Sep

pty.c

1*

4.21

5 19:09:16 1986

82/03/23

1
1* No features (nor raw mode) *1
tp->t cflag - 0; tp->t oflag = 0;
tp->t-iflag = 0; tp->t-lflag = 0;
ttinit (tp);
- 1* set up default chars *1

*1

1*
* Pseudo-teletype Driver
* (Actually two drivers, requiring two entries in 'cdevsw')

*1

if (tp->t.J)roc)
1* ctrlr still around, *1
tp->t state 1- CARR ON;
while «tp->(~state & CARR_ON) == 0) (
tp->t state I- WOPEN;
(void) sleep ( (caddr_t) &tp->t_rawq, TTlPRl);

1*
*
*

billn -- 12/15/82. Mercilessly hacked for system 3.
Remote input editing, etc, need to rework it again
from the original.

To do

}

(*linesw[tp->t line).l open) (tp);
pti->pt_flags T- PF_PTSOPEN; -

*/
tinclude "net/pty.h"
tif NPTY
tinclude
tinclude
#include
#include
tinclude
tinclude
tinclude
tinclude
#include
#include
#include
#include
tinclude
tinclude
#include
tinclude
tinclude
tinclude
tinclude
tinclude

> 0
Usys/param. h"
"sys/config .h"
"sys/types .h"
"sys/mmu. h"
.. sysl sysmacros. h II
"sys/systm.h ll
·sys/tty. h"
"sys/ttold.h"
"sys/termio.h ll
·sys/ioctl.h"
·sys/dir.h"
·sys/siqnal.h ll
"syslerrno.h ll
·sys/user.h"
·sys/conf .h"
·sys/buf .h"
·sys/file .h"
"sys/proc.h"

ptsclose (dev)
dev_t dey;
register struct tty *tp;
register struct pt_ioctl *pti

~

i f (tp->tyroc)
(*linesw [tp->t line).l read) (tp) ;
wakeup ( (caddr_t) &tp->t=:rawq.c_Cf);
i f (pti->pt_selw) (
selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL);
pti->pt selw = 0;
pti->pt=:flags &= -PF_ WCOLL;

1* Chunk size iomoved from user */

Idev/tty[pp] '?
Idev/pty[pp),?

tty pt tty [NPTY) ;
pt ioctl (
int
pt flags;
int
pt=:gensym;
struct proc *pt selr, *pt_selw;
int
pt send;I pt_ioctl [NPTY); -

tdefine PF RCOLL
tdefine PF- WooLL
tdefine PF-NElO
tdefine PF-PKT
tdefine PF-STOPPED
tdefine PF-REMOTE
tdefine PF- NOS TOP
tdefine PF- WTlMER
1* billn
kludge */
tdefine PF PTSOPEN
tdefine P~PTCOPEN

-=

1* other end already gone'? *1

register struct tty *tp = &pt_tty[dev);
register struct pt_ioctl *pti = &pt_ioctl [minor (dev»);

/*

* ptc
*/
struct
struct

0)

ptsread (dev)
dev_t dey;

"net/misc.h"

* pts =

&pt_ioctl [minor (dev) 1;

tp - &pt tty [dev) ;
(*linesw[tp->t_line).l_clOSe) (tp);
pti->pt_flags &- -PF_PTSOPEN;
if «pti->pt_flags & PF_PTCOPEN)
tp->tyroc - 0;

·syslvar.h"

tdefine BUFSlZ 100

=

/*

*
*

write to pseudo-tty.
Wakeups of controlling tty will happen
* indirectly, when tty driver calls ptsstart.
*/
ptswrite (dev)
dev_t dey;

OxOl
Ox02
Ox04
Ox08
OxlO
Ox20
Ox40
Ox80

/* packet mode */

OxlOO
Ox200

/* pts side is open *1
/* ptc side is open */

register struct tty *tp;

/* user told stopped *1
/* remote and flow controlled input * /

tp - &pt tty [dev) ;
i f (tp->t_proc)
(*linesw[tp->t_line].l_write) (tp);

/* waiting for timer to flush *1

I*ARGSUSED* /
ptsopen(dev, flag)
dev_t dey;

ptcwakeup (tp)
struct tty *tp;
struct pt ioctl *pti
int s - sp15 () ;

register struct tty *tp;
register struct pt_ioctl *pti - &pt_ioctl[minor(devl);

=

&pt ioctl [tp - &pt tty [0 II ;
/ *-any NZ spl will lockout ptctimer * /

i f (pti->pt selr)
selWakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL);
pti->pt selr - 0;
pti->pt=:flaqs &- -PF_RCOLL;

i f (dev >- NPTY) {

u. u error - ENXIO;
return;
tp - &pt tty [dey] ;
i f «tp->t_st.ate & ISOPEN)

i f (pti->pt selw) (
selwakeup(pti->pt selw, pti->pt flags' PF_ifCOLL);
pti->pt_selw - 0;pti->pt_flags &- -PF_"COLL;
==

0) {

pty.c

Fri Sep

5 19:09:16 1986

2
register struct tty *tp;
register struct pt_ioctl *pti;
register c:

wakeup «caddr t) &tp->t outq. c cf);
splx(s);
-

ptctimer()
!
register struct tty *tp = &pt tty[O];
register struct pt_ioctl *pti-- &pt_ioctl [0] :
register i:

tp = &pt tty [dev] :
i f «tp->t_state& (CARR_aNI ISOPEN»
0)
return:
pti - &pt ioctl [dev]:
i f (pti->pt flags & PF PKT)
i f (pti->pt send) {
(voId) passc(pti->pt send):
pti->pt_send = 0:
return;
J
(void) passc(O):

timeout (ptctimer, (caddr_t)O, v.v_hz » 2):
for (i-O: ipt fl~gs &- PF- WTlMER) = 0)
contInue:
pti->pt flags &= -PF WTlMER:
if (tp->tyroc ~ 0)continue:
ptcwakeup (tp) :

while (tp->t outq.c cc = 0 II (tp->t state&TTSTOP»
if (pti->pt::::flags&PF_NEIO) { u.u_error = EWOULDBLOCK:
return;
(void) sleep( (caddr_t) &tp->t_outq.c_cf, TTIPRI);

/*ARGSUSED* /
ptcopen (dev, flag)
dey t dey;
int-flag:
register struct tty *tp:
struct pt ioctl *pti;
static first:
extern int ptsstart () :

while (tp->t outq.c cc && (c = getc(&tp->t_outq»
i f (Passc(c) < 0)
break;
tp->t state &= -BUSY:
if (tp->t state&OASLP)
tp->t_state &= -QASLP:
wakeup! !caddr_t) &tp->t_outq);

if (first - 0) {
first++:
ptctimer () ;

if (tp->t state&TTIOW && tp->t outq. c cc-O)
tp->t state &= -TTIOW: wakeup ( (caddr_t) &tp->t_oflag):

{

>=

0)

}

if (dev >= NPTY) {
u. u error = ENXIO:
return:
I
tp = &pt tty [dev] ;
if (tp->tyroc) {
u.u_error - EIO;
return:

/*
* System 5 does not have nbio normally
*/
/* tdefine IF_NBIO */

tp->t iflag - ICRNL I ISTRIP I IGNPAR:
tp->t- oflag - OPOST IONLCR ITlIB3:
tp-><:)flag = ISIG I lCANON: /* no echo -. /
tp->tyroc - ptsstart:
i f (tp->t state & WOPEN)
w-;;keup( (caddr t) &tp->t rawq);
tp->t state 1= CARR ON:
pti =-&pt_ioctl[dev];
pti->pt flags = 0:
pti->pt-send = 0;
pti->pt::::flags 1- PF_PTCOPEN;

ptcwri te (dev)
dev_t dey:
register struct tty -.tp;
register char *cp, *ce;
register int cc, c, ctmp:
char locbuf[BUFSIZ]:
tifdef IF NEIO
lnt cnt = 0;
tendif
tp = &pt tty [dev] ;
i f ((tp->t_state& (CARR_aNI ISOPENI) =
return;
do {
cc - MIN(u.u_count, BUFSIZ):
cp - locbuf:
iomove(cp, cc, B_WRITE):
if (u.u_error)
break:
ce - cp + cc:

ptcclose (dev)
dev_t dey:
register struct tty *tp:
register struct pt_ioctl *pti

=

&pt_ioctl [minor (devl]:

tp - &pt tty [dev] :
if (tp->t state & ISOPEN)
signal (tp->tygrp, SIGHUP I:
tp->t state &- -CARR ON:
/ * virtual carrier gone * /
ttyflush(tp, FREAD I FWRITE) :
pti->pt flags &- -PF PTCOPEN:
if «(ptI->pt flags &-PF PTSOPENl -- 0) /* other end already gone'? *1
tp->tyroc - 0:
/* mark closed */

0)

again:
while (cp < cel
while (tp->t delct && tp->t rawq. c cc >- TTYHOG - 2 l !
wakeup (caddr_t) &tp-=>t_rawq):
if (tp->t_state & TS_NBIO) {
u. u count +- ce - cpo
i f (cnt -- 0)
u.u_error - EWOULDBLOCK;
return;

ptcread (dev)
dev_t dey;
tendif

pty.c

Fri Sep

3

5 19:09:16 1986

register struct pt ioctl "pti - &pt ioctl [dev];
register int stop: -

/" Better than just flushing it! ,,/
/" Wait for something to be read ,,/
(void) sleep «caddr t) &tp->t rawq. c cf, TTOPRI);
goto again;
-

if (ttiocom(tp, cmd,

(int)addr, dey)

0)

/" else .• ,n ,,/
stop ~ tp->t iflag&IXON;
if (pti->pt flags & PF NOSTOP)
if (stop) {
pti->pt send &- TIOCPKT NOSTOP;
pti ->pt- send 1= TIOCPKT- DOSTOP;
Pti->ptflags &= -PF NOSTOP;
ptcwakeup(tp);
-

c - "cp++;
if (tp->t iflag & IXON) {
ctmp = C & 0177;
if (tp->t state & TTSTOP) {
if (c = CSTART 1 1 tp->t_iflag & IXANY)
l"tp->tJ)roc) (tp, T_RESUME);
} else
if (c - CSTOP)
("tp->tJ)roc) (tp, T_SUSPEND);
if Ic = CSTART 1 1 c = CSTOP)
continue;

)

) else {
if (stop = 0) {
pti->pt send &- -TIOCPKT_DOSTOP;
pti ->pt-send 1= TIOCPKT NOS TOP ;
pti->pt-flags 1- PF NOSTOP;
ptcwakeup (tp) ;
-

if (tp->t rbuLc ptr !- NULL) {
if ItP->t iflag&ISTRIP)
C-&= 0177;
"tp->t_rbuf .cJ)tr = c;
tp->t rbuLc count--;
("linesw[tp->t_line] . I_input) (tp);

ptsstart (tp, cmd)
register struct tty "tp;

cnt++;
fendif

{

register struct pt_ioctl *pti - &pt_ioctl[tp - &pt_tty[O]];
extern ttrstrt () ;

} while (u.u_count);

switch (cmd) {
case T_TIME:
tp->t_state &= -TIMEOUT;
goto start;

ptcioctl (dev, cmd, addr, flag)
caddr_t addr;
dey t dey;
{ register struct tty *tp = &pt tty [minor (dev) ] ;
register struct pt_ ioctl *pti- = &pt_ ioctl [dev] ;
if (cmd

case T_WFLUSH:
if (tp->t outq.c cc) {
while (getc(&tp->t_outq) >= 0)

TIOCPKT) {
int packet;
if (copyin{ (caddr_t)addr, (caddr_tl &packet, sizeof (packet)) I
u.u_error = EFAULT;
return;

=

tp->t_state &- -BUSY;
/* fall through */
case T_RESUME:
tp->t_state &- -TTSTOP;
wakeup«caddr t)&tp->t outq.c cf);
/* fall through "/
-

)

if (packet)
pti->pt_flags 1= PF_PKT;
else
return;
start:
if (cmd = FIONBIO)
int nbio;
if (copyin «caddr_t) addr, (caddr t)&nbio, sizeof (nbio») {
u. u_error = EFAULT;
return:

if (tp->t state& (TIMEOUT 1TTSTOP 1BUSY) )
break;
if (tp->t_state&TTIOW && tp->t_outq.c_cc=O)
tp->t state &= -TTIOW;
wakeup ( (caddr_t) &tp->t_oflag);
)

i f (nbio)
pti->pt_flags 1= PF_NBIO;
else

i f (pti->pt flags & PF STOPPED) {
pti=>pt flags &= -PF STOPPED;
pti->pt::::send = TIOCPKT_START;

return:

i f (tp->t outq.c cc < 200) {
pti->pt flags 1- PF_WTIMER:
return:-

}

/" IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG 111
i f « cmd=TIOCSETP) 1 1 I cmd-TCSETAW»
(
while Igetc(&tp->t outq) >= 0):
tp->t_state &- -BUSY;
ptsioctl (dev, cmd, addr, flag);
/" ARGSUSED* I
ptsioct1 (dev, cmd, addr, flag)
register caddr t addr:
register dey t - dev;
{

)

pti->pt_flags &= -PF_IfTIMER;
tp->t state 1- BUSY;
ptcwakeup (tp) ;
if (tp->t state'OASLP &&
tp->t::::outq.c_cc <- tt1owat(tp->t_cflaq&C9A.UD1)
tp->t state &- -OASLP;
wakeup ( (caddr_t) &tp->t_outq);
break;

-

register struct tty *tp

"I

=

&pt_tty [dey] ;

case T_SUSPEND:
tp->t_state 1- TTSTOP;

I

Fri Sep

pty.c

5 19:09:16 1986

4

pti->pt flags 1= PF STOPPED:
pti ->pt-send ! = TIoCPKT STOP:
break: case T_BLOCK:
tp->t state ! - TBLOCK;
tp->t-state &= -TTXON;
if(tp=>t outq.c cc > 0)
wakeup (caddr_t) &tp->t_outq.c_cf):
break;
case T RFLUSH:
- if (! (tp->t state&TBLOCK»
bre-;;-k:
case T_UNBLOCK:
tp->t state &= - (TTXOFF I TBLOCK) ;
if(tp=>t outq.c cc > 0)
wakeup caddr_ t) &tp->t_ outq. c _ cf) ;
break:

«

case T_BREAK:
tp->t state 1- TIMEOUT;
timeo'iit(ttrstrt, (caddr_t)tp, v.v_hz/4):
break:

ptcselect (dev, rw)
dev t dev:
int-rw:
register struct tty *tp = &pt tty [minor (dev) 1:
struct pt ioctl ·pti = &pt_ioctl [minor (dev) 1;
struct proc *p;
int s:
if «tp->t state& (CARR ONI ISOPEN» = OJ
return (1):
- 1* ?2'? billn *1
s = spl7 (I:
switch (rw)
case FREAD:
if (tp->t outq.c cc && (tp->t_state&TTSTOP)
splx(s); return (1):

~ 0)

{

}

if «p

=

pti->pt selr) && p->p wchan -- (caddr_t) &selwait)
pti->pt_flags 1- PF_RCOLL:

else
break:
case FWRITE:
splx(s) :
return 1:
tifdef notdef

1*

* only do this if using "PF_REMOTE" ala 4 .la.
"it? -- history ...

So why keep

*1
if (tp->t rawq.c cc splx(s) :return (1);

0)

{

if «p - pti->pt selwl && p->p wchan
pti->pt_flags 1- PF_WCOLL:
else
pti->pt_selw - u.uyrocp:
tendif
break:
j

splx(s);
return (0);
iendif

(caddr_tl &selwait)

pup.c

Fri Sep

pup.c

1*
tinclude
finclude
finclude
finclude
finclude
finclude
finclude
finclude
f incl ude
finclude
finclude
tinclude
tinclude
finclude

4.2

5 19:09:33 1986

82/06/20

*1

"sys/param.h"
"sys/config.h u
Hsys/errno.h"
"sys/types.h"
"sys/systm.h u
"net/misc.h"
"net/mbuf .h"
"net/protosw. h"
"net / socket. h H
"net 1 socketvar. h"
"net/in.h"
"net/in systm. h"
"net/af-:-h"
"net/pup.h"

tifdef PUP
pup_hash(spup, hpj
struct sockaddr pup "spup:
struct afhash *hp;
hp->afh nethash - spup->spup addr .pp net;
hp->afh- hosthash = spup->spup addr. pp host;
if (hp->afh hosthash < 0)
hp->afh_hosthash - -hp->afh_hosthash:
pup_netmatch(spupl, spup2)
struct sockaddr_pup *spupl, *spup2:
return (spupl->spup_addr .pp_net
fendif

=- spup2->spup_addr .pp_net):

1

raw cb.c

Fri Sep

4.16
raw cb.c
1*
tinclude IIsYs/para:m. h"
Usys/confiq
.hu
tinclude
tinclude "sys/errno.h"
tinclude "sys/types .h"
tinclude Usys/sysmacros .h"
tinclude "sysl systm. hOI
tinclude "sys/sysmacros.h"
tinclude Hsys/dir.h"
tinclude "sys/siqnal.hu
tinclude "sys/user.h"
tinclude Hnet/misc. h U
tinclude "netl socket. h"
tinclude "netl socket var . h"
tinclude "net/mbuf.h"
tinclude "net/protosw.h"

5 19:09:34 1986

83/02/10

1

*1

tinclude Anet/if .h"
tinclude "net/raw_ cb. h"

1*
* Disconnect and possibly release resources.
*1
raw_disconnect (rp)
struct rawcb *rp:

rp->rcb flaqs &- -RAW FADDR;
11< billn: -- meld with-old .•.
if (rp->rcb_socket->so_state & SS_NOFDREF)
*1
if (rp->rcb_socket->so_state & SS_USERGONE)
raw_detach (rp) ;

tifdef notdef
raw bind (so, na:m)
reqister struct socket *so;
struct mbuf *na:m;

1*
* Routines to manaqe the raw protocol control blocks.

struct sockaddr *addr - mtod(na:m, struct sockaddr *);
reqister struct rawcb *rp;

* TODO:
hash lookups by protocol family/protocol + address family
take care of unique address problems per AF?
redo address bindinq to allow wildcards

*1
/*

* Allocate a control block and a nominal a:mount

*

of buffer space for the socket.

*1
raw_attach (so)
register struct socket *so;

if (ifnet ~ 0)
return (EADDRNOTAVAIL);

1*
tinclude
*1
tinclude
tinclude
I * BEGIN

struct mbuf *m;
register struct rawcb *rp;

1* billn, meld wI old note don' t gtclr -- will it work?
m = m getclr (M DONTWAIT, MT PCB):
*1
m = m get (M DONTWAIT);
if (m-- 0)return (ENOBUFS);
0)
if (sbreserve (& so-> so snd, RAWSNDQ)
goto bad;
if (sbreserve (&so->so rcv, RAWRCVQ)
0)
goto bad2;
rp = mtod (m, struct rawcb *);
rp->rcb socket - so;
insque (rp, &rawcb);
so->soycb = (caddr_t)rp;
rp->rcb""'pcb = 0;
return (0);
bad2:
sbrelease(&so->so_snd) ;
bad:

" .. /h/domain.h"
Unet/in.h"
"net/in systm.h"
DUBIOUS-*1
1*
* Should we verify address not already in use?
* Some say yes, others no.
*1
switch (addr->sa_ family)

case AF_IMPLINK:
case AF lNET:
-if « (struct sockaddr in *) addr) ->sin addr. s addr &&
if ifwithaddr (addr) == 0)
- return (EADDRNOTAVAIL);
break;
tifdef PUP
1*
* curious, we convert PUP address format to internet
* to allow us to verify we're asking for an Ethernet
* interface. This is wrong, but things are heavily
* oriented towards the internet addressing scheme, and
* converting internet to PUP would be very expensive.
*1
case AF PUP: {
tinclude " .. /netpup/pup.h"
struct sockaddr""'pup * spup - (struct sockaddr_pup *) addr;
struct sockaddr_in inpup;

(void) m_free(m);
return (ENOBUFS);

bzero «caddr t) &inpup, (unsigned) sizeof (inpup) ) ;
inpup.sin faiiiily - AF INET;
inpup. sin- addr. s net ~ spup-> sp net;
inpup. sin- addr. s - impno - spup->sp host;
if (inpup-:-sin addr. s addr &&
if_ifwi thaddr ( (struct sockaddr *) &inpup) == 0)
return (EADDRNOTAVAIL);
break;

1*
* Detach the raw connection block and discard
* socket resources.
*I
raw detach (rp)
register struct rawcb *rp;
tendi~

struct socket *so - rp->rcb_socket;
default:
so->so""'pcb = 0;
sofree(so) ;
remque (rp) ;
m_freem (dtorn (rp) );

return (EAFNOSUPPORT);
!

/ * END DUBIOUS * /
rp

=

sotorawcb(so);

raw cb.c

Fri Sep

5 19:09:34 1986

bcopy( (caddr_t)addr, (caddr_t) &rp->rcb_laddr, sizeof (*addr»;
rp->rcb flaqs 1- RAW LADDR;
return (0);
)

tendif

1*
* Associate a peer's address with a
" raw connection block.

*1
raw_ connaddr (rp, nam)
stroct rawcb *rp;
struct mbuf *nam;
struct sockaddr * addr

=

mtod (nam, struct sockaddr * I ;

bcopy( (caddr t)addr, (caddr t) &rp->rcb faddr, sizeof(*addr»;
rp->rcb_flaq; I- RAW_FADDR;-

2

Fri Sep
1*
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

4.13

5 19:09:35 1986

82/06/20

1
m->m off = MMAXOFF - sizeof(struct ip);
m->m-len ~ sizeof(struct ip):
m->m-next - mO;
ip =-mtod(m, struct ip "I;
ip->ipy - so->soyroto->pryrotocol;
ip->ip len = sizeof(struct ip) + len:
if (rp=>rcb_flags & RAW_LADDRI {
sin = (struct sockaddr in "I &rp->rcb laddr;
i f (sin->sin family !=-AF lNET) {
error ~ EAFNOSUPPORT;
goto bad;

*1

"sys/param.h"
"sys/config .h"
Usys/errno.h"
"svs/tvnes.h"

"sYs/sY~tm.hU

"net/misc.h"
"net/mbuf.h"
"net/ socket. h H
-net/protosw. hOI
"net/socketvar .h"
"net/if.h"
"net/in. hit
"net lin systm.h"
"net I ip-:-h"
"net/ip_var.h"
"net/raw cb.h H
"net/route .h"
"errno.h"

) else
ip->ip src. s addr = 0;
ip->ip dst - «struct sockaddr in *) &rp->rcb_faddr) ->sin_addr;
ip->ip- ttl = MAXTTL;
return- lip_output (m, (struct mbuf ") 0, (struct route *) 0, 1»;
bad:
m_freem(m) ;
return (error);

1*
" Raw interface to IP protocol.
*/
static struct sockaddr in ripdst =
static struct sockaddr-in ripsrc static struct sockproto ripproto =

AF_lNET );
AF_lNET );
PF_INET );

1*
" setup generic address and protocol structures
" for raw input routine, then pass them along with
" mbuf chain.
"/
rip input (m)
struct mbuf "m;
register struct ip * ip = mtod (m, struct ip ");
register int hlen - ip->ip_hl « 2;
ripproto. spyrotocol = ip->ipy;
ripdst.sin_addr - ip->ip_dst;
ripsrc. sin addr = ip->ip src;
m adj (m, hlen);
raw input (m, &ripproto, (struct sockaddr *) &ripsrc,
(~truct sockaddr ") &ripdst) ;

1*
" Generate IP header and pass packet to ip output.
" Tack on options user may have setup with-control call.
*/
rip_output(mO, so)
struct mbuf *mO;
struct socket *so;
register struct mbuf *m;
register struct ip *ip;
int len - 0, error;
struct rawcb *rp = sotorawcb(so);
struct sockaddr_in "sin;

1*
" Calculate data length and get an mbuf

* for IP header.
*/
for (m

mO; m; m - m->m next)
len +- m->m len;m - m qet (M DONTWAITI;
i f (m-- 0)-1
error - ENOBUFS;
goto bad;
~

/"
" Fill in IP header as needed.
"/

I

raw_usrreq:~

I"
tinclude
tinclude
tinclude
finclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

raw usrreq.c
4.25
"sYs/param.h"
"sys/config. hOI
"sys/errno.h"
"sys/types.h"
"sys/sysmacros.h"

Fri Sep
83/02/10

5 19:09:36 1986

1

,,/

"sys/systm.h"
"sys/sysmacros.h"
"sys/dir.h u
·sys/signal.h"
"sys/user. h"
"net/misc.h"
"net/mbuf .hu
"net/socket.h"
"net/socketvar .h"
"net/protosw. h"
"net/in.h"
"net/in systm.h"
"net/if-:-hu
"net/af .h"
"errno .h"
"net/raw_cb.h"

/*
* Raw protocol input routine. Process packets entered
* into the queue at interrupt time. Find the socket
" associated with the packet (5) and move them over. If
* nothing exists for this packet, drop it.
,,/
rawintr()
{

int s;
struct mbuf "m;
register struct rawcb *rp;
register struct protosw *lproto;
register struct raw header "rh;
struct socket *last;
next:
s = splimp () ;
IF DEQUEUE (&rawintrq, m);
splx(s) ;
i f (m 0)
return;
rh - mtod(m, struct raw_header *);
last = 0;
for (rp ~ rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next)
Iproto - rp->rcb_socket->so_proto;
if (lproto->pr_family !- rh->rawyroto.sp_family)
continue;
if (lproto->pryrotocol &&
Iproto->pryrotocol != rh->rawyroto. spyrotocol)
continue;

1*
* Initialize raw connection block q.

*1
raw init ()
{ rawcb.rcb_next - rawcb.rcbyrev = &rawcb;
rawintrq.iftt-maxlen = IFQ_MAXLEN;

1*

1*

* We assume the lower level routines have
* placed the address in a canonical format
" suitable for a structure comparison.

" Raw protocol interface.

*1
raw input (mO, proto, src, dst)
struct mbuf *mO;
struct sockproto "proto;
struct sockaddr "src, *dst;
register struct mbuf *m;
struct raw_header "rh;
int s;

/"
* Rip off an mbuf for a generic header.
"I
/" billn -- meld with old
m = m get (M DONTWAIT, MT HEADER);
*1
m - m get (M DONTWAIT);
i f (m-== O)-{

,,/
tdefine equal (a1, a2) \
(bcmp«caddr t)&(a1), (caddr t)&(a2), sizeof (struct sockaddr» == 0)
if «rp->rcb flags &-RAW LADDR) &&
! equal (rp->rcb laddr~ rh->raw dst»)
continue; i f «rp->rcb flags & RAW FADDR) &&
!equal(rp->rcb faddr~ rh->raw src»
continue; i f (last) {
struct mbuf *n;
if (In = m_copy(m->m_next, 0, (int)M_COPYALL» -- 0)
goto nospace;
if (sbappendaddr(&last->so_rcv, &rh->raw_src, n)~O)
1* should notify about lost packet */
m_ freem (n) ;
goto nospace;

return;
rn->rn next - rnO;
m->m-len = sizeof(struct raw_header);
rh =-rntod(m, struct raw_header *);
rh->raw_dst - *dst;
rh->raw src = *src;
rh->rawyroto - *proto;

/"
*
"
"
"

.. /

Header now contains enough info to decide
which socket to place packet in (if any).
Queue it up for the raw protocol process
running at software interrupt level.

s = splimp () ;
i f (IF_QFULL (&rawintrq) )
m_freern(m) ;
else
IF ENQUEUE(&rawintrq, m);
splx(s); schednetisr (NETISR_RAW);

sorwakeup(last) ;
nospace:
last - rp->rcb_socket;
i f (last) {
I" header "I
m = rn free (m);
if (sbappendaddr(&last->so_rcv, &rh->raw_src, m) ~
goto drop;
sorwakeup(last) ;
goto next;

drop:
m freem(m);
gato next;

I*ARGSUSED*/
raw ctlinput (cmd, arg)
int cmd;
caddr_t argo

0)

Fri Sep

5 19:09:36 1986

2
i f (rp->rcb flags & RAW FADDR)
return (EISCONN):
raw connaddr (rp, nam):
} else i f ({"rp->rcb_flags & RAW_FADDR) = 0)
return (ENOTCONN):
error = (*so->soyroto->pr_output) (m, so):
i f (nam)
rp->rcb_flags &= -RAW_FADDR:
break:

i f (cmd < 0 II cmd > PRC_NCMDS)
return:
/" INCOMPLETE "/

/" ARGSUSED* /
raw usrreq (so, req, m, nam)
struct socket *so:
int req;
struct mbuf "m, "nam;
register struct rawcb "rp
int error - 0:

~

case PRU ABORT:
;aw disconnect (rp) :
sof;ee(so) ;
soisdisconnected(so) ;
break:

sotorawcb(so):

i f (rp = 0 && req !- PRU ATTACH)
return (EINVAL): -

switch (req) {

/*
" Allocate a raw control block and fill in the
.. necessary info to allow packets to be routed to
* the appropriate raw interface routine.
*/
case PRU ATTACH:
If «so->so_state & SS PRIV) = 0)
return (RACCES):
i f (rp)
return (EINVAL);
error - raw_attach (so) :
break;
/*
.. Destroy state just before socket deallocation.
" Flush data or not depending on the options.
*/
case PRU DETACH:
If (rp = 0)
return (ENOTCONN);
raw_detach (rpl :
break:

/*

* If a socket isn't bound to a single address,
* the raw input routine will hand it anything
* within that protocol family (assuming there's

* nothing else around it should go to) .
*/
case PRU CONNECT:
If (rp->rcb flags & RAW FADDR)
return (EISCONN);
raw connaddr (rp, nam):
sOi-;connected(so) ;
break;
case PRU DISCONNECT:
If «rp->rcb flags & RAW FADDR) retu;n (ENOTCONN);
raw_disconnect (rp):
soisdisconnected(so) ;
break;

0)

/*
* Mark the connection as being incapable of further input .
/

..

socantsendmore (so) ;
break;

I"
.. Ship a packet out. The appropriate raw output
" routine handles any massaging necessary .
/

..

if (nam)

/*
.. Not supported.
*/
case PRU_ACCEPT:
case PRU_RCVD:
case PRU_CONTROL:
case PRU_SENSE:
case PRU_RCVOOB:
case PRU SENDOOB:
error = EOPNOTSUPP;
break;
case PRU_SOCKADDR:
bcopy( (caddr_t) &rp->rcb_laddr, mtod(nam, caddr_t),
sizeof (struct sockaddr»:
nam->m len - sizeof (struct sockaddr);
break;default:
panic (IIraw_usrreq") ;
return (error);

rdwri.c

Fri Sep

5 19:07:58 1986

1
break;
on - up->uyboff;
if «n = up->uybsize) ~ 0)
break;
dey = up->uybdev;
i f «lonq)bnu_rablock)
bp = breada(dev, bn, up->u_rablock);
else
bp - bread(dev, bn);
if (bp->b resid) {

1* @(t)rdwri.c
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

1.4 *1
"sys/param.h"
"sys/types .hU
"sys/sysmacros . hOI
"sys/inode.h"
"sys/dir.h"
·sys/signal.h"
·sys/user. hOI
·sys/proc.h"
·sys/errno.h"
"sys/buf.h"
·sys/conf .h"
·sys/file.h"
·sys/systm.h"
• sys/tty. hOI

n-- 0;

1*

* Read the file corresponding to
* the inode pointed at by the argument.
" The actual read arguments are found
* in the variables:
u base
core address for destination
u:=offset
byte offset in file
u_count
number of bytes to read
u_segflg
read to kernelluser luser I

i f (n!=O)
iomove(bp->b un.b addr+on, (int)n, B_READI;
i f (type ~ lFIFO) {ip->i size -- n;
i f (up->u offset >= PlPSlZ)
up->u offset = 0;
i f «on+n) =-FSBSIZE(dev) && ip->i_size < (PIPSlZ-FsBSIZE(dev»)
bp->b_flags &= -B_DELWRl;

*1
readi(ip)
register struct inode *ip;

brelse (bp) ;
ip->i flag 1= lACC;
while (up->u error~O && up->u count !-O && n!-O);
i f (tYPe = IFIFO) {
i f (ip->i size)
ip->i_frptr - up->u_offset:
else {
ip->i frptr - 0;
ip->i:=fwptr = 0;

{

register struct user *up;
register struct buf *bp;
register dey t dey;
register daddr_ t bn;
register unsigned on, n;
register type;
register struct tty "tp;
struct cdevsw *cdevp;

)

i f (ip->i fflag&IFIW) {
ip->i fflag &- -IFIW;
curprl = PPlPE;
wakeup ( (caddr_t) &ip->i_fwcnt);

up - &u;
if (up->u_count ~ 0)
return;
if (up->u_offset < 0)
up->u error = EINVAL;
returi;;

break;
default:

type = ip->i mode &I FMT ;
switch (type)-{
case IFCHR:
dey = (dev t) ip->i rdev;
ip->i flag-I= IAcc7
cdevp-= &cdevsw[ (short)major(devll;
i f (tp = cdevp->d ttys) {
tp += (sh"(;rt) (minor (dev) &077) ;
(*linesw[ (short)tp->t_linel . I_read) (tp);
) else
(*cdevp->d_read) (minor (dev»;
break;
case IFlFO:
while (ip->i size ~ 0)
if (Ip->i_fwcnt
0)
return;
if (up->u_fmode&FNDELAY)
return;
ip->i fflag 1- IFIR;
prele(ip) ;
(void) sleep( (caddr t) &ip->i frcnt, PPIPE);
plock(ip);
up->u_offset - ip->i_frptr;
case IFBLK:
case IFREG:
case IFDlR:
do {
bn - bmap(ip, B READ);
if (up->u_error)

up->u_error

=

ENODEV;

1*

* Write the file corresponding to
* the inode pointed at by the argument.
* The actual write arguments are found
" in the variables:
core address for source
u_base
byte offset in file
u_offset
number of bytes to write
u count
write to kernelluser/user I
u:=segflg

"I
writei (ip)
register struct inode Kip;
{

register struct user *up;
register struct buf *bp;
register dey_ t dev;
register daddr t bn;
register unsig;;ed n, on;
register type;
unsigned int usave;
register struct tty *tp;
struct cdevsw *cdevp;
up - &u;
i f (up->u offset < 0) {
up->u_error - EINVAL:
return;

rdwri.c

Fri Sep

5 19:07:58 1986

2
i f (type - IFIFO) {
ip->i fwptr = up->u offset;
i f (ip->i fflag&IFIR) {
ip->i fflag &~ -1F1R;
curpri - PP1PE;
wakeup ( (caddr_t) &ip->i_frcnt);

type = ip->i mode&IFMT;
switch (type) {
case 1FCHR:
dev = (dev t) ip->i rdev;
ip->i flag-! - IUPDTICHG;
cdevp-- &cdevsw[ (short)major (dev) 1;
if (tp - cdevp->d ttys) {
tp += (short) (minor (dev) &077) ;
I * line sw [ I short) tp->t_line] .1_write) (tp) ;
) else
(*cdevp->d_write) {minor (dev) );
break;

if (up->u error=O && usave!-O)
up->u_count - usave;
goto floop;

break;
case 1FIFO:
floop:
usave = 0;
while «up->u count+ip->i size) > PIPSIZ) {
i f (ip->i frcnt ..:: 0)
break;
if «up->u_count > P1PSIZ) && (ip->i_size < PIPSIZ»
usave = up->u_count;
up->u_count - P1PS1Z - ip->i_size;
usave -= up->u count;
break;
if (up->u_fmode&FNDELAY)
return;
ip->i fflag 1- 1FIW;
prele(ip) ;
(void) sleep ( (caddr t) &ip->i fwcnt, PP1PE);
plock (ip) ;
i f (ip->i_frcnt = 0) {
up->u error - EPIPE;
psignal (up->uyrocp, SIGPIPE);
break:

up->u_offset - ip->i_fwptr;
case 1FBLK:
case 1FREG:
case IFD1R:
while (up->u error=O && up->u_count!-O)
bn --bmap(ip, B WRITE);
i f (up->u error)
break;
on = up->uyboff;
n = up->uybsize:
dev = up->uybdev;
i f (n = FsBS1ZE (devl )
bp = getblk(dev, bn);
else if (type=IFIFO && on-O && ip->i_size < (PIPSIZ-FsBSIZE (dev»)
bp = getblk(dev, bn);
else
bp - bread (dev, bn);
iomove(bp->b un.b addr+on, (int)n, B_WRITEI;
i f (up->u_errOr) brelse (bpI:
else if (up->u fmode&FSYNC)
bwrite(bpI;
else i f (type -- IFBLKI {
/* IFBLK not delayed for tapes */
bp->b flaqs 1- B AGE;
bawrlte (bp) ;
I else
bdwrite(bp) ;
i f (type -- IFREG 1 I type -- IFDIR) {
if (up->u offset> ip->i size)
ip->i size - up->u offset;
) else i f (type - 1FIFO) {
ip->i size +- n;
i f (up->u offset - PIPSIZ)
Up->u_offset - 0:

default:
up->u_error

=

ENODEV;

/*
* Move n bytes at byte location
1< &bp->b un.b addr [0] to/from (flag) the
* user/k;rnel-(u.segflg) area starting at u.base.
* Update all the arguments by the number
1< of bytes moved.

*/
iomove Icp, n, flag)
register caddr t cpo
register n;
{

register struct user *up;
register t:
if

(n~O)

return;
up = &u:
i f (up->u segflg !- 1) {
if (flag~B WRITE)
t =-copyin(up->u_base, (caddr_t)cp, n);
else
t - copyout( (caddr_t)cp, up->u_base, n):
i f (t) {
up->u_error = EFAULT:
return:

else
i f (flag

=
B WRITE)
bcopY(Up->u_base, (caddr_t) cp,n);

else
bcopy( (caddr tlcp,up->u base,n);
up->u_base +- n;
up->u offset += n;
up->u:::count -- n:
return;

reboot.c

Fri Sep

5 19:09:04 1986

1
if «cfp

= open("/dev/console", 2»
< 0)
perr("cannot open /dev/console");
ioctl (cfp, RESTART, (caddr t) 0) ;
/* jump to start of unix * /
perr("restart failed");
-

char _version_[] - "(C) Copyright 1984 UniSoft Corp., Version V.l.O";
char _Origin_[] = "UniSoft Systems of Berkeley";

1*
* reboot rootdev
Change rootdev; pipedev, dlL1!lpdev; swapdev and nswap
in the incore copy of unix and then restart unix.
This is used during installation after a minimal
file system has been set up on the hard disk. It
results in the first boot of unix from the hard disk.

*1
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

"stdio.h"
"nmaddrs .h"
"sys/types. hIt
"sys/config.h"
"sysl sysmacros. hIt
"sys/swapsz.h"
"sys/reboot.h"

tdefine USAGE "usage: reboot rootdev"
main (argc, argv)
char **argv;
{

register fp, cfp;
short rootdev;
long nswap;
int i;
i f (argc !- 2)
perr (USAGE) ;
rootdev - (short)strtol(*(argv+1), (char **)NULL, 16);
if «fp - open("/dev/mem", 2» < 0)
perr("cannot open /dev/mem");

if (lseek(fp, ROOTDEV, 0) < 0)
perr ("lseek to rootdev %x failed", ROOTDEV);
if (write (fp, &rootdev, 2) !- 2)
perr("write of rootdev Ox%x at %x failed", rootdev, ROOTDEV);
printf (arootdev = Ox%x\n", rootdev):
if (lseek(fp, PIPEDEV, 0) < 0)
perr("lseek to pipedev %x failed", PIPEDEV);
if (write (fp, &rootdev, 2) != 2)
perr ("write of pipedev Ox%x at %x failed", rootdev, PIPEDEV);
printf ("pipedev - Ox%x\n", rootdev);
i f (lseek(fp, DUMPDEV, 0) < 0)
perr ("lseek to dumpdev %x failed", DUMPDEV);
if (write (fp, &rootdev, 2) !- 2)
perr ("write of dumpdev Ox%x at %x failed", rootdev, DUMPDEV);
printf ("dumpdev = Ox%x\n", rootdev);

rootdev++;
/ * now it's swapdev * /
if (lseek(fp, SWAPDEV, 0) < 0)
perr("lseek to swapdev %x failed", SWAPDEV);
if (write (fp, &rootdev, 2) != 2)
perr("write of swapdev Ox%x at %x failed", rootdev, SWAPDEV);
printf("swapdev - Ox%x\n", rootdev);
if (lseek(fp, NSKAP, 0) < 0)
perr("lseek to nswap %x failed", NSWAP);
i f (major (rootdev) - PRO)
nswap - PRNSKAP;
else if (major (rootdev) ~ CV2)
nswap - CVNSKAP;
else if (major (rootdev) == PM3)
nswap - PMJfSWAP;
else
perr ("cannot determine size of swapdev");
if (write (fp, &nswap, 4) !- 4)
perr("write of nswap 'd at 'x failed", nswap, NSWAP);
printf ("nswap - 'd\n", nswap);
for (i-a; i<200000; i++) ;

perr (mes, par)
char *mes, *par;
{

fprintf(stderr, mes, par);
fprintf(stderr, "\n");
perror ("reboot") ;
exit (1);

Fri Sep

reinit.c

5 19:09:04 1986

1

/*

*

(C) 1984 UniSoft Corp. of Berkeley CA

"
"
"
"

UniPlus Source Code. This program is proprietary
with Unisoft Corporation and is not to be reproduced
or used in any manner except as authorized in
writing by Unisoft.

*

reinit.c - reinitialize parts of data segment for restarting unix

retabinit (tab, dev, stat)
register struct iobuf "tab;
struct iostat stat [] ;
{

tab->b flags = 0;
tab->b~)orw - 0;
tab->b_back = 0;
tab->b_actf - 0;
tab->b_actl = 0;
tab->b dey - makedev(dev, 0);
tab->b=active ~ 0;
tab->b errcnt - 0;
tab->io erec = 0;
tab->io-nreg = 0;
tab->io-addr - 0;
tab->io- stp = stat;
tab->io-start - 0;
tab->io-s1
0;
tab->io=s2 = 0;

*/

tinclude "sys/param.h"
tinclude "sys/config.h"
tinclude "sys/types. h"
tinclude "sys/systm.h"
tinclude "sys/dir.h"
tinclude "sys/signal.h"
tinclude "sys/user .h"
tinclude "sys/errno.h"
tinclude "sys/file.h"
tinclude "sys/tty.h"
tinclude "sys/termio.h"
tinclude "sys/conLh"
tinclude "sys/sysinfo.h"
tinclude "sys/var.h"
tinclude "sys/reg.h"
tinclude "setjmp.h"
tinclude "sys/kb.h"
tinclude "sys/sysmacros .h"
tinclude ·sys/iobuf .h"
tinclude ·sys/map.h"
tdefine CMAPSIZ 50
1* also in conLc *1
tdefine SMAPSIZ 50
1* also in conLc "I

1* used by newproc to decide whether first "init A or not */

extern mpid;

iostat prostat [] ;
iobuf protab;
iostat snstat [];
iobuf sntab;
iostat cvstat [J ;
iobuf cvtab;

extern
extern
extern
extern
extern
extern

struct
struct
struct
struct
struct
struct

extern
extern
extern
extern
extern
extern
/*

char *kb keytab;
char ToLA[];
char kb altkp;
int (*teyutc) () ;
int vtyutc ( ) ;
char vt_ tabset [ ] ;
reinit - called from RESTART console ioctl call in sunix

*/
reinit ()
{

extern int teslotsused;
register i;
mpid - 0;
retabinit (&protab, PRO, prostat);
retabinit (&sntab, SN1, snstat);
retabinit (&cvtab, CV2, cvstat);
kb keytab - To LA;
kb=:Shft ~ kb_Iock - kb_altkp
teyutc = vtyutc;
for (i - 0 ; i < 88 ; i++
vt_tabset[i] - 0;

=

0;

remapinit (&coremap [0], CMAPSIZ);
remapinit(&swapmap[O], SMAPSIZ);
/*
* reset tecmar four port card
*/
teslotsused - 0;

rem.apinit (map, szmap)
struct map *map;
{

map->m size - szmap - 2;
map->m-addr - 0;
for (~p++, szmap--; szmap > 0; map++, szmap--) {
map->m_size = 0;
map->m_addr - 0;

rom mon.c

Fri Sep

5 19:08:43 1986

/*
* IC) 1984 UniSoft Corp. of Berkeley CA
*
*
*
*

UniPlus Source Code. This program is proprietary
with Unisoft Corporation and is not to be reproduced
or used in any manner except as authorized in
writing by Unisoft.

* "rom monR is used by the software power off feature (see kb. c)
* and the reboot system call (see config.c, doboot) to return to
* the ROM monitor in "Customer Mode".
*/
-tinclude "sys/mmu.h"
typedef int (*pfri) ();
tdefine ROMADDR «pfri) (OxFE0084)
rom mon!)
(

-

asm("
movl
asm("
subl
asm("
subl
asm("
movl
ROMADDR() ;

to,dO H ) ;
a2,a2");
a3,a3");
OxlOOO, sp");

1* no error code * I
1* no icon */
1* no message */

1

Fri Sep

route.c
1*
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

route.c 4.16
83/02/10
Bnet/misc.h lO
·sys/param.hlO
"sys/config.h lO
"sys/errno.h"
"sys/types .h"
·sys/systm.hQ
"net/mbuf .hlO
"net/socket.h lt
"net/protosw. h"
·sys/ioct1.h lO
"net/in.h lO
"net/in systm. h"
"net/if-:-h"
"net/af .h lO

5 19:09:37 1986

if (rt -

0)

panic ("rtfreelO) :
rt->rt refcnt--;
i f (rt=>rt refcnt = 0 && (rt->rt_flagS&RTF_UP) =
rttrash--:
(void) m_free (dtom(rt» :

0) (

1*
" Carry out a request to change the routing table. Called by
* interfaces at boot time to make their "local routes" known
" and for ioctl's.

*1

1* routes not in table but not freed *1

rttrash:

register struct rtentry *rt;

*1

t incl ude "net I route. h"
t include "ermo. h 10
int

1

rtrequest (req, entry)
int req:
register struct rtentry "entry;

1*
* Packet routing routines.

*1
rtalloc (ro)
register struct route *ro:
register struct rtentry *rt, "rtmin;
register struct mbuf *m:
register unsigned hash;
register int ("match) () :
struct afhash h:
struct sockaddr *dst = &ro->ro dst:
int af = dst->sa_family:
if (ro->ro_rt && ro->ro_rt->rt_ifp)
1* xxx *1
return:
if (af >= AF_MAX)
return:
("afswitch[af] .af hash) (dst, &hl:
rtmin = 0, hash =-h.afh hosthash;
for (m = rthost [hash % RTHASHSIZ]; m; m - m->m next)
rt - mtod (m, struct rtentry *);
if (rt->rt hash !- hash)
continue;
if «rt->rt flags & RTF UP) - 0 I I
(rt->rt-ifp->if flags & IFF_UP) = 0)
continue; if (bcmp{(caddr t)&rt->rt dst, (caddr_t)dst, sizeof (*dst»)
continue:
if (rtmin = 0 I I rt->rt use < rtmin->rt_use)
rtmin - rt;
if (rtmin)
goto found;

register struct mbuf "m, "*mprev:
register struct rtentry *rt:
struct afhash h:
unsigned hash;
int af, s, error = 0, (*match) ():
struct ifnet *ifp;
af - entry->rt dst. sa family;
if (af >- AF_~WO
return (EAFNOSUPPORT);
(*afswitch[af].af hashl (&entry->rt dst, &h):
if (entry->rt flags & RTF HOST) { hash:: h.afh_hosthash;
mprev = &rthost [hash % RTHASHSIZ]:
l else (
hash - h.afh_nethash;
mprev = &rtnet [hash % RTHASHSIZ];
match = afswitch[af] .af netmatch;
s = splimp();
for (; m - *mprev; mprev - &m->m next)
rt = mtod (m, struct rtentry *):
if (rt->rt hash != hash)
continue:
if (entry->rt flags & RTF HOST)
tdefine equal (aI, a2) \
(bcmp«caddr t) (a1), (caddr t) (a2), sizeof (struct sockaddr» == 0)
if (! equal (&rt->rt dst, &entry->rt dst»
continue: } else
if (rt->rt dst.sa family != entry->rt dst.sa family II
(*match) (&rt->rt dst, &entry->rt dst) ==-0)
continue:
}

hash - h.afh nethash;
match = afswltch[af].af netmatch:
for (m = rtnet [hash % RTHASHSIZ]; m: m = m->m next)
rt = mtod (m, struct rtentry *):
if (rt->rt hash !- hash)
continue:
i f «rt->rt flags & RTF UP) -= 0 II
(rt->rt-ifp->if flags & IFF_UP) - 0)
continue: if (rt->rt dst.sa family !~ af II ! (*match) (&rt->rt_dst, dst»
continue:if (rtmin - 0 I I rt->rt use < rtmin->rt_use)
rtmin - rt;
-

if (equal (&rt->rt gateway, &entry->rt_gateway»
break:
switch (req) {
case SIOCDELRT:
i f (m -= 0)

{

error = ESRCH:
goto bad:
*mprev = m->m next:
if (rt->rt refcnt > 0) {
rt=>rt flags &- -RTF_UP:
rttrash++:

found:
ro->ro rt - rtmin;

} else

i f (rt;inl

rtmin->rt_ refcnt ++:

(void) m_free 1m) :
break:
case SIOCADDRT:

rtfree irtl

i f (m)

{

Fri Sep

route.c

5 19:09:37 1986

error - EEXIST;
goto bad;
}

ifp = if ifwithaddr (&entry->rt gateway);
if (ifp::" 0) {
ifp ~ if ifwithnet (&entry->rt gateway);
if (ifp
0) {
error - ENETUNREACH;
goto bad;

=-

/* billn -- meld with old
m = m get (M DONTWAIT,MT RTABLE);

*/

-

-

-

m - m get (M DONTWAIT);
if (m-- O)-{
error = ENOBUFS;
goto bad;
*mprev = m;
m->m off = MMINOFF;
m->m-len = sizeof (struct rtentry);
rt =- mtod (m, struct rtentry ");
rt->rt_hash = hash;
rt->rt dst = entry->rt dst;
rt->rt-gateway = entry::>rt gateway;
rt->rt::::flags RTF UP I (entry->rt flags & (RTF_HOST I RTF_GATEWAY) );
rt->rt_ refcnt = 0;
rt->rt use = 0;
rt->rt-ifp - ifp;
break;bad:
splx(s) ;
return (error);

/*
" Set up a routing table entry, normally
* for an interface.
*/
rtinit (dst, gateway, flags)
struct sockaddr *dst, "gateway;
int flags;
struct rtentry route;
bzero «caddr t) &route, sizeof (route»;
route. rt_ dst- - "dst;
route. rt gateway = "gateway;
route. rt-flags - flags;
(void) rtrequest «int) SIOCADDRT, &route);

2

rtc.c

Fri Sep

5 19:09:14 1986

1

1* fdefine
HOWFAR *1
1*
* Real time clock driver

l2copscmd (READCLOCK) ;
rtcrwait ~ 1;
while (rtcrwait)
(void) sleep( (caddr t) &rtcrwait, TTIPRI);
return (rtime.rt_tod) ;
-

* (C) 1984 UniSoft Corp. of Berkeley CA
* UniPlus Source Code. This program is proprietary
" with Unisoft corporation and is not to be reproduced
* or used in any manner except as authorized in
* writing by Unisoft.
" Only reads and writes of 4 bytes (sizeof time t, the standard unix
* representation of time) are ~llowed for the real time clock.
* The rtime structure contains the time most recently read or written.

* struct rtime
time_t
long
short
short
short
short
short
short

" J:
*1
#include
#include
iinclude
#include
#include
tinclude
finclude
#include
iinclude
finclude
#include
#include
#include
#include
#include
#include
#include
iinclude
#include
#include

rt_tod:
rt_alrm:
rtJear:
rt_day:
rt hour:
rt::::min:
rt_sec;
rt_tenth;

See page 35 LHRM
Seconds since the Epoch (unix time)
Seconds remaining to trigger alarm (unused)
year
(0 - 15)
julian day
(1 - 366)
hour
(0 - 23)
minute
(0 - 59)
second
(0 - 59)
tenths of a second
(O - 9)

"sys/param.h"
"sys/config .h"
"sys/mmu.h"
·sys/types. h"
·sysl sysmacros .h"
·sys/dir.h"
·sys/signal.h"
·sys/user.h"
·sys/errno.h"
·sys/utsname.h"
·sys/buf .h"
·sys/elog.h"
"sys/erec.h"
·sys/iobuf .h"
·sys/systm.h"
"sys/var.h"
"set j.mp. h"
·sys/reg.h"
·sys/tty.h"
"sys/local.h"

struct rtime rtime:
int rtcrwai t :

1* flag to sleep on waiting for read to complete *1

1*
" Read the real time clock. The command to do this is issued through
* the COPS. In response, the keyboard gets 6 special interrupts with
" the data. kbintr stores this data in rtime and calls rtcsettod when
* the sixth one has been handled. rtcsettod calculates the time as
* unix likes to think of it, which is as it is returned.
*1
I" ARGSUSED * 1
rtcread(dev)
dey t dey:
{ -

if (u.u_count !- sizeof(time_t»
u.u_error - ENXIO;
return:
rt - rtcdoread ( ) :
iomove( (caddr_t) 'rt, sizeof (time_t), B_READI;

1*
" This routine is normally called from rtcread. However the kernel
" reads the clock by calling rtcdoread directly from clkset.

"/

rtcdoread ()

/*

*
*
*

set rt tod (real time in seconds since epoch) given the real
time clock time currently in the rest of the rtime structure.
Those values (rt year, rt dav, rt hour, rt min, rt sec) are
* set in response
l2~opsC.md(READCLOCK), and are returned through
* special keyboard interrupts (kbintr).
*1
fdefine dsize(x) (x%4=0 1366 :365)
fdefine YEAR 70
rtcsettod ()

to

{

register struct rtime *p
register short i, j;

=

&rtime;

i = -1;
for (j=YEAR; j-YEARrt_year; j++)
i += dsize (j);
p->rt tod = i + p->rt day;
1* Days since epoch */
p->rt- tod *= 24;
p->rt- tod +- p->rt hour;
p->rt::::tad *- 60: p->rt tad += p->rt min;
p->rttad *= 60; p->rt- tod +- p->rt sec;
fifdef HOOFARprintf{IIDATE: %d.%d %d:%d.%d\n", p->rtJear, p->rt_day,
p->rt_hour, p->rt_min, p->rt_sec);
fendif HOOFAR
if (rtcrwait) {
rtcrwait - 0;
wakeup ( (caddr_t) &rtcrwait):

1*
" Set the real time clock to the time indicated. Note that nt is in
* seconds since midnight 1/1/1970 GMT. The timezone has already been
* corrected for.
*1
1* ARGSUSED * I
rtcwri te (dev)
dev_t dev:
{

register struct rtime *p
register long nt:
register long i, j:

=

&rtime;

if (u.u_count != sizeof(time_t»
u.u_error - ENXIO;
return:
iomove «caddr t) ,rtime.rt_tod, sizeof(time_t), B_WRITE);
nt - p->rt tod;
/* 864QO - 24*60*60 - number secs ./day
i - nt % 86400;
j - nt I 86400;
if (i < 0) {
i +- 86400;
j -= 1:
nt - j;
p->rt sec ,. 60:
i 1- 60:
p->rt min - i
60;
i 1- 60;
p->rt hour - i " 24;
j - YEAR;

for (j-YEAR; i-dsize(j); j++) {
i f (nt < i)

*/

rtc.c

Fri Sep

5 19:09:14 1986

break;
nt

i;

p->rt3ear = j - YEAR;
if (p->rt3ear < 10) (
tifdef

HOt-J'F&~

printf("can't remember dates before 1980\n"):
tendif HOWFAR
u. u_error - EINVAL:
return:

1*
}

p->rt day - ++nt;
l2copscmd(SETCLOCK);
/* stop clock, start setup mode */
for (i=O; i<5; i++)
l2copscmd(CLKNIBBLE);
1* no alarm implemented yet *1
l2copscmd(CLKNIBBLE I (p->rt year - 10»;
i - p->rt day I 10;
j = i I 10;
l2copscmd( (char) (CLKNIBBLE I j»;
l2copscmd «char) (CLKNIBBLE I (i % 10»);
l2copscmd (CLKNIBBLE I (p->rt day % 10»;
l2copscmd (CLKNIBBLE I (p->rt-hour / 10»:
l2copscmd(CLKNIBBLE I (p->rt-hour % 10»:
l2copscmd(CLKNIBBLE I (p->rt-min I 10»;
l2copscmd(CLKNIBBLE I (p->rt-min % 10»;
l2copscmd(CLKNIBBLE I (p->rt-sec / 10»;
l2copscmd(CLKNIBBLE I (p->rt-sec % 10»:
l2copscmd(STRTCLOCK);
1* start clock, leave timer disabled *1
l2copscmd(READCLOCK);
1* Now read it back *1

2

S

Fri Sep

00.0

5 19:09:06 1986

1

/*
tp = co ttptr[dev].tt tty;
tp->t_index - dey;
SPL6() ;
if «tp->t_state& (lSOPENIWOPEN» - 0) {
tp->tyroc = coproc:
ttinit (tp) ;
tp->t state - WOPEN I CARR_ON;
if (dev = CONSOLE) {
tp->t iflag - lCRNL I lSTRlP;
tp->t-oflag = OPOST I OHLCR I TAB3;
tp->t-lflag - lSlG ! lCANON ! ECHO I ECHOK:
tp->(::cflag = sspeed I CS8 I CREAn I HUPCL;

* (C) 1984 Unisoft Corp. of Berkeley CA
" UniPlus Source Code. This program is proprietary
" with unisoft Corporation and is not to be reproduced
* or used in any ma!"....~er except as authorized in
* writing by Unisoft.
* co.c - "console" (ie, bitmap screen and keyboard) driver for the lisa.
*/
tinclude "sys/para."1,h"
tinclude "sys/config.h"
tinclude "sys/types .h"
tinclude "sys/systm.h"
tinclude Hsys/dir.h"
tinclude "sys/signal.h"
tinclude "sys/user.h"
tinclude ·sys/errno.h"
tinclude ·sys/file. h"
tinclude IIsyS/tty. h"
tinclude ·sys/termio.h H
tinclude ·sys/conf.h"
tinclude "sys/sysinfo.h"
tinclude .. sys/var. h U
tinclude "sys/reg.h"
tinclude "setjmp.h"
tinclude "sys/ioctl.h u
tinclude "sys/kb.h"
tinclude ·sys/al ioctl.h"
tifdef SUNIX
tinclude "sys/reboot.h"
tendif SUNIX
tinclude "sys/mmu.h"
tinclude "sys/cops.h"
tinclude Hsys/12.h"

}

SPLO ();
(*linesw[tp->t_line] . I_open) (tp);

1 * ARGSUSED * /
coclose (dev, flag)
{

register struct tty *tp;
tp = co_ttptr[devJ .tt_tty;
(*linesw[tp->t_line] . I_close) (tp);

core ad (dev)
{

struct tty *tp;
tp = co ttptr [dev] . tt tty;
(*linesw[tp->t_line).l_read) (tp);

cowrite (dev)
int
coproc () ;
extern int co cnt:
extern struct-tty co tty [] ;
extern struct ttyptr-co_ttptr[];
extern char bmbck, bmnormal;
extern char *bmscrn;

{

struct tty "tp;
tp = co_ttptr[devJ.tt_tty;
(*linesw[tp->t_line] . I_write) (tp);

1* pointer to screen -- initialized in bminit */

1*
"
"
*

calls to the putc routine are made indirectly through
the teyutc pointer which is used to
keep track of the current state for escape character
processing, ie, although initialized to point to
* the normal putc, an escape character causes other
" functions to process the next character (s)
*1
extern int vt_putc () ;
int (*teyutc) ()=vt_putc;
I*tifdef SUNIX
extern caddr t start:
tendif SUNIX*1
struct device
char
char
char

csr;
idum(2);
dbuf;

1* Command status register * 1
1* fillers *1
1* data buffer * 1

};

/" ARGSUSED * 1
coopen (dev I flag)
register dev;
{

register struct tty *tp;
if (dev >- co cnt) {
u.u_error - ENXIO;
ret.urn;

/ * ARGSUSED * /
coioctl (dev, cmd, arg, mode)
{

int i;
switch (cmd) (
case AL SBVOL:
-12_bVOl - arg & 7;
break;
case AL SBPITCH:
-12 bpitch - arg & OxlFFF;
break;
case AL SBTlME:
-if (arg <= 0)
arg - 1;
if (arg > 10 * v.v hz)
arg - 10 *-v.v_hZ;
l2_btime - arg;
break;
case AL_SDIMTlME:
12 dtime - arg;
l2::::dtrap - lbolt + 12- dtime;
break;
case AL_SDIMCONT:
12 dimcont = (-arq) & OxFF;
break;
case AL_SDIMRATE:
12_crate - arq;
break;
case AL_SCONTRAST:
12_defcont = (-arq) & OxFF;

1* limit to 10 seconds *1

s co.c

case

case

case

case

case

case

case

case

case

case

case

case

case

Fri Sep

5 19:09:06 1986

12 desired - 12_defcont;
12ramp(0) ;
break;
AL SREPWAIT:
-kb_repwait - arg;
break:
AL SREPDELAY:
- kb repdlay = arg;
break;
AL GBVOL:
-i - 12_bvol;
if (copyout( (caddr_t) &i, (caddr_t)arg, 4»
u.u_error = EFAULT;
break;
AL GBPITCH:
- i f (copyout «caddr_t) &l2_bpitch, (caddr_t) arg, 4»
u.u_error = EFAULT;
break;
AL GBTIME:
-if (copyout «caddr_t) &l2_btime, (caddr_t) arg, 4»
u.u_error - EFAULT;
break;
AL GDIMTIME:
-if (copyout«caddr_t)&12_dtime, (caddr_t)arg, 4»
u. u_error - EFAULT;
break;
AL GDIMCONT:
-i = (-12 dimcont) & OxFF;
i f (COpyout«caddr_t)&i, (caddr_t)arg, 4))
u.u_error - EFAULT;
break;
AL GDIMRATE:
-if (copyout«caddr_t)&l2_crate, (caddr_t)arg, 4))
u.u_error = EFAULT;
break;
AL GCONTRAST:
-i = (-12 defcont) & OxFF;
i f (Copyout«Caddr_t)&i, (caddr_t)arg, 4»
u.u_error ~ EFAULT;
break;
AL GREPWAIT:
-i = kb repwait & OxFFFF;
i f (Copyout«Caddr_t)&i, (caddr_t)arg, 4»
u.u_error = EFAULT;
break;
AL GREPDELAY:
-i - kb repdlay & OxFFFF;
i f (copyout( (caddr_t) &i, (caddr_t)arg, 4»
u.u_error = EFAULT;
break;
AL GBMADDR:
-if (copyout «caddr_t) &bmscrn, (caddr_t) arg, 4»
u.u_error = EFAULT;
break;
AL REWIDEO:
- i f (arg > 0)
i - 0;
else i f (arg == 0)
i = -1;
else
-1;
i - (bmbck) '1
if (bmbck != i) (
bmswi tch () ;
bmsinv() ;
bmbck = i;
bmnormal - bmbck;
break;

Hfdef SUNIX
case RESTART:
/* jump to the start of unix *1
reinit ();
«int (*) () OxCDDD) ();
break;
tendif SUNIX
default:
(void) ttiocom(co_ttptr [D] .tt_tty, cmc, arg, mode);

2
break;

coproc (tp, emd)
reqister struct tty *tp;
register struct ccblock *tbuf;
extern ttrstrt ();
switch (emd) {
case T_TlME:
tp->t state &= -TIMEOUT;
goto start;
case T_ WFLUSH:
tbuf = &tp->t tbuf;
tbuf->c size
tbuf->c count;
tbuf->c-count - 0;
I * fall-through • I
case T_RESUME:
tp->t state &- -TTSTOP;
goto start;

==

case T_OUTPUT:
start:
i f (tp->t state & (TTSTOP I TIMEOUT I BUSY) )
break;
tbuf - &tp->t tbuf;
i f «tbUf->cytr = 0) II (tbuf->c count - 0»
i f (tbuf->cytr)
tbuf->cytr -- tbuf->c_size;
i f (! (CPRES & (·linesw[tp->t_line] . I_output) (tp»)
break;
(*teyutc) «*tbuf->cytr++) &Dx7f);
tbuf->c count--;
sysinfo-:-xmtint++;
1* this is the xmit interrupt *1
splx ( spll () ) ;
goto start;
case T_SUSPEND:
tp->t_state 1= TTSTOP;
break;
case T_BLOCK:
break;
case T_ RFLUSH:
if (! (tp->t_state&TBLOCK»
break;
1* fall through *1
case T_UNBLOCK:
break;
case T_BREAK:
break;

cointr (dev)
(

register struct ccblock *cbp;
register int c, lcnt, flg;
struct tty *tp;
register char ctmp;
char Ibuf[3];
sysinfo.rcvint++;
c - kb_chrbuf;
tp - co ttptr[devJ.tt tty;
i f (tp->t_rbUf.cytr ::.. NULL)
return:
fundef NULLDEBUG
tifdef NULLDEBUG

Fri Sep

s co.c
if ( c

5 19:09:06 1986

3

Oxoo ) (

~

sccdebug ( ) ;
return;
tendif

if (tp->t_iflaq & IXON) {
ctmp = c & 0177;
i f (tp->t state & TTSTOP) {
if (ctmp - CSTART II tp->t_iflag & lXANY)
(*tp->tyroc) (tp, T_RESUME);
} else
if (ctmp ~ CSTOP)
(*tp->tyroc) (tp, T_SUSPEND);
i f (ctmp - CSTART II ctmp =
return;

CSTOP)

/*
* Check for errors
*/
lcnt = 1;
flg - tp->t_iflag;
if (flg&ISTRIP)
c &= 0177;
else (
if (c = 0377 && flg&PARMRK)
Ibuf[l] = 0377;
lcnt = 2;

/*
* Stash character in r_buf
*1
cbp = &tp->t rbuf;
if (lent != 1) {
Ibuf[O] = c;
while (lcnt)
*cbp->cytr++ = lbuf [--lcnt] ;
if (--cbp->c count ~ 0) (
cbp->c ptr -= cbp->c size;
(*linesw[tp->t_line]-:-l_input) (tp);
if (cbp->c size !- cbp->c count) (
cbp->cytr -= cbp=>c_size - cbp->c_count;
(*linesw[tp->t_line].l_input) (tp);
)

I else (
*cbp->cytr = c;
cbp->c count--;
(*linesw(tp->t_line] . I_input) (tp);

/*
* This version of putchar writes directly to the bitmap display
* for those last-ditch situations when you just have to get stuff to the CRT.
xl
coputchar (c)
register c;
(

(xte putc) (c , Ox7F);
if (~ - '\n')
(*te_putc) (f \r' ) ;

Fri Sep

s conf.c

5 19:09:02 1986

1

/*
Configuration information

*I
1* tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
+define
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

NBUF
NINODE
NFlLE
NMOUNT
CMAPSIZ

30
50
60

50
S~_:a..pSIZ 50
CXMAPSIZ 50
NCALL
15
NPROC
30
NTEXT
20
NSVTEXT 20
NCLIST 100
STACKGAP 8
NSABUF 5
POWER
0
MAXUP
25
NHBUF
64
NPBUF
4
NFLOCK 200
X25LINKS
X25BUFS 256
X25MAPS 30
X25BYTES
CSIBNUM 20
VPMBSZ 8192
MESG
1
MSGMAP 100
MSGMAX 8192
MSGMNB 16384
MSGMNI 50
MSGSSZ 8
MSGTQL 40
MSGSEG 1024
SEMA
1

1* also in reinit.c *1
1* also in reinit.c *1

nodev (), nulldev () ;
proopen (), proread (), prowrite (), prostrategy (), proprint (), proioctl () ;
snbopen (), sncopen (), snbclose (), sncclose (), snread (), snwrite (), snstrategy (), snprint (), sni
cvopen (J, cvread (), cvwrite (), cvstrategy (), cvprint () ;
pmopen (), pmread (), pmwrite (I, pmstrategy (!, pmprint (), prnioctl () ;
coopen (), coclose 0, coread (), cowrite (), coioctl () ;
syopen (), syread (), sywri te (), syioctl () ;
mrnread (), rmnwrite () ;
scopen (), scclose 0, scread (), scwrite (), scioctl () ;
erropen (), errclose (), errread () ;
proread (), prowri te (), proioctl () ;
ejioctl () ;
msopen (), msclose (), msread (), msioctl () ;
lpopen (), lpclose (), lpwrite (), lpioctl () ;
skopen (), skclose (), skwrite 0 ;
rtcread (), rtcwrite () ;
teopen (), teclose 0, teread (), tewrite (), teioctlO;

tifdef
extern
extern
extern
tendif

UCB
intint
int

NET
ptsopen (), ptsclose (), ptsread (), ptswrite () ;
ptcopen ( ), ptcclose (), ptcread (), ptcwri te () ;
ptsioctl (), ptcioctl () ;

-

(16*1024)

S~.l4.AP

10

SEMMNI
SEMMNS
SEMMNU
SEMMSL
SEMOPM
SEMUME
SEMVMX
SEMAEM
SHMEM
SHMMAX
SHMMIN
SHMMNI
SHMBRK
SHMALL
STIHBUF
STOHBUF
STNPRNT
STIBSZ
STOBSZ

10
60
30
25
10
10
32767
16384
1
(128*1024)
1
100
16
512
(ST_0*4)
(ST_0*4)
(ST 0»2)
8192
8192

tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinc1ude
tinclude
tinclude
tinclude
tinclude
'include
tinclude
tinclude

extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern
extern

"sys/param.h"
"sys/config.h"
"sys/rmnu. hOI
"sys/types.h"
"sys/sysrnacros .h Ol
"sys/conf.h"
"sys/cpuid. h"sys/space.h"
"sys/io.h"
"sys/terrnio .h"
"sys/reg. h"
"sys/scc. h"
"sys/pport.h"
"sys/swapsz.h"

{
struct bdevsw bdevsw []
proopen, nulldev,
snbopen, snbclose,
nulldev,
cvopen,
pmopen,
nulldev,

pro strategy ,
snstrategy ,
cvstrategy ,
pmstrategy ,

proprint,
snprint,
cvprint,
pmprint,

/*
1*
1*
/*

*/
*/
*/
*/

};

struct cdevsw cdevsw[] = {
coopen, coclose,
syopen, nulldev,
nulldev, nulldev,
erropen, errclose,
scopen, scclose,
proopen, nulldev,
sncopen, sncclose,
nUlldev, nulldev,
lpopen, lpclose,
msopen, msclose,
skopen, skclose,
cvopen, nulldev,
pmopen, nulldev,
nulldev, nulldev,
teopen, teclose,
tifdef UCB_NET
nodev,
nodev,
nodev,
nodev,
nodev,
nodev,
nodev,
nodev,
nodev,
nodev,
ptcopen, ptcclose,
ptsopen, ptsclose,
tendif

,;

int
int

bdevcnt
cdevcnt

=
=

coread,
syread,
mrnread,
errread,
scread,
pro read,
snread,
nodev,
nodev,
msread,
nodev,
cvread,
pmread,
rtcread,
teread,

cowrite,
sywrite,
mrnwrite,
nodev,
scwrite,
prowrite,
snwrite,
nodev,
lpwrite,
nodev,
skwrite,
cvwrite,
pmwrite,
rtcwrite,
tewrite,

coioctl,
syioctl,
nodev,
nodev,
scioctl,
proioctl,
snioctl,
ejioctl,
lpioctl,
msioctl,
nodev,
nulldev,
pmioctl,
nulldev,
teioctl,

0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,

/*
/*
/*
/*
1*
/*
/*
1*
1*
1*
1*
/*
1*
1*
/*

nodev,
nodev,
nodev,
nodev,
nodev,
ptcread,
ptsread,

nodev,
nodev,
nodev,
nodev,
nodev,
ptcwrite,
ptswrite,

nodev,
nodev,
nodev,
nodev,
nodev,
ptcioctl,
ptsioctl,

0,
0,
0,
0,
0,
0,
0,

/*
1*
1*
1*
1*
1*
1*

1
2
3
4

*/
*/
*/
*/

*1
*1

6 */
*1
8 *1
9 *1
10 */
11 *1
12 *1
13 */
14 *1
15 *1
16 *1
17 *1
18 *1
19 *1
ptc 20 *1
pts 21 *1

sizeof (bdevsw) / sizeof (bdevsw [0] ) ;
sizeof(cdevsw) Isizeof(cdevsw[O]);

tifdef SUNIX
1* Sony (installation) root file system *1
dev_t
rootdev - makedev(1, 0);
dev_t
pipedev - rnakedev(l, 0);
dey t
dumpdev - rnakedev (1, 0);
1* nswap and swapdev are set in lisainit in config.c *1
dey t
swapdev - rnakedev (0, 1);
daddr t swplo - 0:
int n;wap PRNSNAP;
telse SUNIX
/* ProFile root file system */
tdefine ROOTBASE
0
/* (port * 16) for port-0,1,2,4,5,7, or 8 *1
dev_t
rootdev - rnakedev(O, ROOTBASE)
dev_t
pipedev - makedev(O, ROOTBASE)
dey_ t
durnpdev - makedev (0, ROOTBASE)

s conf.c

Fri Sep

5 19:09:02 1986

dey t
swapdev - makedev (0, ROOT BASE + 1);
daddr t swplo - 0;
int nswap PRNSWAP;
tendif SUNIX

int
int
int

*1

(*dev_init [J) () -

tdefine TTHIGH
tifdef TTLOW
tdefine M
tdefine N
tendif
tifdef TTHIGH
tdefine M
tdefine N
tendif
{
tthiwat[16]
int
60*M,
60*M,
O*M,
120*M, 180 xM, 180*M,

(int (") () ) 0

int

(*d~~p)

() = nulldev;

dump_addr

=

OxOOOO;

(*pwr clr []) () - {
(int (x) () 0

-

};

int

2

{

};

};

tifdef SCC_CONSOLE
int
scputchar () ;
int
(*putchar) () - scputchar;
telse
int
coputchar () ;
int
("putchar) ()
coputchar;
tendif

-

ttlowat [16]
OXN,
20 xN,
40 x N,
60"N,

20*N,
60"N,

60*M,
240*M,

60*M,
240*M,

60*M,
240 xM,

60*M,
100*M,

120"M,
100"M,

20"N,
80"N,

20 xN,
80 xN,

20 xN,
80"N,

20"N,
SOxN,

40xN,
SOxN,

};

/"
" Default terminal characteristics

xl
char

tifdef UCB NET
tdefine PTC DEY 20
int ptc dev-- PTC DEY;
tendif -

ttcchar [NCC] - {
CINTR,
CQUIT,
CERASE,
CKILL,
CEOF,
0,
0,

o

int co cnt = 1:
struct-tty co_tty[lJ;

};

struct ttyptr co_ttptr[] - {
1,
&co_tty [0] ,

/* tt_addr field not used */

0,

tifdef lint
Ix LINTLIBRARY "I
forlint ()
(

}:

bminit ():
nmikey() ;
llintr struct args ") 0) ;
kbintr() ;
scintr ( (struct args ") 0) ;
pmintr struct args x) 0) ;
ebintr(O) :
netintr() :

int sc_cnt - NSC:
struct tty sc tty [NSC] :
char sc_mode,lD.[NSC]:

«

«

struct ttyptr sc ttptr [] = {
OxFCD240;
&sc tty [1],
OxFCD242,
&sc-tty[O],
0,
-

}

};

tendif

struct scline sc line []
W9BRESET;
W9ARESET,
I:

=

{

(4000000/16),
(4000000/16),

/* clock frequency b "/
/" clock frequency a */

tif NTE !- 0
int te cnt = NTE:
struct-tty te tty[NTE];
char te dparam[NTE];
char te=:modem[NTE]:

I" net 89 *1

o
};

struct ttyptr te_ ttptr [NTE+1] :
tendif

/* +1 for pstat "I

1*
* pointers to ttyptr structures for terminal monitoring programs

*1
struct ttyptr "tty stat []
co_ttptr, sc ttptr,

tifdef UCB NET
tinclude 
tinclude 
extern struct uba driver ebdriver:
struct uba device- ubdini t [] - {
I "-driver,
unit,
addr,
flags"l
{&ebdriver,
0,
(caddr_t)5, OxS9002908},

=

{

Hf N"l'E !",-O

te_ttptr,
tendif
};

1*
" tty output low and high water marks

int iff noarp
tendif -

=

0;

1* 0 -> do ARP;

not 0 -> no ARP *1

Fri Sep

5 19:08:57 1986

I"
" This file contains
1. oem modifiable configuration personality parameters
2. oem modifiable system specific kernel personality code

"I
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

"sys/param. h"
"sys/config .h"
"sys/mmu.h"
"sys/types.h"
Usys/sysmacros .h"

1
1* Some of the initialization requires that interrupts be enabled to
* pick up coded sequences from the keyboard cops. I f interrupts were
* masked out then the time returned by READCLOCK would fill the
* buffer and KBENABLE, which also returns a value, would have trouble.
*1
SPL1 ();
/* ok, do it to me */
12copscmd (MOUSEOFF) ;
/* shut off mouse interrupts */
12copscmd (READCLOCK) :
/* get time of day "I
12copscmd(KBENABLE);
/* enable keyboard * /
/* Sony initialization *1

sninit() ;

Hsys/sys~1!l.h"

Usys/map.h"
Hsys/dir.h"
"sys/signal.h"
"sys/user.h"
"sys/errno.h"
"sys/proc.h"
"sys/buf.h"
"sys/iobuf.hH
·sys/reg. hOI
"sys/file.h"
"sys/inode.h"
·sys/seg.h"
"sys/acct.h"
"sys/sysinfo.h"
·sys/var.h"
"sys/ipc.h"
·sys/shm.h"
"sys/termio.h"

/* Wait 'til the clock data (from READCLOCK) and keyboard ID (from
KBENABLE) have come in, and the keyboard is back in NORMALWAIT * /
while (kb state);
time = rtIme.rt_tod;

1* it should be at level 7 for the rest (Z) *1

SPL7 ();

/* Find out what's in each of the expansion slots.
*/
for (i = 0, sidp - SLOTIDS; i < NSLOTS; i++, sidp++)
slot [i] = OxFF;
/* not supported * I
slotid = *sidp & SLOTMASK;
i f (! slotid) {
if (iocheck«caddr t) (STDIO+i*Ox4000+1») (
printf("ExPansion slot 'lid: quad serial card\n",
i+1) ;

if (teinit(i) -

0)

/*
tinclude
iinclude
tinclude
tinclude
tinclude
tinclude
tinclude

.. point to interrupt vector,
.. set tecmar quad serial board inter loc,
* and initialize hdwr

·sys/conf .h"
"sys/cops.h u
"sys/pport. hIt
·sys/local.h"
·sys/12.h"
"sys/kb.h"
·sys/swapsz .h"

*1
ip *ip -

I*char oemmsg [] "UniSoft Systems distribution system release 1. S"; * I
char oe.!!!l!lsg [] = "Unisoft SYSte.1D.S pre-distribution system (release 1. S+) u;
int
int
int
int
char

sspeed = B9600;
parityno = 28;
cmask = CMASK;
cdlimi t = CDLIMIT;
slot [NSLOTS] ;

1*
I"
1*
1*
/*

printf("Expansion slot 'lid:" i+1);
switch (slotid) (
case ID APLNET:
-printf("applenet card\n lO );
break;
case ID PRO:
-printf("proFile card\nlO);
break;
case ID 2PORT:
-printf("two port card\n");
slot[i] - PRO;
1* valid *1
break;
case ID PRIAM:
-printf("priam card\n");
ip - & «long *) 0) [EXPIVECT+devtoslot (i) ] ;
1* point to int vector *1
*ip - (long)pmvect + (long) (devtoslot(i)«2);
/* set to Priam intr */
if (pmcinit(i) ~ 0)
/* initialize controller */
slot[i] = PM3; /* valid */
break;
default:
printf("card ID Ox%x\n", slotid);

default console speed *1
parity interrupt vector */
default file creation mask *1
default file size limit *1
card ID numbers for expansion cards *1

1* alias (formerly) "lisainit" *1

{

tifdef SUNIX
int dev;
extern dev_t swapdev;
extern int nswap;
tendif SUNIX
extern struct rtime rtime;
extern int prnvect [ ] ;
extern int tevect [ ] ;
register short *sidp;
register slotid, i;
register long *ip;
12init ();

*) 0) [EXPIVECT+devtoslot (i)];
(long) tevect + (long) (devtoslot (i) «2) ;

continue;

1*
* Kernel initialization functions.
* Called from main. c while at sp17 in the kernel.
*/
oem7init ()

& «long

I * slot ID pointer * /
)

1* setup the COPS ports */

1* This mess disables the ':ertic~e retrace interr'.lpt, f:J:::: n::w.
"I
do {
VRON - 1;
I while «STATUS' S_VR) !- 0) ;
do {
VROFF - 1;
} while «STATUS & S_VRI 0);

scinit ();
1* SCC serial initialization *1
tifdef UCB NET
netinit () :
tendif
I" Now enable the verticle retrace interrupt, used for the system clock.
*1
do {
VRON - 1;
I while «STATUS' S_VR) !- 0);
tifdef SUNIX
SPLO ();
1* This is the first unix booted during installation so find swapdev. -;

Fri Sep

2

5 19:08:57 1986

setppint (addr, fnc)
struct device_ d * addr ;
int (*fnc) ();

if (rootdev = makedev(SNl, 0» {
while (chkdev(dev = getdevnam())
printf(-Unable to use that device\nTry again:\n");
printf("\n\nswapdev = Ox%x\n\n-, dev);
swapdev - dey;
if (major (dev) ~ PRO) n.s~ap - PRNSWAP;
else if (major (dev) - PM3) nswap = PMNSWAP;
else if (major (dev) ~ CV2) nswap - CVNSWAP;
else panic(lfcannot determine size of swapdev");

(

register int i;
extern int cvint ()

tendif SUNIX
}

/*

* Kernel initialization functions.
* Called from main. c while at splO in the kerneL
*/
oemOinit ()
{
}

/*

*

1/

prointr ( ), Ipintr () ;

for (i-O; ip_flag++;
tendif

if( (i

=

ap->a dey) =- 0) (
if(fnc - pi fnc[i])
fnc!i) ;
return;

1* special case for pp 0 * /

J
struct device_ d
PPADDR,
(struct
(struct
(struct
(struct
(struct
(struct

*pro_ da [NPPDEVS]
device d
device-d
device-d
device-d
device-d
device-d

*)

*)
*1
*1
*)
*1
(struct device-d *1
(struct device-d *)
(struct device:=d *)

-!

(STDIO+Ox2000),
(STDIO+Ox2800),
(STDIO+Ox3000),
(STDIO+Ox6000),
(STDIO+Ox6800),
(STDIO+Ox7000),
(STDIO+OxAOOOI,
(STDIO+OxA8001,
(STDIO+OxBOOO)

J

/" DEV
/* OxOO
1* OxlO
1* Ox20
1* Ox30
1* Ox40
1* Ox50
1* Ox60
/* Ox70
/* Ox80
1* Ox90

Description * /
parallel port * /
FPC port 0 slot 1
FPC port 1 slot
FPC port 2 slot
FPC port
slot
FPC port
slot 2
FPC port
slot
slot
Fl'C port
FPC port
slot
slot
FPC port

*/
*/
! ! ! */
*/
*1
! ! ! */
*1
*/
! ! ! */

}:

int (*pi_fnc[NPPDEVS]) ():

/* slots for interrupt handler addresses */

1* Set the interrupt handler for a given parallel port controller.
*I

j = i + 2;
while (i < j) !
dp - pro da [i];
if «a =-dp->d ifr) & FCAl) !
asm(" - nop ");
dp->d ifr - a; 1* reset interrupt *1
i f (fnc - pi fnc [i]) (
i f (fnc - lpintr)
lpflq[i] - 0;
else if (fnc !- ebintr &&
fnc ! - prointr &&
fnc !- cvint) (
printf("pi fnc[%d] - Ox%x invalid! !\n",
i,fnc) :
return;

Fri Sep

5 19:08:57 1986

3
default:

fnc(i) ;
return;

printf("Invalid input. Try again. \n");
goto retry:

Hfdef INTDUMP
printf("Where will the disk OO1\n");
i f «dev - PRO) ! I (dev = CV2») !
printf (UEnter: ' 0' for builtin port\n"):
printf(1I
'1' for Expansion Slot 1, Bottom Port\n");
printf("
'2' for Expansion Slot 1, Top Port\n U):
printf("
'4' for Expansion Slot 2, Bottom Port\n"):
printf("
, 5' for Expansion Slot 2, Top Port\n");
printf!"
'7' for Expansion Slot 3. Bottom port\n");
printf("
'8' for Expansion Slot 3, Top Port\n");
p - gets ();
switch (p[O])
case '0' :
case ' 1':
case '2' :
case '4' :
case ' 5':
case '7' :
case ' 8':
, 0' ;
unit = p[O]
break;
default:
printf("Invalid input. Try again. \n");
goto retry;

ppdump(i,dpl;

tendi f INTDt"MP
return;

I
i++;

tifdef INTDUMP
ppdump(n, pI
register struct device_ d "'p;
{

printf (lIpport %d: n, n) ;
printf("ifr=%x acr-%x pcr-%x ddra-%x ddrb-%x irbc=%x\n",
p->d_ifr&OxFF, p->d_acr&OXFF, p->dycr&OxFF, p->d_ddra&OxFF,
p->d_ddrb&OxFF, p->d_irb&OxFF);
tendif INTDUMP

-

I"
called from clock if there's a panic in progress

"I
clkstop()
(

VROFF = 1;

1* disable vertical retrace intr *1

}

nmikey()
{

int i;
register short status;

1* added 7/25/84 to provide more info than "NMI keyll.
" (taken from section 2.8 of Lisa Theory of Operations)
*1
printf ("non-maskable interrupt: II I ;
status = STATUS;
if (status & S SMEMERR)
printf("soft memory error\n");
else if (status & S HMEMERR)
printf("hard memory error\n");
else
printf (llpower failure/keyboard reset\n");
tifdef HOWFAR
showbus() ;
lendif HOWFAR
for (i=OxcOOOOO; i>O; i--)

else { /* dev - PM3 */
printf ("Enter: ' 0' for Slot 1 \n");
, l' for Slot 2\n") ;
printf("
printf("
'2' for Slot 3\n") ;
p - gets II;
switch (p[O] )
case'O':
case '1':
case '2':
unit = p[O] - '0';
break;
default:
printf("!nvalid input. Try again. \n");
goto retry;

return makedev(dev, (unit«4)

I 1 );

chkdev(d)
{

return(*bdevsw[hmajor(d)].d_open) (minor (d), FREAD I FWRITE);

1* delay *1

tifdef SUNIX
1* Get swap device name
*1
getdevnam ()
(

char *p, *gets () ;
int unit, dev;
retry:
printf("\n\nWhere is the swap area1\n");
printf("Enter: 'p' for builtin disk or a profile disk\n");
printf("
'c' for Corvus disk\n");
printf ("
, pm' for Priam disk\n");
p - gets ();
switch (p[O])
case 'pI:
dev - PRO;
i f (p [1] -- , m' )
dev - PM3;
break;
case 'c':
dev - CV2;
break;

1*
* This version of get char reads directly from the keyboard in order to get
* swapdev when the parallel port is not available. It will not work once
* the console has been formally opened.
*1
char kb_getchr;
cogetchar ( )
(

SPLO II;
while (kb_state) ;
kb getchr - 1;
whIle (kb getchr)
return kb:=chrbuf;

1* wait for kb driver to finish special cmd *1
1* wait flag "'I
1* wait for it to happen *1

1* Kernel qet string routine.
" Useful for qetting information from the console before the system
* comes up. The getchar routine will not work once the console has
* been opened.
*1
int ("qetchar) () - coqetchar;
extern int (*putchar) II;
char getsbuf[lOO];

Fri Sep

5 19:08:57 1986

char"
gets I)
(

register char "p;
register char c;
extern short kb_keycoll."l.t;
p - getsbuf;
while (c - ("getchar) ()
switch (c) (
case I \r':
case' \n':
goto out;
case I \b ' :
i f (p > getsbuf)
p--;

break;
case '@':
case 'X'&OxlF:
/* line kill */
i f (p > getsbuf) (
p - getsbuf;
I" echo a newline ,,/
c - '\n';
break;
default:
*p++

=

c;

("putchar) (c);
if (p >= getsbuf + sizeof (getsbuf» (
printf("\nInput line too long, try again ... \n");
p = getsbuf;
out:
"p = '\0';
(*putchar) (' \n');
return getsbuf;
tendif SUNIX

4

s leb.c

Fri Sep

5 19:08:31 1986

1
kb chrbuf - Esc:
colntr(O) :
kb chrbuf ~ , 0' :
colntr(O) :
kb chrbuf - a;
colntr(O) :
goto out;

/*
" (C) 1984 UniSoft Corp. of Berkeley CA
" UniPlus Source Code. This program is proprietary
" with Unisoft corporation and is not to be reproduced
* or used in any mar.u."lsr except as authorized in
* writing by unisoft.

*

a

Interrupt handler for level 2 interrupts.
keyboard, mouse, real time clock, on/off switch
if (a >=

*/

=

0)

kb_keytab[i
{

&

/* send 3-char sequence

Ox7F];/* reset to ascii ,,/

1* ascii? *1

kb keycount ++ :

tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

if- (kb ctrl) a &- Ox1F;
else if (kb keycount ~ 1) {
kb reptrap = kb repwait:
kb-lastc - a; } else kb_reptrap = 0;
kb chrbuf = a;
colntr(O) ;
goto out;

"sys/param.h"
"sys/types .h"
"sys/mmu.h"
"sys/reg.h"
Usys/local.h"
"sys/cops.h"
"sys/keyboard.h u
Usys/mouse.h"
"sys/ms.h"
"sys/12.h M
"sys/kb.h"

}

1* key went up */
kb reptrap - 0;
if-(a >= 0) {
if (kb keycount-- < 0) {
- kb_keycount = 0;

} else {

extern struct rtime rtime;
char "kb keytab - ToLA:
char kb_altkp;

1* are we in alternate keypad mode? (set in vt100.c) */

goto out;

char pportplug;
char msylg, ms_btn:
short ms_row, ms_col;

switch (a & OxF) {
case KB_CTRL:
kb_ctrl

kbintr()

case KB_ SHFT:

{

register char i;
register struct device_e *p - COPSADDR;
register char a, ud;
register int tmp;
extern time_t lbolt;
tifdef SUNIX
extern char kb_getchr ; /* flag for polling keyboard
tendif SUNIX

*/

a = p->e ifr;
/* Read and save reason for interrupt */
if (a & FCA1)
/" keyboard input * /
i = p->e ira;
/* get keyboard/mouse input */
if (a & FTIMER1)
a - COPSADDR->e t1cl;
/* prime timer */
-Ix no character input */
) else
a = COPSADDR->e t1cl;
/* prime timer */
if (--kb reptrap - 0)
kbrepeat () ;
/" possible char repeat * /
return;
switch (kb_state) {
case NORMALI'lAIT:
/* IDLE LOOP */
ud = i & Ox80:
/* whether up or down keycode * I
12 dtrap - lbolt + 12 dtime:
/* reset dim delay */
if- (12 dimmed)
- /* restore screen intensity *1
- 12undim () ;
a - kb keytab[i & Ox7F]: /* convert to ascii * /
if (ud) {
1* "key went down" bit *1
/* click(); 1* key click *1
if (ARROI'l(i,a»
1* check arrow keys *1
kb chrbuf - Esc:
1* send 3-char sequence *1
colntr(O);
kb chrbuf = '~':
colntr(O) ;
kb chrbuf - a;
colntr(O) ;
goto out:
I
if (kb altkpl { 1* send special sequence for keypad chars *1
- i f (a - alckpad[i , Ox7Fj) U* is it in the keypad:? *1

case
case
case
case

KB_MSB:
KB_PPORT:
KB_D2B:
KB_D2P:

default:

ud; kb reptrap = 0; msintr(M CTL);
goto out;
kb_shft = ud; kbsetcvtab{); msintr(M SFT);
goto-out;
goto out;
kb lock - ud; kbsetcvtabO:
prlntf(" [SOFT OFF %x]\n",i);
goto out;
msylg = ud; msintr (M_PLUG);
goto out;
ms btn = ud; msintr (M BUT);
goto out;
pportplug = ud;
goto out;
printf(" [disk1button %xl \n",i); goto out;
printf("[disk1 %x]\n",i);
goto out
printf (II [disk2button %x] \n M, i) ; goto out
printf("[disk2 %xj\n",i);
goto out
if (ud = 0) {
kb_state - MOUSERD;
) else
kb_state = RESETCODE;
goto out;
printf (" invalid key [Ox%x] u, i) :
=

)

goto out:
case MOUSERD:
/* PICKUP Y axis change in mouse pos */
kb state - YMOUSE:
ms-col - (short) i;
goto out:
case YMQUSE:
/* PICKUP Y axis change in mouse pos *1
kb state - NORMALI'lAIT:
ms-row - (short)i;
mslntr (M MOVE):
goto out;
case RESETCODE:
1* special condition *1
switch (i & OxFF) {
case KB KBCOPS: 1* keyboard cops failure detected *1
-printf("KEYBOARD COPS FAILURE\n"):
break:
case KB IOCOPS: / * 10 board cops failure detected * /
-printfC"IO BOARD COPS FAILURE\n"):
break;
case KB UNPLUG: /* keyboard unplugged */
-kb_chrbuf - , s' &Ox1F;
/* cntl S *1
cointr (0) :
break:
case KB CLOCKT: /* clock timer interrupt *l
-prlntf("Real Time Clock interrupt\n");
b;reak,;

*/

Fri Sep

5 19:08:31 1986

2

case KB SFTOFF: 1* soft power switch */
-kb state ~ SHUTDOWN:
prIntf("Shutting down ... \n");
update ();
for (tmp = 0; tmp < 500000; tmp++);
12 crate - 2;
l2-desired = TOTALDIM; /" completely blacken screen "I
l2ramp(0) :
l2ramp(0) ;
SPL7 ();
/* extreme priority */
l2copscmd (SHUTOFF) :
rom monO;
1* return to the ROM monitor */
I "NOTREACHED* I
default: switch (i & OxFO) {
case KB RESERV:
-printf(" [Reserved keycode Ox%x] \n", i):
break;
case KB ROeLK:
-rtime.rtJear - (i & OxF) + 10;
kb_state = CLKREAD;
goto out;
default:
kb_idcode - i;
kb chrbuf = , q' &OxlF;
/* cntl Q * /
coIntr(O) ;
printf ("Keyboard type Ox%x\n", i) ;

kb_state - NORMALWAIT;
goto out:
case CLKREAD:
rtime.rt day = «(i&OxFO)>>4)*10 + (i&OxF»"10:
kb_state++;
goto out;
case CLKREAD+l:
rtime.rt day += (i&OxFO) » 4;
rtime.rt-hour = (i & OxF) " 10;
kb_ state++;
goto out;
case CLKREAD+2:
rthl.e.rt hour +- (i & OxFO) » 4;
rtime.rt:::min = (i & OxOF) " 10;
kb_state++;
goto out;
case CLKREAD+3:
rtime.rt min += (i & OxFO) » 4;
rtime.rt:::sec = (i & OxOF) " 10;
kb_ state++;
goto out:
case CLKREAD+4:
rtime.rt sec +- (i & OxFO) » 4;
rtime. rt-tenth - i & OxOF;
kb_state-= NORMALWAIT;
rtcsettod () ;
goto out;
case SHUTDOWN:
goto out;
out:
tifdef SUNIX
i f (Jud)
kb_getchr - 0;
tendif SUNIX
}

kbrepeat ()
!
/" reset repeat timeout "I
i f (kb keycount -- 1)

(

- kb chrbuf = kb lastc;

1* click(); I" key-click "I

-

cointr (0);
1 else

I" reset repeat timeout "I

kbsetcvtab ( )
{

kb_keytab = ccvtab[ (kb_shft'?2:0) + (kb_lock?l: 0) ];
kb_reptrap - 0;

Fri Sep

5 19:08:51 1986

1

1* @(t)slp.c
tinclude
tinclude
tinclude
tinclude
t include
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

1.8 *1
"sys/param.h"
"sys/config.h"
"sys/mmu.h"
"sys/types.h"
"sysl sysmacros . h"
"sys/dir.h"
"sys/signal.h"
"sys/user. h"
·sys/proc.h"
·sys/context.h"
.sys/text.hu
·sys/systm.h"
·sys/sysinfo.h"
·sys/map. hOI
·sys/file.h"
·sys/inode.h"
• sys/buf . h"
.. sys/var . h"
.sys/ipc.h H
·sys/shm.h"
·sys/errno.h·
·sysl scat. hOI

*q - rp->p_link;
SPLO () ;
goto psig;
)

SPLO () ;
if (runin != 0) {
run in = 0;
wakeup ( (caddr_t) &runin);
swtch(l;
if (rp->p_sig && issig()
goto psig;
) else (
SPLO ();
swtch() ;
splx(s) ;
return(O) ;

/*

* If priority was low (>PZERO) and there has been a signal,
* if PCATCH is set, return 1, else
* execute non-local goto to the qsav location.

*1

typedef int

psig:

tdefine NHSQUE 64
1* must be power of 2 *1
tdefine sqhash (Xl
(&hsque [ ( (int) (X) » 3) & (NHSQUE-l I ] )
struct proc *hsque[NHSQUE];
char
runin, runout, runrun, curpri;
struct proc *curproc, *runq;

1*

splx(s) ;
if (disp&PCATCH)
return (1) ;
tifdef NONSCATLOAD
resume(u.uyrocp->p_addr, u.u_qsav);
telse
resume (ixtoc(u.uyrocp->p_scat), u.u_qsavl;
tendif

" sleep according to a cpu adjusted priority

1*

NOTREACHED

*1
asleep(chan, pri)
caddr_t chan;

*/

Ix

(

" Wake up all processes sleeping on chan.
return(sleep(chan, pri + «u.uyrocp->p_CPu&OxFF) »

5»);

*1
wakeup (chan)
register caddr_ t chan;

I"
"
*
*
"

"*

*
*

*
*

{

Give up the processor till a wakeup occurs
on chan, at which time the process
enters the scheduling queue at priority pri.
The most important effect of pri is that when
pri<=PZERO a signal cannot disturb the sleep;
if pri>PZERO signals will be processed.
Callers of this routine must be prepared for
premature return, and check that the reason for
sleeping has gone away.

*1
tdefine TZERO
10
sleep (chan, disp)
caddr_t chan;
(

register struct proc *rp - u. u procp;
register struct proc * *q = sqh-;sh (chan) ;
register s;
s - splhi ();
i f (panicstr) (
SPLO ();
splx(s) ;
return(O) ;
rp->p stat - SSLEEP;
rp->p- wchan - chan;
rp->p-link - *q:
*q - rp;
i f (rp->p time > TZERO)
rp->p time - TZERO;
i f «(rp->p prI - (disp&PMASK» > PZERO)
i r (rp->p sig && issig (» {
rp->p wchan - 0;
rp->p=stat = SRUN;

register struct proc *p;
register struct proc **q;
register s;
s = splhi ();
for (q - sqhash (chan); p - *q; )
if (p->p wchan-chan && p->p stat==SSLEEP)
p->p stat - SRUN;
p->p- wchan = 0;
1* t-;ke off sleep queue, put on run queue *1
*q - p->p_link;
p->p_link - runq;
runq = p;
i f (! (p->p flag&SLOAD»
p->p time - 0;
1* defer set run to avoid breaking link chain *1
if (runout > 0)
runout - -runout;
) else if (p->pyri < curpri)
runrun++;
) else
q = &p->p_link;
i f (runout < 0) {
runout = 0;
setrun (&proc [0] ) ;
splx(s) ;

setrq (pI
register struct proc *p;
!
register struct proc *q;
register s;

Fri Sep

5 19:08:51 1986

2
loop:

p->p_link - rung;
rung = p;

SPL6() ;
outage = -20000;
tifdef NONS CAT LOAD
for (rp - &proc[O]; rp < (struct proc *)v.veyroc; rp++)
if (rp->p stat-SRUN && (rp->p flag&SLOAD) == 0 &&
rp->p:=time > outage)!
p = rp;
outage = rp->p_time;

splx(s) ;

telse

s - splhi ();
for (q-runq; q!=NULL; g-g->p link)
if (g - p) {
printf(lIproc on g\n");
gato out:

out:

/*
* set the process running;
* arrange for it to be swapped in if necessary.
*/
setrun(p)
register struct proc *p;
!
register struct proc **q;
register s;

for (rp = &proc(O]; rp < (struct proc *)v.veyroc; rp++)
if «rp->p_flag&(SSWAPITISLOAD» == (SSWAPITISLOAD») !
p = rp;
SPLO ();
got a swapit;
else if (rp->p stat-SRUN && (rp->p_flag&SLOAD) = 0 &&
rp->p_time >-outage) {
p = rp;
outage = rp->p_time;
tendif

/*

s - splhi ();
if (p->p stat = SSLEEP) {
7* take off sleep queue */
for (g = sghash (p->p wchan); *q != p; q = &(*g) ->p_link)
*g = p->p link;
p->p wchan = 0;
) else if (~>p stat ~ SRUN)
/* already on run queue - just return */
splx(s) ;
return;

* If there is no one there, wait.
*/
if (outage = -20000) {
runout++;
(void) sleep! (caddr_t) &runout, PSWP);
goto loop;
)

SPLO ();

/*

* See if there is memory for that process;

/* put on run queue * /
p->p stat - SRUN;
p->p:=link = rung:
runq = p;
if (! (p->p flag&SLOAD»
p->p time = 0;
if (runout > 0)
runout = 0;
setrun(&proc[O]) ;
) else if (p->pyri < curpri)
runrun++;

*

if so, swap it in.

*/
if (swapin (pI)
goto loop;

/*

*

none found.
* look around for memory.
* Select the largest of those sleeping
* at bad priority; if none, select the oldest.
*/

splx(s) ;

1*

* The main loop of the scheduling (swapping) process.
* The basic idea is:
see if anyone wants to be swapped in;
swap out processes until there is room;
swap him in;
repeat.
* The run out flag is set whenever someone is swapped out.
* Sched sleeps on it awaiting work.

* Sched sleeps on runin whenever it cannot find enough
" memory (by swapping out or otherwise) to fit the
" selected swapped process. It is awakened when the
* memory situation changes and in any case once per second.
*/
sched II
!
register struct proc *rp, *p;
register outage, inage;
im maxbad;
int tmp;
/*
" find user to swap in;
" of users ready, select one out longest

"/

SPL6() ;
p - NULL;
maxbad - 0;
inage - 0;
for (rp - &proc[O]: rp < (struct proc *)v.veyroc; rp++1
i f (rp->p stat=SZOMB II
(rp->p flag& (SSYSISLOCKISLOAD» !-SLOAD)
continue;
if Irp->p_textp && rp->p_textp->x_flag&XLOCK)
continue;
if (rp->p stat-SSLEEP II rp->p stat-SSTOP) {
tip = rp->pyri - PZERO-+ rp->p_time;
if (maxbad < tmp) I
p - rp;
maxbad - tmp;
} else if (maxbad<=O && rp->p stat=SRUN) !
tmp - rp->p_time + rp=>p_nice - NZERO;
if (tmp > inage) {
p - rp;
inage - tmp;

SPLO () ;
/*
* Swap found user out if sleeping at bad pri,
" or if he has spent at least 2 seconds in memory and
* the swapped-out process has spent at least 2 seconds

OLlt:..

Fri Sep

5 19:08:51 1986

3

* Otherwise wait a bit and try again.
*1
if (maxbad>O II (outage>~2 && inage>-2»
tifndef NONS CAT LOAD
swapit:
tendif
p->p flag &= -SLOAD;
xswap(p, 1, 0);
goto loop:
I
SPL6() ;
r1Ll1in++;
(void) sleep ( (caddr tl &runin, PSWP);
goto loop;
-

register struct text *xp;
register int a, x;
int ta;
if (p->p flag&SCONTIG) {

If

«a - cme..-rn.alloc{p->p_size»

-==

NULL)

return (0) ;
} else if «a - memalloc(p->p_size» - NULL)
return(O) ;
if (xp = p->p textp) {
xlock(xp) ;
i f ! !XJ!I~ink!xp) && xp->x_ccount--Ol {
i f «x = memalloc(xp->x_size»
memfree (a) :
xunlock(xp) ;
return (0) ;

/*
* Swap a process in.
*/
tifdef NONSCATLOAD
swapin(pl
register struct proc *p;

-- NULL) {

xp->x scat - x;
if «xp->x flag&XLOAD)=O)
(v~id) swap(xp->x_daddr, x, xp->x_size, B_READ);
xp->x_ccount++;
xunlock (xp) ;

{

register struct text *xp;
register int a, x;
int ta;

/* swapping in, do not set mmu registers */
p->p flag 1- SNOMMU;
if (p->p_xaddr [0]) {
ta = a;
for (x-O; x < NSCATSWAP; x++)
if (p->p xaddr[x] - 0)
~ontinue;
a - swap(p->p_xaddr[x], a, p->p_xsize[xl, B_READ);
mfree{swapmap, ctod (p->p_xsize[x]), (int)p->p_xaddr (x]);
p->p_xaddr[xl = 0;

if «a = malloc(coremap, p->p_size» = NULL)
return (0) ;
i f (xp - p->p textp) {
xlock(xp) ;
if (!xmlink(xp) && xp->x ccount-O) {
if «x = malloc (coremap, xp->x size» - NULL) {
mfree(coremap, p->p size, a);
if «x - malloc(cor;map, xp->x_size» ~ NULL)
xunlock (xp) ;
return(O) ;

p->p_scat - ta;
} else {
(void) swap ( (daddr_t)p->p_dkaddr, a, p->p_size, B_READ);
mfree (swapmap, ctod (p->p_size), (int) p->p_dkaddrl ;
p->p_scat = a;

if «a = malloc(coremap, p->p size» == NULL)
mfree(coremap, xp->x_size, x);
xunlock (xp) ;
return (0) ;

p->p flag &- -SNOMMIJ;
p->p-addr = ixtoc(p->p scat);
cxrelse (p->p_context);p->p flag 1- SLOAD;
p->p-time ~ 0;
return (1) ;

xp->x caddr - x;
if «xp->x_flag&XLOAD)=O)
swap (xp->x_daddr, x, xp->x_size, B_READ);
tendif
xp->x_ ccount ++;
xunlock(xpl;
I
i f (p->p_xaddr[Oll {
ta - a;
for (x=O; x < NSCATSWAP; x++) {
i f (p->p xaddr[x] - 0)
"Continue;
swap (p->p xaddr [xl, a, p->p xsize [xl, B READ);
mfree (swaPmap, ctod (p->p xslze [xl), (int) p->p xaddr [xl) ;
a +- p->p_xsize[x];
p->p_xaddr [xl - 0;

p->p addr - ta;
} else {
swap( (daddr t)p->p dkaddr, a, p->p size, BREAD);
mfree (swapniap, ctod (p->p_ size), (int) p->p_dkaddr) ;
p->p_addr - a;
cxrelse (p->p context);
p->p_flaq !--SLOAD:
p->p_time - 0;
return (1) ;
.else
swapin(p)
register struct proc "p;
{

/*
* put the current process on
.. the Q of running processes and
"" call the scheduler.

*1
qswtch()
(

setrq(u.uyrocp) :
swtch() ;

1*
..
..
..
..

This routine is called to reschedule the CPU.
if the calling process is not in RUN state,
arrangements for it to restart must have
been made elsewhere, usually by calling via sleep.
* There is a race here. A process may become
.. ready after it has been examined.
* In this case, idle () will be called and
.. will return in at most 1HZ time.
* i. e. its not worth putting an spl () in.
*/
swtch()
{

register n:
register struct proc "p, "q, "pp, *pq;
tifdef mc68881
/* MC68881 floating-point coprocessor *i

Fri Sep
extern short fp8 S1;
tendif mc688Sl

5 19:08:51 1986

4

/* is there an MC68S81'? * /

curpri = n;
curproc - p;
SPLO ();
/*
* The rsav (ssav) contents are interpreted in the new address space

/*

* If not the idle process, resume the idle process.
*1
sysinfo. pswi tch++;
if (u.u procp !- &proc[O]) {
-if (save(u.u rsav» {
sureg() ;
return;
tifdef FLOAT

tendif
tifdef mc688S1

/" sky floating point board *1
if (u.u fpinuse && u.u fpsaved=O)
-savfp();
u.u_fpsaved = 1;

1* MC6SS81 floating-point coprocessor */
if (fp8Sl)
fpsaveO;

tendif mc688S1
tifdef NONS CAT LOAD
resume(proc[O].p_addr, u.u_qsav);
telse
resume (ixtoc(proc [0] .p_scat), u. u_qsav);
fendif

*1
n - p->p flag&SSWAP;
p->p flag 10- -SSWAP;
tifdef NONSCATLOAD
telse
tendif
)

/* external for sunix so it can be reinitialized *1
int mpid;
/*
* Create a new process-- the internal version of
* sys fork.
* It returns 1 in the new process, 0 in the old.
*/
newproc(i)
{

register struct proc *rpp, *rip;
register struct user "up;
register n;
register a;
struct proc "pend;
/* static mpid; */

1*
" The first save returns nonzero when proc 0 is resumed
by another process (above); then the second is not done
* and the process-search loop is entered.

*

* The first save returns 0 when swtch is called in proc
* from sched(). The second save returns 0 immediately, so
" in this case too the process-search loop is entered.
* Thus when proc 0 is awakened by being made runnable, it will
* find itself and resume itself at rsav, and return to sched().
*/
if (save (u.u_qsav) ~ 0 && save(u.~rsav»
return;
loop:
SPL6 () ;
runrun = 0;

1*

* Search for highest-priority runnable process

*1
if (p - runq) {
q = NULL;
pp = NULL;
n = 128;
do {
if «p->p_flag&SLOAD) && p->p_pri <= n) (
pp - p;
pq - q;
n - p->PJlri;
q - p;
) while (p - p->p_link);
) else
goto cont;

1*
" I f no process is runnable, idle.

*/
cont:

if (pp -- NULL) {
curpri = PIDLE;
curproc ~ IOproc[O];
idle ();
(Joto loop;
p - pp;
q - pq;
if (q else

NULL)
runq = p->p_link;

1*
" First, just locate a slot for a process
" and copy the useful info from this process into it.
* The panic ·cannot happen· because fork has already
* checked for the existence of a slot.
*/
up = &u;
rpp = NULL;
retry:
mpid++;
i f (mpid >= ~.AXP!D)
mpid = 0;
goto retry;
rip - &proc[O];
n = (struct proc *)v.veJlroc - rip;
a = 0;
do {
if (rip->p stat ~ NULL) {
if- (rpp - NULL)
rpp - rip;
continue;
i f (rip->p_pid--mpid)
goto retry;
if (rip->p_uid - up->u_ruid)
a++;
pend - rip;
) while (rip++, --n);
if (rpp==NULL) (
if «struct proc *)v.veJlroc >~ &proc[ (short)v.vJlroc])
if (i) (
syserr .procovf++;
up->u error - EAGAIN;
return(-l) ;
I else
panic ("no procs");

rpp = (struct proc *) v . veJlroc;
I
if (rpp > pend)
pend - rpp;
pend++;
Efdef lint
v.ve_proc - pend;
telse

Fri Sep
v.ve_proc -

5 19:08:51 1986

5

(char *)pend;

up->uJlrocp - rip;
curproc = rip;
/* only do if not scheduler */
i f (rip != &proc[Ol)
suregO;
setrq(rpp) ;
rpp->p flag 1- SSWAP;
/* parent returns pid of child
up->u_rvall = rpP->PJlid;
return(O) ;

tendif
if (up->u uid && up->u ruid)
if (rpp - &proc[ (short) (v.vJlroc-l) 1 II a > v.v_maxup) (
up->u_error - EAGAIN;
return(-l) ;

*/

/*

*

make proc entry for new proc

*/

/*

*
*

Change the size of the data+stack reqions of the process.
If the size is shrinking, it's easy-- just release the extra core.
* If it's growing, and there is core, just allocate it
* and copy the image, taking care to reset reqisters to account
* for the fact that the system's stack has moved.
* If there is no memory, arrange for the process to be swapped
* out after adjustinq the size requirement-- when it comes
* in, enough memory will be allocated.

rip = up->uJlrocp;
rpp->p stat = SRUN;
rpp->p- clktim - 0;
rpp->p-flag = SLOAD;
rpp->p- uid = rip->p uid;
rpp->p:=suid - rip->p_suid;
rpp->p~rp

=

rip->p~rp;

rpp->p nice = rip->p nice;
rpp->p-textp - rip->p textp;
rpp->pyid - mpid;
rpP->PJlpid = rip->PJlid;
rpp->p_time - 0;
rpp->p cpu - rip->p cpu;
rpp->p- sigiqn = rip=>p sigign;
rpp->pyri = PUSER + rIp->p_nice - NZERO;
tifndef NONS CAT LOAD

*
*

After the expansion, the caller will take care of copying
the user's stack towards or away from the data area.

*/
tifdef NONSCATLOAD
expand (newsize)
reqister newsize;
{

register struct proc *p;
register al, a2;
register i, n;

tendif
rpp->p addr
rpp->p:=size

=

=

rip->p addr;
rip->p:=size;

p = u.uJlrocp;
n = p->p size;
p->p size - newsize;
if (il - newsize)
return:
al = p->p addr;
i f (n >= newsize)
tifdef EXPANDTRACE
printf(lOexpand:shrinking process by %d clicks\n lO , n-newsize);
tendif
mfree (coremap, (mem_t) (n-newsize), (mem_t) (al +newsize) ) ;
return:

/*

* make duplicate entries
* where needed
*/
for (n-O; nu_ofile[nl != NULL)
up->u ofile [nj->f count++;
i f (rpp->p_textp != NULL) {
rpp->p textp->x count++;
rpp->p::::textp->x:=ccount ++;

if (save (u.u_ssav) )
suregO;
return;

up->u cdir->i count++;
i f (up->u rdir)
up->u_ rdir-> i_count ++;

/*
" See if can just expand in place
*/

shmfork (rpp, rip);

/*

loop:

* Partially simulate the environment
* of the new process so that when it is actually
* created (by copying) it will look right.
*/
up->uJlrocp = rpp;
curproc = rpp;
/*
* When the resume is executed for the new process,
* here's where it will resume.
*/
if (save (up->u ssav»)
sureg();
return (1) ;
I
/*
* If there is not enough memory for the
* new process, swap out the current process to qer:erate
* copy.
*/
if (procdup (rpp) -- NULL) {
rip->p stat - SIDL;
xswap(rpp, 0, 0);
rip->p_stat - SRUN;

a2 = mallocat(coremap, newsize-n, (mem_t) (al+n»;
i f (a2 != NULL) {
tifdef EXPAND TRACE
printf(lOexpandinq in place by %d clicks at click %d\n lO ,
newsize-n, al+n);
tendif
cxrelse (p->p_context);
sureq() ;
return;
/*

*
*

will we be releasing shared text space anyway.

If so, then release it now and try in place

* expansion again.
:'~e

*/
if «a2 - domall(coremap, (mem_t)newsize» - NULL)
:'f (xmrelse () )
goto loop;
if (a2 - NULL && (a2 - malloc(coremap, (rnem_t)newsize»)
tifdef EXPANDTRACE
printf("expand:calling xswap\nlO);
tendif
xswap (p, 1, n);
p->p_flag 1= SSWAP;

=

NULL) {

Fri Sep

5 19:08:51 1986

qswtch() ;
/* no return */
p->p addr - a2;
for (I=o; ip_context);
resume «mem_t)a2, u.u_ssav);

6
tifndef NONSCATLOAD
checkscat(s)
char "s;
{

register struct proc *p;
register struct text *xp;
register i;
i = countscat (scatfreelist. sc index);
printf(lI%s nscatfree-%d actual-%d\n", s, nscatfree, i);
if (nscatfree < 30) {
printf("
freelist chain is tI);
dumpscat (scatfreelist. sc_index) ;

telse
expand (newsize)
register newsize;

for (p = &proc[Ol; p < (struct proc ")v.ve_proc; p++) {
i f (p->p stat-O)
-;;ontinue;
xp - p->p textp;
printf(" - pid-%d %d used (%d text)\n tl ,
p->pyid, countscat (p->p_scat),
xp '] countscat (xp->x_scat) : 0);
dumpscat (p->p_scat);
i f (xp) {
dumps cat (xp->x_scat);

{

register
register
register
register
int t;

struct scatter "s;
struct proc *p;
al, a2;
i, n;

p = u.uyrocp;
n = p->p size;
p->p size = newsize;
if (n -- newsize)
return;
s - scatmap;
al = p->p scat;
if (n >= newsize)

1*

dumpscat(a1)
register a1;
{

register struct scatter *s;

" shrink memory

*/
for (i-l; ip flag 1- SSWAP;
qswt~h() ;
1* no return *1
I
fendif

return (i) ;

I
tendif

scc.c

Fri Sep

5 19:08:45 1986

1

1*

};

* SCC device driver

1*
* we call this in startupO to preinitialize all the ports

Copyright 1982 UniSoft Corporation

*1

*/
scinit{}

tinc1ude
tinclude
tinclude
tinc1ude
tinclude
tinclude
tinclude
tinc1ude
tinc1ude
tinc1ude
tinc1ude
tinc1ude
tinc1ude
tinclude
tinc1ude
tinc1ude
tinc1ude
tinclude

"sys/param.h"
"sys/config .h"
·sys/types .h"
"sys/systm.h"
·sys/dir.h ll
"sys/signal.h H
·sys/user.h"
"sys/errno.h"
"sys/fi1e.h"
·sys/tty.h"
"sys/termio.h"
"sys/conf.h"
·sys/sysinfo.h"
"sys/var .h"
·sys/reg.h"

·sys/proc. h"
"setjmp.h"

register struct device *addr;
unsigned short nsc;
for (nsc=O;nsccsr = scitable [i];

;" modem control on bit *1
1* from unix device number to device *1

tdefine DELAYO asm(lI\tnopll);
DELAY() ;
splx(s) ;
tdefine SCTlm (v.v_hz*S)

1* scscan interval *1

1*

1* ARGSUSED .. I

* Note: to select baud rate
k - chip_input_frequencyl (2 * baud * factor) - 2
put factor in register 9 and k in registers D & C
NOTE:
normally, factor = 16
for this driver, chip input frequency = 2400000 Hz
.. scspeeds is a table of these numbers by UNIX baud rate
*1
int scspeeds [] - {
1,
50,
75,
110,
150,
200,
300,
134,
600,
1200,
1800,
2400,
4800,
9600,
19200, 38400,

scopen(dev, flag)
register dev;

};

1*

{

register struct tty *tp:
register struct device *addr;
register d;
tifdef SINGLEUSER
register struct proc *p;
tendif SINGLEUSER
d = scdev (dev);
if (d >- sc_cnt)
u.u_error - ENXIO;
retu=;

* table to initialize a port to 9600 baud

*1
char sci table []
WONULL,

=

9, 0,

tdefine SCClRESET
4, 1if4CLK16
10, 0,
11, WllRBR
12, 0,
tdefine SCCISPLO
13, 0,
tdefine SCCISPHI

{

1* set according to sc_line reset value */
scitable [2]
W41STOP,
WllTBR,

1* 12/13 are baud rate, from sc_line speed value *1
scitable [10]
sci table [12]

14, "14BRGE : 1'I14BRIN'l',

3, W38BIT I W3RXENABLE,
5, W58BIT I W5TXENABLE,
1, WIRXIALL I WlTXIEN /*1 W1EXTIEN*I,
2, 0,
1* auto vector */
0, WORXINT,
15, 0,
9, W9MIE I W9DLC,

tp - sc ttptr[d].tt tty;
Hfdef SINGLEUSER
P - u.uyrocp;
if «p->pyid - p->pygrp)
&& (u.u ttyp ~ NULL)
&& (tp->tygrp 0» {
u.u_error - ENOTTY;
return;
tendif SINGLEUSER
tp->t index - d;
SPL6();
i f «tp->t_state& (ISOPENIWCP~Y) == 0)
tp->tyroc - scproc;
ttinit (tp) ;
sc modem[d] - dev & MODEM;
addr - (struct device *1 sc ttptr [d] . tt addr;
i f (dev & MODEM" (addr->csr , RODCD) - 0)
tp->t_state - HOPEN;
else

scc.c

Fri Sep

5 19:08:45 1986

2
start:
if (tp->t state & (TTSTOP I TIMEOUT I BUSY) )
break;
if (tp->t_state & TTXOFF) {
tp->t_state &= -TTXOFF;
tp->t_state != BUSY;
addr->data - CSTOP;
break;
I
if (tp->t state & TTXON) {
tp->t_state &= -TTXON;
tp->t_state 1= BUSY;
addr->data = CSTART;
break;

tifdef SCC CONSOLE
if (d =- CONSOLE) (
tp->t_iflag - ICRNL I ISTRIP;
tp->t_oflag = OPOST I ONLeR I TAB3;
tp->t lflag - ISIG ! ICANON ! ECHO I ECROK;
tp->t cflag = sspeed I CS8 I CREAn I HUPCL;

=:

tendif SCC_CONSOLE
scparam(dev) ;
if

(!

(flag & FNDELAY»
while «tp->t state&CARR ON) -- 0)
(void) sleep ( (caddr_t) &tp->t_rawq, TTOPRI);

SPLO ():

tbuf = &tp->t tbuf;
if «tbuf->cj)tr - 0) II (tbuf->c count = 0»
if (tbuf->c-ptr)
tbuf->c-ptr -= tbuf->c_size;
if (! (CPRES & (*linesw[tp->t line].l output) (tp»)
break;
--

(*linesw[tp->t_linel.l_open) (tp);

1* ARGSUSED * I
scclose (dev, flag)
{

register struct tty *tp;
register int d;
d = scdev (dev);
tp - sc ttptr[d].tt tty;
(*linesw[tp->t lineT.I close) (tp);
if (tp->t cflaq & HUPCL)
schup(dev) ;

tp->t_state 1= BUSY;
addr->data = *tbuf->c-ptr++;
tbuf->c count--;
break; case T_SUSPEND:
tp->t_state 1= TTSTOP;
break;

/* hang up */

scread(dev)

case T_BLOCK:
tp->t state &- -TTXON;
tp->t-state 1= TBLOCK;
tp->t state 1= TTXOFF;
goto start;

(

register struet tty *tp;

=:

tp - sc ttptr [scdev (dev) ] .tt tty;
(*linesw[tp->t_line].l_read)(tp) ;

case T_ RFLUSH:
if (! (tp->t state&TBLOCK»
bre~k;

scwrite (dev)

1* fall through xl

(

register struet tty *tp;
case T_UNBLOCK:
tp->t state &= - (TTXOFF I TBLOCK) ;
tp->t-state 1= TTXON;
goto start;

tp- sc ttptr[sedev(dev) 1 .tt tty;
(*linesw[tp->t_line].I_writ"E;) (tp);

scproc (tp, crnd)
register struct tty *tp;

case T_BREAK:
scwS (tp, addr, INSBREAK);
tp->t state 1- TIMEOUT;
timeout (ttrstrt, (caddr t) tp, v. v_hz»2);
break;
-

(

register struet ccblock *tbuf;
register struct device *addr;
register dev_t dey;
extern ttrstrt () ;
int s;
s - spl6 ();
dey - tp->t index;
addr = (struct device *)sc_ttptr[dev].tt_addr;
switch (crnd) {

splx(s) ;

scwS (tp, addr, dl
struct tty *tp;
struct device *addr;
int d;
(

case T_TlME:
1* clear break * I
sewS (tp, addr, 0);
tp->t state &- -TIMEOUT;
goto start;
case T_WFLUSH:
tbuf - &tp->t tbuf;
tbuf->·c size·
tbuf->c count ~
tbuf->c-count - 0;
/* fall-through */
case T_RESUME:
tp->t state &- -TTSTOP;
goto start;

=-

register int wS;
int s;
wS - WSTXENABLE I d;
switch(tp->t_cflag & CSIZE) {
case CSs:
wS I- INSSBIT;
case eS6:
wS 1- HS6BIT;
case eS7:
wS 1- liS7BIT;
case eS8:
wS 1- tfS8BIT;
s - splS ();

break;
break;
break;
break:

scc.c

Fri Sep

5 19:08:45 1986

3

addr->csr - 5;
addr->csr ~ w5:
splx(s) :

addr->csr - 5;
DELAY() ;
addr->csr - W5TXENABLE I W58BIT;
splx(s) :

/* turn off DTR/RTS *1

scioctl (dev, cmd, arq, mode)
{

if (ttiocom(sc ttptr[scdev(dev)].tt tty, cmd, arg, mode»
scparaiii(dev):
-

scintr(ap)
register struct args *ap;
{

register struct device * addr;
for (ap->a dey - 0; ap->a dey < sc_ent; ap->a_dev++) !
addr = (struct device *) sc ttptr[ap->a dev).tt addr;
while (addr->csr & RORXRDY)
-addr->esr = 1;
DELAY() :
if (addr->csr & (R1PARERR I RlOVRERR I R1FRMERR) )
scsintr (ap) ;
else
scrintr (ap);

scparam! dey)
(

register
register
register
int s:
register

flag:
struct tty *tp:
struct device * addr:
int w4, w5, speed:

tp = sc_ttptr[scdev(dev) ].tt_tty:
flag - tp->t cflag:
i f « (flag&CBAUD) ~= BO) && (dev&MODEM»
schup(dev) ;
return:

}

( 1* hang up line *1

addr = (struct device *)sc_ttptr[scdev(dev)].tt_addr;
w4 = W4CLK16:
i f (flag & CSTOPB)
10'4 1- W42STOP;
else
10'4 1= W41STOP;
10'5 - W5TXENABLE:
switch(flag & CSIZE) {
case CS5:
10'5 I- W55BIT; break;
case CS6:
10'5 1- W56BIT: break;
case CS7:
10'5 1- W57BIT; break:
case CS8:
1015 1- W58BIT; break;
i f (flag & PARENB)
if (flag & PARODD)
10'4 1= W4PARENABLE:
else
10'4 1- W4PARENABLE I W4PAREVEN:
speed - sc_line[scdev(dev)].speed:
speed - (speedl (scspeeds [flag&CBAUD) «1» - 2;
s - sp16 ();
addr->csr - 4;
DELAY() ;
addr->csr = 10'4;
DELAY() ;
addr->csr - 12;
DELAY() ;
addr->csr = speed;
DELAY() ;
addr->csr = 13;
DELAY() ;
addr->csr = speed » 8;
DELAY() ;
addr->csr - 5;
DELAY() ;
addr->csr - 10'5;
splx(s);

if (addr->csr & ROTXRDY)
scxintr (ap) ;

serintr (ap)
register struct args *ap;
(

register struet device *addr;
register struet ccbloek *cbp;
register int e, lent, fIg;
struct tty *tp;
register char etmp;
char Ibuf[3);
addr = (struct device *)se ttptr[ap->a dev).tt addr;
addr->csr = WORXINT;
/*- reinable receiver interrupt ,,/
addr->csr = WORIUS;
/* reset interrupt */
c = addr->data & OxFF;
sysinfo. revint++;
tp = sc ttptr[ap->a dev).tt tty;
i f (tp->tJbuf.cytr = NULL)
return;
i f (tp->t_iflag & IXON) (
ctmp - c & 0177;
i f (tp->t state & TTSTOP) {
if (ctmp - CSTART II tp->t iflag & lXANY)
(*tp->tyroc) (tp, T=RESUME);
} else (
i f (etmp - CSTOP)
(*tp->tyroc) (tp, T_SUSPEND);
i f (ctmp

~ CSTART I I ctmp
return;

~

CSTOP)

lent = 1;
flg - tp->t iflag;
i f (flg&ISTRIP)
e &- 0177;
else (
/* c &- 0377; not needed */
i f (c =- 0377 && flg&PARMRK)
Ibuf[l) - 0377;
lcnt - 2;

/*
schup (dev)
{

" Stash character in =_buf

*1
register struct device *addr;
int s;
dey - scdev ( dev) ;
addr - (struct device *)sc_ttptr[dev].tt_addr;
s - sp16();

cbp - &tp->t rbuf;
i f (lent !- 1) {
lbuf[O) - c;
while (lent)
*cbp->e ptr++ - lbuf [--lent] ;
i f (--ebp->c_count -- 0) {

scc.c

Fri Sep

5 19:08:45 1986

4
if (stat & RIFRMERR)
c 1- FRERROR;

cbp->cytr -- cbp->c_size;
(*linesw[tp->t_line].l_input) (tp):

i f (C& (FRERROR I PERROR I OVERRUN) )
i f «c&0377) = 0) {
i f (flg&!GNBRK)
return;
i f (flg&BRKINT)
signal (tp->t pgrp, SIGINT):
ttyflush (tp, - (FREAD I FWRITE) ) ;
return;

if (cbp->c size != cbp->c count)
Cbp->cytr -= Cbp-=->c size - cbp->c count;
(*linesw[tp->t_line]-:-l_input) (tp);}

I else {
*cbp->cytr - c:
cbp->c count--;
(*lin~w[tp->t_linel . I_input) (tp);

}

} else (
i f (flg&IGNPAR)
return;

scxintr (ap)
register struct args *ap;

i f (flg&PARMRK)
lbuf[2) - 0377;
lbuf[I) - 0;
lcnt - 3;
sysinfo.rawch +- 2;
else
c - 0:

{

register short dey;
struct tty *tp;
register struct device *addr;
sysinfo. xmtint ++:
dey - ap->a dev;
addr - (struct device *)sc ttptr[dev].tt addr;
addr->csr - WORTXPND;
/*-reset transmitter interrupt * /
addr->csr - WORIUS;
1* reset interrupt *1
tp - sc_ttptr[dev].tt_tty;
tp->t_state &- -BUSY;
scproc(tp, T_OUTPUT);

} else
if (flg&ISTRIP)
e &- 0177;
else {
/* c &= 0377; not needed "I
i f (c = 0377 && flg&PARMRK)
lbuf[l] - 0377;
lent - 2;

scsintr (ap)
register struct args *ap;

}

/*
* Stash character in r_buf
*/
cbp = &tp->t rbuf;
i f (lent !- 1) (
lbuf[O] = e;
while (lent) {
*cbp->cytr++ - lbuf[--lcnt];
if (--cbp->e eount =- 0) {
cbp->cytr -= cbp->c_size;
(*linesw[tp->t_line].l_input) (tp);

(

register struct ccblock *cbp;
register int c, lcnt, fIg;
struct tty *tp;
register char ctmp;
char lbuf[3):
register struct device *addr;
unsigned char stat;
sysinfo. rcvint++;
addr - (struct device *)sc ttptr[ap->a dev] .tt addr:
c - addr->data & OxFF; 1* read data BEFORE reset error *1
addr->csr - Oxl:
1* crnd to read register 1 */
stat - addr->csr;
/* read the status * I
addr->csr = WORERROR;
1* reset error condition *1
addr->csr - WORXINT;
/* reinable receiver interrupt *1
addr->csr - WORIUS;
1* reset interrupt under service *1
tp - sc ttptr [ap->a dev). tt tty:
i f (tp->t_rbuf .c_ptr == NULL)
return:
i f (tp->t iflag & IXON) {
ctmp = C & 0177;
if (tp->t state & TTSTOP) {
if (ctmp - CSTART II tp->t iflag & lXANY)
(*tp->tyroc) (tp, T_RESUME);
I else
i f (ctmp - CSTOP)
(*tp->tyroc) (tp, T_SUSPEND);
}

if (ctmp = CSTART 1 1 ctmp return:

}

if (cbp->e size != ebp->c count) {
cbp->e ptr -= cbp=>c size - ebp->c count;
(*linesw[tp->t_line)-:-l_input) (tp):
I
} else {
*cbp->cytr = c;
cbp->c count--;
(*linesw[tp->t_line].l_input) (tp);

scscan()
{

register int i;
register struct tty *tp;
register struct device "addr;

CSTOP)

}

1*
* Check for errors
*/
lcnt - 1;
flg - tp->t iflag;
i f (stat & (RIPARERR 1RIOVRERR 1RIFRMERR»
{
i f «stat Ii RIPARERR ) " (flg & INPCK»
c 1- PERROR;
if (stat Ii RI0VRERR)
e 1- OVERRUN;

timeout (scscan, (caddr t) 0, SCTlME);
for (i - 0; i < se cnt-;- i++) {
addr - (struct device ")sc ttptr[i].tt addr;
addr->csr - 1f0REXT;
I"-update DCD */
tp - !lC ttptr[i] .tt tty:
if (addr->csr Ii RODeO) {
i f «tp->t_state&CARR_ON) == 0)
tp->t state 1- CARR ON;
i f (tp->t 9tate&IfOPEN)
wakeup! (caddr_tl litp->t_rawq);
}

} else {

scc.c

Fri Sep

5 19:08:45 1986

if (tp->t state&CARR ON && sc modem[i]I {
tp->t state &- -CARR ON:
if (tp->t state&ISOPEN) {
tty flush (tp, FREAD I FWRITE) ;
signal (tp->tJ>Q'rp, SIGHUP);

tifdef SCC_CONSOLE

scputchar (c)
{

register struct device *addr
int s, i;
addr = (struct device *) sc_ttptr[CONSOLE].tt_addr;
s - spl6();
if (c ~ '\n'l
scputchar (' \r' I ;
i ~ 100000;
while «addr->csr & ROTXRDY) = 0 && --i)
addr->data = c;
sp1x(s) ;

I
fendif SCC_CONSOLE

5

Fri Sep

scc.su.c

5 19:08:59 1986

1
);

1*
it

SCC device driver

1*
" we call this in startup!) to preinitialize all the ports
*1
3cinit ()

Copyright 1982 UniSoft corporation

*1
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
#include
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

"sys/param.h"
"sys/config.h"
"sys/types.h"
"sys/systm.h"
"sysldir.h"
"sys/signal.hD
·sys/user.h"
·sys/errno.h"
"sys/file.h"
·sys/tty.h"
"sys/termio. h"
·sys/conf.h"
.. sysl sysinfo. h II
·sys/var.h"
·sys/reg.h"

"sys/proc.h"
"setjmp.h"

register struct device * addr;
unsigned short nsc;
for (nsc-O;nsccsr - scitable til ;

1* modem control on bit *1
1* from unix device number to device *1

fdefine DELAYO asm("\tnop"l;

)

DELAY();
splx(s) ;

1* scscan interval */

fdefine SCTIME (v.v_hz*SI

/*
" Note: to select baud rate
k - chip input frequency I (2 it baud it factor) - 2
put fact-;;r in register 9 and k in registers D & C
NOTE:
normally, factor = 16
for this driver, chip_input_frequency = 2400000 Hz
* scspeeds is a table of these numbers by UNIX baud rate
it /

int scspeeds [] - {
1,

50,

75,

110,

600,

1200,

1800,

2400,

134,
4800,

150,

9600,

200,
19200,

300,
38400,

);

1*

1* ARGSUSED */
scopen(dev, flag)
register dev;
{

register struct tty *tp;
register struct device it addr;
register d;
#ifdef SINGLEUSER
register struct proc "p;
tendif SINGLEUSER
d - scdev (dev) ;
if (d >- sc_cnt)
u. u_error - ENXIO;
return;

* table to initialize a port to 9600 baud
*1
char sci table [] - {
WONULL,
9, 0,

Hefine SCClRESET
4, W4CLK16
10, 0,
11, WllRBR
12, 0,

fdefine SCCISPLO
13, 0,
'define SCCISPHI
14, Wl4BRGE

3, 1f38BIT I
5, WS8BIT I
1, WIRXIALL
2, 0,

1* set according to sc_Iine reset value *1
scitable[2]
W41STOP,
WllTBR,

1* 12/13 are baud rate, from sc_line speed value *1
sci table [10]
scitab1e[12]
, W14BRIN'!',
1f3RXENABLE,
IfSTXENABLE,
I 1f1 TXIEN / * I 1f1EXT IEN* I ,
/* auto vector */

0, WORXINT,
15, 0,
,9, W9MIE I W9DLC,

tp = sc ttptr [d] . t t tty;
tifdef SINGLEUSER
P - u.uyrocp;
if «p->pyid - p->pygrp)
&& (u.u ttyp NULL)
&& (tp->tygrp =- 0)) {
u. u_error = ENOTTY;
return;
fendif SINGLEUSER
tp->t index - d;
SPL6();
i f «tp->t_state& (ISOPENI WOPENi )
UI
tp->tyroc - scproc;
ttinit (tp) :
sc modem[d] - dey & MODEM;
addr - (struct device R)SC ttptr[d].tt addr;
if (dev & MODEM" (addr->csr , RODCD)--- 0)

scc.su.c

Fri Sep

5 19:08:59 1986

2
start:
i f (tp->t state & (TTSTOP I TIMEOUT I BUSY) )
break:
if (tp->t state & TTXOFF) {
tp->t_state &- -TTXOFF;
tp=>t state I = BUSY;
addr->data - CSTOP;
break;

Hfdef SCC CONSOLE
if (d == CONSOLE) (
tp->t iflag - ICRNL I ISTRIP:
tp->(:oflag = OPOST I ONLeR I TAB3:
tp->t lflag = ISIG I lCANON I ECHO
BeHOK;
tp->(:cflag = sspeed I CS8 I CREAn I HUPCL:
tendif SCC_CONSOLE
scparam(dev) :

if (tp->t state & TTXON) {
tp->t_state &= -TTXON;
tp->t_state 1= BUSY;
addr->data - CSTART;
break:

if {! (flag &: FNDELAY»
while «tp->t state&CARR ON) = 0)
(void) sleep ( (caddr_t) &tp->t_rawq, TTOPRI):
SPLO () :
(*linesw[tp->t_linej.l_open) (tp):

tbuf = &tp->t tbuf;
if «tbuf->cytr == 0) II (tbuf->c count == 0»
if (tbuf->cytr)
tbuf->cytr -= tbuf->c_size;
if (!(CPRES & (*linesw[tp->t_line].l_output) (tp»))
break;

1* ARGSUSED * I
scclose (dev, flag)
{

register struct tty *tp:
register int d:
d - scdev (dev):
tp ~ sc ttptr[d].tt tty;
(*linesw[tp->t line]".l close) (tp);
if (tp->t cflag & HUPCL)
sChup(dev) ;

tp->t_state 1- BUSY;
addr->data = *tbuf->cytr++;
tbuf->c_count--:
break;
case T_SUSPEND:
tp->t_state 1- TTSTOP;
break:

1* hang up */

scread (dev I

case T_BLOCK:
tp->t state &= -TTXON:
tp->t:= state 1= TBLOCK:
tp->t_state 1= TTXOFF;
goto start;

{

register struct tty *tp;
tp - sc ttptr[scdev(dev)].tt tty:
(*linesw[tp->t_line].l_read)(tp) :

case T_RFLUSH:
if (! (tp->t state&TBLOCK»
break:
1* fall through *1

scwrite (dev)
(

register struct tty *tp:
case T_UNBLOCK:
tp->t_state &= - (TTXOFF I TBLOCK);
tp->t state 1- TTXON:
goto ~tart;

tp=o sc ttptr [scdev (dev) ] .tt tty:
(*line~w[tp->t_line] . I_write) (tp):

scproc (tp, cmd)
register struct tty *tp:

case T_BREAK:
sew5 (tp, addr, WSBREAK);
tp->t state I- TIMEOUT;
timeout (ttrstrt, (caddr_t)tp, v.v_hz»2):
break;

(

register struct ccblock *tbuf:
register struct device *addr:
register dev_t dey:
extern ttrstrt () :
int s:
s = spl6 ();
dey = tp->t index:
addr - (struct device *)sc_ttptr[devj.tt_addr:
switch (cmd) (

splx(s) ;

scwS (tp, addr, d)
struct tty *tp;
struct device *addr:
int d;
(

case T_TlME:
scwS(tp, addr, 0):
1* clear break *1
tp->t_state &- -TIMEOUT;
goto start;
case T_ifFLUSH:
tbuf - &tp->t tbuf;
tbuf->c_size -== tbuf->c_c:l1.:.nt;
tbuf->c count - 0;
1* fall-through *1
case T_RESUME:
tp->t state &- -TTSTOP;
goto start;

register int wS;
int s;
w5 - WSTXENABLE I d;
switch(tp->t_cflag & CSIZE) (
case CSS:
w5 1- WSSBIT;
case CS6:
w5 1- WS6BIT:
case CS7:
wS 1- W57BIT;
case CS8:
wS 1- "S8BIT;
s - splSl,);

break;
break;
break;
break:

Fri Sep

scc.su.c

5 19:08:59 1986

3
addr->csr = 5;
DELAY() ;
addr->csr - W5TXENABLE I W58BIT;
splx(s) :

addr->csr = 5;
addr->csr - w5;
splx(s) ;

1* turn off DTR/RTS *1

scioctl (dev, cwd, arg, mode)
if (ttiocom(sc_ttptr[scdev(dev) ].tt_tty, cmd, arg, mode»
scparam(dev) ;

scintr(ap)
register struct args *ap;
!
register struct device *addr;
for !ap->a dey - 0: ap->a_dev < sc_cnt: ap->a_dev++) {
addr - (struct device *)sc ttptr[ap->a dev].tt addr:
while (addr->csr & RORXRDY) {
addr->csr = 1:
DELAY() :
i f (addr->csr & (RIPARERR I RI0VRERR I RIFRMERR) )
scsintr (ap) ;
else
scrintr lap);

scpara.~{dev)

register
register
register
int s;
register

flag;
struct tty *tp;
struct device *addr;
int w4, w5, speed;

tp - sc ttptr [scdev (dev) ].tt tty;
flag - tp->t cflag;
i f « (flag&cBAUD) = BO) && (dev&MODEM»
schup(dev) ;
return;

if (addr->csr & ROTXRDY)
scxintr (ap) :

( /* hang up line */

addr - (struct device *) sc_ttptr [scdev(dev)] . tt_addr;
w4 = W4CLKI6;
i f (flag & CSTOPB)
w4 1= W42STOP;
else
w4 1= W41STOP;
w5 - W5TXENABLE;
switch(flag & CSIZE) {
case CS5:
w5 1= W55BIT; break;
case CS6:
w5 I- W56BIT; break;
case CS7:
w5 1- W57BIT; break:
case CS8:
w5 1- W58BIT: break;
i f (flag & PARENB)
i f (flag & PARODD)
w4 1= W4PARENABLE;
else
w4 I- W4PARENABLE I W4PAREVEN:
speed = sc line [scdev(dev) ].speed;
speed = (sPeedl (scspeeds [flag&CBAUD] «1» - 2;
s - spl6():
addr->csr - 4;
DELAY() ;
addr->csr = w4;
DELAY() ;
addr->csr = 12;
DELAY!) ;
addr->csr = speed:
DELAY!) :
addr->csr - 13:
DELAY() :
addr->csr = speed » 8;
DELAY() ;
addr->csr - 5:
DELAY() :
addr->csr - w5;
splx(s) :

scrintr (ap)
register struct args *ap;
{

register 9truct device "addr;
register struct ccblock *cbp:
register int c, lcnt, flg:
struct tty *tp;
register char ctmp;
char lbuf[3]:
addr - (struct device ") sc ttptr [ap->a dev]. tt addr:
addr->csr = WORXINT:
/*- reinable receiver interrupt * /
addr->csr - WORIUS:
1* reset interrupt */
c ~ addr->data & OxFF;
sysinfo.rcvint++;
tp = sc ttptr[ap->a dev].tt tty:
i f (tp->t_rbuf.cytr = NULL)
return:
if (tp->t iflag & IXON) {
ctmp - c & 0177;
i f (tp->t state & TTSTOP) !
if (ctmp = CSTART II tp->t_iflag & lXANY)
(*tp->tyroc) (tp, T_RESUME);
I else
i f (ctmp -- CSTOP)
(*tp->tyroc) (tp, T_SUSPEND):
i f (ctmp - CSTART II ctmp == eSTOP)
return:

lcnt = 1;
flg - tp->t iflag:
i f (flg&ISTRIP)
c &- 0177:
else!
1* c &- 0377; not needed *1
i f (c - 0377 && flg&PARMRK)
lbuf[l] = 0377;
lcnt - 2;

1*

s::!:~);:(:!ev)

{

register struct device
int s;

* addr;

dey - 9cdev (dev) ;
addr - Istruct device *)sc_ttptr[dev].tt_addr;
9 - spl6 ();

* Stash character in r_buf
*I
cbp - &tp->t rbuf:
i f (lcnt !- 1) (
lbuf[O] - c;
while (lcnt)
*cbp->cytr++ - lbuf[--lcnt);
if (--cbp->c_count =- 0) i

Fri Sep

scc.su.c

5 19:08:59 1986

4

cbp->cytr -= cbp->c_size;
(*linesw[tp->t_line].l_input) (tp);

i f (stat & RIFRMERR)
c 1= FRERROR:

)

i f (C& (FRERROR I PERROR I OVERRUN) )
i f «c&0377) == 0) {
if (flq'IGNB.,.tta.~)
return:
i f (flg&BRKINT) {
signal (tp->tygrp, SIGINT):
ttyflush (tp, (FREAD I FWRITE) ) :
return:

if (cbp->c size !- cbp->c count) (
Cbp->c ptr -- Cbp=>c size - cbp->c count;
(*linesw[tp->t_line]-:-l_input) (tp);)

) else (
*cbp->cytr - c;
cbp->c count--;
(*line;w[tp->t_linel.l_input! (tp!;

} else (
i f (flg&IGNPAR)
return;
scxintr lap)
register struct args *ap;

I
i f (flg&PARMRK)
lbuf [2]
0377:
lbuf[l] - 0:
lent - 3:
sysinfo.rawch += 2:
else
c - 0:

{

register short dev;
struct tty *tp;
register struct device * addr;
sysinfo. xmtint ++;
dev ~ ap->a dev;
addr = (str;:ict device * I sc ttptr [dev] . tt addr;
addr->csr = WORTXPND;
/"-reset transmitter interrupt "I
addr->csr = WORIUS;
/" reset interrupt *1
tp - sc ttptr [dev] . tt tty;
tp->t_state &= -BUSY;scproc(tp, T_OUTPUT);

I else
i f (flg&ISTRIP)
c &- 0177:

else {

1* c &- 0377: not needed */
if (c ~ 0377 && flg&PARMRK)
lbuf[l] = 0377;
lent - 2;

scsintr (ap)
register struct args *ap;
{

1*
* Stash character in r_buf
*/
cbp - &tp->t rbuf:
i f (lent !- 1) {
lbuf[O] = c:
l!1hile (lent)
"cbp->cytr++ - lbuf[--lcnt]:
i f (--cbp->c count - 0) {
ebp->cytr -= cbp->c_size:
(*linesw[tp->t_line].l_input) (tp):

register struct ccblock *cbp:
register int c, lcnt, flg:
struct tty *tp:
register char ctmp:
char lbuf[3]:
register struct device *addr;
unsigned char stat:
sysinfo. rcvint ++:
addr = (struct device ")sc ttptr[ap->a dev].tt addr:
c - addr->data & OxFF: I"-read data BEFORE reset error */
addr->csr - Oxl;
I" cmd to read register 1 "I
stat - addr->csr:
/* read the status "/
addr->csr = WORERROR:
/* reset error condition */
addr->csr = WORXINT:
/* reinable receiver interrupt */
addr->csr = WORIUS:
/* reset interrupt under service *1
tp = sc ttptr [ap->a dev] . tt tty:
i f (tp->t_rbUf.cytr == NULL)
return;
i f (tp->t iflaq & IXON) {
ctmp = c & 0177;
i f (tp->t state & TTSTOP) {
if (ctmp - CSTART II tp->t iflag & lXANY)
(*tp->tyroc) (tp, (:RESUME);
I else
i f (ctmp - CSTOP)
(*tp->t_proc) (tp, T_SUSPEND):
i f (etmp - CSTART II ctmp == CSTOP)
return:
}

/*
" Check for errors
*1
lent - 1;
flq - tp->t iflag:
i f (stat & (R1PARERR 1 RlOVRERR 1 RIFRMERR) ) (
i f «stat" RIPARERR ) "
(flg & INPCK»
c 1- PERROR:
if (stat" RI0VRERR)
e i-OVERRUN:

}

if (cbp->c size !- cbp->c count) {
Cbp->cytr -- cbp=>c_size - cbp->c_count:
("linesw[tp->t_line].l_input) (tp):
}

I else {
*cbp->cytr = c:
cbp->e count--:
("linesw[tp->t_line].l_input) (tp):

scscan()
{

register int i;
register struct tty *tp;
register struct device *addr:
timeout (scscan, (caddr_t)O, SCTlME):
for (i - 0: i < sc cnt; i++) (
addr - (struct device *)se ttptr[i].tt addr:
addr->csr - WOREXT:
I"-update DCD */
tp = sc ttptr[i).tt tty:
i f (addr->csr & RODeO) {
i f «tp->t state&CARR ON) - 0)
tp=>t state
CARR ON:
i f (tp->t stateufOPEN)
wakeup! (caddr_tl &tp->t_rawq):
I
} else [

1=

scc.su.c

Fri Sep

5 19:08:59 1986

if (tp->t state&CARR ON && sc modem[i]) {
tp->t state &- -CARR ON;
if (tp->t state&ISOPEN) {
ttyflush (tp, FREAD I FWRITE) ;
signal(tp->tJ)qrp, SIGHUP):

tifdef SCC CONSOLE
scputchar (e)
{

register struct device *addr
int s, i;
addr - (struct device *)sc_ttptr[CONSOLE].tt_addr;
s - sp16 ():
if (c ~ '\n')
scputchar (' \r'):
i = 100000;
while «addr->csr & ROTXRDY) == 0 && --i)
addr->data = c;
splx(s) ;
}

tendif SCC_CONSOLE

5

sem..c
1* @(t)sem.c
1*

Fri Sep

5 19:08:00 1986

1

1.5 *1

for(uup

Inter-Process Communication Semaphore Facility.

*1
Hnclude "sys/types.h"
tinclude "sys/param.h lt
tinclude Itsys/dir.h lt
Hfdef u3b
tinclude "sys/istk.h"
tendif
tinclude Msys/map. h"
tinclude Itsys/errno.h"
tinclude "sys/signal.h"
tinclude "sys/ipc.h"
tinclude "sys/sern.h"
tinclude "sys/user . hit
tinclude "sys/seg.h"
iinclude "sys/proc.h H
tinclude ·sys/buf . hit
tifdef pdpll
idefine MOVE
telse
tdefine MOVE
tendif

}

if (! found) (
if(uo->un cnt >= serninfo.semurne)
..
u-:-u error = EINVAL;
return(1) ;
if(up->un_cnt ~ 0)
up->un_np - sernunp;
sernunp - up;
uup2 - &up->un_ent [up->un_cnt++];
while (uup2-- > uup)
* (uup2 + 1) = *uup2;
uup->un_id = id;
uup->un nurn - nurn;
uup->un- aoe = -val;
return (0) ;

sernpimove
iomove

extern
extern
extern
extern
extern
extern
extern

struct sernid_ds sema[] ;
1* semaphore data structures *1
struct sem
sem[] :
1* semaphores *1
struct map
sernrnap [ ] :
1* sem allocation map "I
struct sem_undo "sem undo [];
1* undo table pointers */
struct sem_undo semu[];
1* operation adjust on exit table *1
struct seminfo seminfo:
1* param information structure "I
union {
short
sernvals[1]; 1* set semaphore values "I
struct sernid_ds
ds;
1* set permission values "I
struct sembuf
semops [1] :
I" operation holding area * /
serntrnp;
struct sem_undo *semunp;
1* ptr to head of undo chain "I
struct sem_undo *semfup;
1* ptr to head of free undo chain *1

extern time_t

time;

struct ipc perm
struct semId_ds

up->un ent, found - i - O;i < up->un cnt;i++) {
if (uup->Un_id < id II (uup->un_id -- lei && uup->un_nurn < nurn»
uup++;
continue;
!
if(uup->un id = id && uup->un_nurn -- nurn)
foUnd = 1;
break;
=

uup->un aoe -- val:
if (uup->un_ aoe > serninfo. semaem I I uup->un_ aoe < -seminfo. semaem) {
u.u error - ERANGE;
uup=>un aoe += val:
return (1) :
if (uup->un aoe = 0)
uuPl - &Up->un ent [-- (up->un cnt)]:
while (uup++ < uup2)
* (uup - 1) - *uup;
if(up->un_cnt = 0) (
/* Remove process from undo list. *1
if(semunp = up)
semunp = up->un_np;
else
for (up2 - semunp; up2 ! = NULL; up2 = up2->un np)
if (up2->un np - up) {
up2->un np = up->un np;
break; -

1* system idea of date *1
"ipcget ();
*semconv() ;

/*
semaoe - Create or update adjust on exit entry.

up->un_np - NULL;

*/

semaoe (val, id,
short
val,
nurn;
int
id;

nurn)
1* operation value to be adjusted on exit "/
I" semaphore t *1
I" sernid ,,/

(

register struct undo
register struct sem_undo
register int

"uup,
*uup2;
*up,
*up2;
i,
found;

/" ptr to entry to update * /

return(O) ;

/*
semconv - Convert user supplied semid into a ptr to the associated
semaphore header.

I" ptr to move entry * /
/*
1*
1*
1*

ptr to process undo struct *1
ptr to undo list * I
loop control "I
matching entry found flag "/

if(val -- 0)
return(O) ;
if (val > seminfo. sernaem I I val < -serninfo. semaem) {
u.u_error - ERANGE;
return (1) ;

*1
struct sernid_ds
semconv(s)
register int

/* sernid "/

{

register struct sernld_ds

"sp;

1* ptr to associated header */

sp - &sema[s \ serninfo.sernrnnil;
iff (sp->semJ>erm.mode & IPC_ALLOC) -- 0 II
s I serninfo. sernrnni ! - sp-> semJ>erm. seq)
u. u error - EIHVAL;
return (NULL) ;

}

ifllup - sem undo{u.u procp - proc]) == NU!..L)
if (up - semfup) {
semfup - up->un_np;
up->un np - NULL;
sem_undo[u.u_procp - procl - up;
I else {
u. u_error - ENOSPC;
return(l) ;

*
S;

return (sP) ;

1*
semctl - Semctl system call.

(

Fri Sep

sem.c

5 19:08:00 1986

2
up->u_error - EINVAL;
return;

*1
semctl II

up->u_rvall
return;

{

register struct a {
int
se.."nid;
sernnurn;
uint
crnd;
int
arg;
int
*uap - (struct a *)u.u_ap;
register struct sernid_ds
*sp;
register struct sem
*p;
register int
i;
register struct user *up;
if(lsp

~

semconv(uap->sernid»
return;

-

up->u_rvall = (sp->sem_base + uap->sernnurn)->sempid;
return;

NULL)

I * Get semval of one semaphore. * I
case GETVAL:
if (ipcaccess (&sp->semyerrn, SEM_R»
return;
if(uap->sernnurn >- sp->sem_nsems)
up->u_error - EINVAL;
return;

up = &u;
up->u rvall = 0;
switch (uap->crnd)

1* Remove semaphore set. * /
case IPC RMID:
If(up->u_uid != sp->semyerrn.uid && up->u_uid != sp->semyerrn.cuid
&& ! suser () )
return;
semunrrn(uap->sernid, 0, sp->sem nsems);
for(i = sp->sem nsems, p = sp->sem base;i--;p++)
p->semval = p->sempid - 0;if Ip->sernncnt) {
wakeup ( (caddr t) &p->sernncnt);
p->sernncnt ~ 0;

up->u_rvall return;

(sp->sem_base + uap->sernnurnl->semval;

/ * Get all semvals in set. "/
case GETALL:
if (ipcaccess (&sp->semyerrn, SEM_R) I
return;
up->u base - (caddr t) uap->arg;
up->u-offset - 0; up->u- segflg - 0;
for(i-= sp->sem nsems, p = sp->sem base;i--;p++)
MOVE«caddr tl&p->semval, sizeof(p->semvall, B_READ);
i f (up->u error)
return;

}

if (p->semzcnt) {
wakeup ( (caddr_t) &p->semzcnt);
p->semzcnt = 0;
mfree (sernmap, (int) sp->sem nsems, (sp->sem base - sem) + 1);
if(uap->sernid + serninfo.selDrnni < 0)
sp->semyerrn.seq - 0;
else
sp->semyerrn. seq++;
sp->sem_perrn.mode - 0;
return;

sp->semyerrn.uid - semtrnp.ds.semyerrn.uid;
sp->semyerrn. gid - semtrnp. ds. semyerrn. gid;
sp->sem_perrn.mode = semtrnp.ds.semyerrn.mode & 0777 I IPC_ALLOC;
sp->sem_ctime - time;
return;

(sp->sem_base + uap->sernnurn)->sernncnt;

/* Get pid of last process to operate on semaphore. */
case GETPID:
if (ipcaccess (&sp->semyerrn, SEM_R»
return;
if(uap->sernnurn >- sp->sem_nsemsl
up->u error - EINVAL:
return;

1* ptr to semaphore header */
/* ptr to semaphore *1
/* loop control * /

/* Set ownership and permissions. *1
case IPC SET:
If(up->u_uid != sp->semyerrn.uid && up->u_uid != sp->semyerrn.cuid
&& ! suser () )
return;
if (copyin ( (caddr_t)uap->arg, (caddr_tl &semtrnp.ds, sizeof (semtrnp. ds) »
up->u_error = EFAULT;
return;

~

return;

/* Get t of processes sleeping for semval to become zero. */
case GETZCNT:
if (ipcaccess (&sp->semyerrn, SEM_R»
return;
if(uap->sernnurn >= sp->sem_nsems)
up->u_error - EINVAL;
return;
{

up->u_rvall
return;

=

(sp->sem_base + uap->sernnurnl->semzcnt;

1* Set semval of one semaphore. */
case SETVAL:
if (ipcaccess (&sp->sernyerrn, SEM_A»
return;
if (uap->sernnurn >- sp->sem nsems)
up->u_error - EINVAL;
return;
)

/* Get semaphore data structure. "/
case IPC STAT:
If(ipcaccess(&sp->sem perm, SEM_R»
return;
if (copyout «caddr_tl sp, Icaddr_t)uap->arg, sizeof(*sp) II {
up->u error - EFAULT;
return:

if ( (unsigned) uap->arg > seminfo. semvmx)
up->u_error = ERANGE;
return:
)

if ((p - sp->sem base + uap->sernnurn) ->semval - uap->arg)
i f (p->sernncnt) {
p->sernncnt - 0;
wakeup ((caddr_t) &p->semncnt);

return;
) else
/* Get t of processes Sleeping for greater semval. */
case GETNCNT:
if(ipcaccess(&sp->sem perm, SEM R»
return;
if (uap->semnurn >- sp->sem_nsems) (

if (p->semzcnt)
p->semzcnt - 0;
wakeup ( (caddr_t) &p->semzcnt):
}

p->sempid - up->uyrocp->p""pid;

sem..c

Fri Sep

5 19:08:00 1986

3

semunrm(uap->semid, uap->semnum. uap->semnum);
return;
/* set semvals of all semaphores in set. */
case SETALL:
if {ipcacces3 (&3p->se.lil~rm, SEM_A»
return;
up->u base = (caddr t) uap->arg:
up->u:=offset - 0; up->u segflg ~ 0;
MOVE (tcaddr t) semtmp. semvals,
(int) (sizeof(semt..Tflp.se.."llvals[O]) * gp->sem_ns~~s},
B WRITE);
i f (up->u_error)
return;
forti = O;i < sp->sem nsems;)
if (semtmp. semvals [i ++] > seminfo. semvmx)
up->u_error - ERANGE;
return;

if(semunp -- up)
semunp - up->un_np;
else
for(p = semunp;p !- NULL:p - p->un_np)
if (p->un_ np ~ up) (
P->Ul'l np = up->un np;
break:
cleanup:
up->un np - semfup:
semfup- = up;
sa~_~'do[u.u-procp

- proc]

~

WJLL;

/*
semget - Semget system call.

*/
semget()
(

semunrm(uap->semid, 0, sp->sem nsems);
for (i = 0, p = sp->sem base; i "< sp->sem nsems;
(p++)->sempid ~ up->u-procp->p~id) (
if(p->semval = semtmp. semvals [i++] ) {
i f (p->semncnt) {
p->semncnt = 0;
wakeup «caddr_tl &p->semncnt);

register struct a {
key t
key;
intnsems;
int
semflg;
*uap = (struct a *lu.u_ap;
register struct semid_ds
*sp;
register int
i;
int
s;

/* semaphore header ptr */

/* temp */
/" ipcget status return */

) else
if (p->semzcnt)
p->semzcnt = 0;
wakeup ( (caddr_t) &p->semzcnt);

if( (sp - (struct semid ds *)
ipcget (uap->key, uap->semflg. (struct ipc-perm * 1 sema,
seminfo.semmni. sizeof("spl. &s» = NULL)
return;
if(s) {

return;
default:

/* This is a new semaphore set. Finish initialization. */
if (uap->nsems <= 0 I I uap->nsems > seminfo. semmsl) (
u. u error - EINVAL;
sp->sem-perm.rnode = 0;
return;
l
if( (i - malloc(seI!llllap, uap->nsems» = NULL) (
u. u error = ENOSPC:
sp->sem~rm.mode = 0;
return:

up->u_error - EINVAL;
return;

/*

sernexit - Called by exit(sys1.c) to clean up on process exit.

"/
semexit()

sp->sem_base = sem + (i - 1);
sp->sem nsems - uap->nsems;
sp->sem:=ctime - time:

{

register struct sem_undo
register
register
register
register

struct semid_ds
int
long
struct sern

"up.
*p;
*sp;

i;
v;
"semp;

1* process undo struct ptr *1
/* undo struct ptr *1
/* semid being undone ptr "I
I" loop control *1
/" adjusted value */
/* semaphore ptr ,,/

if( (up ~ sem_undo[u.u_procp - proc]) = NULL)
return;
if(up->un_cnt - 0)
goto cleanup;
for(i - up->un cnt;i--;)
if«sp-- semconv(up->un ent[i].un id» == NULL)
continue;
v - (long) (sernp - sp->sem base + up->un_ent[il.un_numl->semval +
up->un ent til . un aoe;
if(v < 0 II v> seminfo.semvmx)
continue;
semp->semval - v;
if (v - 0 && semp->semzcnt)
semp->semzcnt - 0;
wake'.lp( (caddr_t) &serr.p->semzcr.t~;
if(up->un_ent[il.un_aoe > 0 && semp->semncnt)
semp->semncnt - 0;
wakeup ( (caddr_tl &sernp->semncnt);

} else
if(uap->nsems && sp->sem_nsems < uap->nsems) {
u.u_error - EINVAL;
return;
u.u_rva11

sp->sem-perm.seq" seminfo.semmni + (sp - serna);

/"
seminit - Called by main(main.c) to initialize the semaphore map.

"I
seminit ()
{

register i;
mapinit (semrnap, seminfo. semmap);
mfree(semmap, serninfo.semmns, 1);
semfup = semu;
for (i - 0; i < seminfo.semmnu - 1; i++)
semfup->un_np - (struct sem_undo
sernfup - sernfup->un_np;
semfup->un np - NULL;
semfup - semu;

up->un_cnt - 0;

*)

«uint) semfup+serninfo. semusz);

Fri Sep

sem.c

5 19:08:00 1986

4
semp->semncnt = 0;
wakeup ( (caddr_t) &semp->semncnt):

/*
semop - Semop system call.

"/

continue;

if (oP=>S2.t"'l1 op < 0)
if(semp->semval >- -op->sem op) {
if (op->sem flg & SEM UNDO &&
semaoe (op->sem op, uap->semid, (short) op->sem_num) )
if(i)
semundo (semtmp. semops, i, uap->semid, sp);
return;

sa.'Uop()

register struct a {
int
semid;
struct sembuf
"sops;
uint
nsops;
}
"uap ~ (struct a *)U.ll
register struct sembuf
register int
register struct semid_ds
register struct sem
int
again;

ap:
"op;
i;
"sp;
*semp;

/*
/*
/"
/"

ptr to operation *1
loop control */
ptr to associated header */
ptr to semaphore ,,/

semp->semval += op->sem op;
if(semp->semval = 0 &&-semp->semzcnt)
semp->semzcnt - 0;
wakeup ( (caddr_t) &semp->semzcnt);

if«sp = semconv(uap->semid» == NVLL)
return;
if (uap->nsops > seminfo. semopm)
u.u_error = E2BIG;
return;

continue;
}

if(i)
semundo (semtmp. semops, i, uap->semid, sp);
if(op->sem_flg & IPC_NOWAIT) {
u.u_error - EAGAIN;
return;

u.u base = (caddr t)uap->sops;
u.u-offset = 0; u.u-segflg = 0;
MOvE«(caddr t)semtmp.semops, (int)(uap->nsops * sizeof("op», B_WRITE);
if (u.u_error)
return;

semp->semncnt++ ;
if(sleep( (caddr t) &semp->semncnt, PCATCH I PSEMN»
if«semp->semncnt)-- <~ 1) {
semp->semncnt - 0;
wakeup ( (caddr_t) &semp->semncnt);

/* Verify that sem ts are in range and permissions are granted. *1
for(i = 0, op = semtmp.semops;i++ < uap->nsops;op++) {
if (ipcaccess (&sp->sem~rm, (ushort) (op->sem_op'?SEM_A:SEM_R»)
return;
if(op->s~num >- sp->sem_nsems)
u.u_error = EFBIG;
return;

u.u_error - EINTR;
return;
goto check;
}

if (semp->semval) {
if(i)
semundo (semtmp. semops, i, uap->semid, sp);
1f(op->sem_flg & IPC_NOWAIT) {
u. u_error - EAGAIN;
return;

again - 0;
check:
/" Loop waiting for the operations to be satisified atomically. */
/" Actually, do the operations and undo them if a wait is needed
or an error is detected. */
if (again) {
/" Verify that the semaphores haven't been removed. *1
if (semconv(uap->semid) = NVLL)
u.~error = EIDRM;
return;

/* copy in user operation list after sleep */
u.u_base = (caddr_t)uap->sops;
u.u_offset = 0;
u.u segflg - 0;
MOvE «caddr t) semtmp. semops,
(intI (uap->nsops * sizeof (*opl), B_WRITE);
if(u.u_error)
return;
again - 1;
for(i

~

0, op - semtmp.semops;i < uap->nsops;i++, op++) {
semp = sp->sem base + op->sem num;
if (op->sem op "> 0) {
if(op->sem_op + (long)semp->semval > seminfo.semvmx II
(op->sem flg , SEM UNDO H
semaoe (op->sem op, - uap->semid, (short) op->sem_num» )
!!(U.l1_e~ror
0)
u. u_error - ERANGE;
if(il
semundo (semtmp. semops, i, uap->semid, sp);
return;

==

semp->semval +- op->sem op;
if (semp->semncnt) {
-

{

semp->semzcnt++;
if(sleep( (caddr t) &semp->semzcnt, PCATCH I PSEMZ»
if( (semp->semzcnt)-- <= 1) {
semp->semzcnt = 0;
wakeup ( (caddr_t) &semp->semzcnt);
u.u_error
return;

=

{

EINTR;

goto check;

1* All operations succeeded.

Update sempid for accessed semaphores. *1
0, op = semtmp.semops;i++ < uap->nsops;
(sp->sem_base + (op++)->sem_num)->sempid = u.uyrocp->p_pidl;
sp->sem otime ~ time;
u.u_rvall - 0;
for(i

=

tifdef pdpll
/*
sempimove - PDP 11 pimove interface for possibly large copies.
"/
sempimove (base, count, model
paddr t
base;
register unsigned
count;
int
mode;
register unsigned

/* base address */
/* byte count *1
/* transfer mode *1
tcount; 1* current transfer count *1

Fri Sep

sem.c

5 19:08:00 1986

while(u.u_error == 0 && count) {
tcount = count> 8064 '] 8064
pimove (base, tcount, mode);
base += tcount;
count -- tcount;

5

count;

/* Search through current structure for matching entries. "/
for (up - p->un ent, i - 0; i < p->un cnt:) {
if(id"< up->un_id)
break;
if(id > up->un_id II low > up->un_num) {
up++:

}

i++:

iendif

continue:
}

if (high < up->un_ num)
break:
forI; = i:++i < D->un cnt:
.~
p->~_ent[j --1] = p->un_ent[j]):
p->un_cnt--:

/*
semsys - System entry point for semctl, semget, and semop system calls.

*/
semsys ()
(

int

semctl () ,
semget(),
semopO:
static int
(*calls[]) () = {semctl, semget, semop}:
register struct a {
uint
id:
/* function code id * /
*uap = (struct a *)u.u_ap:

/* Reset pointers for next round. */
if(p->un_cnt ~ 0)
/* Remove from linked list. */
if (pp - NULL) {
semunp - p->un_np;
p->un_ np - NULL:
p = semunp;
} else {
pp->un_np = p->un_np:
p->un_np - NULL;
p = pp->un_np;

if(uap->id > 2) {
u. u error - EINVAL:
return:
u.u ap - &u.u arg[l];
(*calls [uap->Id] ) () ;
else {

pp - p;
p - p->un_np;

1*
semundo - Undo work done up to finding an operation that can't be done.
"I
semundo (op, n, id, sp)
register struct sembuf
register int
register struct semid_ds

wop;
n,
id:
*sp;

/* first operation that was done ptr */
/* i of operations that were done ,,/
1* semaphore id * /
/* semaphore data structure ptr */

*semp:

/* semaphore ptr .. /

(

register struct sem

for(op += n - l:n--:op--) (
if(op->sem op = 0)
continue;
semp - sp->sem_base + op->sem num:
semp->semval -= op->sem op;
if(op->sem flg & SEM UNDO)
(void) semaoe(-op->sem_op, id, (short)op->sem_num);

1*
semunrm - Undo entry remover.
This routine is called to clear all undo entries for a set of semaphores
that are being removed from the system or are being reset by SETVAL or
SETVALS commands to semctl.
*/

semunrm(id, low,
int
id:
ushort low,
high:

high)
/* semid "/
/* lowest semaphore being changed */
/* highest semaphore being changed */

register struct sem_undo

*pp,
*p:

register struct undo
register int

"up;

pp - NULL;
p - semunp;
while (p !- NULL)

i,
j;

/*
/*
/*
/*
/*

ptr to predecessor to p *1
ptr to current entry * /
ptr to undo entry" /
loop control * /
loop control * /

Fri Sep

shm.c
1* @(t)shm.c
tinclude
tinclude
tinclude
tinclude
fincludE
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
extern
extern
extern
extern
int

5 19:08:21 1986

1
« (int)uap->addr !- 0) &&
«(int)uap->addr + ctob (stoc (ctos (btoc(sp->shm segsz)))) I >
ctob(stoc(ctos (btoc(v. v uend) -up->u ssize»)
up->u_error ~ EINVAL;
return;

1.7 *1

Usys/types. hft
"sys/param.h"
·sys/config.h"
"sys/mmu.h"
"sys/sysmacros.h"
"sys/dir.h"
·sys/errno.h"
• sysl signal. hOI
"sys/user.h"
·sys/seg.h"

III {

1*
* An address of 0 places the shared memory into a first fit location

*1
i f (uap->addr - NULL) {
if (sr'-'!I..TJ. > 0) { /* there was a previous attach */
/* try the virtual address just beyond the
last one attached */
segbeg - (short) (p - proc) * (shortlshminfo.shmseg +
shmn - 1;
1* index of last shmem *1
segbeg ~ shm-pte[segbeg].shm_segbeg +
ctob (stoc (ctos (btoc (
shm shmem[segbeg]->shm segsz»)));
} else
1* this is the 1st attach *1 segbeg = v. v ustart +
ctob(stoc(ctos(up->u tsize)) +
ctob (stoc (ctos (up->u-dsize))) +
ctob (stoc (ctos (shminfo. shmbrk»);

IIIsys/ipc.h ll

·sys/ shm.h"
·sys/proc.h"
·sys/context.h H
·sys/systm.h"
·sys/map.h"
·sys/var. hOI
·sys/scat.h"

struct shmid ds
struct shmid::::ds
struct shmpt ds
struct shminfo
shmtot;

shmem[] ;
*shm shmem[];
shmyte[] ;
shminfo;
1* total shared

1*
1*
1*
1*

shared memory headers *1
ptrs to attached segments *1
segment attach points *1
shared memory info structure */
memory currently used "I

time;
struct ipc~rm
struct shmid_ ds

1* need to avoid any phys areas *1
for (ph - &u.uJ>hYs[O]; ph < &u.u_phys[v.v-phys]; ph++) {

/* system idea of date * /

i f (ph->u-phsize) {
as - segbeg;
bs ~ segbeg +
ctob(stoc (ctos (btoc(sp->shm segsz»));
ap - ph->uJ>hladdr;
bp - ph->uJ>hladdr +
ctob (stoc (ctos (ph->uJ>hsize) ) ) ;
i f «as < ap) && (bs <- ap) j
/* shmat all before phys - ok */
continue;
i f «as >- bpj && (bs > bpj)
1* shmat all after phys - ok *1
continue;
1* allocation would conflict with phys *1
1* choose another location ... where? *1
up->u_error - ENOMEM;
return;

*ipcget () ;
* shmconv ( ) ;

1*
shrnat - Shrnat system call.

*1
shrnat ()
{

register struct a {
int
shmid;
char
*addr;
int
flag;
*uap - (struct a *)u.u ap;
register struct shmid ds
- *sp;
register struct user *up;
register struct proc *p;
register int
shmn;
register int
segbeg;
register struct phys *ph:
int
i, aa, ix;
int
as,bs,ap,bp:

1* shared memory header ptr *1
}

} else {

1*
* Check to make sure segment does not overlay any valid segments

*1

up - &u;
p - up->u-procp;
if «sp = shmconv(uap->shmid, SHM_DEST)) - NULL)
return;
if (ipcaccess(&sp->shm perm, SHM R))
return;
i f «uap->flag & SHM ROONLY) == 0)
i f (ipcaccess (&Sp->shm-perm, SHM_N))
return;
for (shmn = 0; shmn < shminfo. shmseg: shmn++)
i f (shm_shmem[ (p - proc) *shminfo. shmseg+shmnj break;
i f (shmn >- shminf 0 • shmseg I {
up->u_error - EMFlLE;
return;
i f (uap->flag & SHM RND)
uap->addr =-(char *J «:lint)ilap->addr

&

-{SP.ML3A-

1*

segbeg - vtoseg( (intluap->addr);
for (i - btoc(sp->shm segsz); i > 0; i -- aa) {
aa = min (NPAGEPERSEG, (unsigned) i) ;
i f «getmmu«short *1 (segbegIACCLIM))&PROTMASK) !-ASINVAL)
up->u_error - ENOMEM;
return:
segbeg +- (l«SEGSHIFT);
segbeg
NULL)

,,\.
J..j,I

1*

" Check for page alignment and containment within data space

1*

"I
& (SHMLBA - 1) !!
sp->shm seqsz <- a I I
«int)uap:->~ddr & Ox80000000) II

i f «int)uap->addr

=

(int) uap->addr;

if (chksize (up->u_tsize, up->u_dsize, up->u_ssize»
up->u_error - ENOMEM;
return;

i - (short) (p - proc) * (short)shminfo.shmseg + shmn;
shm shmem[i] - sp;
shm-pte [ i] . shm segbeg - segbeg;
shm-pte[i].shm-sflg - (uap->:lag & SHM_RDONLYl
RO
shm- pte [ i] . shm- seg - 0;
cxr;lse(p->p_context); *1
sureg() ;

* Clear segment on first attach

*1

{

RW);

5 19:08:21 1986

Fri Sep

shm..c

2
this segment now are shmdt () and shmctl (IPC STAT).
All others will give bad shmid. */
sp->shm~rm.key - IPC_PRIVATE:

i = btoc(sp->shm segsz):
Hfdef NONSCATLOAD
ix - btoc (segbeg) :
while (--i >= 0)
clearseg(ix++) :
talse
ix - sp->shm scat:
while (--i >:: 0) (
clearseg(ixtoc(ix» :
ix - scatmap[ixl.sc_index:

/* Adjust counts to counter shmfree decrements. ,,/
sp->shm nattch++;
sp->shm-cnattch++:
shmfree(sp) :
break:
/* Set ownership and permissions. */
case

tendif
sp->shmyerm.mode

&=

If (up->u uid !- sp->shm perm.uid && up->u_uid != sp->shm_perm.cuid
&& !suser()
return:
if (copyin«caddr_t)uap->arg, (caddr_t) &ds, sizeof(ds))) {
up->u_error - EFAULT:
return:

i f (p->p_smbeg = 0 II p->p_smbeg > segbeg)
p->p_smbeg - segbeg;
sp->shm nattch++;
sp->shm- cnattch++:
up->u rvall = segbeg;
sp->shm atime - time;
sP->Shm~)pid - p->pyid;

)

sp->shmyerm.uid - ds.shmyerm.uid:
sp->shmyerm.gid = ds.shm_perm.gid;
sp->shmyerm.mode = (ds.shm~rm.mode & 0777)
(sp->shm~rm.mode & -0777);
sp->shm ctime = time;
break: -

/*
shmconv - convert user supplied shmid into a ptr to the associated
shared memory header.

1* shmid *1
1* error if matching bits are set in mode *1

register struct shmid_ds

*sp:

I

/* Get shared memory data structure. *1
case IPC STAT:
If (ipcaccess(&sp->shmyerm, SHM_RI)
return:
if (copyout( (caddr_t) sp, (caddr_tluap->arg, sizeof(*splll
up->u_error - EFAULT;
break:

*/
struct shmid_ds *
shmconv(s, fIg)
int
s;
int
flg:

~lt'lfl.

TDr""

-SHM_CLEAR:

}

/* ptr to associated header *1
default:

sp - &shmem[(shartl (s % shminfo.shmmnill;
i f (! (sp->shm~rm.mode & IPC_ALLOC) II sp->shmyerm.mode & flg II
s I shminfo.shmmni != sp->shmyerm.seql (
u. u error - EINVAL:
return (NULL) ;

up->u error - EINVAL:
break-;

1*
return (sp) ;

shmdt - Shmdt system call.

*1
shmdt()

1*
shmctl - Shmctl system call.

{

*1

struct a {
char
*addr:
*uap - (struct a *)u.u_ap:
register struct shmid ds
"sp, *"spp:
int
segbeg;
*pt;
register struct shmpt_ds
register i, j:
register struct proc *p:

shmctl ()
{

register struct a {
int

shmid,
cmd;
struct shmid_ds *arg;
"uap - (struct a *lu.u
register struct shmid ds
struct shmid ds
register struct user

ap;
*sp;
ds;
*up;

I * shared memory header ptr * /
1* hold area for IPC_SET */

if «sp - shmconv(uap->shmid, (uap->cmd NULL)
return;
up - &u;
up->u rvall - 0;
switch (uap->cmd)

* Check for page alignment

*I
IPC_STATI

1* Remove shared memory identifier. * I
case IPC RHID:
If (Up->u_uid != sp->shm_perrr..:.l:'d
" ! suser ( »
return;
sp->shm ctime - time;
sp->shm=perm.mode 1- SHM_DEST;

/*

&&

:.lp->u_1:.id

i f «int)uap->addr & (etob(l) - 1) II
(segbeg - (int)uap->addr) -- 0) {
u. u error - EINVAL;
return:

/*
* find segment
*1
spp - &shm shmem[i- «p-u. u procp) -proc) *shminfo. shmseg] ;
pt - &shmj)te til :
for (i-O; i < shminfo.shmseg; itt, pttt, spptt) {
if «sp - *spp) !- NULL U pt->shm_segbeg -- segbeg)
break:
sp - NULL;
)

i f (sp -- NULL)

1* Change key to private so old key can be reused without
waiting for last detach.

Only allowed accesses to

(

u.u_error - EIWAL;
return;

Fri Sep

shm.c

5 19:08:21 1986

3
/* Copy ptrs and update counts on any attached segments. */
cpp - &shm shmem[(cp - procl*shminfo.shmseg]:
ppp - &shm-shmem[(pp - proc)*shminfo.shmseg]:
cppp = &shiiiyte [(cp - proc) *shminfo. shmseg]:
pppp - &shmyte [(pp - proc) *shminfo. shmseg]:
cp->p srnbeg = pp->p srnbeg:
for(i-- o:i < shminfo.shmseg; i++, cpp++, ppp++, cppp++, pppp++) {
if (*cpp - *ppp) (
(*cpp) ->shm nattch++;
(*CPpl->shm-cnattch++;
cPPP->Shm_segbeg - pppp->shm_segbeg;
cppp->sh.!!! sflq = pppp->shm sflq:
cppp->shm::::seg - 0;
-

shmfree (sp) :
sp->shm dtime = time;
sp->shm-lpid - p->pyid:
*spp - NuLL:
pt->sh...·'il segbeg = 0:
p->p smbeg - 0:
pt --&shmyte[ (p-proc) *shminfo.shmseg]:
for (j-O: jshm segbeg) {
if (p->p smbeg) {
if (p->p s!!lbeq > i)
p->p_smbeg - i:
else {
p->p_smbeg - i;

/*

1*

cxrelse (p->p_context): * 1
sureg() :
u.u_rvall - 0:

shmfree - Decrement counts.
indicated.

Free segment and page tables if

*1
shmfree (sp)
register struct shmid_ ds

1*
shmexec - Called by setregs (os/ sysl. c) to handle shared memory exec
processing.

*sp:

1* shared memory header ptr *1

{

register int size;

*1
if (sp

shmexec()
(

register struct shmid_ds
register struct shmpt_ ds
register int

**spp;
*sppp;
i:

/* ptr to ptr to header *1
1* ptr to pte data * I
1* loop control */

if (u.uyrocp->p_smbeg -= 0)
return;
1* Detach any attached segments. *1
sppp - &shmyte[i = (u.uyrocp - proc)*shminfo.shmseg]:
u.uyrocp->p_smbeg = 0;
spp = &shm shmem[i]:
for (i = 0;-i < shminfo. shmseg; i ++, spp++, sppp++) {
if (*spp - NULL)
continue;
shmfree (,. spp) ;
*spp = NULL;
sppp->shm_segbeg - 0;

NULL)
return;
sp->shm nattch--:
if (-- (sp->shm_cnattchl - 0 && sp->shmyerm.mode & SHM_DEST)
size = btoc(sp->shm segsz);
tifdef NONSCATLOAD
mfree(coremap, size, (int) sp->shm_scat):
telse
memfree «int) sp->shm_scat);
tendif
1* adjust maxmem for amount freed */
maxmem += size;
shmtot -= size;
~

sp->shmyerm.mode - 0;
if «(int) (++(sp->shmyerm.seq)*shminfo.shmmni + (sp - shmem)) <
sp->shmyerm. seq - 0:

1*
shmget - Shmget system call.

1*

*1
shmexit - Called by exit(os/sysl.c) to clean up on process exit.

*/

shmget()
(

shmexit()
(

1* Same processing as for exec. *1
shmexec() :

1*
shmfork - Called by newproc (os/slp. c) to handle shared memory fork
processing.

register struct a {
key t
key;
intsize,
shmflg;
*uap - (struct a *)u.u_ap;
*sp;
register struct shmid_ds
s;
int
size;
register int

I*if (uap->size -= 0)
return; *1
1*

*1
shmfork(cp, pp)
struct proc
*cp,
*pp;

1* ptr to child proc table entry *1
/ * ptr to parent proc table entry * I

register struct shmpt_ds
register int
if (pp->p_slllbeg -- 0)
return:

"*cpp,
**ppp:
*cppp,
*pppp;
i;

1* ptr to chile. s~er.: ptrs .. /
1* ptr to parent shmem ptrs */
1* loop control * 1

1* shared memory header ptr *1
1* ipcget status * 1

1* Bug #675 ••• Paul *1

if «sp - (struct shmid ds *) ipcget (uap->key, uap->shmflg,
(struct ipcyerm ")'ihmem, shminfo.shmmni, sizeof(*sp), &s)) -- NULL)
return:
i f (s) I
/* This is a new shared memory segment. Allocate memory a::d
finish initialization. *1
if (uap->size < shminfo.shmmin II uap->size > shminfo.shmmax)
u. u error - EINVAL:
sp->shm_perm.mode - 0;
return:
size - btoc (uap->size) ;

0)

Fri Sep

shm.c

5 19:08:21 1986

4

if (shmtot + size > shminfo. shInall)
u.u_error - ENOMEM;
sp->shmJ>erm.mode = 0;
return;

*1
if (p->p smbeg return;

0)

1*

Sp->shln seqsz - uap->size;
iifdef NONSCATLOAD
if «sp->shm_scat - malloc(coremap, size»
u.u_error = ENOMEM;
sp->shm-perm.mode - 0;
return;

=

0)

{

* clear unused pte's
*/
seg - pObr + ub->u tsize + ub->u dsize;
for (i = ub->u tsize + ub->u_dsize; i < pOlr; i++)
*seg++-- 0;
1*
" move in the shared memory segments

*1
sp - &shm shmem[i = (p - proc) *shminfo. shmseg];
pt - &Shm~te[i];
for Ii - 0; i < shminfo.shmseg: i++, sp++, pt++)
if (shm = pt->shm segbeq) {
seq = pObr + shm:
pte - (int X) «*spl->shm ptbl):
for (j - 0: j < btoc( (*sp)->Shm seqsz): j++)
*seg++ = *pte++ 1 PG_v"I pt->shm_sflq;

ielse
if I (sp->shm_scat = memalloc(size»
u. u error - ENOMEM;
sp->shm~rm.mode ~ 0;
return;

=

0) {

iendif
/* adjust maxmem for the segment */
maxmem -= size;
shmtot +- size;
sp->shm~rm.mode 1- SHM_CLEAR;
sp->shm nattch - 0;
sp->shIIlcnattch - 0;
sp->shm-atime = 0;
sp->shm-dtime - 0;
sp->shm-ctime = time;
sp->shm-Ipid = 0;
sp->Shm=cpid - u.u-procp->p-pid;

iendif
Hfdef notdef
dumppte (pObr, pOlr, pllr, plbr)
int *pObr, pOlr, pllr, *plbr;
{

register i;

J else

printf("tsize 'kd, dsize 'kd\n", u.u tsize, u.u dsize);
printf(npObr 'kx plbr 'kd\nplbr 'kx pllr 'kd\n\nn~pObr,pOlr,plbr,pllrl;
for (i=O; isize && uap->size > sp->shm_segszl
u.u_error = EINVAL;
return;
u.u_rvall

=

sp->shm~rm.seq

* shminfo.shmmni + (sp - shmem);

printf("\n\n\n") ;

1*
shmsys - System entry point for shmat, shmctl, sl'.mdt, a:J.d sh:nget
system calls.

*1
shmsys()
{

register struct a {
uint
id;
*uap - (struct a *)u.u ap;
shInat (),
int
shmctl() ,
shmdt() ,
shmgetl) ;
static int
("calls [)) () - {shInat, shmctl, shmdt, shmqet};
if (uap->id > 3) {
u.u_error - EINVAL;
return;
u.u ap - &u.u arg[l];
(*calls[uap->Id]) ();

Hfdef notdef
sbmreset (p, ub, pObr, pOlr)
struct proc "p;
struct user *ub;
int "pObr, pOlr;
!
register struct shmid ds ** sp;
register struct shmpt=dS "pt;
register i, j;
register int *seq, shm, "pte;

I"
• do only if there is shared memory ate ached

tendif

sig.c

Fri Sep

5 19:08:22 1986

I" @(t) sig. c
1. 3 .. I
tinclude "sys/param.h"
tinclude "sys/config.h"
tinclude "sys/mmu.h H
tinclude ·sys/types.h H
tinclude "sysl sy&""n.a.cros. hi.
tinclude ·sys/systm.h"
tinclude Hsys/dir .h H
tinclude "sys/signa1.h"
tinclude Hsys/user. hH
tinclude "sys/errno.h ll
tinclude ·sys!proc.h"
tinclude ·sys/inode.h ll
tinclude "sys/file.h Ol
tinclude Hsys/reg.h"
tinclude ·sys/text.h u
tinclude "sys/seg.h"
tinclude ·sys/var. h"
.include ·sys/ps1. h"
.include "sys/scat.h"

1
if (p->p stat - SSLEEP && p->p pri > PZERO) {
If (p->pyri > PUSER) p->p_pri = PUSER;
setrun(p) :

1*
..
..
..
..
*
*
*
*
*

Returns true if the current
process has a signal to process.
This is asked at least once
each ti!'!!.e a process enters the
system.
A signal does not do anything
directly to a process: it sets
a flag that asks the process to
do something to itself.

*1
issig()
{

register n;
register struct proc *p, *q;

/*
* Priority for tracing
*1
tdefine IPCPRI PZERO

1 ipc;

p = u. uyrocp;
while (p->p sig) {
n :: fsig (p) ;
if (n == SIGCLD) {
i f (u.u signal[SIGCLD-l]&Ol)
-for (q - &proc[l]:
q < (struct proc *)v.veyroc; q++)
i f (p->pyid ~ q->pypid &&
q->p stat == SZOMBI
freeproc(q, 0);
} else i f (u.u signal[SIGCLD-l])
return(n) ;
) else if (n =- SIGPWR) {
i f (u.u signal[SIGPWR-l] && (u.u_signal [SIGPWR-l] &1)==0)
-return (n) ;
I else i f «u.u_signal[n-l)&1) == 0 II (p->p_flag&STRC»
return(n) ;
p->p_sig &= -(lL«(n-l»;

1*

return (0) ;

1*
* Tracing variables.
.. Used to pass trace command from
* parent to child being traced.
* This data base cannot be
.. shared and is locked
.. per user.

*1
struct ipctrace
int
int
int
int

ip data;
ip-lock;
ip-req;
*ip_addr;

*
..
..
..

Send the specified signal to
all processes with 'pgrp' as
process group.
Called by tty.c for quits and
* interrupts.

1*
.. Enter the tracing STOP state.
.. In this state, the parent is
.. informed and the process is able to
* receive commands from the parent.

.. I
signal (pgrp, sig)
register pgrp;

*1

(

stop()
register struct proc *p;

{

register struct proc *pp, *cp;
i f (pgrp

for (p

=

== 0)

return;
&proc [1); p < (struct proc *) v. veyroc; p++)
i f (p->pygrp ~ pgrp)
psignal (p, sig):

loop:
cp = u.uyrocp;
i f (cp->pypid != 1)
for (pp = 'proc[O); pp < (struct proc *lv.veyroc; pP++1
i f (pp->pyid == cp->p_ppid)
wakeup ( (caddr_tlpp);
cp->p_stat - SSTOP;
slitch() ;
i f «cp->p_flag&STRC) -0 I I procxmt ()
return;
goto loop;

1*
.. Send the specified signal to
.. the specified process.

*1
psignal (p, sig)
register struct proc *p;
register sig;
sig--:
i f (sig < 0 i I sig >- NSIG)
return:
i f (((p->p_siqiqn» sig) & 1) H
return;
p->p_siq 1= lL«sig:

}

exit (fsig(u.uyrocp»;

1*
sir; !- (S!GCLD - 1)

* Perform the action specified by
* the current signal.
.. The usual sequence is:
i f (issig () )
~si~O

;

siq.c

Fri Sep

5 19:08:22 1986

2
* user. h area followed by the entire
* data+stack segments.

*1
psig()

*1

{

register n, p:
register struct proc *rp;
tifdef l'llc6888l
1* MC68881 floating=point coprocessor * /
extern short fp881:
1* is there an MC68881'1 * 1
tendif mc68881

corel)
{

reqister struct inode *ip;
register struct user *up:
register s;
extern schar () ;

rp ~ u.uJlrocp;
tifdef FLOAT
1* sky floating point board *1
if (u .. u fpinuse && u.u_fpsaved==O) {
-savfp() :
u.u_fpsaved - 1;

up - &u;
if (up->u uid !- up->u ruid)
return (01 ;
up->u error = 0;
up->u- dirp = "core";
ip - namei (schar, 1);
if (ip == NULL) {
if (up->u_error)
return (0) ;
ip = maknode(0666);
if (ip=NULL)
return (0) ;

tendif
Hfdef mc68881
1* MC68881 floating-point coprocessor *1
if (fp881)
fpsave() :
tendif mc68881
if (rp->p flag&STRC)
stop() ;
n = fsig(rp):
if (n=O)
return;
rp->p sig &- -(lL«(n-ll);
if «p=u.u signal[n-l]) !- 0) {
if-(p & II
return;
u. u error = 0;
if In != SIGILL && n != SIGTRAPI
u.u signal[n-l] = 0:
sendsig( (caddr_tIP, n):
return:

)

i f (!access(ip, IWRITE) && (ip->i_mode&IFMT) - IFREG) {
itrunc(ip) ;
up->u offset = 0;
up->u-base = (caddr t)up;
up->u-count = ctob(;.v usize);
up->u- segflg - 1;
up->U-limit = (daddr t)ctod(MAXMEM);
up->u-fmode = FWRlTE:
1* make register pointer relative for adb *1
up->u arO ~ (int *) «int)up->u arO - (int) up) ;
up->u- usrtop - btoc (v. v uend);writeI (ip) ;
up->u arO = (int *1 «int)up->u arO + (intI up) ;
s = up->uJlrocp->p_size - v.v_usize;
(void) estabur«unsigned) 0, (unsigned)s, (unsigned)O, 0, RO);
up->u base - (caddr t)v.v ustart;
up->u-count = ctob(s);
up->u- segflg - 0;
writeI(ip) ;
) else
up->u error - EACCES;
iput(ip);
return (up->u_error--O) ;

switch(n) {
case
case
case
case
case
case
case
case
case

SIGQUIT:
SIGILL:
SIGTRAP:
SIGIOT:
SIGEMT:
SIGFPE:
SIGBUS:
SIGSEGV:
SIGSYS:
if (core() )
n += 0200:

1*
exit(n) :

* grow the stack to include the SP
* true return if successful.

*1
find the signal in bit-position
* representation in p sig.

tifdef NONSCATLOAD
qrow(sp)
unsigned sp;

*1

{

1*

*

-

fsig (pI
struct proc *p;

register struct user *up;
register struct proc *p;
register si, i, al;

{

register short i;
register long n;
n - p->p sig;
i - NSIG-- 1;
do {
i f (n
n

»-

&

IL)
return(NSIG - i);

1;

1 while (--i !- -1);
return(O) ;

up - &u;
if «v.v uend-sp) < ctob(up->u ssize»
return(O);
si - btoct (v. v uend-sp) - up->u ssize + SINCR;
if (si <- 0) return (0) ;
if (estabur (up->u tsize, up->u_dsize, up->u_ssize+si, 0, RO»
return (0):
p = up->uJlrocp;
expand ( (int) (p->p size+si»;
al - p->p addr + p->p size;
for (i-up->u_ssize: i;-i--) {

1*

al--;

" Create a core image on the file "core"

copyseg(al-si, all:
}

" It writes USIZE (v. v_usize) block of the

for {i-si: i; i--l

Fri Sep

sig.c

5 19:08:22 1986

3

clearseg(--a1) ;
up->u ssize +- si;
return (1) ;

up = &u;
uap - (struct a *)up->u_ap;
if (uap->req <- 0) {
up->uyrocp->p_flag 1- STRC;
return:

telse
grow(sp)

}

unsigned sp;

for (p=proc; p < (struct proc *)v.ve_proc; p++)
if (p->p stat-SSTOP
&& p->pyid=uap->pid
&& p->pypid-up->uyrocp->pyid)
goto found:
up->u error = ESP-CH;
return:

{

register
register
register
register
register
short t;

struct
struct
si, i,
strllct
a2, n;

user "up;
proc *p;
a1;
scatter *s;

found:
ipcp = &ipc:
while (ipcp->ip_Iock)
(void) sleep ( (caddr t) ipcp, IPCPRI):
ipcp->ip lock = p->pyid; ipcp->ip-data - uap->data:
ipcp->ip-addr - uap->addr;
ipcp->ip-req = uap->req;
p->p_flag &- -SWTED:
setrun(p) ;
while (ipcp->ip req > 0)
(void) ;leep«caddr t)ipcp, IPCPRI):
up->u_rvall - ipcp->ip_data;
if (ipcp->ip_req < 0)
up->u error - EIO;
ipcp->ip lock-= 0;
wakeup ( (caddr_tl ipcp):

up - &u;
if «v.v_uend-sp) < ctob(up->u_ssize»
return (0) ;
si = btoct (v. v uend-sp) - up->u ssize + SINCR;
i f (si <- 0) return (0) ;
if (chksize (up->u tsize, up->u_dsize, up->u_ ssize+si»
return (0);
p = up->uyrocp;
expand ( (int) (p->p size+si»;

1*

* locate last click of old data size
*/
s - scatmap;
al = p->p_scat:
n - v. v usize + up->u dsize;
for (i-I: iu ssize;
if

(n -

0)

printf(lIgrow:ssize not expected to be zero\n");
for (i-1; ip flag &= -SCONTIG:
up->u ssize +- si;
(void) estabur(up->u tsize, up->u_dsize, up->u_ssize, 0, RO);
return (1) ;
-

/*
* Code that the child process
* executes to ilnplement the command
* of the parent process in tracing.
*/
procxmt()
{

register
register
register
register
register

struct ipctrace *ipcp;
struct user *up;
int i;
*p:
struct text *xp;

up - &u:
ipcp = &ipc:
if (ipcp->ip_Iock != up->uyrocp->p_pid)
return(Ol;
i - ipcp->ip_req;
ipcp->ip req - 0:
wakeup! (caddr t) ipcp):
switch (i) ( /* read user I * /
case 1:
ipcp->ip_data - fuiword«caddr_t)ipcp->ip_addr);
break:

tendif
/*
" sys-trace system call.
*/
ptrace ()
{

register
register
register
register

) "uap;

struct
struct
struct
struct
int
int
int
int

ipctrace *ipcp:
user .up;
proc "p:
a {
req;
pid;
*addr;
data:

1* read user D * /
case 2:
ipcp->ip data - fuword( (caddr_t)ipcp->ip_addr);
break; /* read u */
case 3:
i - (int)ipcp->ip_addr:
i f (i- ctob(v.'J_1.,;.size)
goto error;
ipcp->ip_data - * «int *) «char *)up + (i & -1)));
break;
/* write user I *1
1* Must set up to allow writing *1
Ca,sli! ,4,:

siq.c

Fri Sep

5 19:08:22 1986

4
up->u arO [regloc [1711 (up->u arO [regloc [17J J & -OxFFFF)
(ipcp->ip_data & OxFFFF);

1*

* If text, must assure exclusive use
*1
) else

i f (xp - up->u procp->p textp) {
i f (Xp=>x_countl=1 II xp->x_iptr->i_mode&ISVTX)
goto error:
xp->x_iptr->i_flag &- -ITEXT:
)

(void) estabur (up->u tsize, up->u dsize, up->u_ssize, 0, RW):
i = suiword( (caddr_t)ipcp->ip_addr, 0):
(void) suiword«caddr t)ipcp->ip addr, ipcp->ip data):
(void) estabur (Up->u_tsize, up->'li_dsize, up->u_;size, 0, RO);
i f (ix_flag 1= XWRIT;
break;

1* write user D *1
case 5:
i f (suword( (caddr t)ipcp->ip addr, 0) < 0)
goto error;
(void) suword( (caddr_t)ipcp->ip_addr, ipcp->ip_data);
break;
1* write u *1
case 6:
i - (int) ipcp->ip addr;
p - (int *) «char-"')up + (i & -1»;
for Ii-O; i<17; itt)
i f (p - &up->u_arO [regloc[ill)
goto ok;
if (p ~ &up->u arO [RPS1) {
/* assure user space and priority 0 */
ipcp->ip data &- -Ox2700;
goto ok;goto error;
ok:
*p - ipcp->ip data;
break;
-

/* set signal and continue */
/* one version causes a trace-trap */
case 9:
case 7:
i f «int)ipcp->ip addr != 1)
up->u arO[PCl - (int) ipcp->ip addr;
up->uyrocp->p_sig - OL;
i f (ipcp->ip data)
psignal (up->u procp, ipcp->ip_data);
return (1) ;
-

/* force exit * /
case 8:
exit (fsig(up->u_procp»;
/,. read u registers ,. I
case 10:
i f «i - (int)ipcp->ip addr) < 0 II
> 17)
goto error;
i f (i-17)
ipcp->ip_data - up->u_arO [reg1oc [1711
else
ipcp->ip_data - up->u_arO [regloc [ill;
break;

&

OxFFFF;

1* write u registers *1
case 11:
i f «i i f (i -

(int) ipcp->ip addr) < 0 I I i > 17)
goto error;
17) I
ipcp->ip_data &- -Ox2700;
/* user only */

up->u_arO [regloc [ill
break;
default:
error:
ipcp->ip_req - -1;

return (0)

:

=

ipcp->ip_data;

sk.c

Fri Sep

5 19:08:45 1986

1
while (sktrap)
(void) sleep( (caddr_t) &sktrap, SKPRI);
COPSADDR->e irb - (COPSADDR->e irb & OxFl) 1 «spkr.sk volume&7) «
sksound(spkr.sk wavlen&MAXWLEN~ spkr.sk duration);
SPLO II;
-

1*

*

copyright 1982 UniSoft Corporation

* Speaker Driver
" Used to operate the lisa speaker.
*1
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

·sys/param.h"
·sys/config.h·
·sys/types .h"
"sysl systm. h"
·sys/dir .h"
·sys/signal.h H
·sys/user.h"
·sys/errno.h"
"sys/file.h"
"sys/tty.h M
"sys/terroio. h"
"sys/conf.h"
·sys/sysinfo.h"
·sys/var .h"
·sys/reg.h"
·sys/callo.h"
·sys/ttold.h"
·setjmp.h"
"sys/mmu.h"
"sys/cops.h"
·sys/local.h"
·sys/speaker .h"
·sys/12.h"

1* Produce a sound on the speaker at wavelength w microseconds
" for duration d clock ticks

*1
sksound(w, d)
register unsigned w, d;
(

extern int skquiet () ;

1* max wavelength xl

w &= MAXWLEN;

i f (w

< MINWLEN)

w - MINWLEN;
sktrap ~ d:
1* call skquiet at now + d *1
if (sktrap <= 0) sktrap = 1;
/* in case < MILLIRATE */
timeout (skquiet, (caddr_t)0, (int)sktrap);
sktone (w):

1* Start a tone at wavelength w microseconds.

Sound is produced by rapidly
turning on and off the speaker. The 6522 cops chip has an output to the
" speaker connected to a shift register. A built in timer controls the rate
* at which the shift register bits are output to the speaker.

*

*1
typedef unsigned long u_long:
u_long sktrap;

1* flag and slot to calculate spkr delay */

sktone(w)
register unsigned W:
(

/x active flag *1

register struct device e "p - COPSADDR;
register int cmd - Ox55;
1* sk shift reg *1

tdefine SKPRI (PZER0+8)
w = w » 3;
i f (w > OxFF)
cmd = Ox33;

skopen(dev, flag)
dey t dev;
{

-

w = w

i f (dev != 0) {
u. u_error
return;

=

ENXIO:

if (flag -- 1) {
u. u error
return;

=

EINVAL:

»

1* wavelength resolution is 8 microseconds * /

1;

if (w > OxFF) !
cmd = OxF;
w - w » 1;

Ix minor device number is wrong *1

1* open for reading 2? *1
p->e_acr 1- Ox10;
p->e t2cl = w;
p->e::::sr - cmd:

if (sk_open++ > 0) (
/* already opened */
u. u error - EBUSY;
return:

Ix enable *1
/* set timer *1
1* set output pattern *1

skquiet()
(

struct device e *p = COPSADDR;
p->e acr &- OiE3;
sktrap - 0;
wakeup ( (caddr_t) &sktrap):

/" ARGSUSED "/
skclose (dev, flag)
(

u.u_error = EINVAL:
else

beep()
(

/ * ARGSUSED "I
skwrite (dev)
{

struct speaker spkr;
while (u.u_count >- sizeof(spkr)' !
if (copyin(u.u_base, (caddr_t) &spkr, sizeof(spkr») {
u.u_error - EFAULT;
return:
u.u_base +- sizeof(spkr);
u. u count -- sizeof (spkr) ;
SPL2 ():

int sp;
if (sktrap) return;
sp = sp12 ():
COPSADDR->e irb - (COPSADDR->e irb , OxFl) I (12 bvol «
sksound ( (un'iigned) 12 bpitch, (unsigned) 12 btime)-;
splx(sp);
-

tifdef notdef
/*
* Produce a short click to implement keyboard clicking
*1
click()
I
register struct device_e *p - COPSADDR;

1):

1);

sk.c

Fri Sep
int i - 20;
int sp;
if (sktrap) return;
sp - sp12 ();
p->e_acr 1- OxlO;
p->e t2cl = OxlO;
p->e-sr - Ox55;
while (--i != -1)
p->e acr &- OxE3;
splx(sp) ;

)

tendif

5 19:08:45 1986

2

slp.c

Fri Sep

5 19:08:24 1986

1

1* @(t)slp.c
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
finclude

1.8 *1
"sys/param.h"
·sys/config.h"
·sys/mmu.h"
"sys/types .h"
·sys/sysmacros.h"
·sys/dir.h"
·sys/signal.h"
·sys/user.h"
·sys/proc.h"
·sys/context.h"
·sys/text .h"
·sys/systm.h"
·sys/sysinfo.h"
·sys/map.h"
·sys/file .h"
·sys/inode.h"
·sys/buLh"
·sys/var.h"
·sys/ipc.h"
"sys/shm.h"
·sysl errno. h"
·sys/scat.h"

*q - rp->p link;
SPLO ();
goto psig;
SPLO ();
if (ru.!'lin !- 0) !
runin - 0;
wakeup ( (caddr_t) &runin);
)

swtch() ;
i f (rp->p sig && issig()
q;to psig;
) else {
SPLO ();
swtch() ;
splx(s) ;
return (0) ;

1*
" If priority was low (>PZERO) and there has been a signal,
* if PCATCH is set, return 1, else
* execute non-local goto to the qsav location.

*1
typedef int

psig:

tdefine NHSQUE 64
1* must be power of 2 "I
tdefine sqhash(X)
(&hsque[«int) (X) » 3) & (NHSQUE-l)]l
struct proc "hsque [NHSQUE];
char
runin, runout, runrun, curpri;
struct proc "curproc, "runq;

1*

* sleep according to a cpu adjusted priority

splx(s) ;
i f (disp&PCATCH)
return(1) ;
tifdef NONSCATLOAD
resume(u.uyrocp->p_addr, u.u_qsav);
telse
resume (ixtoc(u.uyrocp->p_scat) , u.u_qsav);
tendif
1* NOTREACHED * I

*1
asleep(chan, pri)
caddr t chan;
{
return(sleep(chan, pri + «u.uyrocp->p_cpu&OxFF) »

1*

* Wake up all processes sleeping on chan.

5»);

*1
wakeup (chan)
register caddr_t chan;

1*
* Give up the processor till a wakeup occurs

{

register struct proc *p;
register struct proc "*q;
register s;

* on chan, at which time the process
" enters the scheduling queue at priority pri.
* The most important effect of pri is that when
* pri<-PZERO a signal cannot disturb the sleep;
" if pri>PZERO signals will be processed.
* Callers of this routine must be prepared for
* premature return, and check that the reason for
* sleeping has gone away.
*I
tdefine TZERO
10
sleep(chan, disp)
caddr t chan;
{
register struct proc * rp - u. u procp;
register struct proc **q - sqhash(chan);
register s;

s = splhi ();
for (q = sqhash (chan); p = *q; )
if (p->p wchan--chan && p->p stat~sSLEEP)
p->p_stat - SRUN;
p->p wchan = 0;
I" take off sleep queue, put on run queue "I
"q = p->p link;
p->p_Iink-= runq;
runq - p;
i f (! (p->p flag&SLOAD) I
p->p time = 0;
1* defer setrun to avoid breaking link chain *1
if (runout > 0)
runout - -runout;
} else i f (P->pyri < curpri)
runrun++;
I else
q = &p->p_link;
i f (runout < 0) {
runout - 0;
setrun(&proc[O]) ;

s - splhi ();
i f (panicstr) {
SPLO ();
splx(sl;
return (0) ;
rp->p_ stat - SSLEEP;
rp->p wchan - chan;
rp->p::)ink - *q;
*q - rp;
i f (rp->p time > TZERO)
rP->p time - TZERO;
i f «rp->pyrI - (disp&PMASKI I > PZERO)
i f (rp->p sig && issiq (»
{
rp->p_wchan - 0;
rp->p_stat - SR{;N;

splx(s);

setrq (pI
register struct proc *p;
{

register struct proc *q;
register s;

slp.c

Fri Sep

5 19:08:24 1986

2
loop:

p->p_Iink - runq;
runq = p;

SPL6 ();
outage ~ -20000;
tifdef NONSCATLOAD
for (rp - 'proc[Ol; rp < (struct proc ")v.veyroc; rp++)
if (rp->p_stat=SRUN && (rp->p_flag&SL.Q.l!..D) - 0 H
rp->p_time > outage) {
p ~ rp;
outage - rp->p_time;

splx (s);

telse

s - splhi();
for(q-runq; q!-NULL; q=q->p_link)
i f (q ~ pI {
printf("proc on q\n");
goto out;
}

out:
for (rp - &proc[Ol; rp < (struct proc ")v.veyroc; rp++)
(SSWAPITISLOAD» {
p ~ rp;
SPLO ();
goto swapit;
else if (rp->p stat=SRUN && (rp->p_flag&SLOAD) ~ 0 &&
rp->p_time >-outage) {
p = rp;
outage = rp->p_time;

i f «rp->p_flag&(SSWAPITISLOAD»

/*
" set the process running;
" arrange for it to be swapped in if necessary.
*/
setrun(p)
register struct proc *p;
{

register struct proc *"q;
register s;

lendif

/"
s - splhi (l;
i f (p->p stat = SSLEEP) {
/" take off sleep queue * /
for (q - sqhash(p->p wchan); "q != p; q = &(*q)->p_Iink)
*q = p->p link;
p->p wChan = 0;
else i f (p=>p stat = SRUN) !
/* already on run queue - just return *1
splx(s) ;
return;
/" put on run queue */
p->p stat - SRUN;
p->p=link - runq;
runq = p;
i f (! (p->p flag&SLOAD»
p->p time = 0;
i f (runout > 0)
runout = 0;
setrun(&proc[Ol) ;
I else if (p->p_pri < curpri)
runrun++;
splx(s) ;

I"
* The main loop of the scheduling (swapping) process.
.. The basic idea is:
see if anyone wants to be swapped in;
swap out processes until there is room;
swap him in;
" repeat.
" The runout flag is set whenever someone is swapped out.
* Sched sleeps on it awaiting work.

"
"
"
"

.

Sched sleeps on runin whenever it cannot find enough
memory (by swapping out or otherwise) to fit the
selected swapped process. It is awakened when the
memory situation changes and in any case once per second.

/
sched()
{

register struct proc "rp, "p;
register outage, inage;
int maxbad;
int tmp;

/*
" find user to swap in;
" of users ready, select one out longest
*/

.. If there is no one there, wait.
*/
if (outage = -20000) {
runout++;
(void) sleep ( (caddr_tl &runout, PSWP);
goto loop;
}

SPLO ();

/*
.. See if there is memory for that process;
.. if so, swap it in.
,,/
i f (swapin(p»
goto loop;

/"
" none found.
" look around for memory.
.. Select the largest of those sleeping
" at bad priority; if none, select the oldest.
,,/
SPL6() ;
p = NULL;
maxbad = 0;
inage = 0;
for (rp - &proc[Ol; rp < (struct proc ")v.veyroc; rp++)
i f (rp->p_stat=SZOMB I I
(rp->p_flag& (SSYS I SLOCK ISLOAD» !=SLOAD)
continue;
if (rp->p textp && rp->p textp->x flag&XLOCK)
continue;
i f (rp->p stat-SSLEEP II rp->p stat-SSTOP) {
tInp - rp->p pri - PZERO- + rp->p time;
i f (maxbad "< up) {
p - rp;
maxbad - up;
I
} else if (maxbad<-O && rp->p stat-SRUN) {
tmp - rp->p time + rp=>p nice - NZERO;
i f (tmp > {nage) {
p - rp;
inage - up;

SPLO ();
/"
" Swap found user out if sleeping at bad pri,
* or if he has spent at least 2 seconds in memory and
" the swapped-out process has spent at least 2 seconds aut..

slp.c

Fri Sep

5 19:08:24 1986

3
register struct text *xp;
register int a, x;
int ta;

" otherwise wait a bit and try again.
*/
if (maxbad>O 1 1 (outage>=2 && inage>-2»
Hfndef NONSCATLOAD
swapit:
tendi!
p->p flag &= -SLOAD;
xswap(p, 1, 0);
goto loop;
I
SPL6 ():
runin++;
(void) sleep ( (caddr t) &runin, PSWP):
goto loop:
-

if (p->p flag&SCONTIG) {
If «a - cmemalloc (p->p size}) = hTTJLL)
return(O);
I else if «a - memalloc(p->p size» ~ NULL)
return(O);
if (xp ~ p->p textp) {
xlock(xp) ;
if (!X!I'~ink(Kpl && xp->x_cco1.lnt--O) {
if «x - memalloc(xp->x_size» ~ NULL) {
memfree (a);
xunlock (xp) :
return (0) :

1*
• Swap a process in.
*1
tifdef NONSCATLOAD
swapin(p)
register struct proc "p:
I
register struct text ·xp;
register int a, x;
int ta:

xp->x scat - x;
if «xp->x flag&XLOAD) =0)
(void) swap (xp->x_daddr, x, xp->x_size, B_READ);
xp->x ccount++;
xunlock (xp) ;
/* swapping in, do not set mmu registers * /
p->p flag 1= SNOMMU;
if (P->p_xaddr [0]) {
ta - a;
for (x-O; x < NSCATSWAP; x++) {
if (p->p xaddr [x] -- 0)
continue;
a = swap(p->p xaddr [x], a, p->p xsize [x], BREAD):
mfree(swapmap; ctod(p->p xsize[x]), (int)p->p_xaddr[x]);
p->p_xaddrlx] = 0;
-

if «a = malloc(coremap, p->p_size» -= NULL)
return (0) ;
i f (xp - p->p textp) {
xlock(xp) ;
if (!xmlink(xp) && xp->x ccount~O) {
if «x - malloc(coremap, xp->x size» - NULL) {
mfree (coremap, p->p size, a);
if «x = malloc(coremap, xp->x_size» = NULL)
xunlock(xp) ;
return (0) ;

p->p_scat - ta;
I else {
(void) swap ( (daddr t) p->p dkaddr, a, p->p size, B READ);
mfree (swapmap, ctoct (p->p_size), (int) p->p=:dkaddr)-;
p->p_scat - a;

if «a - malloc(coremap, p->p size» -- NULL)
mfree(coremap, xp->x_size, x);
xunlock Ixp) ;
return(O) ;

p->p flag &- -SNOMMU;
p->p-addr - ixtoc(p->p scat);
cxrelse (p->p_context) ;p->p flag 1= SLOAD;
p->ptime = 0;
return(l);

xp->x caddr = x;
if «Xp->x flag&XLOAD)-O)
swap(Xp->x_daddr, x, xp->x_size, B_READ);
tendif
xp->x ccount++;
xunlock (xp) ;
if (p->p_xaddr[O]) {
ta = a;
for (x-O; x < NSCATSWAP; x++) {
if (p->p xaddr[x] -- 0)
continue;
swap(p->p_xaddr[x], a, p->p_xsize[x], B_READ);
mfree (swapmap, ctod (P->p_xsize [x]), (int) p->p_xaddr [x]) ;
a +- p->p_xsize[x];
p->p_xaddr[x] - 0;
p->p_addr - ta;
} else {
swap ( (daddr_t)p->p_dkaddr, a, p->p_size, B_READ);
mfree(swapmap, ctod(p->p_size), (int)p->p_dkaddr);
p->p_addr - a;
cxrelse (p->p context);
p->p flag !--SLOAn:

p->p-time - 0;
return (1) ;
i
telse
swapin(p)
register struct proc *p;
{

/*
• put the current process on
" the Q of running processes and
" call the scheduler.
*1
qswtch()
{

setrq(u.uyrocp) ;
swtch() ;

/*
"
*
"
"
"
*
"
"
•

.

This routine is called to reschedule the CPU.
if the calling process is not in RUN state,
arrangements for it to restart must have
been made elsewhere, usually by calling via sleep.
There is a race here. A process may become
ready after it has been examined.
In this case, idle () will be called and
will return in at most 1HZ time.
i.e. its not worth putting an spl () in.

/

swtch()
{

register n;
register struct proc .p, *q, .pp, *pq;
tifdef mc68881
1* MC68881 floating-point coprocessor "I

slp.c

Fri Sep

5 19:08:24 1986

4

/* is there an MC68881'? */

extern short fp8 81 :
tendif mc68881

curpri - n:
curproc - p:
SPLO () ;

1*

/*

*

*

If not the idle process, resume the idle process.

sysinfo. pswi tch++:
if (u.uyrocp !- &proc[O]) {
if (save(u.u rsav)
(
sureq() :
return:

/* sky floating point board */
if (u.u_fpinuse && u.u_fpsaved~O) (
savfpO:
u.u_fpsaved = 1:

tifdef FLOAT

fendif
Hfdef mc68881

n = p->p flag&SSWAP:
p->p flaq &- -SSWAP:
tifdef NONSCATLOAD
felse
tendif
}

I"

* Create a new process-- the internal version of
" sys fork.
* It returns 1 in the new process, 0 in the old.

/* MC68881 floating-point coprocessor */

if (fp881)
fpsave() :
fendif mc68881
fifdef NONS CAT LOAD
resume(proc[O].p_addr, u.u_qsav):
felse
resume (ixtoc(proc[O].p_scat), u. u_qsav):
fendif

"I
newproc(i)
{

register struct proc "rpp, "rip:
register struct user "up:
register n;
register a:
struct proc "pend:
static mpid:

/*
" The first save returns nonzero when proc 0 is resumed
" by another process (above); then the second is not done
" and the process-search loop is entered.

" The first save returns 0 when swtch is called in proc
" from sched (). The second save returns 0 immediately, so
" in this case too the process-search loop is entered.
* Thus when proc 0 is awakened by being made runnable, it will
" find itself and resume itself at rsav, and return to sched().

"I
if (save (u.u_qsav) return:

0 && save(u.u_rsav»

loop:
SPL6 () :
runrun - 0:
/"
* Search for highest-priority runnable process

"I
if (p

=

runq)
q = NULL:
pp - NULL:
n - 128:
do (
if «p->p_flag&SLOAD) && p->p_pri <- n) {
pp = p:
pq - q:
n - p->pyri;
q - p;
} while (p - p->p_link):

} else
goto cont:

1*
" If no process is runnable, idle.

*1
cont:

i f (pp -- NULL) {
curpri - PIDLE;
curproc - &proc [0] :
idle ():
goto loop:

p - pp:
q = pq;
i f (q else

The rsav (ssav) contents are interpreted in the new address space

*1

*/

NULL)
runq - p->p_Iink;

1*
"
*
*
"

First, just locate a slot for a process
and copy the useful info from this process into it.
The panic "cannot happen" because fork has already
checked for the existence of a slot.

*1
up - &u;
rpp - NULL;
retry:
mpid++:
if (mpid >= MAXPID)
mpid - 0;
goto retry;
rip - &proc[O]:
n - (struct proc *)v.veyroc - rip;
a - 0:
do {
if (rip->p stat == NULL) {
if- (rpp == NULL)
rpp - rip:
continue;
if (rip->pyid==mpid)
goto retry:
if (rip->p_uid == up->u_ruid)
a++:
pend - rip;
while (rip++, --n);
i f (rpp-NULL) {
if «struct proc ")v.veyroc >- &proc[ (short)v.v_proc])
if (i) (
syserr. procovf++:
up->u error - EAGAIN;
return(-l) ;
} else
panic ("no procs"):
rpp -

(struct proc *)v.veyroc:

i f (rpp > pend)
pend - rpp:
pend++:
Hfdef lint
v . ve_proc - pend:
felse
v.veyroc - (char *)pend;

Fri Sep

slp.c

5 19:08:24 1986

5
curproc - rip:
if (rip !- &proc[O)
1* only do if not scheduler *1
sureg() ;
setrq (rpp);
rpp->p_flag 1- SSWAP;
up->u rvall == rpP->pJ)id;
1* parent retu!:'ns pid of child */
return (0) ;

tendif
if (up->u uid && up->u ruid) {
if (rpp ~ &proc[ (short) (v.vyroc-l) j II a > v.v_maxup) (
up->u_error - EAGAIN:
return(-l) ;
}

1*

* make proc entry for new proc
1*

*1
rip - up->uyrocp:
rpp->p stat - SRUN;
rpp->p=clktim - 0;
rpp->p flag = SLOAD;
rpp->p- uid - rip->p uid;
rpp->p- suid - rip->p suid;
rpp->pJ:.grp = rip->pJ:.grp;
rpp->p nice - rip->p nice;
rpp->p- textp = rip->p textp;
rpp->pyid - mpid;
rpp->pypid = rip->pyid;
rpp->p time = 0;
rpp->p-cpu - rip->p cpu;
rpp->p-sigign - rip=>p sigign;
rpp->pyri = PUSER + rlp->p_nice - NZERO;
tifndef NONSCATLOAD

*
*

Change the size of the data+stack regions of the process.
If the size is shrinking, it's easy-- just release the extra core.
* If it's growing, and there is core, just allocate it
* and copy the image, taking care to reset registers to account
* for the fact that the system's stack has moved.
* If there is no memory, arrange for the process to be swapped
* out after adjusting the size requirement-- when it comes
* in, enough memory will be allocated.

* After the expansion, the caller will take care of copying
* the user's stack towards or away from the data area.
*1
tifdef NONSCATLOAD
expand (newsize)
register newsize:
{

register struct proc .p;
register aI, a2:
register i, n;

lendif
rpp->p addr = rip->p addr;
rpp->p=size - rip->p=size;

/*

*

make duplicate entries

* where needed
*1
for (n=O; nu ofile [n) != NULL)
up->u ofile [nj->f count++;
if (rpp->p_textp != NULL) {
rpp->p textp->x count++:
rpp->p= textp->x= ccount ++;

p - u.uyrocp;
n - p->p size;
p->p size = newsize;
i f (n - newsizel
return;
al - p->p addr;
if (n >- new size)
tifdef EXPANDTRACE
printf ("expand: shrinking process by %d clicks\n", n-newsize);
fendif
mfree (core!!lap, (mem_t) (n-newsize), (mem_tl (al +newsize) ) ;
return;
if (save(u.u ssav»
sureg() :
return:

up->u cdir->i count++;
if (up->u rdir)
up->u_rdir->i_count ++;

1*

*

shmfork (rpp, rip);

See if can just expand in place

*1

1*

* Partially simulate the environment

*

of the new process so that when it is actually
* created (by copying) it will look right.

*I
up->uyrocp = rpp;
curproc - rpp;
1*
" When the resume is executed for the new process,
* here's where it will resume.

loop:
a2 = mallocat (coremap, newsize-n, (mem_tl (al+nl);
if (a2 != NULL) {
fifdef EXPANDTRACE
printf("expanding in place by %d clicks at click %d\n",
newsize-n, al +n) ;
tendif
cxrelse (p->p context);
sureg():
return;

*1
if (save (up->u_ ssav) )
sureg() ;
return (1) ;

1*
" If there is not enough memory for the
* new process, swap out the current process to generate the
* copy.

*/
if (procdup(rpp) - NULL)
rip->p stat - SIDL;
xswap(rpp, 0, 0);
rip->p_stat - SRUN;
up->uyrocp - rip;

lit

* will we be releasing shared text space anyway.
" If so, then release it now and try in place
* expansion again.
*1
if «a2 - domall(coremap, (rnem_t)newsize» -- NULL)
if (xmrelse (»
goto loop;
i f (a2 -- NULL && (a2 - malloc(coremap, (rnern_t)newsize) I -- NULL) (
Hfdef EXPANDTRACE
printf(" expand:calling xswap\nll);
lendif
x9vap(p, 1, nl:
p->p_flaq 1- SSNAP;
qswtch() ;

Fri Sep

slp.c

5 19:08:24 1986

/* no return */

p->p addr ~ a2:
for <"I-a: ip_context) ;
resume ( (mem_t)a2, u.u_ssav):

6
Hfndef NONSCATLOAD
checkscat (s)
char *s;
{

register struct proc *p;
register struct text *xp;
register i:
i - countscat (scatfreelist. sc index);
printf ("%s nscatfree-%d actual-%d\n", s, nscatfree, i);
i f (nscatfree < 30) {
printf(1I
freelist chain is "):
dumpscat (scatfreelist. sc_index);

telse
expand (newsize)
register newsize;

for (p

{

register
register
register
register
int t;

struct scatter *s;
struct proc *p;
aI, a2;
i, n;

p ~ u.uyrocp:
n = p->p size;
p->p size = newsize;
i f (il - newsize)
return;
s = scatmap;
al - p->p scat:
i f (n >- newsize)
/*
* shrink memory
*/
for (i~l; ip_flag 1= SSWAP;
qswtch ();
1* no return *1
fendif

&proc[O]; p < (struct proc *)v.veyroc; p++) {
if (p->p stat-Oj
~ontinue:
xp = p->p textp;
printf(" - pid=%d %d used (%d text) \n",
p->pyid, countscat (p->p_scat),
xp '? countscat (xp->x_scat) : 0):
dumpscat (p->p scat);
if (xp) {
dumps cat (Xp->x_scat);

dumpscat(a1)
register al;

if (save (u.u_ssav) )
sureg() ;
return;

/*

=

return (i) ;
tendif

Fri Sep

socket.c
1*
tinclude
finclude
+include
finclude
+include
+include
finclude
+include
+include
tinclude
+include
+include
+include
+include
tinclude
Hnclude
tinclude
finclude
tinclude
tinclude
Hnclude
tinclude
tinclude
tinclude
tinclude

socket.c

1.3

84/11/02

5 19:09:20 1986

1
return (ENOBUFS);
so->so options - options;
so->so-state = 0;
if (u.1i uid ~ 0)
- so->so_state = SS_PRIV;

*1

Hsys/param.h"
"sys/config .h"
"sys/errno.h"
"sys/types.h"
"sys/sysmacros.hD
"sys/systm.h"

1*

"sys/dir.h"

" Attach protocol to socket, initializing
* and reserving resources.

"sys/termio.h"

*1

"syslsignal.h"
"sys/user .hU
"sys/proc.h"
"sys/file.h"
"sys/inode.h u
"sys/buf. h"
"net/misc.h"
"net/mbuf .h"
"net/protosw. hOI
"net/socket.h H
"net/socketvar .h M
"net/ubavar. hOI
·syslstat.h"
"sys/ioctl.h"
"net/in.h"
"net/in_systm.h"
"net/route. h"

1*
* Socket support routines.

so->soyroto - prp;
error - (*prp->pr usrreq) (so, PRU_ATTACH, Q, asa!;
if (error) {
tifdef NEVER
1*
* This commenting-out came from jsq@utexas-ll; see the
* iptcpll messages. Simply means temp lack of mbufs ..•

*1
if (so->so snd.sb mbmax II so->so_rcv.sb_mbmax)
panic (llsocreate ll ) ;
tendif
so->so_state 1= SS_USERGONE;
sofree (so) ;
return (error);
"aso - so;
return (0);

sofree(so)
struct socket *so;

* DEAL WITH INTERRUPT NOTIFICATION.
if (so->soycb II (so->so_state & SS_USERGONE) == 0)
return;
sbrelease(&so->so_snd) ;
sbrelease(&so->so_rcv) :
MSFREE (so) ;

*1

1*
* Create a socket.

*1
socreate (aso, type, asp, asa, options)
struct socket *"aso;
int type;
struct sockproto "asp;
struct sockaddr rasa;
int options;
register struct protosw ·prp;
register struct socket ·so;
int pf, proto, error;

1*
* Use process standard protocol/protocol family if none
* specified by address argument.

I"

* Close a socket on last file table reference removal.
" Initiate disconnect if connected.
" Free socket when disconnect complete.

" THIS IS REALLY A UNIX INTERFACE ROUTINE
,,/
soclose (so, exiting)
register struct socket *so;
int exiting;
int s

=

spInet () :

/* conservative */

*1
i f (asp =

0)

{

pf - PF INET;
1* should be u.uyrotof */
proto =-0;
I else {
pf - asp->sp family:
proto - asp->spyrotocol;

/*
" If protocol specified, look for it, otherwise
* for a protocol of the correct type in the right family.
*1
i f (proto)
prp - pffindproto (pf, proto);
else
prp - pffindtype(pf, type);
i f (prp - 0)
return (EPROTONOSUPPORT);
/*

* Get a socket structure.
*/
M5GET (so, struct socket, 1);
i f (so -- 0)

i f (so->soycb =- 0)
goto discard;
i f (exiting)
so->so_options 1- SO_KEEPALIVE;
if (so->so state & SS ISCONNECTED) {
if- «so->so state & SS ISDISCONNECTING) = 0) {
u. u-error - sodisconnect (so, (struct sockaddr *) 0) ;
i f lu. u error) {
-if (exiting)
goto drop;
splx (s) ;
return:

I
if «so->so options & SO OONTLINGER) -- 0) {
i f I (So->so_state & SS_ISDISCONNECTING) &or.
(so->so state
5S_NBIO) &&
exiting-- 0)
u.u_error - EINPROGRESS;
/*
* billn. This is a kludge rendered unnecessary
* by a bug fix 12127/83.
so->so state 1- SS_USERGONE;
*/
-

Fri Sep

socket.c

5 19:09:20 1986

splx(s) ;
return;

2
bad:
splx(s) ;
return (error);

/* should use tsleep here, for at most linger */
while (so->so state & SS ISCONNECTED)
(void) sleep ( (Caddr_t) &So->so_timeo, PZERO+l);

drop:
i f (so->soycb) {
u.u_error - (*so->soyroto->pr_usrreq) (so, PRU_DETACH, 0, 0);
if (exiting - 0 && u.u error) (
splx(s);
return;

/*

* Disconnect from a socket.
* Address parameter is from system call for later multicast
* protocols. Check to make sure that connected and no disconnect
* in progress (for protocol's sake), and then invoke protocol.
*/
sodisconnect (so, asa)
struct socket *so;
struct sockaddr *asa;
int s = spInet () ;
int error;

discard:
so->so state 1= SS_USERGONE;
sofree(so) ;
splx(s) ;

i f «so->so_state " ss ISCONNECTED) =
error - ENOTCONN;
goto bad;

0) {

i f (so->so_state & SS_ISDISCONNECTING)
error - EALREADY;
goto bad;

/*ARGSUSED* /
sostat (so, sb)
struct socket *so;
struct stat *sb;

error = (*so->soyroto->pr_usrreq) (so, PRU_DISCONNECT, 0, asa);
bad:
/* bug fix by JC stewart of sri; this zeros the kernel, should zero
user data (! I ...
bzero «caddr_t) sb, sizeof (*sb»;
/* xxx */
return (0);
/* xxx */

/*
* Send on a socket.
* If send IlIUst go all at once and message is larger than
* send buffering, then hard error.
* Lock against other senders.
* If must go all at once and not enough room now, then
* inform user that this would block and do nothing.
*/
sosend(so, asa)
register struct socket *so;
struct sockaddr *asa;

/*
* Accept connection on a socket.
*/
soaccept (so, asa)
struct socket *so;
struct sockaddr *asa;
int s = splnet () ;
int error;
if {(so->so options & so ACCEPTCONN)
error = EINVAL; goto bad;
if ({so->so_state & SS_CONNAWAITING) error - ENOTCONN;
goto bad;

struct mbuf *top = 0;
register struct mbuf **mp = ⊤
register struct mbuf *m;
register struct user *up - &u;
register u int len;
register iilt space;
int error = 0, s;

0)

/* xxx */

0) {

so->so_state &- -SS_CONNAWAITING;
error = (*so->soyroto->pr_usrreq) (so, PRU_ACCEPT, 0, (caddr_t)asa);
bad:
splx(s) ;
return (error);

1*
* Connect socket to a specified address.
* If already connected or connecting, then avoid
* the protocol entry, to keep its job simpler.
*/
soconnect (so, asa)
struct socket * so;
struct sockaddr *asa;

s - splnet () ;
if (so->so state" SS CANTSENDMORE) {
psignal (up->uyrocp, SIGPIPE);
snderr (EPIPE) ;

if (so->so_state " (SS_ISCONNECTED1 SS_ISCONNECTING) )
error - EISCONN;
goto bad;

(*so->so_proto->pr_usrreq) (so,

P~U_CONNECT,

if (sosendallatonce (so) && up->u_count > so->so_snd. sb_hiwat)
return (EMSGSIZE);
tifdef notdef
1* NEED TO PREVENT BUSY WAITING IN SELECT FOR WRITING *1
if «so->so snd. sb flags & SB LOCK) && (so->so_state & SS_NBIO»
return (EwOULDBLOCK);tendif
restart:
sblock(&so->so_snd) ;
tdefine snderr (errno)
( error - errno; splx(s); goto release; I
again:

int s - splnet ( ) ;
int error;

error -

splx(s) ;
return (error);

~,

(caddr_t)asa);

if (so->so_error) (
error - so->so_error;
so->so error - 0;
splx{s);
goto release;
J
if «so->so_state " SS_ISCONNECTED)

1* 2?1 *1

==

0) {

Fri Sep

socket.c

5 19:09:20 1986

3

if (so->soyroto->pr_flags & PR_CONNREQUIRED)
snderr (ENOTCONN) ;
i f (asa ~ 0)
snderr (EDESTADDRREQ) :

if ({SO->90 state & SS ISCONNECTED) - 0 &&
(90->90yroto->pr_flags & PR_CONNREQUIRED»
rcverr (ENOTCONN) ;
if (so->so_state & SS_NBIO)
rcverr (EWOULDBLOCK) :
9bunlock(&so->so rcv);
sbwait(&90->90_rcv) ;
9plx(s) ;
goto restart;

i f (top) {
error - (*so->soyroto->pr_usrreq) (so, PRU_SEND, top, asa);
top = 0;
i f (error) (
splx(s) ;
goto release;

m = so->so rcv. sb mb;
i f (m ~ 0)
panic (llrecei veil) ;
if (so->soyroto->pr_flags & PR_ADDR) {
if (m->m len !- sizeof (struct sockaddr»
Panic("soreceive addr"l;
i f (asal
bcopy(mtod(m, caddr t), (caddr_t)asa, sizeof (*asa»;
so->so_rcv.sb_cc -- m->m_len;
so->so rcv. sb mbcnt -= MSIZE;
m - m free (m);
i f (m-= 0)
panic("receive 2");
so->so_rcv.sb_mb = m;

mp - ⊤
if (up->u count ~ 0)
splx(s) ;
goto release;
space = sbspace (&so->so snd);
if (space <- 0 II sosendallatonce (so) && space < up->u_count) {
if (so->so_state & SS_NBIO)
snderr (EWOULDBLOCK) ;
sbunlock(&so->so snd);
sbwait (&so->so S;d);
splx(s);
goto restart;
splx(s) ;
while (up->~count && space> 0)
MGET(m, 1);
i f (m = NULL) {
error = ENOBUFS;
goto release;

so->so state &= -S5 RCVATMARK;
if (So=>so_oobmark && =t > so->so_oobmark)
cnt = so->so_oobmark;
eor = 0;
do (
len = MIN(m->m len, cnt);
splx(s);
iomove (mtod (m, caddr_ t), (int) len, B_READ) ;
=t -- len;
s = spInet () ;
if (len = m->m len) {
eor - (lnt)m->m_act;
sbfree(&so->so_rcv, m);
so->so_rcv.sb_mb - m->m_next;
MFREE (m, n);
} else {
m->m off += len;
m->m:::len -= len;

(

1* SIGPIPE? ,,/

m->m off - MMINOFF;
len -: (u int) MIN ( «int)MLEN), «int)up->u count»;
iomove (mtod (m, caddr t), (int) len, B WRITE);
if (error = up->u error) goto releas;;
m->m_len = len; "mp = m;
mp = &m->m_next;
space = sbspace(&so->so_snd);
goto again;
release:

}

sbunlock(&so->so snd);
i f (top)
m freem(top);
return (error);

} while «m = so->so_rcv.sb_mb) && cnt && !eor);
if «So->soyroto->pr_flags & PR_ATOMIC) && eor ~
do {
i f 1m 0)
panic("receive 3");
sbfree (& so-> so rcv, m);
eor = (int)m->m_act;
so->so_rcv.sb_mb - m->m_next;
MFREE (m, n);

soreceive (so, asa)
register struct socket "so;
struct sockaddr "asa;

0)

m - n;

register struct mbuf *m, "n;
u_int len;
int eor, s, error - 0, cnt - u.u_count;
caddr_t base - u.u_base;

} while (eor = 0);
if «so->soyroto->pr_flags & PR_WANTRCVD) && so->soycb)
(*so->soyroto->pr_usrreq) (so, PRU_RCVD, 0, 0);
if (so->so oobmark) {
SO=>90 oobmark -- u.u base - bage;
if (SO=>90 ooanark --0)
90=>90_ state 1- SS_RCVATMARK;

restart:
sblock(&so->so rcv);
s - spInet (); release:
tdefine rcverr(errno)
(error = errno; splx(s); goto release; }
if (so->so rcv.sb cc - 0) {
if- (So->so_error) {
error - 90->SO_error;
so->so error - 0;
splX(S);
goto release:

9bunlock (&90->90 rcv);
splx(s);
return (error);
sohasoutofband (so)
struct socket *so;

}

if (so->so state & S5 CANTRCVMORE)
splX(S);
goto release:

9truct proc *pfind ( ) ;
if Iso->s0,....pqrp -- 0)

Fri Sep

socket.c

5 19:09:20 1986

return;
i f (so->soJ>qrp > 0)

4
case SIOCSKEEP: (
int keep;
if (copyin(cmdp, (caddr_t) &keep, sizeof (keep») (
u.u_error - EFAULT;
return;

1*
gsignal (so->s0-'pgrp, SIGURG);

*1
signal (so->so_pgrp, SIGURG);
else (

i f (keep)
so->so_options 1- SO_KEEPALlVE;
else

struct proc "p - pfind(-so->so_pgrp);
i f (pi

psignal (p, SIGURG);

return;

case SIOCGKEEP: {
int keep = (so->so options & so KEEPALlVEI !- 0;
if (copyout «Caddr:=t) &keep, cmdp, sizeof (keep) I)
u.u_error = EFAULT;
return;

I*ARGSUSED" /

soioctl (so, cmd, cmdpl
register struct socket "so;
int cmd;
register caddr_ t cmdp;
extern struct uba_device ubdini t [ 1;
long *iaddrp

=

case SIOCSLINGER: {
int linger;
i f (copyin(cmdp, (caddr_t) &linger, sizeof (linger») (
u.u_error = EFAULT;
return;

(long *1 «int)ubdinit + OxAI;

switch (cmd) {
case SIOCCIADDR:
I" set internet address ie write into uba flags *1
i f (u.u_ruid != 0 && u.u_uid != 0) {
u.u_error - EPERM;
return;
i f (copyin{cmdp, (caddr_t)iaddrp, sizeof (long») {
u. u_error = EFAULT;
return;

return;
case SIOCGIADDR:
if (copyout((caddr_tliaddrp, cmdp, sizeof (long»)
u.u_error = EFAULT;
return;
case FIONBIO: {
int nbio;
i f (copyin(cmdp, (caddr_t) &nbio, sizeof (nbio)
u. u_error ~ EFAULT;
return;

I)

{

so->so linger = linger;
if (so=>so linger)
so=>so_options &= -SO_OONTLINGER;
else
so->so_options 1- SO_DONTLINGER;
return;

case SIOCGLINGER: {
int linger - so->so_linger;
if (copyout «caddr_t) &linger, cmdp, sizeof (linger))) (
u.u_error - EFAULT;
return;

case SIOCSPGRP:
int pgrp;
i f (copyin (cmdp, (caddr_t) &pgrp, sizeof (pgrp) I) {
u.u_error = EFAULT;
return;
so->soygrp - pgrp;
return;

i f (nbio)

else
return;

case FlOASYNC: (
int asyne;
if (copyin(cmdp, (caddr_t) &async, sizeof (asyne) I) {
u.u_error - EFAULT;
return;
i f (asyne)

case SIOCGPGRP: {
int pgrp = so->s0-'pgrp;
if (copyout«caddr_t)&pgrp, cmdp, sizeof (pgrp») {
u.u_error - EFAULT;
return;

case SIOCDONE: {
int flags;
if (copyin(cmdp, (eaddr_t) &flags, sizeof (flags») {
u. u_error = EFAULT;
return;

else
return;
case FIONREAD: {
long nread - 90->90 rev. 9b ce;
if (eopyout «eaddr_t) &nread, cmdp, sizeof (nread»)
u.u_error - EFAULT;
return;

flags++;
i f (flags & FREAD) {
int 9 - splimp(l;
socantrcvmore (sol;
sbflush(&so->so_rcvl;
splx(9) ;
}

i f (flags & FWRITEI

return;

Fri Sep

socket.c

5 19:09:20 1986

case SIOCSENDOOB: {
char oob;
struct mbuf *m;
if (copyin(cmdp, (caddr_t) &oob, sizeof (oob))) {
u.u_error = EFAULT;
return;
m ~ m get (M DONTKAIT);
i f (m-~O)-{
u.u_error - ENOBUFS;
return;
m->m off - MMINOFF;
m->IIC)en = 1;
*mtod(m, caddr t) - oob;
C*so->s0J>roto=>pr_usrreq) (so, PRU_SENDOOB, m, 0);
return;

case SIOCRCVOOB: {
struct mbuf *m = m get eM DONTWAIT);
i f em = 0) {
u.u_error - ENOBUFS;
return;
m->m_off - MMINOFF; *mtod (m, caddr t) = 0;
(*so->soJ>roto->pr_usrreq) (so, PRU=RCVOOB, m, 0);
if (copyout(mtod(m, caddr_t), cmdp, sizeof (char»)
u.u_error - EFAULT;
return;
}

(void) m_free(m);
return;

case SIOCATMARK: {
int atmark - (so->so state&SS RCVATMARK) !- 0;
if (copyout ( (caddr_t)&atmark, -cmdp, sizeof (atmark»)
u.u_error = EFAULT;
return;
return;

/* routing table update calls */
case SIOCADDRT:
case SIOCDELRT:
case SIOCCHGRT:
struct rtentry route;
i f (! suser () )
return;
if (copyin (cmdp, (caddr_t) &route, sizeof (route») {
u.u_error - EFAULT;
return;
u. u_error - rtrequest (cmd,
return;

1* type/protocol specific ioctls * I
}

u. u_error - EOPNOTSUPP;

& route)

;

5

socketsubr:~

1*
+include
+include
+include
Hnc1ude
Hnc1ude
tinc1ude
tinc1ude
iinclude
finc1ude
tinclude
tinclude
tinclude
tinclude
Hnclude
Hnclude
Hnclude
tinclude
Hnclude
Hnclude
Hnc1ude
tinclude

socketsubr. c

Fri Sep
4.23

82/06/14

5 19:09:22 1986
*1

·sys/param.h"
"sys/config .h"
.sys/types. hH
·sys/nunu .h"
"sys/sysmacros .h"
·sysl systm. h"
·sys/dir.h"
·sys/signa1.h"
·sys/errno.h"
"sys/user.h"
"sysiproc.h"
·sys/file.h"
·sys/inode .h"
"sys/buf.h"
"net/misc.h"
·net/mbuf .h"
"net/protosw.h"
"netl socket. h"
"net I socketvar. h"
"net/in.htl
"net/in_systm. hOI

1
soisdisconnected (so)
struct socket *50;

so->so state &- - (55 ISCONNECTING! SS ISCONNBCTED I 55 ISDISCCN}''ECTING):
so->so-state 1- (SS CANTRCVMORE 1SS CANTSENDMORE); wakeup! (caddr t) 'so=>so timeo);
sowwakeup(so);
sorwakeup (so) ;

1*
*
*
*
*
*

*
*

*1
socantsendmore (so)
struct socket *so;

1*
* primitive routines for operating on sockets and socket buffers
*1
1*
* Procedures to manipulate state flags of socket
x and do appropriate wakeups.
Normal sequence is that
1< soisconnecting ()
is called during processing of connect () call,
x resulting in an eventual call to soisconnectedO iflwhen the
" connection is established. When the connection is torn down
* soisdisconnecting () is called during processing of disconnect () call,
1< and soisdisconnected ()
is called when the connection to the peer
* is totally severed. The semantics of these routines are such that
* connectionless protocols can call soisconnected () and soisdisconnected ()
* only, bypassing the in-progress calls when setting up a "connection"
* takes no time.
" When higher level protocols are implemented in
" the kernel, the wakeups done here will sometimes
* be implemented as software-interrupt process scheduling.
*1
soisconnecting (so)
struct socket *so;

so->so state 1= SS CANTSENDMORE;
sowwakeup (so) ;
-

socantrcvmore ( so)
struct socket *so;
so->so_state 1= SS_CANTRCVMORE;
sorwakeup(so) ;

1*
* Socket select/wakeup routines.
*1
1*

* Interface routine to select () system
* call for sockets.
*1
soselect (so, rw)
register struct socket *so;
int rw;
int s - spInet () ;

so->so state &- - (SS ISCONNECTED 1SS ISDISCONNECTING);
so->so-state 1- SS ISCONNECTING;
wakeup! (caddr_t) &S~->so_timeo);

switch (rw)
case FREAD:
if (soreadable (so)
splx(s) ;
return (1);

soisconnected (so)
struct socket *so;

sbselqueue (&so->so rcv);
break;
-

so->so state &= - (SS I SCONNECT ING 1SS ISDISCONNECTING);
so->so- state 1= S5 ISCONNECTED;
wakeup! (caddr t) &S~->so timeo);
sorwakeup (so) ;
sowwakeup(so) ;

case FWRITE:
if (sowriteable(so))
splx(s) ;
return (1);

soisdisconnecting (so)
struct socket *50;
so->so state ,- -SS ISCONNECTING;
so->so-state 1- (SS- ISDISCONNECTING 1SS CANTRCVMORE 155 CANTSENDMORE);
wakeup! (caddr t) &so=>so timeo);
sowwakeup (so) ;
sorwakeup (so) ;

Socantsendmore indicates that no more data will be sent on the
socket; it would normally be applied to a socket when the user
informs the system that no more data is to be sent, by the protocol
code (in case PRU SHUTDOWN). Socantrcvmore indicates that no more data
will be received, -and will normally be applied to the socket by a
protocol when it detects that the peer will send no more data.
Data queued for reading in the socket may yet be read.

sbselqueue (&so->so snd);
brei!lk;
splx(s) ;
return (0);

1*
1<

Q1..sb sell && p->p wchan sb->sb_flags 1- SB_caLL;
else
sb->sb_sel - u.uyrocp;

2

(caddr_t) &selwait)

/*
* wait for data to arrive at/drain from a socket buffer.
*/
sbwait(sb)
struct sockbuf * sb;

Hfdef notdef
/* billn -- add this routine from 4.lc for 4 .lc udp *1
soreserve (so, sndcc, rcvcc)
struct socket *so;
int sndcc, rcvcc;

if (sbreserve(&so->so snd, sndcc)
goto bad;
if (sbreserve (&so->so rcv, rcvcc)
goto bad2;
return (0);

0)
0)

bad2:
sbrelease (&So->so_snd);
bad:

sb->sb flags 1= SB WAIT;
(void)-sleep( (caddr_t) &sb->sb_cc, PZERO+1);

/*
* Wakeup processes waiting on a socket buffer.
*/
sbwakeup (sb)
struct sockbuf * sb;

return (ENOBUFS);

I
fendif

/*
* Allot rnbufs to a sockbuf.
*/
sbreserve (sb, cc)
struct sockbuf * sb;

if (sb->sb_sel) (
selwakeup(sb->sb sel, sb->sb_flags & SB_COLL);
sb->sb sel - 0; sb->sb::::flags &- -SB_COLL;
if (sb->sb flags & SB WAIT) {
sb-=>sb flags &- -SB WAIT;
wakeup! (caddr_t) &Sb-=>Sb_Cc);

/* someday maybe this routine will faiL .. */
sb->sb_hiwat = cc;
sb->sb mbmax = cc*2;
return- (1);

/*
* Free rnbufs held by a socket, and reserved mbuf space.
*/
sbrelease (sb)
struct sockbuf *sb;

/*
1<

Socket buffer (struct sockbuf) utility routines.
sbflush(sb) ;
sb->sb_hiwat

* Each socket contains two socket buffers: one for sending data and
* one for receiving data. Each buffer contains a queue of mbufs,
* information about the number of mbufs and amount of data in the
1< queue, and other fields allowing select ()
statements and notification
* on data availability to be implemented.

*

Before using a new socket structure it is first necessary to reserve
* buffer space to the socket, by calling sbreserve. This commits
1< some of the available buffer space in the system buffer pool for the
* socket. The space should be released by calling sbrelease when the
* socket is destroyed.

* The routine sbappend () is normally called to append new mbufs
1< to a socket buffer, after checking that adequate space is available
* comparing the function spspace () with the amount of data to be added.
* Data is normally removed from a socket buffer in a protocol by
* first calling m copy on the socket buffer rnbuf chain and sending this
* to a peer, and then removing the data from the socket buffer with
* sbdrop when the data is acknowledged by the peer (or immediately
* in the case of unreliable protocols.)
* Protocols which do not require connections place both source address
1< and data information in socket buffer queues.
The source addresses
* are stored in single mbufs after each data item, and are easily found
* as the data items are all marked with end of record markers. The
* sbappendaddr () routine stores a datum and associated address in
* a socket buffer. Note that, unlike sbappend (), this routine checks
* for the caller that there will be enough space to store the data.
* It fails if there is not enough space, or if it cannot find
1< a mbuf to store the address in.
* The higher-level routines sosend and soreceive (in socket. c)

~

sb->sb_mbmax - 0;

/*

* Routines to add (at the end) and remove (from the beginning)
* data from a mbuf queue.
*/

/*
* Append mbuf queue m to sockbuf sb.

*/
sbappend(sb, m)
register struct mbuf *m;
register struct sockbuf *sb;
register struct mbuf *n;
n - sb->sb_mb;
Hfdef SIGH
mcheck(n, "sbappend");
tendif
if (n)
while (n->m_next)
while 1m) {
i f (m->m len - 0 && (int)m->m act -- 0) {
iii - m free (m) ;
continue;
}

if In && n->m off <- MMAXOFF U m->m off <- MMAXOFF
lintln->m act -- 0 && (int)m->m act -- 0 &&
(n->m_off-+ n->m_len + m->m_len) <- MMAXOFF) {

&&

socketsubr:,'-O

5 19:09:22 1986

Fri Sep

MBCOPY(m, 0, n, n->m_len, (u_int)m->m_Ien);
n->m_len +- m->~len;
sb->sb cc +- m->m len;
m - m free (m) ;
continue;
sballoc (sb, m);
if In ~ 0) {
sb->sb_mh

3

if (sb->sb flags & SB LOCK)
panic ("sbflush") ;
if (sb->sb_cc)
sbdrop(sb, sb->sb_cc);
Hfdef SIGH

1*
~

m;

else

tifdef SIGH
mcheck(n, "sbappend2");
tendif

return;

*1
tendif
if (sb->sb cc II sb->sb mbcnt I I sb->sb mb)
Hfdef SIGH
extern struct mbuf *mfreep;

else
n = m;

printf("sbflush: sb_cc-%x, sb_mbcnt=%x, sb mb-%x, mfreep-%x\n",
sb->sb_cc,sb->sb_mbcnt, sb->sb_mb, mfreep);

m - m->~next;
n->m_next = 0;
tendif

panic(lIsbflush 2");

1*
* Append data and address.
" Return 0 if no space in sockbuf or if
* can't get mbuf to stuff address in.

1*
* Drop data from (the front of) a sockbuf chain.

*1

*1

sbappendaddr(sb, asa, mOl
struct sockbuf * sb;
struct sockaddr *asa;
struct mbuf *mO;

sbdrop(sb, len)
register struct sockbuf * sb;
register int len;
register struct mbuf *m = sb->sb_mb, *mn;

struct sockaddr *msa;
register struct mbuf *m:
register int len - sizeof (struct sockaddr);
struct sockaddr sa:
sa = *asa;
m = mO;

if

(m -

0)

panic ("sbappendaddr") :
for (;:) {
len += m->m len;
if (m->m_ne"it == 0) {
m->m act - (struct mbuf ") 1:
break;

Hfdef SIGH
mcheck (m, "sbdropl"):
tendif
while (len > 0) {
if (m 0)
panic ( .. sbdropll) :
if (m->m_len > len) {
m->m len -= len;
m->m:=Off += len;
sb->sb cc -- len:
break;-

1* This else clause is an sri bug-fix by JC Stewart *1

len -= m->m len;
sbfree (sb, m);
MFREE (m, mn);

else {

m - ron;

m->m_act - (struct mbuf

I
if (len> sbspace(sb»
return (0):
m - m get (M DONTWAIT):
if (m-- 0)return (0);
m->m off = MMINOFF;
m->m:=len = sizeof (struct sockaddr);
MAPSAVE() ;
msa - mtod (m, struct sockaddr ");
*msa - sa;
MAPREST() ;
m->m_act - (struct mbuf *) 1;
sbappend(sb, m);
sbappend(sb, mO);
return (1);

*/

sbflush (sb)

struct sockbuf *sb;

0;

sb->sb mb - m;
Hfdef SIGH
mcheck (m, Isbdrop2");
tendif

1* *1

1*
* Free all llbufs on a sockbuf mbuf chain.
* Check that resource allocations return to

*)

}

o.

sony.c

Fri Sep

5 19:08:53 1986

1

1* tdefine HOWFAR *1
11< tdefine WBBLK
1* allows writing block 0 *1
/* allows access to restricted blocks on boot disk */
/* tdefine UNISOFT
tdefine KLUDGE 1* kludge for format to work * /
1*
* (C) Copyright 1983 UniSoft systems of Berkeley CA

sn_sizes[]

(

800,
599,
201,

0,

0,

0,
0,
0,

" sony driver
* and eject driver

0,

0,
0,
0,

0,

800

I" a - filesystem ,,/
1* b - filesystem on a boot sony *1
1* c = 1-100 for lisa (serialization),
101-200 for boot program *1
/" d - unused *1
I" e - unused */
I" f = unused *1
1* g - unused *1
1* h = entire disk */

);

*1
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
t include
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

=

0,

201,

"sys/param.h"
"sys/config .h"
"sys/mmu.h"
"sys/types .h"
"sysl sysmacros. h"
"sys/dir.h"
"sysl signal. h"
"sys/user.h"
"sys/errno.h"
·sys/utsname.h u
"sys/buf.h"
"sys/elog.h"
"sys/erec.h"
"sys/iobuLh"
"sys/systm.h"
"sys/var .h M
"sys/uioctl. h"
"sys/al ioctl.h"
"sys/diskformat.h"
"setjmp.h"
·sys/pport. h"
"sysl sony. hit
"sys/cops. h"

tdefine NRETRY

/*
called from oem7init at (at least) levell, so won't be interrupted
by parallel port 0 or sony

*/
sninit ()
(

char c

SNIOB->gobyte-SN CLRST;
SNIOB->mask -Ox80;
1* enable interrupts *1
i f ( snwai trdy () (
printf("Unix sninit: command to clear status failed\n");
SNIOB->gobyte-SN_STMASK;

1*
check block 0 to see whether this is a boot disk
*1
sncz(dev)
register dey t dev;
static char hp[BSIZE]:
register struct buf *bp - &snhbuf;
register rc - 0;
GETBUF (bpI:
sn bcount[boot(physical(devl)] - 0;
bp=>b bcount = BSIZE;
bp->b-dev - dey 1 7;
bp->b-blknO - 0;
bp->b-un. b addr - hp;
bp->b-flags 1- B READ;
snbf :: 1:
snstrategy (bpI;
iowait (bp) ;
i f (bp->b_flaqs & B_ERROR)
rc++;
snbf - 0;

/ * block opens * I
/* character opens "/
(d«l)
/* first char is how many opens */
«(d«l) +1)
/* 2nd char (sn bcount only) is whether a boot disk *1
I * index into sn_fns array */ -

1* for now set to non-boot *1
1* set logical unit 7 *1

}

FREEBUF (bp)
return(rc) ;

1* read before format is acceptable error */

st.ruct. sn sizes
daddr_t sn_offset, sn_size:

-

(

snhbuf;
struct buf
/* header buffer (for reading block 0) */
struct buf
sncbuf:
1* command buffer * /
struct buf
snrbuf;
struct iostat snstat [NSN] ;
struct iobuf sntab - tabinit (SN1, snstat) ;
/* active buffer header */
tifdef WBBLK
char sn bblk[512];
tendif KBBLK
char sn bcount [NSN*2] ;
char sn- ccount [NSN* 2] ;
tdefine-count (d)
tdefine boot (d)
char snbf;
tifdef KLUDGE
char noerror:
tendif KLUDGE

/* to avoid clear byte intstructions */

if (SNIOB->drv connect != Oxff)
printfC"Unix sninit: no drive connected\n");
return;

5

tdefine FREEBUF (bp)
splsn () ;
i f (bp->b flags & B WANTED) \
wakeup ( (caddr t)bp); \
bp->b flags = 0; \
splO()

OxOO;

SNIOB->dri ve-Ox80;
1* always lower drive *1
/* always first side *1
SNIOB->side - c;
SNIOB->mask= Oxff;
/* clear ints and enable */
i f (snwaitrdyO) (
printf("Unix sninit: command to clear status failed\n");
return;

tdefine physical(d) (minor(d)>>4) &OxF) 1* physical unit number 0-15 *1
tdefine logical(d) (minor(d)&Ox7)
/* logical unit number, 0-7 *1
tdefine splsn
spll
tdefine GETBUF (bp)
splsn (): \
while (bp->b flags & B BUSY) { \
bp->b flags I=-B WANTED:
(void)sleep( (caddr_t)bp, PRIBIO+1);
I \
bp->b flags 1= B_BUSY;
splO ()

=

if (SNIOB->type)
printf("Microdiskette with 'lid head%s\n", SNIOB->type,
(SNIOB->type=l) 1 .... : "s");
I else
printf("unix sninit: not a sony drive\n");
return;

;

1*
don' t really check whether it.' s a boot disk

sony.c

Fri Sep

5 19:08:53 1986

2

"/

sntab.b_actf - bp:

/" ARGSUSED */
snconf(dev)
dey t dey;

else
sntab.b actl->av font = bp;
sntab.b actl = bp;
bp->av_forw - (struct buf *)NULL;
) else {
i f « * sn fns [snbf1 . fnc) (bp->b dev»
bp->b flags 1= B ERROR;
iOdone (bpI;
/* resets flags * /
return;

1 snbf = 1;
return (0) :

struct sn fns 1
iilt
("fnc) ():
s~fns[1 - 1
sncz,
/" the real routine to check block 0 ,,/
snconf
/* fake routine to confuse ,,/

snstat[punit1.io_ops++: /* errlog: */
/* resid for disksort * /
bp->b_resid = bp->b_blkno + sn_s!zes[logical(bp->b_dev)
splsn() ;
disksort (&sntab, bp);

):

snopen (dev)
register dev_t dey;

i f (sntab.b_active =
snstart ():
splO ();

1
dey - physical (dev) ;
if (dev >= NSN) 1
u. u_error - ENXIO;
return(-l) ;

1.s~offset;

0)

snstart ()
{

return (0) ;

register struct buf *bp;
register punit, lunit;
reqister daddr_ t bn;
caddr_t addr;

snbopen (dev)
register dev_t dey;
(

loop:

i f (snopen(dev) - 0)
sn_bcount [count (physical (dev» 1++;

if «bp - sntab.b_actf) ~ (struct buf *)NULL)
return;
if (sntab.b active - 0) 1
sntab.b active - 1;
if(bp != &sncbuf)
bp->b_resid - bp->b_bcount;

sncopen (dev)
register dey_ t dev;
(

)

if (snopen(dev) - 0)
sn_ccount [count (physical (dev» 1 ++;

punit - physical (bp->b_dev) ;
lunit = loqical (bp->b dev);
blkacty 1= (1«SN1); if (bp = &sncbuf) 1
fifdef WBBLK
if (bp->b resid -= UIOCWBBLK)
SIlWa (punit) ;
else
fendif WBBLK
sncmd(bp->b_residl;
return;

snclose (dev)
register dev_t dey;
{

i f (physical (dev) >- NSN) (
u. u error - ENXIO;
return (-1) ;

snbf = 0;
return(O) ;

snbclose (dev)
register dey_ t dev;
(

if (snc1ose(dev) -= 0)
sn_bcount[count(physical(dev»1 - 0;
sncclose (dev)
register dev_t dey;
(

if (snclose(dev) - 0)
sn_ccount [count (physical (dev» 1

0;

snstrategy (bp)
register struct buf "bp;
{

register punit;
punit - physical (bp->b dev);
if (bp - &sncbuf) { /* if command "/
snstat[punit] .io misc++; /* errlog: */
splsn ();
if (sntab.b_actf (struct buf *)NULL) /* set up links */

/* b_resid holds the command */

bn = bp->b blkno + «bp->b bcount - bp->b_resid) » 9);
if (bp->b resid < 512 II bn >=-sn sizes [lunit1 . sn size II
«bn += -;n sizes[lunit].-;n offset) >- SN MAXBN) II
(bn <- 200-" sn bcount[bo-;)t(punit)])I 1fifdef HOWFAR
if (bp->b resid !- 0)
printf ("Unix snstart: blkno-%d resid-%d bn=%d\n",
bp->b_blkno, bp->b_resid, bn);
fendif HOWFAR
blkacty &- -(1«SN1);
if ( sntab. b errcnt)
logberr(&sntab, 0); /* errlog non-fatal errors */
sntab.b_active - 0;
sntab. b_ errcnt - 0:
sntab.b_actf - bp->av_forw;
iodone (bp) :
goto loop;
addr - bp->b_un.b_addr + bp->b_bcount - bp->b_resid;
snrw (punit, bn, bp->b_flags&B_READ, addr);
snread (dev)
dey t dey;
{ physio(snstrategy, &snrbuf, dey, B_READI;

sony.c

Fri Sep

3

5 19:08:53 1986

uou_error - EINVAL:
return:
snwrite (dev)
dev_t dev:

break:
case UIOCFORMAT:
if (! suser () )
uou_error
return:

{

physio(snstrategy, &snrbuf, dey, B_WRITE);

struct sn blockmap {
int maxblock, sectors;
} sn_blockmap[] = {
192, 12,
176,
160,
144,
128,

EPERM:

fifdef KLUDGE
noerror=l:
(void) (sncz (0»;
noerror=O:

11,
10,
9,
8

tendif KLUDGE
break;
tifdef WBBLK
case UIOCWBBLK:
if (! suser () )
u u_error = EPERM;
return;

);

1* ARGSUSED *1
snrw (unit, bn, rw, addr)
int unit, rw;
register daddr t bn;
register caddr::::t addr;

=

0

/* always called at priority sn (see splsn above) */

if (copyin(adr, (caddr_t)sn bblk, sizeof(sn_bblk»)
uou_error = EFAULT;
return:

{

register char *pm ~ (char *) SN DATABUF;
register struct sn block:map *p = sn_blockmap;
register int i;
int track, sector:
char c = OxOO;

break;
tendif WBBLK
default:
Uou_error = ENOTTY:
return:

track = 0;
while ( bn >= p->maxblock )
bn -= p->maxblock;
track += 16;
p++;
sector = bn % p->sectors;
track += bn / p->sectors;
i f (snwaitrdy()
return;
SNIOB->side=c;
SNIOB->dri ve-Ox8 0;
SNIOB->track = track;
SNIOB->sector= sector:
i f (rw) {
SNIOB->cmd=SN READ;
) else {
SNIOB->cmd-SN WRITE;
i = 511;
do {
*pm++:
*pm++ - *addr++:
} while (--i !- -1);

)

GETBUF (bp) :
bp->b dev - dev;
bp->b- resid - cmd:
Uou_error - 0:
snstrategy{bp) ;
iowa it (bp) :
if (bp->b_flags & B_ERROR)
uou_error = EIO;
FREEBUF (bp) :

/* stash the command in resid */
/* any error on sncz is OK */

sncmd(cmd)
/* always called at priority sn (see splsn above) */
unsigned int cmd;
{

i f (snwai trdy () )
return:
switch (cmd) {
case UIOCFORMAT:
SNIOB->confirm-Oxff;
SNIOB->cmd=SN_FORMAT;
break;
case AL EJECT:
- SNIOB->cmd=SN_EJECT;
break;
default:
return:

1* cmos ram, every other byte */

i f (snwaitrdy ()
return:
SNIOB->gobyte - SN_CMD;

SNIOB->gobyte - SN_CMD;
/ * ARGSUSED "I< I
snioctl(dev, cmd, adr, flag)
dev_t dey;
caddr t adr;
{
int unit;
register struct buf *bp;

fifdef WBBLK
snwD (punit)
int punit;
{

i f «unit = physical (dev» >- NSN)
uou_error - EFAULT;
return;

register char *pm;
struct sn hdr sn_hdr;
register char *addr;
regilJter i;
char c = OxDD;

bp - 'sncbuf:
switch (cmd) {
case AL EJECT:
-if «sn_bcount [coimt (imit.) J > C)
II (sn_ccount [count (unit)] > 1)

i f (snwaitrdy () )
return;
SNIOB->side-c;
SNIOB->drive-Dx8D;
SNIOB->track - 0;

(

sony.c

Fri Sep

5 19:08:53 1986

SNIOB->sector- 0;
SNIOB->cmd-SN WRITE:
sn_hdr.version = 0:
sn hdr. volume - 0;
sn=:hdr.fileid - FILEID:
sn hdr.relpq - 0:
sn-hdr.duml - 0:
sn-hdr.dum2 ~ 0:
i :: sizeof(sn hdr) - 1:
pm - (char *) SN HDRBUF:
1* write special 12-byte hdr *1
addr = (char *)&sn_hdr:
do {
*pm++:
Ix cmos ram, every other byte */
*pm++ = (unsigned) *addr++;
} while (--i !- -1);
i - 511:
pm - (char *)SN DATABUF:
/* write regular 512-byte buffer */
addr - (char ") -;n bblk;
do {
*pm++;
/* cmos ram, every other byte */
*pm++ ~ *addr++;
} while (--i != -1);
if (snwai trdy () )
return:
SNIOB->gobyte = SN_CMD;

4
if (++sntab.b errcnt > NRETRY II bp = &sncbuf)
bp->b-flags 1- B ERROR;
logberr(&sntab, 1); 1* errlog: */

1*
* because a single buffer can take several io operations,
* we leave it to snstart () to figure out when it's done
*/
if (bp->b flags&B ERROR I I bp - &sncbuf)
Hfdef KLUDGE
if (!noerror)
tendif KLUDGE
if (bp->b flags & B ERROR) (
printf("Unlx: HARD I/O ERROR on Idev/s%d%c ",
physical (bp->b_dev), logical (bp->b_deV) +' a');
if (bp !- &sncbuf)
printf ("00 %d\n",
bp->b bIkno + «bp->b bcount-bp->b resid) » 9)
+ sn -;izes [logical (bp=>b dey) 1 • sn ~ffset);
else printf ("\n U ) :
- blkacty &- -(1«SN1);
sntab.b active - 0;
sntab. b- errcnt - 0;
sntab.b-actf - bp->av forw;
iodone (bp) ;
if
(ent && bp->b flags & B READ)
I else
addr - bp->b un-:-b addr + bp->b bcount - bp->b_resid:
i - 511;
do {
*pm++;
1* cmos ram, every other byte */
*addr++ = *pm++:
} while (--i != -1):
if (! (bp->b_blkno + «bp->b_bcount-bp->b_resid) » 9)
+ sn sizes [logical (bp->b dey) 1. sn offset»
( 1* bn=O *1
regi-;ter caddr t pm;
register unsigned short fileid:

tendif WBBLK
snintr()

/* called at pl 1 * I

{

struct buf *bp:
register short i;
register char *addr:
register char *pm - (char *)SN_DATABUF:
int cnt:
struct deverreg snreg[l]: /* errlog: */
i = SNIOB->status;
tifdef ROWFAR
if (i)
printf(IIUnix snintr: SNIOB->status - Ox%x\n",i):
fendif HOWFAR
if (sntab.b active -= 0) {
Hfdef HOWFAR
printf(IIUnix snintr: b_active-O\n"):
tendif ROWFAR
snbf = 0:
/* force real check for boot disk */
SNIOB->mask - SN CLEARMSK;
SNIOB->gobyte=SN- CLRST:
(void) snwaitrdy();
return;

pm - I char *) SN HDRBUF;
fileid - (* (pm+9» «8;
fileid 1- * (pm+11):
if (fileid - FILEID) {
sn_bcount[boot(physical (bp->b_dev»]
sn_bcount[boot (physicallbp->b_dev»]

=

1:

0;

tendif UNISOFT

}

if «bp
tifdef ROWFAR

=

Hfdef UNISOFT

bp->b resid -- ent;
SNIOB=>mask - SN_CLEARMSK;
SNIOB->gobyte=SN_ CLRST;
snstart ();

sntab.b actf) = (struct bUf *)NULL)
printf(IIUnix snintr: bp--O\n");

=

tendif ROVlFAR
snbf = 0:
/* force real check for boot disk */
SNIOB->mask = SN CLEARMSK;
SNIOB->gobyte-SN- CLRST;
(void) snwaitrdy():
return:
cnt - 512:
if (i) {
cnt - 0;
/* errlog: * /
sntab. io stp = &snstat [physical (bp->b dev)];
snreg [0]-:-drvalue - i:
snreg[O] .drname - "status":
snreg[O) .drbits - "status register";
fmtberr ('sntab, (unsigned) physical (bp->b dev),
(unsigned) (SNIOB->track),
/* trk * I
(unsigned) (SNIOB->side),
1* head */
(unsigned) (SNIOB->sector),
/* sector "I
(long) (sizeof(snreg) /sizeof(snreg(Oj», /x regcnt. XI
'snreq[O) I:

snwaitrdy ()
{

register int i, j, k;
k - 1024;
do {
i - 1000;
while « (PPADDR) ->d irb & DSKDIAG) == 0) (
/* floppy is busy */
for(j-0;j<1024;j++) ;
/" don't access flpy */
if (--i < 0) (
printf(lIunix snwaitrdy: DSKDIAG not ready\nll);
return(l) ;
I
i f (SNIOB->gobyte -- 0)

return(O) ;
I while (--k);
printf(IIUnix snwaitrdy: drive not ready\nll);
return (1);

Fri Sep

sony.c

5 19:08:53 1986

5

snprint(dev, str)
char "str;
{

printf("%s on sn drive %d, slice %d\n", str, (dev»4)&OxF, dev&Ox7);

/" This is the eject driver
" which uses a different major device so
" it can tell whether the sony is being used or not

,,/
I" ARGSUSED ,,/
ejioctl (dev, cmd, adr, flag)
dev t dev;
caddr_ t adr;
{

int unit;
register struct buf *bp;
i f «unit = physical (dev» >=
u. u_error = EFAULT;
return;
I
bp = &sncbuf;
i f ( cmd != AL_EJECT ) {
u. u error - ENOTTY;
return;
if

«s~bcount[count(unit»)

NSN)

!- 0) II (sn_ccount[count(unit») != 0»

u. u_error - EINVAL;
return;

I
GETBUF (bp) ;
bp->b dev - dev;
bp->b-resid = cmd;
snstrategy (bp) ;
iowait «struct buf *)bpl;
if (bp->b_flags & B_ERROR)
u. u_error = Ero;
FREEBUF (bpj ;
return;

1* stash the command in resid "/

{

subr.c

Fri Sep

5 19:08:01 1986

1

/ * @(t) subr . c 1. 4 * /
tinclude "sys/param.h"
tinclude "sys/types .h"
tinclude ·sys/sysmacros.h"
tinclude ·sys/systm.h"
.. include ·sys/inode.h·
Hnclude "sys!dir.h"
tinclude ·sys!signal.h"
tinclude .sys/user .hn
tinclude ·sys/errno.h"
tinclude ·sys!buLh"
tinclude ·sys/mount.h N
tinclude "sys/var .h"

} else
rem - ip->i size - up->u_offset:
i f (rem < 0)
rem = 0:
if (rem < sz)
sz - rem;
i f «up->uybsize = sz) ~ 0)
return ( (daddr_t) -1):
) else {
i f (bn >- FsPTOL(dev, up->u_limit»
up->u_error = EFBIG:
return ( (daddr_t) -1):

1*

*

Bmap defines the structure of file system storage
by returning the physical block number on a device given the
inode and the logical block number in a file.
When convenient, it also leaves the physical
block number of the next block of the file in u. u_ rablock
* for use in read-ahead.
"!

"
"
"
"

register struct buf "bp:
register j, sh:

I"
" blocks 0 •• NADDR-4 are direct blocks

""I
bmap Up, readflg)
register struct inode Kip:

i f (bn < NADDR-3) {
i = bn;
00 - ip->i addr [i] :
i f (00 = 0) {
i f (readflg II (bp - alloc(dev)
return ( (daddr_t)-l):
00 = FsPTOL(dev, bp->b blkno);
bdwrite (bp) :
ip->i addr [i] - 00:
ip->i::::flag 1- IUPD 1ICHG:

{

register struct user "up;
register i;
register dev;
daddr_t bn;
daddr t 00, "bap;
int raflag:
up - &u;
up->u_rablock
raflag - 0;

=

i f «i < NADDR-4) && raflag)
up->u rablock - ip->i addr [i+1];
return (nb) : -

0;

{

register sz, rem, type;
type = ip->i mode&IFMT;
i f (type - IFBLK) {
dey - (dev t)ip->i rdev;
for (i=O; Ii dey;
up->u pbdev - dev; bn - FSBNO(dev, up->u offset);
i f (bn < 0) (
up->u_error = EFBIG;
return «daddr_t) -1);

I"

*

addresses NADDR-3, NADDR-2, and NADDR-1
have single, double, triple indirect blocks.
the first step is to determine
"" how many levels of indirection.

*
*

*1
sh - 0:
00 - 1;
bn -= NADDR-3;
for(j-3; j>O; j--)
sh +- FsNSHIFT (dev);
00 «- FsNSHIFT (dev);
i f (bn < 00)
break:
bn -= nb;
i f (j =

i f ({ip->i lastr + 1) - bn)
raflag++;
up->uyboff - FSBOFF(dev, up->u_offset);
sz - FsBSIZE{dev) - up->uyboff;
if (up->u_count < sz) {
sz ~ up->u count;
raflag - 0;
} else
ip->i_Iastr = bn;

up->u pbsize - sz:
i f (type - IFBLK) (
i f (raflag)
up->u rablock - bn
return (bn): i f (readflg) {
i f (type IFIFO) {
raflaq - 0:
rem - ip->i_size;

)~NULL)

T

1;

0)

{

up->u_error - EFBIG;
return ( (daddr_t)-11;

/*

* fetch the address from the inode
*/
nb - ip->i addr [NADDR-j 1 :
i f (00 - 0) {
i f (readflg II (bp = alloc(dev) )--NULL)
return «daddr t) -1);
00 - FsPTOL(dev, bp->b blknol;
bwrite(bp);
ip->i addr[NADDR-j] - 00;
ip->i::::flag 1- IUPDI ICHG;
/*
" fetch through the indirect blocks
/

"

Fri Sep

subr.c

5 19:08:01 1986

2
return(-l);

forI; j<-3; j++) (
bp - bread(dev, nb):
if (up->u error) {
brelse (bp) ;
return ( (daddr_tl -1);
bap - bp->b un.b daddr;
sh -- FSNSHIFT(dev);
i = (bn»sh) & FsNMASK(dev);
nb - bap[i);
i f (nb ~ 0)
register struct buf *nbp;

up->u count--;
up->u- offset++;
up->u=:base++;
return (c) ;

I"

*

*

Routine which sets a user error; placed in
illegal entries in the bdevsw and cdevsw tables.

*1
nodev()

i f (readflg II (nbp - alloc(dev) )=NULL)
brelse (bp) ;
return ( (daddr_t)-l);

nb = FsPTOL(dev, nbp->b blkno);
i f (j < 3)
bwrite (nbp) ;
else
bdwrite(nbp) ;
bap[i) = nb;
bdwrite (bp) ;
} else

(

u.u_error

=

ENODEV;

1*

* Null routine; placed in insignificant entries
" in the bdevsw and cdevsw tables.

*1
nulldev()
(
)

brelse (bp) ;

1*

*

1*
" calculate read-ahead.

*1
if «i < FsNINDIR(dev)-l) && raflag)
up->u rablock = bap[i+l);
return (nb) ; -

max(a, b)
unsigned a, b;
{

if

1*

>-

b)

1*
Pass back c to the user at his location u base;
update u base, u count, and u offset. Return-l
on the last character of the user's read.
u base is in the user data space.

"I -

passc(c)
register c;
register struct user ·up;
up - &u;
if (subyte (up->u_base, c) < 0)
up->u_error - EFAULT;
return (-1) ;
up->u count--;
up->u-offset ++;
up->u=:base++;
return(up->u_count -

" Min function

*1
min(a, b)
unsigned a, b;
!
i f (a <-

b)

return (a) ;
return (b) ;

{

01 -1: 0);

1*
*
"
"
*
"

(a

return (a) ;
return (b) ;

}

"
"
"
"

Max function

*1

Pick up and return the next character from the user's
write call at location u_base;
update u base, u count, and u offset. Return-1
when u_count is exhausted.
u base is in the user data space.

"I -

cpass ()
{

reqillter IItruot user "up;
register c;
up - &u;
if (up->u_count - 0)
return(-l) ;
if Ilc - fubyte(up->u_base» < 0) (
up->u_error - EFAULT;

Fri Sep

sys.c
1*
1*

5 19:08:01 1986

1

1.2 *1

@(f)sys.c

indirect driver for controlling tty.

*1
'include
'include
'include
'include
'include
'include
'include
'include
'include

1*

"sys/param.h"
"sys/types.hn
"sys/sysmacros.h"
"sys/dir.h"
"sys/signal.h"
"sys/user.h"
·sys/errno.h"
"sys/conf.h"
·sys/proc.h"

ARGSUSED

*/

syopen!dev, flag)
{

if (sycheck () )
!*cdevsw[ (short)major (u. u_ttyd) 1 .d_open) (minor (u. u_ttyd), flag);

/" ARGSUSED

*/

syread (dev)
{

i f ( sycheck () )
(*cdevsw[ (short) major Cu. u_ttyd) 1 .d_read) (minor (u. u_ttyd»;

I"

ARGSUSED

"I

sywrite (dev)
{

i f ( sycheck () )
("cdevsw[ (short)major(u.u_ttyd) l.d_write) (minor (u.u_ttyd»;

/* ARGSUSED */
syioctl (dev, cmd, arg, mode)
{

i f ( sycheck () )
("cdevsw[ (short)major (u. u_ttyd) 1 .d_ioctl) (minor (u. u_ttyd), cmd, arg, mode);

sycheck()
{

i f (u.u_ttyp ~ NULL) (
u. u error = ENXIO;
return (0) :

if ("u.u_ttyp !~ u.u_procp->pygrp)
u.u error = EIO;
return(O) ;
return(l) ;

sys1.c

Fri Sep

5 19:08:25 1986

1

1* tdefine HOWFAR *1

)

if (apa=NULL && uap->envp) (
uap->arqp - NULL;
if «ap - fuword( (caddr_t)uap->envpl) =
break;
uap->envp++ ;
ne++;

1* @(f)sys1.c
1.8 *1
tinclude "sys/param.h u
tinclude "sys/config.h"
tinclude "sys/rnmu.h"
tinclude "sys/types.h"
tinclude "sys/sysmacros .h"
tinclude ·sys/systm.h"
tinclude "sys/map.h"
tinclude ·sys/dir.h"
tinclude ·sys/signal.h"
tinclude "sys/user. h"
tinclude ·sys/errno.h"
tinclude "sys/proc.h"
tinclude ·sys/context.h"
tinclude ·sys/buf.h"
tinclude ·sys/reg.h"
tinclude ·sys/file.h"
tinclude ·sys/inode.h"
tinclude ·sys/seg.h"
tinclude ·sys/acct.h"
tinclude ·sys/sysinfo.h"
tinclude ·sys/var. h"
tinclude ·sys/ipc.h"
tinclude ·sys/shm.h"
tinclude ·sys/scat.h"

)

if (ap-=NULL)
break;
na++;
if (ap - -1)
up->u_error = EFAULT;
do
if (nc >- NCARGS-l)
up->u error = E2BIG;
if «c - fubyte( (caddr_t)ap++») < 0)
up->u_error = EFAULT;
i f (up->u_error)
goto bad;
if «nc&BMASK) = 0) (
if (bp)
bdwrite (bp) ;
bp ~ getblk (swapdev,
(daddr t) (swplo+bno+ (nc»BSHIFT»);
cp = bp->b_un.b_addr;
nc++;
*cp++ ~ c;
) while (c>O);

/*

*

NULL)

exec system call, with and without environments.

*1

if (bp)

struct execa
char
char
char

*fname;
**arqp;
"*envp;

);

exec()
{

«struct execa *)u.u_ap)->envp
exece() ;

tdefine NCABLK
exece ()

=

NULL;

bdwrite (bp);
bp - 0;
nc - (nc + NBPW-l) & - (NBPW-l);
getxfile(ip, (int) (nc + sizeof(char *) *nal);
if (up->u error) (
printf("exec error: u_error %d u_dent.d name ", up->u error);
for (namep - &Up->u dent.d name[O]; namep-&& *namep && namep < &up->u_dent.d_name[DIRS
(*putchar) (*namep)~
(*putchar) (' \n');
psignal (up->uyrocp, SIGKILL);
goto bad;

(NCARGS+BSIZE-l) IBSIZE

1* copy back arglist * /

{

register unsigned nc;
register char *cp;
register struct buf *bp;
register struct execa "uap;
register struct user "up;
int na, ne, ucp, ap, c, bno;
struct inode *ip;
extern struct inode *gethead () ;
char *namep;
extern int (*putchar) () ;
sysinfo. sysexec++;
if «ip = gethead () - NULL)
return;
up - &u;
bp - 0; na - 0; nc = 0; ne = 0;
uap - (struct execa *)up->u ap;
I" collect arglist * I
i f «bno - swapalloc(NCABLK, 0» -- 0)
printf(IINo swap space for exec args\nll);
iput(ip) ;
up->~error - ENOMEM;
return;
)

i f (uap->arqp) for (;;) {
ap - NULL;
if (uap->arqp) {
ap - fuword( (caddr_t)uap->arqp);
uap->arqp++ ;

ucp - v.v uend - nc - NBPW;
ap - ucp -= na*NBPW - 3*NBPW;
up->u arO [SP] - ap;
tifdef HOWFARprintf ("setting new stack pointer to Ox%x\n", ap);
tendif
(void) suword «caddr t) ap, na-ne);
nc = 0;
for (;;) {
ap +- NBPW;
if (na~ne)
ap +- NBPW;
i f (--na < 0)
break;
(void) suword( (caddr_t)ap, ucp);
do (
if «nc&BMASK) - 0) {
i f (bp) {
bp->b_flaqs 1- B_AGE;
bp->b flags &- -B_DELWRI;
breIs; (bpJ ;

bp - bread (swapdev,
(daddr t) (swplo+bno+ (nc»BSHIFTI) I:
bp->b_flags I--B_AGE;
bp->b_flags &- -B_DELWRI;
cp - bp->b_un.b_addr;

Fri Sep

sys1.c

5 19:08:25 1986

(void) subyte( (caddr_t)ucp++, (c
nc++;
while (c&0377);

=

2

*cp++»;

if (access (ip, 1EXEC) I I
(ip->i mode' 1FMT) !- 1FREG II
(ip->i:=mode & (1EXECI (1EXEC»3) I (1EXEC»6») up->u error = EACCES;
goto bad;

}

(void) suword «caddr t) ap, 0);
if «long)ucp & 1) (void) subyte«caddr t)ucp++, 0);
(void) suword( (caddr_t)ucp, 0);
set regs ():
if (bp) {
bp->b_flags 1= B_AGE;
bp->b flags &- -B_DELWRI;
brelse (bpj ;
}

iput(ip) ;
mfree (swapmap, NCABLK, bno);
return;
bad:
if (bp)
brelse (bp) ;
iput (ip);
for (nc - 0; nc < NCABLK; nc++) {
bp = getblk(swapdev, (daddr_t) (swplo+bno+nc»);
bp->b flags 1= B AGE;
bp->b-flags &= -3 DELWRI;
brelse (bp) ;
mfree (swapmap, NCABLK, bno);

struct inode *
gethead()
{

register struct exdata *ep;
register struct inode Kip;
register unsigned ds, ts;
register struct user *up;
struct exdata exdata;
struct

naout
short
short
long

/*
,. read in first few bytes of file for segment sizes
* ux mag ~ 407/410/411
407 is plain executable
* 410 is RO text
* 411 is separated 1D
570 Common object
575 II
set ux_tstart to start of text portion
*/
ep = &exdata;
up->u base = (caddr t) ep;
up->u-count - sizeof(*ep);
up->u-offset - 0;
up->u- segflg = 1;
readi(ip) ;
tifdef notdef
if (ep->ux_mag - 0570 II ep->ux_mag == 0575) {
up->u base - (caddr t) ep;
up->u-count ~ sizeof(*ep);
up->u-offset = sizeof(struct filhd);
up->u- segflg - 1;
readl!ip) ;
ep->ux tstart = sizeof(struct naout) +
- sizeof(struct filhd) + (3 ,. sizeof(struct scnhdr»;
ep->ux_ent1oc - ep->ux_ssize;
else {
ep->ux_tstart - sizeof(up->u_exdata):
*

tendif
up->u segflg = 0;
if (Up->u_count!=O)
ep->ux mag - 0;
if (ep->ux maq-- 0407)
ds-- btoc( (long)ep->ux tsize +
(long) ep->ux_d-;ize + (long) ep->ux_bsize) ;
ts = 0;
ep->ux dsize +- ep->ux tsize;
ep->ux:=tsize - 0:
} else {
ts = btoc (ep->ux tsize);
ds - btoC(ep->ux:=dsize+ep->ux_bSize);
i f «ip->i flag&1TEXT)~O && ip->i count!-l)
register struct file Kfp: -

magic;
vstamp;
tsize,
dsize,
bsize,
entry,
ts,
ds;

};

struct

filhd
unsigned short
unsigned short
long
unsigned short

for (fp - file; fp < (struct file *)v.ve_file; fp++)
if (fp->f count && fp->f inode = ip &&
(fp->f flag&FWR1TE» - {
up=>u_error - ETXTBSY;
goto bad;

magic:
nscns;
timdat,
symptr,
nsyms;
opthdr,
flags;

i f (ep->ux_mag !- 0410) {
up->u error = ENOEXEC;
goto bad:

} ;

struct

scnhdr
char
long

unsigned short
long

s_name[8j;
syaddr,
s_vaddr,
s_ size,
s_scnptr,
s_relptr,
s_lnnoptr;
s_nreloc,
s nlnno;
s:=flaqs;

(void) chksize (ts, ds, (unsigned) (SS1ZE+btoc (NCARGS-1) ) ) ;
up->u_exdata - exdata;
bad:
i f (up->u error) {
lput(ip) ;
ip - NULL;

return (ip) ;

I;
i f ( (ip - namei (uchar, 0) ) -- NULL)
return (NULL) ;

up - ,u;

0) {

1*
• Read in and set up memory for executed file.
*!

Fri Sep

sys1.c

5 19:08:25 1986

3

getxfile (ip, nargc)
register struct inode "ip:

if «"rp

& 1) 0)
*rp = 0:
for (cp - ®loc[O]: cp <: ®loc[15]:
up->u arO [*cp++] = 0:
up->u_arO[PC]-= up->u_exdata.ux_entloc & -01;

(

register
register
register
register
register

struct exdata *ep:
struct user *up:
struct proe *p;
unsigned ts, ds, ss:
i:

tifdef HOWF!o.R
printf(HNew pc
lendif

up = &u:
p - up->uyrocp:
ep = sup->u exdata:
tifdef HOWFAR
printf("getxfile:reading in program\n H ) ;
lendif
shmexec() :
(void) punlock ( ) :
xfree() ;
ts = btoc (ep->ux tsize) :
ds = btoc (ep->ux-dsize + ep->ux bsizel:
ss = SSIZE + v. v- usize + btoc (nargc) :
i - v . v usize+dstss;
expand (I) :
(void) estabur «unsigned) 0, dS, ss, 0, RO):
procclear {pI :
1*
while (--i >- v. v usize)
clearseg«int) (p->p_addr+i);
"I
xalloc{ip) :
up->uyrof.pr_scale = 0:

I"
* Remember file name for accounting.
*1
up->u acflag &- -AFORK:
bcopy( (caddr_t) up->u_dent. d_name, (caddr_t)up->u_comm, DIRSIZ):

1*
" clear the data space for a process
*1
tifdef NONSCATLOAD
procclear (p)
struct proc *p:
(

register i, a;
a = p->p addr:
i = p->p-size:
while(--l >- v.v usize)
clearseg(a+i) :

"I

telse
procclear (p)
struct proc *p:
{

register struct scatter *s;
register i, a1:
s - scatmap:
a1 - p->p scat:
for (i=O:-ip flag&STRCI=OI {
if (ip->i mode&ISUID)
up->u uid = ip->i uid;
i f (ip->i mod;&ISGID)
up->u gid = ip->i gid:
p->p_suid = up->u_uid:
) else
psignal (p, SIGTRAP):
up->u tsize - ts:
up->u- dsize - ds:
up->u- ssize - ss:
(void) estabur(ts, ds, ss, 0, RO):

)

tendif

I"

* exit system call:
* pass back caller's arg
*/
rexit ()
{

register struct a {
int
rval:
} *uap:

1*
" Clear registers on exec
•I
setregs ()
{

register
register
register
register

struct user ·up:
char ·cp:
int *rp:
i:

uap - (struct a *)u.u_ap;
exit«uap->rval & 0377) <<: 8):

1*

* Release resources.
" Enter zombie state.
" Wake up parent and init processes,
* and dispose of children.

*/

up -

&u:

fo.r (rp - &Up->u_signal[OJ: rp <: &Up->u_signal[NSIG]: rp++)

Ox%x\n H, up->u_arO [PC]):

for (i-O: i<:NOFlLE: i++) (
if «up->uyofile[i]&EXCLOSE) && up->u_ofile[i] != NULL) {
closef (uP->u ofile til );
up->u_of1.le[l] = NULL:

1*
* read in data segment
(void) estabur (ts, ds, (unsigned) 0, 0, RO);
if (v.v_doffset)
up->u_base = (caddr_t)v.v_doffset:
else
up->u base
(caddr t) !v.v ustart + ctob(stcc(ctcs(ts»)):
up->u offset:; sizeOf{up->u-exdata) + ep->ux_tsize:
up->u-count = ep->ux dsize:readi(ip):
if (up->u_count!-O)
up->u_error - EFAULT:

=

exit (rv)
{

sys1.c

Fri Sep

5 19:08:25 1986

4
for (q - &proc[1]; q < (struct proc ")v.veyroc; q++) {
i f (p->pyid = q->pypid) {
q->pypid - 1;
if (q->p stat - SZOMB)
psignal (&proc[1l, SIGCLD);
i f (q->p stat -- SSTOP)
setrun(q) ;
} else
if (p->pypid - q->pyid)
psignal (q, SIGCLD);
i f (p->pyid - q->pygrp)
q->pygrp = 0;

register struct user *up;
register int i;
register struct proc *p, *q;
Hfdef mc6888l
1* MC68881 floating-point coprocessor *1
extern short fp88l;
/* is there an MC6888l'? */
tendif mc68881

up - &u;
p - up->uyrocp;
p->p flag &~ - (STRC) ;
p->p::::clktim = 0;
for (i=O; iu signal til - 1;
expand(v.v usIze);
(void) estabur «unsigned) 0, (unsigned) 0, (unsigned) 0, 0, RO);
if «p->pyid = p->pygrp)
&& (up->u_ttyp !- NULL)
&& (*up->u_ttyp ~ p->pygrp»
*up->u ttyp - 0;
signai"(p->pygrp, SIGHUP);
I
p->pygrp = 0;
for (i=O; iu ofile til !- NULL)
closef(up->u_ofile[i]) ;
I
(void) punlock () ;
plock(up->u cdir);
iput (up->u cdir) ;
if (up->u ~dir) {
plock (up->u rdir);
iput(up->u_rdir) ;
tifdef FLOAT
/*

}

tifdef NONSCATLOAD
resume(proc[O].p_addr, up->u_qsav);
telse
resume(ixtoc(proc[O].p_scat), up->u_qsav);
tendif
I" no deposit, no return *1

I"
"
"
"
*
*

wait system call.
Search for a terminated (zombie) child,
finally lay it to rest, and collect its status.
Look also for stopped (traced) children,
and pass back status from them.

*1
wait()
{

register struct user *up;
register f;
register struct proc "p;

/" sky floating point board *1

up

=

&U;

loop:
If this process was using the SKY FFP, restore
the board to a known state.

f = 0;

for (p - &proc [1]; p < (struct proc ") v. ve_proc; p++)
if (p->pypid -- up->uyrocp->pyid) {
f++;
i f (p->p stat = SZO!A.B)
freeproc (p, 1);
return;

"I
if (up->u fpinuse)
savfp() ;
tendif
tifdef mc6888l
/* MC68881 floating-point coprocessor "I
/*
" If there is an MC6888l, save the internal state and user
* registers so they'll be available in a core image.
* Then reset the coprocessor by restoring it to a null state.

}

if (p->p stat = SSTOP) {
If (Ip->p flag&SWTED) - 0) (
p=>p_flag 1= SWTED;
up->u_rvall = p->pyid;
up->u_rva12 = (fsig(p)«8) 1 0177;
return;

*1
if (fp88l) (
fpsave() ;
fpreset ();

continue;
tendif mc6888l

1*

i f If)
(void) sleep ( (caddr_t)up->uyrocp, PWAIT);
goto loop;

" call OEM supplied subroutine on process exit

"I
oemexit (p) ;

up->u_error - ECHILD;
xfree (l

;

semexit() ;
shmexit() ;
acct(rv) ;
tUdef NONSCATLOAD
mfree(coremap, p->p_size, p->p_addr);
telse
memt:ree (p->p scat);
p->p_scat - SCATEND;
tendif
cxrelse (p->p context);
p->p stat - SZOMB;
«struct xproc *lpl->xp xstat - rv;
«struct xproc ") p)->xp- utime - up->u cutime + up->u utime;
((struct xproc ") pI ->xp:'stime - up->u:'cstime + up->tLstime;

/"

*

Remove zombie children from the process table.

"I
freeproc (p, flag)
register struct proc .p;
(

register struct user ·up;
up - &U;
if (flag)
register n;
n - up->u procp->p cpu + p->p_cpu;
i f In > 80)
n - 80;

sys1.c

Fri Sep

5 19:08:25 1986

5
/* up->u rvall = pid-of-child; * /
break; default: /* unsuccessful newproc */
up->u_error - EAGAIN;
break;

up->uyrocp->p cpu = n;
up->u_rvall = p->pyid;
up->u_rva12 = «struct xproc *)p)->xp_xstat;
up->u cutime +~ « struct xproc *) p) ->xp utime;
up->u-cstime += «struct xproc *)p) ->xp=stL..,;,e:
p->p stat = NULL;
p->pyid - 0;
p->pypid = 0;
p->p sig - OL;
p->p::::flag - 0;
p->p_wchan = 0;

out:
up->u rva12 = 0; /* parent
up->u::::aro [PC] += 2;

*I

/*
• break system call.
-- bad planning: "break" is a dirty word in C.
*/
tifdef NONSCATLOAD
sbreak()

/*
* fork system call.
*/
fork()

{

register struct user ·up;
struct a {
unsigned nsiz;

{

register struct user *up;
register a, i;
int sz, xsize [NSCATSWAP], xaddr [NSCATSWAP];

};

register n, d, a;
int i;

up = &U;
sysinfo. sysfork++;
/*
* Disallow if
* No processes at all;
* not su and too many procs owned; or
* not su and would take last slot; or
* not su and no space on swap.
* Part of check done in newproc () .
*1
if (up->u uid && up->u ruid) {
if «a = malloc(swapmap, ctod(maxmem») - NULL) {
sz = ctod (maxmem) ;
for (i = 0; i < NSCATSWAP; i++)
i f (sz = 0) {
xsize[i] = 0;
break;
J else {
a = MIN (mal loci (swapmap), sz);
xsize [i] = a;
xaddr[i] = malloc(swapmap, a);
sz -= a;

up - &u;
/*
* set n to new data size
* set d to new-old
* set n to new total size
*/
i f (v. v doffset)
-n - btoc«int) «(struct a *)up->u ap)->nsiz» btoc (v. v_doffset) ;
else (
n = btoc«int) ({(struct a *)up->u ap)->nsiz» btoc (v. v ustart);
n -= stoc(ctoS(Up->u_tsize»;
i f In < 0)
n = 0;

d = n - up->u dsize:
i f (d -= 0) return;
n +- v. v usize+up->u ssize:
if (chkslze(up->u_tslze, up->u_dsize+d, up->u_ssize»
return;
up->u dsize +- d;
(void) estabur (up->u tsize, up->u_dsize, up->u_ssize, 0, RO);
i f (d > 0)
goto bigger;
a - up->uyrocp->p_addr + n - up->u_ssize;
i = n;
i f (d < 0) (
n - up->u_ ssize;
while (n--) (
copyseg(a-d, a);
a++;

}

for (i - 0; i < NSCATSWAP; i++)
i f (xsize[i] - 0)
break;
else
mfree (swapmap, xsize [i], xaddr [i]);
i f (sz !- 0)
printf ("Not enough swap space to fork\n");
up->u error - ENOMEM;
goto ~ut;
) else
mfree (swapmap, ctod (maxmem), a);
swi tch ( newproc (1) ) (
case 1: /* child -- successful newproc * /
up->u_rvall - up->uyrocp->pypid;
up->u rva12 - 1; /* child */
up->u-start - time;
up->u::::ticks - lbolt;
up->u mem - v. v usize + procsize (up->u_procp) ;
up->u-ior - 0; up->u-iow - 0;
up->u-ioch - 0;
up->u- cstime - 0;
up->u- stime - 0;
up->u-cutime - 0;
up->u=utime - 0;
up->u_acf1aq - AFORK;
return;
case 0: /* parent -- successful newproc */

)

expand (i) ;
return;
bigger:
expand(n) ;
a - up->u procp->p addr + n;
n - up->u-ssize; while (n-=) (
a--;

copyseq(a-d, a);
while (d--)
clear seq (--a);
felse

Fri Sep

sys1.c

5 19:08:25 1986

6
printf("sbreak:bigger: unusual condition fl \n"l;
i f (up->u ssize = 0) {
while (d-- > 0)
clearseg(ixtoc(al - s[al].sc index»;
if (s[al].sc index != SCATEND)
printf("Sbreak:not at end of list\n");
} else

sbreak()
{

register struct scatter *s;
register struct user ·up:
struct a {
unsigned nsiz:
};

/*

register n, d, aI, a2;
int i;
short t:
up

!!!It

" find end of original stack space

*/
a2 - al;
for (i-O; iu ssize: i++)
a2 - s(a2].sc index;
t - s(al].sc index; s(al].sc index - s(a2].sc index;
s(a2].sc-index = SCATEND;while (d=- > 0)
clearseg(ixtoc(al = s(alj.sc_index»;
s(al].sc_index = t:

&U;

/*
* set n to new data size
* set d to new-old
* set n to new total size
*/
n - btoc( (int) « (struct a *)up->u ap)->nsiz»
n -- stoc (ctos (up->u tsize»:
-

if

(n

<

0)

n

- btoc(v.v_ustart);

I
(void) estabur (up->u tsize, up->u dsize, up->u_ ssize, 0, RO);
up->uyrocp->p_flag &= -SCONTIG; -

=

0;

d = n - up->u dsize;
if (d 0)
return;
n += v. v usize+up->u ssize:
if (chksize (up->u tsize, up->u dsize+d, up->u_ssize»
return; s - scatmap:
up->u dsize +- d;
if (d-> 0)
goto bigger;
nscatfree -- d;
/* note: d is negative */
up->uyrocp->p size c n;
al = up->uyrocp->p_scat:
n - up->u dsize + v. v usize:
for (i-l;-iu tsize, up->u dsize, up->u_ssize, 0, RO);
fifdef OLD
- a = up->uyrocp->p_addr + n - up->u_ssize;
i = n:
if (d < 0) {
n = up->u ssize;
while (n-=) {
copyseg (a-d, a):
a++;
}

expand (i) ;
fendif
up->uyrocp->p flag
return;
-

&- -SCONTIG;

bigger:
expand(n) ;
al - up->u procp->p scat;
/*
* find last index of original data space
*1
n - up->u dsize + v. v usize - d;
i f Cn == 0)
printfC"sbreak:original size is zero\n"):
for (i-I: iu_ssize !-O && (int) (up->u_dsize-d) <- 0)

fifdef OLD
a = up->u procp->p addr + n:
n = up->u- ssize; while (n-=) (
a--;
copyseg(a-d, a);
while (d--j
clearseg(--a) ;
fendif
I

sys2.c

Fri Sep

5 19:08:02 1986

1.6 *1
tinclude "sys/param.h"
tinclude "sys/types.h"
tinclude "sys/systm.h"
finclude "sys/dir .h"
"include tI,sys/signal.h u
tinclude .. sys/user. h"
tinclude "sys/proc.h"
tinclude "sys/errno.h"
tinclude "sys/file.h"
tinclude "sys/inode.h"
iinclude Rsys/sysinfo.h u
tifdef UCB NET
tinclude "net/misc. h"
tinclude "net I socket. h"
tinclude "net I socketvar. h"
tendif

1

1* @(t)sys2.c

fp->f_offset - ip->i_size;
up->u offset
= fp->f offset;
if (ip->i locklist && locked (1, ip, up->u offset,
(off_t) (up->u_offset+up->u_countl»
return;
tifdef

tendif
if (type=IFREG I I type~IFDIR) {
plock (ip) ;
if «up->u fmode&FAPPEND) && (mode =
fp=>f_offset - ip->i_size;
) else if (type - IFIFO) {
plock (ipl ;
fp->f_offset - 0;

1*
" read system call
"I
read()
{

sysinfo. sysread++;
rdwr (FREAD) ;

{

sysinfo. syswrite++;
rdwr (FWRITE);

{

register
register
register
register

struct user "up;
struct file "fp;
struct inode "ip;
struct a {
int
fdes;
char
"cbuf;
unsigned count;

up->u rvall = uap->count-up->u count;
up->u-ioch +- (unsignedjup->u rvall;
i f (mode = FREAD)
sysinfo. readch +- (unsigned) up->u_rvall;
else
sysinfo. writech +- (unsigned) up->u_ rvall;

1*
* open system call
,,/
open()
{

register struct
char
int
int
) "uap;

) "uap;
register int type;
up ~ &u;
uap - (struct a *) up->u ap;
fp - getf (uap->fdes); if (fp -- NULL)
return;
if «fp->f_flag&mode) ~- 0) {
up->u_error - EBADF;
return;

a {
"fname;
mode;
crtmode;

uap = (struct a *)u.u_ap;
copen (uap->mode-FOPEN, uap->crtmode);

/*
" creat system call
*1
creat ()
{

struct a {
char
int
} "uap;

up->u_base - (caddr_t)uap->cbuf;
up->u_count - uap->count;
up->u segflg - 0;
up->u-fmode = fp->f flag;
ip - fp->f inode; type
:'p->:'_mode&IFMT;
/*

"fname;
fmode;

uap - (struct a "Iu.u ap;
copen (FWRITE IFCREAT IFTRUNC, uap->fmode);

I"
Fix from ROOT: check for file lock before attempting
to lock the inode.

*/
i f (type-IFREG) {
i t «up->u_fmode&FAPPEND) && (mode -- FWRITEJ)

FWRITE»

up->u offset - fp->f offset;
if (mode = FREAD) readi (ip);
else
writei (ip);
if (type=IFREG I I type=IFDIR I I type=IFIFO)
prele(ip) ;
fp->f offset +- uap->count-up->u count;
)
-

/"
" write system call
"/
write ()

/*
" common code for read and write calls:
.. check permissions, set base, count, and offset,
* and switch out to readi or writei code.
*/
rdwr(model
register mode;

UCB NET
if (fp->f flag & FSOCKET) {
if (mode ~ FREAD)
u. u_error = soreceive «struct socket ,,) fp->f_socket, (struct sockaddr XI 0) ;
else
u. u_error
sosend «struct socket ") fp->f_socket, (struct sockaddr ,,) 0);
else

" common code for open and creat.
* Check permissions, allocate an open file structure,
.. and call the device open routine if any.

"I
copen (mode, argl

sys2.c

Fri Sep

5 19:08:02 1986

2
openi (ip, mode);
if (up->u_error -- 0)
return;
up->u ofile[i) - NULL;
i f «=-fp->f count) <- 0) {
fo->f next - ffreelist;
ffreelist - fp;
I
iput(ip) ;

register mode;
{

register struct user "up;
register struct inode *ip;
register struct file *fp;
int i;
up = &u;
if «mode& (FREAD IFWRITE» ~- OJ
up->u_error - EINVAL;
return;
if (mode&FCREAT)
ip = namei (uchar, 1);
if (ip = NULL) {
for (i=O; iu_ofile [i) == NULL)
break;
if (i >= NOFlLE) {
iput (u. uJXiir);
up->u_error - EMFlLE;

/*
* close system call
*/
close()
{

register struct file *fp:
register struct a {
int
fdes;
} *uap;

}

if (up->u_error)
return;
ip = maknode (arg&07777& (-ISVTX» ;
i f (ip = NULL)
return;
mode &= -FTRUNC;
I else {
if (ip->i locklist != NULL &&
(ip=>i flag&IFMT) - IFREG &&
10cked(2, ip, (long) (OLI, (long) (lL«30»)
iput(ip) ;
return;
if (mode&FEXCL)
up->u error
iput(Ip );
return;
mode

&=

=

uap = (struct a *)u.u_ap;
fp - getf (uap->fdes) ;
i f (fp == NULL)
return;
u. u ofile [uap->fdes) = NULL;
tifdef UCB NET
/* so sockets close correctly */
fp=>f_flag 1- FISUSER;
iendif
closef(fp) ;

/"
" seek system call
"I
seek()

EEXIST;

{

register struct file *fp;
register struct inode *ip;
register struct a {
int
fdes;
off t
off;
intsbase;
} "uap;
register struct user *up;

-FCREAT;

fifndef VIRTUAL451
xmfree(ip) ;
tendif
} else
ip = namei (uchar, 0);
if lip == NULL)
return;

up = &U;
uap = (struct a ")up->u ap;
fp - getf (uap->fdes) ; if (fp ~ NULL)
return;

}

if

(!

(mode&FCREAT» {
if (mode&FREAD)
(void) access (ip, lREAD);
if (mode& (FWRITE I FTRUNC» {
(void) access (ip, IWRITE):
i f «ip->i mode&IFMT) IFDIR)
up=>u_error = EISDIR:

i f (fp->f_flag&FSOCKET)

u.u_error - ESPIPE;
return:
tendif

if (up->u error II (fp - falloc(ip, mode&FMASK») {put (ip):
return:
I
if (mode&FTRUNC)
itrunc (ip):
prele (ip);
i = up->u rvall;
i f (save (up->u qsav)) { / * catch half-opens ,,/
if (up=>u_error == 0)
up->u error - EINTR;
up->u_ofile [iT - NULL;

NULL) {

ip - fp->f inode:
if «ip->(:mode&IFMT)~IFIFO)
up->u_error - ESPIPE;
return;
}

if (uap->sbase ~ 1)
uap->off +- fp->f offset;
else if (uap->sbase - 2)uap->off +- fp->f inode->i size;
else if (uap->sbase !- 0)- {
up->u error - EINVAL;
psignal (up->uyrocp, SIGSYS);
return;
}

fp->f_flag 1- FISUSER;
tendif
closef(fp) ;
I else {

if (uap->off < 0)
up->u error - EINVAL;
return;

Fri Sep

sys2.c

5 19:08:02 1986

3

fp->f offset - uap->off;
up->u:=roff = uap->off;

} *uap:
uap ~ (struct a *lu.u ap;
if «uap->fmode&IFMT)-!= IFIFO
return;
ip - namei (uchar, 1):
if (ip !- NULL) (
iput(ip) :
u. u error = EEXIST;
return;

1*

* link .system.
*1

call

link()
{

register struct user *up;
register struct inode *ip, *xp;
register struct a {
char
*target;
char
*linkname:
) *uap:

iput(ip) :

1*

*

1*
* Unlock to avoid possibly hanging the namei.
* Sadly, this means races. (Suppose someone
" deletes the file in the meantime'? I
* Nor can it be locked again later
" because then there will be deadly
* embraces.
" Update inode first for robustness.

access system call

*1
saccess()
{

register
register
register
register

*1
ip->i nlink++;
ip->i-flag 1= ICHGIISYN:
iupdat (ip, &time, &time):
prele(ip) ;
up->u dirp = (caddr t) uap->linkname:
xp = namei (uchar, 1);
if (xp !~ NULL) (
iput(xp) :
up->u error = EEXIST;
goto out;
if (up->u error)
goto out;
i f (up->uydir->i_dev != ip->i_dev)
iput (up->uydir) ;
up->u error - EXDEV;
goto out;
}

wdir(ip) :
out:
plock (ip) ;
if (up->u error)
ip->i nlink--;
ip->i:=flag 1- ICHG;
outn:
iput(ip) ;
return:

/*
" mknod system call
*1
mknod()
{

register struct inode *ip;
register struct a (
char
*fname:
int
fmode;
int
dev:

!suser()

if (u. u_error)
return;
ip - maknode (uap->fmode) ;
i f (ip - NULL)
return;
switch (ip->i_mode&IFMT)
case IFCHR:
case IFBLK:
ip->i rdev = (dev t)uap->dev;
ip->i:=flag 1= ICHC;;

up u &U;
uap = (struct a *)up->u_ap;
ip-namei(uchar,O):
i f (ip - NULL)
return:
i f (ip->i nlink >- MAXLINK)
up->u_error = EMLINK:
goto outn:
i f «ip->i mode&IFMT) =IFDIR && ! suser ()
goto outn;

&&

struct
svuid,
struct
struct
char
int

user *up;
svgid:
inode *ip:
a (
"fname:
fmode:

) *uap;
up - &u;
uap - (struct a *)up->u ap;
svuid = up->u uid; svgid = up->u- gid;
up->u uid = up->u ruid:
up->u-gid = up->u-rgid;
ip = namei(uchar,-O);
i f (ip !- NULL) {
i f (uap->fmode& (IREAD»6»
(void) access (ip,
if (uap->fmode& (IWRITE»6)
(void) access (ip,
if (uap->fmode& (IEXEC»6»
(void) access (ip,
iput(ip) ;
}

up->u uid - svuid;
up->u:=gid - svgid;

IREAD);
)
IWRITEI:
IEXEC);

sys3.c

Fri Sep

5 19:08:03 1986

1

1* @(t)sys3.c
1.4 *1
tinclude "sys/param.h"
tinclude ·sys/types.h"
tinclude "sysl sysmacros. h"
finclude "sys/systm.h"
tinclude -- sys/motL.."lt. h"
tinclude "sys/ino .h"
finclude "sys/buf .h"
tinclude ·sys/filsys.h"
tinclude ·sys/dir .h"
tinclude "sys/signal.h"
tinclude • sys/user ~ h"
tinclude "sys/errno.h"
tinclude "sys/inode.h"
tinclude "sys/file.h"
tinclude "sys/conf .h"
tinclude "sys/stat.h"
tinclude "sys/ttold.h"
tinclude "sys/var .hn
tifdef UCB NET
tinclude ,'sys/termio. h"
finclude "net/misc.h"
tinclude ·net/socketvar .h M
tendif

register struct buf *bp;
register struct stat *dsp;
struct stat ds;
i f {ip->i flag& (lACC I lUPD I lCHG) )
iupdat (ip, &time, &time);

/*
* first copy from inode table

*1
dsp ~ &ds;
dsp->st_dev = brdev(ip->i_dev);
dsp->st ino - ip->i number:
dsp->st-mode = ip->I mode:
dsp->st- nlink - ip->I nlink;
dsp->st-uid = ip->i uld;
dsp->st- gid = ip->Cgid;
dsp->st-rdev - (dev-t)ip->i rdev:
dsp->st-size = ip->i size; /*
* next the dates in the disk
*/
bp - bread(ip->i_dev, FslTOD{ip->i_dev, ip->i_number»);
dp - bp->b un. b dino;
dp += FSITOo(ip=>i dey, ip->i number);
dsp->st atime = dp=>di atime;dsp->st-mtime - dp->di-mtime;
dsp->st- ctime = dp->di-ctime;
brelse (bp) ;
if {copyout{ (caddr_t)dsp, (caddr_t)ub, sizeof(ds») < 0)
u.u_error = EFAULT;

1*
" the fstat system call.
*/
fstat ()
{

register struct file "fp;
register struct a {
int
fdes;
struct stat "sb;
I "uap;
uap - (struct a *)u.u ap;
fp - getf (uap->fdes) ;i f (fp ~ NULL)
return;
tUdef UCB NET
if- (fp->f_flag & FSOCKET)
u. u_error = sostat «struct socket ") fp->f_socket, uap->sb);
else
tendif
statl (fp->f_inode, uap->sb);

/*
* the dup system call.
*1
dup{)
(

register struct file *fp;
int i;
struct a {
int
fdes;
} "uap;
uap ~ (struct a ")u.u ap;
fp - getf (uap->fdes) ;if{fp ~ NULL)
return;
i f ({i = ufalloc(O» < 0)
return;
u.u ofile[i] - fp;
fp->f_count++;

/"

*

the stat system call.

*1
state)
{

register struct inode Kip;
register struct a {
char
*fname;
struct stat * sb;
I *uap;
uap - (struct a *)u.u ap;
ip - namei (uchar, 0);i f (ip -- NULL)
return;
stat! (ip, uap->sb);
iput{ip) ;

/*

*

The basic routine :!'or :!'stat and stat:
" get the inode and pass appropriate parts back.
"I
statl (ip, ub)
reqister struct inode Kip;
struct stat *ub;

register st.ruct. dinode "dp;

/*
" the file control system call.
*/
fcntl{)
{

register struct file *fp;
register struct a (
int
fdes;
int
cmd;
int
arg;
) *uap;
register i;
register struct user "up;
up - &u;
uap - (struct a *)up->u ap;
fp - getf (uap->fdes); i f (fp - NULL)
return;
switch (uap->cmd) {
case 0:
i - uap->arq;
i f (i < 0 Iii> NCFILE) {

Fri Sep

sys3.c

up->u_error
return;

5 19:08:03 1986
=

2
return;

EINVAL;
telse

if «ip->i modeUFMT) !- IFCHR)
u. u _error = ENOTTY;
return;

ufalloc(i» < 0)
return;
up->u ofile [i] == fp:
fp->f-count++;
break:

i f «i

a

tendif UCB NET
dev - (dev t) ip->i rdev;
(*cdevsw [(short)major (dev)] .d_ioctl) (minor (dev) ,uap->cmd, uap->arg, fp->f_flag) ;

case 1:
up->u rvall - up->uyofile [uap->fdes] ;
break:

/*
* old stty and gtty
*/
stty()

case 2:
up->uyofile [uap->fdes]
break;

=

uap->arg;

{

case 3:
up->u rvall
break:

=

register struct
int
int
int
} *uap;

fp->f_flag+FO?EN;

case 4:
fp->f flag &= (FREAD I FWRITE) ;
fp->f-flag 1= (uap->arg-FO?EN)
break:

& -

uap = (struct a *)u.u_ap;
uap->narg - uap->arg;
uap->arg - TIOCSET?;
ioctl ();

(FREAD I FWRITE) ;

default:
up->u_error

=

a {
fdes;
arg;
narg;

EINVAL;

gttyO
{

register struct
int
int
int
} *uap;

/"
" character special i/o control
x/

ioctl ()
{

register struct file *fp;
register struct inode *ip;
register struct a {
int
fdes;
int
cmd;
int
arg;
) *uap;
register dev_t dey;
tifdef UCB_NET
register unsigned fmt;
tendif

a {
fdes;
arg;
narg;

uap - (struct a *)u.u_ap;
uap->narg = uap->arg;
uap->arg = TIOCGET?;
ioctl() ;

/*
* the mount system call.
*/
smount()
{

uap - (struct a *)u.u_ap;
if « fp = getf (uap->fdes» ~ NULL)
return;
tifdef UCB NET
if-(fp->f flag & FSOCKET) {
soioctl ( (struct socket *) fp->f_ socket, uap->cmd, (caddr_ t) uap->arg) ;
return;
tendif
ip = fp->f inode;
tifdef UCB NET
fmt - ip->i mode & IFMT;
if (fmt !- IFCHR) {
if (uap->cmd--FIONREAD U
I I fmt -- IFIFO»
off_t nread;

(fmt
{

=- IFREG

II fmt -- IFDIR

if «ip->i modeUFMT)-IFIFO)
nr;ad - ip->i_size;
else
nread - ip->i size - fp->f offset;
if (copyout «caddr t) &nread, (caddr_t) uap->arg,
sizeOf(Off_t» )
u. u error - EFAULT;
I else i f (uap->cmd-- FIONBIO /* II uap->cmd -- FIOASYNC* /)
return;
else
u.u_error - ENOTTY;

register struct user ·up;
register dey t dey;
register struct inode *ip;
register struct mount *mp;
struct mount * smp;
register struct filsys *fp;
struct inode *bip = NULL;
register struct a {
char
·fspec;
char
"freg;
int
ronly;
) *uap;
up = &u;
uap - (struct a *) up->u_ ap;
if ( ! suser () )
return;
ip = namei (uchar, 0);
if(ip - NULL)
return;
iff (ip->i IIIOdeUFMT) !- IFBLK)
up->u error - ENOTBLK;
dey - (dev t)Ip->i rdey;
if (bmajor (dey) >- bdevcnt)
if (!up->u_error)
up->u_error - ENXIO;
if (up->u error)
gato out;

Fri Sep

sys3.c

5 19:08:03 1986

3
iput(bip) ;
if (up->u_error - 0)
up->u error - EBUSY;
iput(ip);
-

bip - ip;
up->u dirp - (caddr t) uap->freg;
ip - namei (uchar, 0);
if(ip - NULL) (
iput(bip) ;
return:

/*
if «ip->i modeUFMT) !- IFDIR)
up=>u error = ENOTDIR;
goto out;

* the umount system call.
*/
sumount()
(

register
register
register
register

if (ip->i_count !- 1)
goto out;
if (ip->i number ~ ROOTINO)
goto out;
smp = NULL;
for(mp = &mount[O]; mp < (struct mount *)v.ve mount; mp++) (
if(mp->m flags != MFREE) (
If (brdev(dev) -= brdev(mp->m dev»
goto out;
l else
if (smp ~ NULL)
smp = mp;
mp - smp:
if (mp - NULL)
goto out;
mp->m flags - MINTER:
mp->m- dey - brdev (dev) :
(*bde;sw[ (short)bmajor (dev) l.d open) (minor (dev),
uap->ronly '1 (FREAD 1-FKERNEL) : (FREAD 1 FWRITE 1 FKERNEL»;
if (up->u_error)
goto outl;
mp->m bufp - geteblk () ;
fp = iiip->m bufp->b un.b filsys;
up->u offs;t = SUPERBOFF;
up->u=:count = sizeof (struct filsysl;
up->u base = (caddr tl fp;
up->u-seqflg = 1; readi(bip) ;
if (up->u_errorj {
brelse (mp->m bufp);
goto outl; mp->m_ inodp - ip;
mp->m flags - MINUSE;
if (fp->s_magic !- FSMAGIC)
fp->s type = Fslb:
/* assume old file system *1
if (fp->s_type ~ Fs2b)
mp->m_dev 1= Fs2BLK;
tif FsTYPE -= 4
if (fp->s_type = Fs4b)
mp->m_dev 1- Fs4BLK;
tendif
if Ibrdev(pipedev) ~= brdev(mp->m dev»
pipedev = mp->m dev;
fp->s ilock - 0;
fp->s-flock = 0;
fp->s-ninode - 0;
fp->s-inode[O] - 0;
fp->s- ronly - uap->ronly & 1;
if (mp->m mount - iget (mp->m dev, ROOTINO»
prele(mp->m_mount); else (
brelse (mp->m_bufp);
goto outl;
}

ip-> i flag 1- lMOUNT;
iput (hip):
prele (ip);
return;
outl:
mp->m_flags - MFREE;
out:
i f (bip

!~

NULL)

dey t dey;
struct inode *ip;
struct mount *mp;
struct a {
char
*fspec;

};

if ( ! suser () )
return;
dey = getmdev () ;
if (u. u_error)
return;
for(mp - &mount[O]; mp < (struct mount *lv.ve_mount; mp++)
if (mp->m flags - MINUSE && brdev (dev) -= brdev (mp->m_dev»)
qoto found;
u. u_error - EINVAL;
return:
found:
dey - mp->m dev;
(void) xumoUnt (dev);
/* remove unused sticky files from text table */
update() ;
if (mp->m mount) (
plock(mp->m mount);
iput (mp->m iount);
mp->m_mount - NULL;
}

for(ip

~

&inode[O]; ip < (struct inode *)v.ve inode: ip++)
if(ip->i number != 0 && dey -- ip->i_dev) {
u.u_error = EBUSY;
return;
}

(*bdevsw [(short)bmajor (dev)] .d_close) (minor (dev), FKERNEL);
binval (dev);
ip - mp->m inodp;
ip->i flag-&- -IMOUNT:
pIOck(ip) ;
iput(ip) ;
brelse (mp->m bufp);
mp->m bufp --NULL;
mp->m=:flags = MFREE;

1*

*

Common code for mount and umount.

* Check that the user's argument is a reasonable
* thing on which to mount, and return the device number if so.
*/
dey t
getiiidev()
{

dey t dey;
regIster struct inode Kip;
ip = namei(uchar, 0);
iflip -- NULL)
return (NODEV) ;
ifllip->i_mode&IFMT) !- IFBLK)
u. u error - ENOTBLK;
dey - (dev t) ip->i rdev;
i f (bmajor (dev) >- hdevcnt)
u. u error - ENXIO;
iput(ip); return (dev) ;

sys3.c

Fri Sep

5 19:08:03 1986

4

Fri Sep

sys4.c

5 19:08:27 1986

/* @(t)sys4.c
1.5 */
tinclude OIsys/param.h"
+include "sys/config.h"
tinclude ·sys/mmu.hR
tinclude .sys/types .h Ol
tinclude • sys/ sysmacrcs. hOI
tinclude ·sys/systm.h"
tinclude ·sys/dir.h"
+include "sys/signal.hOl
tinclude "sys/user .h"
tinclude "sys/errno.h"
tinclude "sys!inode . hOI
tinclude ·sys/file.h"
tinclude ·sys/filsys.h Ol
tinclude "sys/proc.h Ol
tinclude "sys/var .h"

1
setgid(l
{

re'lister unsigned 'lid;
register struct a !
int
'lid:
} *uap:
re'lister struct user *up:
up - &u:
uap - (struct a * I up->u ap;
'lid - uap->gid:
i f ('lid >= MAXUID) !
up->u_error = EINVAL:
return:
i f (up->u r'lid -

gid I I suser (I I
up->u 'lid ~ gid;
up->u=rgid = gid;

1*

* Everything in this file is a routine implementing a system call.

*1
gtime()

'let'lid(l
{

(

register struct user *up;

u.u_rtime = time;

up - &u;
up->u rval1 - up->u rgid:
up->u::::rval2 = up->u::::'lid;

stime()
(

register struct a {
time_ t time;
} *uap;
struct filsys *fp;

getpid()
(

register struct user *up;
uap = (struct a *)u.u ap;
i f (suser ()
(
logtchg(uap->time) ;
time - uap->time;
if (fp - getfs (rootdev) )
fp->s_fmod - 1:

up = &u;
up->u_rvall - up->uyrocp->pyid:
up->u_rval2 ~ up->uyrocp->pypid;
setp'lrp()
{

register struct proc *p
register struct a {
int
flag:
} *uap;

setuid()
(

register unsigned uid;
register struct a {
int
uid;
} *uap:
register struct user *up:
up = &u;
uap - (struct a *) up->u ap:
uid - uap->uid;
i f (uid >- MAXUID) {
up->u_error = EINVAL:
return;

=

u. uyrocp;

uap - (struct a *lu.u_ap;
i f (uap->flag) {
i f (p->pygrp != p->p_pid)
u.u ttyp = NULL;
p->pygrp --p->pyid:
u.u_rvall

=

p->pygrp;

sync!)
{

(uid == up->u ruid II uid == up->uyrocp->p_suidll
up->u uid - uid;else i f (suser () I {
up->u uid - uid:
up->uyrocp->p_uid - uid;
up->uyrocp->p_suid - uid;
up->u_ruid = uid:

i f !uid

&&

'letuid()

update ();

nice()
!
register n:
register struct a {
int
niceness:
} *uap:
re'lister struct user *up;

(

re'lister struct user *up;
up - &u;
up->u_rval1 - up->u ruid;
up->u_rva12 - up->u::::uid;

up - &u:
uap - (struct a *1 up->u ap;
n - uap->niceness;
if «n < 0 I In> 2*NZERO) && ! suser () )
n -

0;

n +- up->uyrocp->p_nice:
i f (n >- 2*NZERO)

Fri Sep

sys4.c

5 19:08:27 1986

2
return;
chdirec(&u. u_rdir);

n - 2*NZERO -1;
if

(n

<

0)

n

~

0;

up->uyrocp->p_nice - n;
up->u_ rval1 = n - NZERO;

chdirec (ipp)
register struct inode *"ipp;
(

register struct inode *ip;
struct a {
char
*fname;

/*
* Unlink system call.
* Hard to avoid races here, especially
* in unlinking directories.
*1
unlink()

};

ip - namei(uchar, 0);
i f (ip ~ NULL)
return;
i f «ip->i_mode&IFMT) != IFDIR)
u.u_error - ENOTDIR;
goto bad;

{

register struct inode *ip, *pp;
struct a {
char
* fname;
};

register struct user *up;
if (access (ip, IEXEC»
goto bad;
prele(ip) ;
i f (*ipp) (
plock (*ipp) ;
iput (*ipp);

up - &u;
pp - namei (uchar, 2);
i f (pp -- NULL)
return;

/*
* Check for unlink (II. ")
1< to avoid hanging on the iget

}

*ipp = ip;
return;

*1
if (pp->i_number ~ up->u_dent.d_ino)
ip = pp;
ip->i_count++;
} else
ip = iget(pp->i dev, up->u_dent.d_ino);
i f (ip - NULL)
goto out1;
i f «ip->i mode&IFMT) = IFDIR && ! suser () I
goto out;
/*
* Don't unlink a mounted file.

bad:
iput(ip) ;
chmod()
{

register struct inode *ip;
register struct a {
char
*fname;
int
fmode;
} *uap;

*1
i f (ip->i_dev != pp->i_dev) !
up->u error = EBUSY;
goto out;

uap = (struct a *)u.u ap;
i f «ip = owner() l =-NULL)
return;
ip->i mode &= -07777;
i f (U~u uid) {
-uap->fmode &- -ISVTX;
i f (u. u gid ! = ip->i gid)
-uap->fmode , : -ISGID;

i f (ip->i flag&ITEXTI
xrele (ip) ;
/ * try once to free text * /
i f (ip->i_flag&ITEXT && ip->i_nlink - 1) (
up->u error - ETXTBSY;
goto out;

up->u_offset -= sizeof(struct direct);
up->u base = (caddr t) &Up->u dent;
up->u-count = sizeof (struct direct);
up->u-dent.d inc - 0;
up->u- segflg- = 1;
up->u- fmode - FWRITE 1 FSYNC;
writeI (pp) ;
if (up->u error)
goto out;
ip->i nlink--;
ip->i:::flag 1- ICHG;
out:
iput(ip) ;
out1:

ip->i mode 1- uap->fmode&07777;
ip->i-flag 1- ICHG;
i f (lp->i flag&ITEXT && (ip->i_mode&ISVTXl-Ol
xi"ele (ip) ;
iput(ip) ;
chown()
(

register struct inode "ip;
register struct a {
char
*fname;
int
uid;
lnt
gid;
} *uap;

iput(pp) :
ehdir ()
{

chdirec(&u.u_cdir) ;
chroot II
{

if (!suser()

uap - (struct a *)u.u ap;
i f «ip = owner II ) --NULL)
return;
ip->i uid - uap->uid;
ip->i:::gid - uap->gid;
i f (u.u uid !- 0)
-ip->i mode &- - (ISUID 1 ISGID) ;
ip->i flaq 1--ICHG;
iput(Ip ) ;

Fri Sep

sys4.c

5 19:08:27 1986

3
if

(!

ssig()
!
register a;
register struct
struct a {
int
int
} "uap;
register struct

proc "p;
signo;
fun;
user "up;

(up->u uid -- 0 I I
up->u uid - p->p uid I I
up->u=:ruid == p->p_uid II
up->u uid - p->p suid I I
up->u- ruid ~ p->p suid »
i f (a;g > 0) {
up->u_error - EPERM;
return;
} else
continue;

f++;
if (uap->signo)
psignal (p, uap->signo);
if (arg > 0)
break;

up - &u;
uap - (struct a·) up->u_ap;
a - uap->signo;
i f (a <= 0 I I a > NSIG II a -- SIGKILL)
up->u_error - EINVAL;
return;

}

i f (f

~ 0)

up->u_error - ESRCH;
up->u rvall - up->u signal [a-I] ;
up->u-signal[a-l] --uap->fun;
up->uyrocp->p_sig &- - (1L« (a-I» ;
if (a == SIGCLD) !
a = up->uyrocp->pyid;
for (p - &proc [1]; p < (struct proc ") v. veyroc; p++)
i f (a == p->pypid && p->p_stat = SZOMB)
psignal (up->uyrocp, SIGCLD);

times()
(

register struct a {
time_t ("times) [4];
} "uap;
register struct user "up;
time_t loctime[4];
up = &U;
uap - (struct a ")up->u ap;
i f (v.v hz==60) {
-if {copyout( (caddr t) &Up->u utime, (caddr_t)uap->times,
sizeof("uap->times») up->u_error - EFAULT;
SPL7 ();
up->u rtime = lbolt;

i f (uap->fun&l)
up->uyrocp->p_sigign 1= (1<<(uap->signo-l»;
else
up->uyrocp->p_sigign &- - (1« (uap->signo-l) I;

kill(1
!
register struct proc "p, "q;
register argo
register struct a !
int
pid;
int
signo;
) ·uap;
int f;
register struct user "up;

SPLO(I;

} else {
loctime[O] - up->u utime " 60 I v.v_hz;
loctime[l] - up->u-stime " 60 I v.v hz;
loctime[2] - up->u=:cutime " 60 I V.V_hZ;
loctime [3] = up->u cstime " 60 I v. v hz;
if {copyout «caddr-t) &loctime [0], (Caddr_t)Uap->times,
sizeof(loctime» < 01
up->u_error = EFAULT;
SPL7 ();
up->u_rtime = Ibolt"60/v.v_hz;
SPLO ();

up = &u;
uap = (struct a ") up->u ap;
i f (uap->signo < 0 I I u"ip->signo > NSIG) !
up->u_error = EINVAL;
return;

I" Prevent proc 1 (init) from being SIGKILLed "I
i f (uap->signo ~ SIGKILL && uap->pid - 1) {
up->u error - EINVAL;
return;

profil()
{

register struct a {
short
"bufbase;
unsigned bufsize;
unsigned pcoffset;
unsigned pcscale;
} "uap;
register struct user "up;

}

f -

0;

arg - uap->pid;
i f (arg > 0)
p - &proc[I];
else
p - &proc[2];
q - up->uyrocp;
i f (arg - 0 && q->pygrp 0) {
up->u_error - ESRCH;
return;
for (; p < (struct proc ") v. veyroc; p++ 1
i f Ip->p stat -- NULL)
continue;
if larg > 0 " p->p pid !- argl
continue; if (arg - 0 " p->pJ>qrp !- q->pJ>qrp)
continue;
if (arq < -1 " p->pJ>qrp !- -arg)
continue;

up = &u;
uap - (struct a ") up->u ap;
up->uyrof .pr_base = uap->bufbase;
up->uyrof .pr_size - uap->bufsize;
up->uyrof.pr_off - uap->pcoffset;
up->uyrof . pr_scale - uap->pcscale;

1*
" alarm clock signal
*1
alarm()
{

reqister struct proc .p;
register c:

Fri Sep

sys4.c

5 19:08:27 1986

register struct a {
int
deltat;
} "uap;

4

ulimit ()
{

register struct
int
long
} *uap;
register struct
register n, ts;

uap - (struct a *)u.u_ap;
D = u.u Droco;
~ - p->p clktim;
p->p_clktim - uap->deltat;
u.u_rvaI1 = c;

a {
cmd;
arg;
user *up;

up = &u;
uap - (struct a *)up->u ap;
switch (uap->cmd) {
case 2:
if (uap->arg > up->u_Iimit && ! suser (»
return;
up->u_Iimit = uap->arg;
case 1:
up->u roff - up->u limit;
break-;-

I"
" indefinite wait.
* no one should wakeup (&u)
*I
pause()
{

for(;; )
(void) sleep ( (caddr_t) &u, PSLEP);

case 3:

/*
" mode mask for creation of files
*/
umask()

ts - up->u_tsize;
n - maxmem - up->u ssize - v.v_usize;
i f (ts > minmem) n = MAX ( (int)n-ts, (int)minmem-up->u ssize-v.v usize);
n = MlN(n, MAXMEM-stoc(ctos (ts» -stoc(ctos (Up->u_ssize));
up->u_roff = v.v_ustart + ctob(stoc(ctos(ts» + n);
break;

{

register struct a {
int
mask;
) *uap;
register t:
register struct user *up;

default:
up->u_error

up - &u;
uap - (struct a *)up->u_ap;
t = up->u cmask:
up->u cmask - uap->mask & 0777:
up->u:=rvaI1 - t:

=

ElNVAL;

/*
" phys - set up a physical address in user's address space.

*1
phys ()
{

/*
* set lUPD and lACC times on file.

register struct a {
unsigned phnum:
unsigned laddr;
unsigned bcount;
unsigned phaddr;
) *uap;

*1
utime()
(

register struct
char
time_t
) "uap:
register struct
time_t tv[2];

a {
*fname:
*tptr;

1*
(caddr_t) tv, sizeof(tv») {

}

ip - namei(uchar, 0);
i f (ip - NULL)
return:
i f (u.u uid != ip->i uid && u.u uid !- 0)
-if (uap->tptr !- NULL) u. u_error - EPERM;
els.e
(void) access (ip, IWRITE);
}

J

iput (ip) ;

" reboot the system
*/
reboot ()
{

} else {
tv[O] - time:
tv[l] = time;

if (!u.u error)
Ip->i flag 1- lACC 1 lUPD 1 ICHG:
iupdat (ip, &tv[O], &tv[l]);

/* logical address * /
/ * byte count * /
/* physical address */

if (! suser () return:
uap = (struct a *)u.u ap;
dophys (uap->phnum, uap->laddr, uap->bcount, uap->phaddr);

inode *ip;

uap = (struct a ")u.u_ap;
i f (uap->tptr != NULL) {
if (copyin( (caddr t)uap->tptr,
u.u_error-= EFAULT;
return;

I" phys segment number */

register i;
update ():
for (i = 0:
doboot () ;
{

< 1000000; i++)

sysent.c

Fri Sep

5 19:08:04 1986

1* @(tlsysent.c 1.3 *1
iinclude "sys/param.h"
tinclude ·sys/types. h"
tinclude • sys/ systm. h"

1*

* This table is the switch used to transfer
" to the appropriate routine for processing a system call.
*I

int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int
int

alarm(l;

int
int
int
int
int
int
tendif

chmod() ;
chown() ;
chroot() ;
close() ;
creatO;
dup() ;
exec() ;
execeO;
fcntl ();
forkO;
fstat{) ;
getgid() ;
getpidO;
getuid() ;
gtime() ;
gttyO;
ioctl (I;
kill ();
link() ;
lock() ;
mknod(l;
msgsys() ;
nice() ;
nosys() ;
nullsysO;
open() ;
pause() ;
pipe ();
profil(l;
ptrace{) ;
read() ;
rexit 0;
saccess() ;
sbreak() ;
seek() ;
semsys() ;
setgid() ;
setpgrp() ;
setuid() ;
shmsys 0;
smount() ;
ssig() ;
stat () ;
stime ();
sttyO;
sumount() ;
sync() ;
sysacct ();
times() ;
ulimit ();
umaskO;
unlink() ;
utime ();
utssys ();
wait 0;
write 0;

sconnect () ;
saccept() ;
ssendO;
sreceive 0 ;
ssocketaddr () ;
netreset () ;

/"
* Local system calls
*/
int
int
int

c...l:!dir() :

tifdef UCB NET
tinclude ..r;-et/misc.h"
1* net stuff */
int
select () ;
int
qethostname ( ) :
int
sethostname ( ) ;
int
ssocket () ;

1

locking() ;
phys ();
reboot() ;

struct sysent sysent [1

=

{

I * not implimented for character devices yet * I

nosys,
rexit,
fork,
read,
write,
open,
close,
wait,
creat,
link,
unlink,
exec,
chdir,
gtime,
mknod,
chmod,
chown,
sbreak,
stat,
seek,
getpid,
smount,
sumount,
setuid,
getuid,
stilne,
ptrace,
alarm,
fstat,
pause,
utime,
stty,
gtty,
saccess,
nice,
nosys,
sync,
kill,
nosys,
setpgrp,
nosys,
dup,
pipe,
times,
profil,
lock,
setgid,
getgid,
ssig,
msgsys,
nosys,
sysaoct,
shmsys,
semsys,
ioctl,
phys,
locking,
utssys,
nosys,

/*
1*
/*
/"
/*
/*
/"
/*
/*
/*
/*
/"
/*
/*
/*
/*
/*
/*
/*
/*
/*
/"
/*
/
/*
/*
/*
/"
/*
/*
/*
/*
1*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

..

/*
/*
/*
/*
/*
/*

/*
/*
/*
/*
/*
/*
/*
1*
/*

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

55
56

57
58

= indir *1
- exit */
= fork */
= read */
~ write .. /
- open */
= close */
= wait */
- creat */
- link */
= unlink ,,/
= exec */
- chdir ,,/
~ time */
- mknod */
~ chmod */
= chown; now 3 args */
~ break */
- stat */
= seek */
- getpid */
= mount */
= umount */
= setuid */
- getuid */
= stilne * /
= ptrace */
= alarm */
- fstat */
- pause */
= utilne * /
- stty "/
- gtty *1
- access */
= nice */
= sleep; inoperative */
= sync */
~ kill *1
- x */
- setpgrp * /
= tell - obsolete */
= dup */
- pipe */
- tilnes * /
- prof */
- proc lock * /
- setgid * /
- getgid */
- sig */
- IPC Messages *1
- reserved for local use */
- turn acct off/on */
- IPC Shared Memory * /
- IPC Semaphores */
- ioetl *1
- phys */
- file locking */
- utssys *1
- reserved for USG *1

sysent.c
exece,
umask,
chroot,
fcntl,
ulimit,
reboot,
nosys,
nosys,
nosys,
nosys,
nosys,
Hfdef UCB_NET
select,
gethostname,
sethostname,
ssocket,
saccept,
sconnect,
sreceive,
ssend,
ssocketaddr,
netreset,
telse
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
iendif UCB_NET
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nos,Ys,

Fri Sep

5 19:08:04 1986
exece *1
umask *1
chroot *1
fcntl */
ulimit */

1*
1*
1*
1*
1*

59
60
61
62
63

-

/*
/*
/*
1*
/*
1*

64
65
66
67
68
69

= reboot */
- x */
= x */
~ x
"/
- x "/
- x *1

I"
/*
1*
/*
/"
/*
/*
/"
1*
/*

70 = select */
71 - gethostname *1
72 = sethostname */
73 = socket */
74 - accept */
75 = connect */
76 = receive *1
77 ~ send *1
78 = socketaddr *1
79 = netreset */

/*
/*
/"
1*
/*
/*

70
71
72
73
74
75
76
77
78
79

/*

/*
/*
/*
/*
/*
1*
/*
/*
/*
/*
/*
/*
1*
1*
1*
1*
/*
/*
1*
/*
1*
/*
1*
1*
/*
/*
1*
1*
/*
1*
/*
/*
1*
/*
/*
/*
/*
1*
1*
/*
1*

=

- x */
- x */
= x */
= x *1
= x */
- x */
- x "/
= x */
= x */
= x */

80 - x */
81 - x *1
82 = x *1
83 = x *1
84 = x *1
85 = x */
86 = x */
87 - x */
88 = x */
89 = x */
90 - x *1
91 - x * /
92 = x */
93 - x *1
94 - x */
95 - x */
96 = x *1
97 = x *1
98 - x *1
99 - x "/
100 - x */
101 - x */
102 = x *1
103 - x */
104 ~ x */
105 - x *1
106 - x *1
107 - x */
108 - x *1
109 - x *1
x *1
110
111 - x */
112 = x *1
~

113 - x *1

114
115
116
117

x
x
x
x
118 - x
1* 119 - x
1* 120 - x

'*

2

-

*1
*1
*/
*/
*/

*1
*/

nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
nosys,
);

1*
/*
1*
1*
1*
1*
I"

121 ~ x *1
122 ~ x */
123 - x */
124 - x */
125 = x *1
126 = x */
127 = x "I

Fri Sep

syslocal . c"
finclude
finclude
Hnclude
Unclude
Hnclude
tinclude
finclude
Hnclude
Unclude
Hnclude
Hnclude
#include
Hnclude
finclude
Hnclude
Hnelude
Hnclude
finelude
finclude
tinclude
finclude
Hnclude
Hnclude
tinclude
Hnclude
tinclude
Hnelude
Hnclude
finclude

5 19:09:21 1986

1
*/

"sys/param.h"
"sys/config .h M
"sys/types. h"
"sys/mmu. h"
"sysl sysmacros .h"
·sys/dir .h"
"sys/proc.h H
"sys/seg.h"
·sysl signal.h"
·sys/errno.h"
·sys/user.h"
"sys/systm.h"
"sys/inode.h"
·sys/ino.h"
"sys/file.h"
"sys/conf.h"
"net/misc. hit
"net/protosw.h"
"netl socket. h"
"net/socketvar .h"
"net/ubavar. hOI
"sys/map.h lt
"sys/callo.h"
"net/if .h"
"net/in.h"
"net/in_systm.h"
"net/ip.h"
"net/ip_var .h"
"sys/var .h"

(

extern int tcp_sendspace, tcp_recvspaee;
tcp_sendspace - tcp_recvspace

=

1024;

fendif
}

/* netreset -- network reset system call */
/* 3/23/83 billn: doesnt quite work yet *1
netreset()
(

register wait - 100000;
register s ~ spl6 () ;
register struct file *fp;
extern int netisr;
netoff = 1;
netisr - 0;

/* prevent net traffic (during resets) */

1* unbeknownst sockets to UNIX * /
for (fp = &file [0]; fp < (struct file

*) v. ve_file; fp++) {
if «fp->f_flag & FSOCKET) && fp->f_count) (
bzero «char *) fp, sizeof (struct file»;

/*
secs id @(t)syslocal.c

1.6 (Berkeley)

2/27/82

*1
/*

* These routines implement local system calls

mbinit ();
fifdef IRET
ifinit ();
pfinit ();
fendif
splx(s) ;
while (wait--);
netoff = 0;

/* relink mbufs

*/

/* re-init interfaces */
1* must follow interfaces */
/* wait for pending ints. * /
/* allow traffic */

*/

splimp()
(

return spl6 () ;
short
int
int
int
int
char
char *

netoff = 0;
protoslow;
protofast;
ifnetslow;
nselcoll;
netstak[3000] ;
svstak:

spInet ()
(

return spl6 () ;

/* stack when system is "in the network" (mch.s) *1
/ * globle where mch. s saves current stack * /
/*

*/
netinit ()

* Entered via software interrupt vector at spl1.
* for tasks requesting service.
*/
netintr()

(

{

/*

*

Initialize network code.

Called from main 0 .

extern struct uba device ubdinit [] ;
register struct uba_driver *udp;
register struct uba_device *ui = &ubdinit[O];
if (netoff) return;
mbinit 0;
for(ui - &ubdinit[O] ; udp - ui->ui driver
/* ud probe could go here */
ui->ui-alive - 1;
udp->ud dinfo [ui->ui unit] - ui;
(*Udp->;:;:d_attach) (ul);

Check netisr bit array

register int onetisr;

ui++) {

Hfdef INET
loattach () ;
/* XXX */
ifinit ();
pfinit ();
/* must follow interfaces *1
tendif
tifdef TCPACKMOST
/*
• Fool some systems into thinking that tcp maxseg -- sbspace -* max window. Ergo, force acking of most packets when talking "c.o
* (the vax)

while (spl 7 ( ) , (onetisr - neti sr) )
netisr - 0;
(void) spInet () :
if (onetisr & (l«NETISR RAW»
rawintr () ;
if (onetisr & (1«NETISR IP»
ipintr();
if (protofast <- 0) (
protofast - HZ
PR_FASTHZ;
pffasttimo() ;
if (protoslow <- 0) (
protoslow - HZ
pfslowtimo () ;

PR_ SLOHHZ;

)

if (ifnetslow <- 0) {
ifnetslow - HZ
if_slowtimo () ;

IFNET_SLOWHZ;

Fri Sep

syslocal.c

5 19:09:21 1986

2
splx(s) :
goto done;

enprint

int

=

rem ~ rem*v.v hz;
timeout (setrun, (caddr_t) u. uyrocp, rem);

1* enable nprintf *1

0:

)

sleep ( (caddr t) &selwait, PZERO+l);
i f (rem) { bcopy( (caddr_t) lqsav, (caddr_tlu. u_qsav, sizeof (label_t»;
rm_callout(setrun, (caddr_t)u.uyrocp);

1*
* net printf.

prints to net log area in memory (nlbase, nlsize).

*1
1* VARARGSI *1
nprintf (fmt, xl)
char *fmt:
unsigned xl:

splx(s) ;
goto retry;
done:

{

if (enprint

rd.fds bits[O] - readable;
wr. fds-bits [0] = writeable;
u.u rvall = nfds;
i f (ap->rp)
(void) copyout( (caddr_t) &rd, (caddr_t)ap->rp, sizeof(fd_set»;
i f (ap->wp)
(void) copyout( (caddr_t) &wr, (caddr_t)ap->wp, sizeof(fd_set»:

0) return;

1* billn -- do regular printf for now
prf (fmt, &xl, 4);

*1
printf (fmt, xl);

1*

*

Select system call.

1*

*1

* remove entry in callout vector
* which is scanned by clock interrupt

select ()
{

register struct uap
int
nfd;
fd_set *rp, *wp;
long
time;
*ap ~ (struct uap *)u.u_ap;
fd set rd, wr;
int nfds = 0;
long selscan () ;
extern setrun () :
long readable - 0, writeable = 0:
time t t - time;
int ;, tsel, ncoll, rem:
label_t lqsav;

*1
rm callout (func, arg)
int (*func) ();
caddr_t arg;
{

register struct callo *pl, *p2;
register int tt:
int pri;
pI - &callout [0] ;
pri - spl? () ;
while (pl->c func ! - 0) {
i f «pl->c func ~ func) && (pl->c_arg
break;
pl++;

i f (ap->nfd > NOFILE)
ap->nfd - NOFlLE;
i f (ap->nfd < 0) {
u.u_error = EBADF;
return;

-= arg»

if (pI >- (struct callo *)v.ve_call-l) {
printf("Timeout entry not found, not deleted\n");
return;

)

}

if (ap->rp && copyin( (caddr_t)ap->rp, (caddr_t)&rd,sizeof(fd_set»)
return;
if (ap->wp && copyin«caddr t)ap->wp, (caddr t)&wr,sizeof(fd set»)
r~urn;
-

1* copy everything that follows in the list up one
position, adding our unused time to theirs *1

retry:
ncoll = nselcoll;
u. u procp->p flag I ~ SSEL;
i f (ap->rp) readable - selscan (ap->nfd, rd, &nfds, FREAD);
i f (ap->wp)
writeable = selscan(ap->nfd, wr, &nfds, FWRITE);
if (u. u error)
-goto done;
if (readable I I writeable)
goto done:
rem - (ap->timo+999) 11000 - (time - t);
i f (ap->timo -- 0 I I rem <= 0)
goto done;
s = spl6();
if «u.u procp->p flag & SSEL) - 0 II nselcoll !- ncoll)
"ii.uyrocp=>p_flag &- -SSEL;
splx(s);
goto retry;

tt - pl->c_time;
p2 - pI;
while(pl->c_func !- 0) {
p2++;
pl->c time - p2->c time + tt;
pl->c=:func - p2->c=:func;
pl->c arg - p2->c arq;
pI -

p2;

-

)

splx(pri) ;

long
selscan (nfd, fds, nfdp, flag)
int nfd;
fd set fds;
int *nfdp, flag;
{

u. uyrocp->p_flag &- -SSEL;
i f (rem) {
bcopy( (caddr t)u.u qsav, (caddr_t)lqsav, sizeof (label_t»;
if (save(u.u-qsav») {
rm_callout (setrun, (caddr_tl u. u_procp);
'.l.u_error - EINTR;

struct file *fp;
struct inode *ip;
lonq bi ta. res - 0;
int i, able;
bits - fds. fds bits [0] ;
while (i - ffs(bits»
{
i f (i >- nfd)
break;
bits &- -(lL«(i-l));

syslocal. c'

Fri Sep

5 19:09:21 1986

3

fp = u.u ofile[i-l];
if (fp .,;: NULL) {
u . u error - EBADF;
return (0);

dev t dev;
int-flag;

return (1);
i f (fp->f_flag & FSOCKET)
able = soselect « struct socket *) fp->f_socket, flag);
else {
ip = fp->f inode;
switch (ip=>i_mode & IFMT) {

}

tendif
selwakeup(p, call)
register struct proc *p;
int call;

case IFCHR:
Hfdef notdef

int s;
able (*cdevsw [major (ip->i rdev)]. d select)
«int) ip->i_rdev~ flag); -

i f (call)
nselcoll ++;
wakeup ( (caddr_t) &selwait);

felse

/*
* for now the only char device we need
* to select on is the control side of
* ptys -- for the rlogin deamon. At
* some point someone can put general
* select code into all char. devices.
*/

s - spI6();
i f (p) {
if (p->p wchan (caddr t) &selwait)
setrun (p) ;
else {
i f (p->p flag & SSEL)
p->p_flag &- -SSEL;

{

extern int ptc_ dev;
if (major ( lint) (ip->i rdev» =- ptc dev)
able - ptcselect «int) ip->i_rdev, flag);
else
able = 0;
tendif
break;

splx(s) ;

Hfdef notdef
/ * ARGSUSED * I
nulselect (x, y)
{

return 0;
case
case
case
case

IFIFO:
IFBLK:
IFREG:
IFDIR:
able - 1;
break;

}

tendif
char
int

hostname [32] = "hostnameunknown";
hostnamelen = 16;

gethostname ()
{

if (able)
res I- (IL«(i-I»;
(*nfdp)++;

register struct a {
char
*hostname;
int
len;
*uap - (struct a *)u.u_ap;
register int len;

return (res);
len = uap->len;
if (len> hostnamelen)
len = hostnamelen;
if (copyout «caddr_t)hostname, (caddr_t) uap->hostname, len»
u.u_error - EFAULT;

ffs(mask)
long mask;
register int i;
register imask;

sethostname ()
if (mask - 0) return (0);
imask - loint (mask) ;
for(i=l; i<-16; i++) {
if (imask & 1)
return (i);
imask »- 1;

{

register struct a {
char
*hostname;
int
len;
*uap - {struct a ")u.u_ap;
if

suser () )
return;
if (uap->len > sizeof (hostname) - 1) {
u. u error - EINVAL;
return;

imask = hUnt (mask) ;
for (; i<-32; i++) {
if (imask & 1)
return (i);
imaak »- 1;
return (0);
Hfdef notdef
/ *ARGSUSED* /
seltrue (dev, :lag)

(!

hostnamelen - uap->len;
if (copyin( (caddr_t)uap->hostname, hostname, uap->len + 1»
u.u_error - EFAULT:

/* can't get here anyway! */

/*

syslocal.6

Fri Sep

Some misc. subroutines.

5 19:09:21 1986

Prob should be in a sep module

4
/*

bzero(p,n) -- zero n bytes starting at p */

*/
Hfdef notdef
/* system 3 has it's own */
/*
* Provide about n microseconds of delay
*/
delay(n)
long n;

bzero(p,n)
register char
register n;

*

p;

{

i f (n)

do {

{

*p++ - 0;
) while (--n);

register hi, low;
low = (n&0177777);
hi = n»16;
if (hi-=O) hi=l;
do {
do { } while (--low) ;
} while (--hi);

/*
*

iomalloc -- allocate clks of memo for io.
Right now, no dma.

*/
mbioalloc (I
{

return 0;

)

tendif

/*
" compare bytes; same result as
*/
bcmp(sl, s2, n)
register char *sl, *s2;
register n:

/*

VAX

cmpc3.

* mballoc should be combined with/done like memapO. THIS STUFF DEPENDS
* ON MSIZE BEING A POWER OF 2.
*/
tdefine MBUFCONFIG 1
/* undef extern of Mbuf, mbuf "/
tinclude 

{

do

char

if(*sl++ l= *s2++) break;
while (--n) ;
return(n) ;

struct mbuf *
mballoc()

mbufbufs [ (NMBUFS+l) *MSIZE);

{

unsigned int location - (unsigned intI (&mbufbufs (0);
int slop = location & (MSIZE-l);

/*
" Insert an entry onto queue.
*/
insque (e, prev)
register struct vaxque *e, "prev;
register x - spl7 () ;
e->vqJ)rev = prev;
e->vtL-next = prev->vtL-next ;
if (prev->vtL-nextl
prev->vtL-next->vqJ)rev
prev->vtL-next - e;
splx(x) ;

=

/* round actual buffers to MSIZE boundry */
return «struct mbuf*1 (location + MSIZE - slop»;

e;

/*
" Remove an entry from queue.
*/
remque(el
register struct vaxque *e;
register x

=

sp17 () ;

e->vtL-prev->vtL-next - e->vtL-next;
if (e->vtL-next)
e->vtL-next->vqJ)rev - e->vqJ)rev;
splx (x) ;

struct proc "
pfind (pid)
int pid;
register struct proc *p;
for (p-proc; p < 'proc [v. v proc); p++)
i f (p->pyid -- pidl
return (p);
return ((struct proc *10);

Fri Sep
/*

tcp_debug.c

82/03/29

4.3

5 19:09:37 1986

if (act

*/

tinclude ·sys/param.h"
tinclude "sys/config.h"
tinclude "sys/errno.h"
-tinclude .. sys/types. h"
tinclude ·sys/systm.h"
tinclude "net/misc. hOI
tinclude "net/mbuf.h"
tinclude "net/ socket. h"
tinclude "net/socketvar.h"
tdefine PRUREQUESTS
tinclude "net/protosw.h"
tinclude "net/in.h"
tinclude "net/route.h"
tinclude "net/inJ>Cb.h"
tinclude "net/in systm. h"
tinclude "net/if-:-h"
tinclude "net/ip.h"
tinclude "net/ip var.h"
tinclude "net/tcp.h"
tdefine TCPSTATES
tinclude "net/tcp fsm.h"
tinclude "net/tcp-seq.h"
tdefine TCPTIMERStinclude "net/tcp timer .h"
tinclude "net/tcp-var.h"
tinclude "net/tcplp.h"
tdefine TlINAMES
tinclude "net/tcp debug .h lO
tinclude "errno.h"

~

TA_OUTPUT) {
seq = ntohl I seq) ;
ack - ntohl lack) ;
len = ntohs I lu_short) len);

tendif
if (act = TA OUTPUT)
len -:: sizeof (struct tcphdr);
if (len)
printf(" ['lox .. %x)", seq, seq+len);
else
printf("%x", seq);
printfl"@%x", ack);
flags = ti->ti flags;
if (flags) { Hfndef lint
char *cp - "<";
tdefine pf(f) { if (ti->ti flags&TH I""/f) { printf("%s%s", cp, "f"); cp
pf(SYN); pf(ACK): pf(FIN): pf(RST):
tendif
printf (">") ;

=

break;
ca se TA USER:
- printf ("'los", prurequests [req&Oxff] ) ;
if «req & Oxff) = PRU SLOWI'IMO)
printf("<%s>", tcptimers[req»8]);
break:

int
tcpconsdebug = 1;
/*
" Tcp debug routines
*1
tcp_trace (act, ostate, tp, ti, req)
short act, ostate;
struct tcpcb *tp;
struct tcpiphdr *ti;
int req;
tcp seq seq, ack;
int-len, flags;
struct tcp_debug *td

1

=

&tcp_debug[tcp_debx++];

i f (tcp_debx = TCP_NDEBUG)
tcp debx ~ 0;
td->td time- - iptime ( ) ;
td->td=:act = act;
td->td ostate - ostate;
td->td-tcb = {caddr t)tp;
if (tP)
-

else
bzero«caddr_t)&td->td_cb, sizeof (*tp»;
i f (ti)

else
bzero «caddr t) &td->td ti, sizeof (*ti»:
td->td_req - req;
if (tcpconsdebug - 0)
return:
if (tp)
printf ("'lox 'los: H, tp, tcpstates [ostate]) :
else
printf ("11111121 "):
printf("%s ", tanames[act]);
switch (aet) f
case TA_INPUT:
case TA_OUTPUT:
seq - ti->ti seq
ack - ti->ti-ack
len - ti->t(:len
Jlifndef WATCHOUT

i f (tp)
printf(" -> %SU, tcpstates[tp->t state]);
1* print out internal state of tp ! 1! * /printf("\n") ;
i f (tp = 0 II tcpconsdebug - 2)
return;
printf("\trcv (nxt,wod) ('lox, 'lox) snd (una,nxt,max) (%x,%x,%x)\n",
tp->rcv riXt, tp->rcv wod, tp->sii:d una, tp->snd nxt, tp->snd_max);
printf(U\tsii:d (wll,w12,wnd) ('lox, 'lox, %x)\n U,
tp->snd_wll, tp->snd_w12, tp->snd_wod);

)

)

Fri Sep
%M%

1*

%1%

%E%

5 19:09:39 1986

1

*1
1*

tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
Hnclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
.finclude
tinclude
tinclude
tinclude
tinclude
tinclude
int
short
struct
struct
extern

"sys/param.h"
"sys/config .h"
"sys/errno.h"
"sys/types .h"
"sys/systm.h"
"net/misc.h"
"net/mbuf. hOI
"net/protosw.h"
"netl socket. h U
"netl socketvar. h"
"net/in.h"
"net / route. h II
"net/inycb.h"
"net/in_systm.h"
"net/if.h"
"net/ip.h"
"net/ip_var.h"
"net/tcp.h"
Rnet/tcp_fsm.h"
"net/tcp_seq.h"
"net/tcp_timer. hOI
"net/tcp_var.h n
"net/tcpip. h II
"net/tcp_debug .h"
"errno.h"

tcpprintfs - 1; 1* l=print, 2- panic *1
tcpcksum = l;
sockaddr in tcp in ~
AF_lNET);
tcpiphdr-tcp saveti;
tcpnodelack;-

struct tcpcb *tcp_newtcpcbO;
1*
* TCP input routine, follows pages 65-76 of the
" protocol specification dated September, 1981 very closely.
*1
tcp input (mO)
register struct mbuf "mO;

* Checksum extended TCP header and data.
*1
tlen - «struct ip *)til->ip len;
len - sizeof (struct ip) + tlen:
1*
if «tlen > 576) II (len> 7001 I
printf ("len-%d, tlen-%d !!! \n", len, tlen);
*1
if (tcpcksum) {
register sum;
ti->ti_next - ti->tiyrev = 0;
ti->ti xl ~ 0:
ti->ti-len - (u short)tlen;
tifndef WATCHOUT
ti->ti_len = htons «u_short) ti->ti_len);
tendif
mbprint (m, -tin before Ck");
nprintf ("len%o\n", (unsigned) len) ;
1*
if (len ~ 40)
lint i; int j; printf("segment:\n");for(j=0;j<4;j++) {for (i-O;iti_sum - in_cksum(m, len» {
*I
if (sum = in cksum(m, len»
(
npriiitf("badsum%o\n", ti->ti sum);
tcpstat. tcps badsum++;
if (tcpprintfs)
/*
printf("tcp cksum 'lox, length 'lod, loca 'lox\n",ti->ti_sum,len,ti);
*1
printf ("tcp cksum 'lox, length 'lid, loca %x\n", sum, len, til ;
if (len = 40)
lint i; int j; printf("segment:\n") ;for(j=0;j<4;j++) {for (i=O;iip hl > (sizeof (struct ipl »211
ip_stripoptions «~truct ip *Iti, (struct mbuf "101;
if (m->m_off > MMAXOFF II m->m_len < sizeof (struct tcpiphdr»
i
if «m - m pullup(m, sizeof (struct tcpiphdr) I I -- 01 {
tcPstll:t . tCp9_ hdrops++:
tifdef SIGH
intcpinput-- ;
tendif
return;
}

* Check that TCP offset makes sense,

*

pullout TCP options and adjust length.
*/
off = ti->ti off « 2;
if (off < sizeof (struct tcphdr) I I off > tlen) {
tcpstat. tcps_ badoff++;
goto drop;
tlen -- off;
ti->ti len - tlen;
if (off> sizeof (struct tcphdr»
i f «m - lllJlullup(m, sizeof (struct ip) + off»
tcpstat. tcps_ hdrops++;
tifdef SIGH
intcpinput-- ;
tendif
return;

~

01 {

ti - mtod (m, struct tcpiphdr * I ;
om - m get (M DONTWAITI;
if (om--- 0)goto drop;
om->m off ~ MMINOFF:
om->m-len - off - sizeof (struct tcphdrl;
{ caddr t op - mtod(m, caddr t) + sizeof (struct tcpiphdrl;
MBCOPY(m, sizeof(struct tcpiphdrl, om, 0, om->m len);
m->lIl...-len -- om->m_len;
bcopy (op+om->m len, op,
(intI (m->m_len-sizeof (struct tcpiphdr»):
}

tiflags - ti->ti_flags;

ti - mtod 1m, struct tcpiphdr *):

1*

Fri Sep
*

5 19:09:39 1986

2
if (tiflags , TH RST)
goto drop;
if (tiflags & TH ACK)
goto dropwithreset;
if «tiflags & TH_SYN) - 0)
got a drop;
tcp in. sin addr = ti->ti src;
tcp:)n. sinyort - ti ->ti sport;
laddr - inp->inp laddr;
if (inp->inp laddr.s addr ~ 0)
inp->inp laddr - ti->ti dst;
if (in pcbconnect (inp, (struct sockaddr in *) &tcp_in»
- inp->inp laddr - laddr;
goto drop;

Drop TCP and IP header s .

*1
m->m_off +- sizeof(struct tcpiphdr);
m->m_len -- sizeof(struct tcpiphdr);
tifndef WATCHOUT

1*

=

* Convert TCP protocol specific fields to host format.
*1
ti->ti_seq
ti->ti ack
ti->ti=win
ti->ti_urp

-

ntohl (ti->ti_seq);
ntohl(ti->ti ack);
ntohs (ti->ti=win);
ntohS(ti->ti_urp);

tendif

tp->t template = tcp template (tp) ;
if (tp->t template":: 0) (
i~J>Cbdisconnect (inp) ;
inp->inp laddr = laddr;
tp = 0; goto drop;

1*

* Locate pcb for segment. On match, update the local
* address stored in the block to reflect anchoring.
*1
inp - inJ>Cblookup
(&tcb, ti->ti src, ti->ti sport, ti->ti_dst, ti->ti_dport,
INPLOOKUp_Wn,DCARD);
-

tp->iss = tcp iss; tcp iss += TCP_ISSINCR/2;
tp->irs = ti->ti seq; tcp sendseqinit (tp);
tcp-rcvseqinit (tp);
tp->t state = TCPS SYN RECEIVED;
tp->t-timer[TCPT KEEP]-= TCPTV KEEP;
goto trimthenstep6;
-

1*

* If the state is CLOSED (i.e., TCB does not exist) then
* all data in the incoming segment is discarded.
*1
if (inp - 0)
goto dropwithreset;
tp - intotcpcb(inp);
if (tp = 0)
got a dropwithreset;
so - inp->inp socket;
if (so->so options & SO DEBUG)
ostate - tp->t state;
tcp_saveti - *ti;

1*

* Segment received on connection.

*

Reset idle time and keep-alive timer.

*1
tp->t idle = 0;
tp->t=timer[TCPT_KEEP] = TCPTV_KEEP;

1*

* Process options.
*1
if

(om)

tcp dooptions (tp, am);
om -= 0;

1*
* If the state is SYN SENT:
if seg contains an ACK, but not for our SYN, drop the input.
if seg contains a RST, then drop the connection.
if seg does not contain SYN, then drop it.
" otherwise this is an acceptable SYN segment
initialize tp->rcv nxt and tp->irs
if seg contains aCk then advance tp->snd una
if SYN has been acked change to ESTABLISHED else SYN_RCVD state
arrange for segment to be acked (eventually)
continue processing rest of data/controls, beginning with URG
*/
case TCPS SYN SENT:
if «tiflags & T~ACK) &&
/* this should be SEQ LT; is SEQ LEQ for BBN vax TCP only ,,/
(SEQ LT (ti->ti ack, tp->iss) 11
SEQ- GT (ti->ti-ack, tp->snd max»)
goto dropwlthreset;
if (tiflags & TH RST) (
if (tiflags & TH ACK) (
tcp_drop(tp, ECONNREFUSED);
tp - 0;

/*

got a drop;

* Calculate amount of space in receive window,
" and then do TCP input processing.

if «tiflags & TH SYN)
0)
got a drop;
tp->snd una - ti->ti ack;
if (SEQ- LT (tp->snd nit, tp->snd una»
-tp->snd nxt = tp->snd u~a;
tp->t timer[TCPT REXMT] = 0; tp->irs - ti->ti-seq;
tcp rcvseqinit (tP) ;
tp->t flags 1- TF ACKNOW;
if (SEQ GT (tp->snd una, tp->iss»
-if (So->so-options & SO ACCEPTCONN)
so-=>so state 1--SS CONNAWAITING;
soisconnected(so);
tp->t state - TCPS ESTABLISliED;
(void) tcp_reass (tp, (struct tcpiphdr *) 0)
I else
tp->t state - TCPS_SYN_RECEIVED;
got a trimthenstep6;

*/
tp->rcv wnd - sbspace (&so->so rcv);
if (tp->rcv_wnd < 0)
tp->rcv_wnd - 0;
switch (tp->t_state)

1*
" If the state is LISTEN then ignore segment if it contains an RST.
* If the segment contains an ACK then it is bad and send a RST.
* If it does not contain a SYN then it is not interesting; drop it.
* otherwise initialize tp->rcv_nxt, and tp->irs, select an initial
* tp->iss, and send a segrQ.ent:

* Also initialize tp->s~d nxt to tp->iss+1 and tp->snd una to tp->iss.
* Fill in remote peer address fields if not previou91y-specified.
" Enter SYN_RECEIVED state, and process any other fields of this
" segment in this state.

*;
case TCPS_LISTEN:

(

t.rim"henst.ep6 :

1*

:

Fri Sep

5 19:09:39 1986

3

*
*

Advance ti->ti seq to correspond to first data byte.
If data, trim to stay within window,
" dropping FIN if necessary.

/*

* If a segment is received on a connection after the

*/

*

ti->ti seq++:
if (ti=>ti len> tp->rcv wnd)
todrop - ti->ti len - tp->rcv_wnd:
m adj (m, -todrop):
tI->ti len - tp->rcv wnd;
ti->ti~)lags &= -TH_FIN;
tp->snd_wll
goto step6:

=

user processes are gone, then RST the other end.

*1
if «so->so state & SS_USERGONE)
ti->ti len) {
tcp close (tp) :
tp:: 0:
goto dropwithreset;

&&

tp->t_state > TCPS_CLOSE_WAIT

&&

ti->ti_seq - 1;

1*

*

/*
w states other than LISTEN or SYN_SENT.
* First check that at least some bytes of segment are within
" receive window.
*/
i f (tp->rcv wnd = 0) {
/* * If window is closed can only take segments at
* window edge, and have to drop data and PUSH from
* incoming segments.

*1
if (tiflagS&TH_RST) switch (tp->t_state)
case TCPS SYN RECEIVED:
if (inp->inp socket->so options & so ACCEPTCONN) {
/* a-miniature tcp close, but invisible to user *1
i f (tp->t_templatel MSFREE (tp->t_template);
MSFREE (tp) ;
inp->inpypcb = 0;
tp - tcp newtcpcb(inp):
i f (tp
0) {
1* unlikely but just in case */
tcp drop(tp, ENOBUFS);
tp :: 0:
goto drop;

*/
if (tp->rcv nxt != ti->ti seq)
goto dropafterack:
if (ti->ti len> 0) {
m ;dj (m, ti->ti len);
tI->ti len - 0;ti->t(~flags &= -(TH_PUSHI TH_FIN) ;

-=

J
J else I
/*
" If segment begins before rcv nxt, drop leading
* data (and SYN); i f nothing left, just ack.
*/
todrop - tp->rcv_nxt - ti->ti_seq;
if (todrop > 0) {
i f (tiflags & TH SYN) {
tiflags &= -TH SYN:
ti->ti flags &:: -TH SYN:
ti->ti-seq++;
i f (ti=>ti urp > 1)
ti=>ti_ urp--;
else
tiflags &= -TH_URG;
todrop--;
i f (todrop > ti->ti len I I
todrop = ti->tI len && (tiflags&TH_FIN) ~
goto dropafterack:
m adj (m, todrop);
tI->ti seq +- todrop:
ti->ti-len -- todrop:
i f (ti=>ti urp > todrop)
ti=>ti_urp -- todrop:
else {
tiflags &- -TH URG;
ti->ti flags ,:: -TH URG;
ti->t(:urp - 0;
-

tp->t state = TCPS LISTEN;
inp->Inp faddr.s addr = 0:
inp->inp-fport =-0;
inp->inp.)addr. s_addr = 0;
tp = 0:
goto drop:

1* not quite right */

tcp drop (tp, ECONNREFUSED):
tp:: 0:
goto drop:

0)

/*

* If segment ends after window, drop trailing data

*

If the RST bit is set examine the state:
SYN_RECElVED STATE:
If passive open, return to LISTEN state.
If active open, inform user that connection was refused.
ESTABLISHED, FIN WAIT 1, FIN WAIT2, CLOSE WAIT STATES:
Inform user that connection was reset, ;nd close tcb.
CLOSING, LAST ACK, TIME_WAIT STATES
Close the tCb.

(and PUSH and FIN): i f nothing left, just ACK.

*/
todrop - Cti->ti seq+ti->ti len) - (tp->rcv_nxt+tp->rcv_wnd):
if (todrop > 0) T
if (todrop >- ti->ti_len)
goto dropafterack;
m adj (m, -todrop):
tI->ti len -- todrop:
ti->ti~)laqs &- -(TH_PUSHITH_FIN):

case
case
case
case

TCPS_ESTABLISHED:
TCPS_FIN_WAIT_l:
TCPS_FIN_WAIT_2:
TCPS CLOSE WAIT:
tcp_drOp(tp, ECONNRESET);
tp = 0:
goto drop;

case TCPS_CLOSING:
case TCPS_LAST_ACK:
case TCPS_TlME_WAIT:
tcp close (tp) ;
tp :; 0:
goto drop:

1*

*
*

If a SYN is in the window, then this is an
error and we send an RST and drop the connection.

*1
i f (tiflaqs , TH SYN) I
tcp drop(tp, ECONNRESET);
tp :: 0:
goto dropwithreset:

1*

* If the ACK bit is off we drop the segment and retT:::l.

Fri Sep

5 19:09:39 1986

4
if (acked > so->so snd. sb cc) (
sbdrop(&so=>so snd, so->so snd. sb cc):
tp->snd wnd -=-so->so snd.sb cc; ) else ( -sbdrop(&so->so_snd, acked):
tp->snd wnd -- acked:
acked --0:

*1
i f «tiflags & TH_ACKI =
goto drop;

0)

1*

*

Ack processing.

*1
switch (tp->t_state)

if «so->so snd.sb flags & SB_WAIT) II so->so_snd.sb_sel)
sowakeup(so) ;
tp->snd una - ti->ti ack:
i f (SEQ-LT(tp->snd nit, tp->snd una»
-tp->snd_nxt = tp->snd_una:

1*

*
*

In SYN_RECElVED state if the ack ACKs our SYN then enter
ESTABLISHED state and continue processing, othewise

* send an RST.
*1
case TCPS SYN RECEIVED:
if (SEQ GT(tp->snd una, ti->ti ackl II
SEQ-GT(ti->ti ack, tp->snd-max»
- goto dropwithreset;
tp->snd una++;
1* SYN acked *1
if (SEQ:=LT (tp->snd_nxt, tp->snd_una»
tp->snd nxt - tp->snd una;
tp->t timer [TCPT REXMTJ - 0; i f (so->so_options & SO_ACCEPTCONNI
so->so state 1= SS CONNAWAITING;
soisconnected (so);
tp->t state = TCPS ESTABLISHED;
(void) tcp reass (tp, (struct tcpiphdr *) 0);
tp->snd wli = ti->ti seq - 1;
1* fall-into ... *1-

switch (tp->t_state) (

1*

*

In FIN WAIT 1 STATE in addition to the processing

* for the ESTABLISHED state if our FIN is now acknowledged

* then enter FIN WAIT 2.
*1
case TCPS FIN WAIT 1:
if (ourfinIsacked)
1*
* If we can't receive any more
* data, then closing user can proceed.
*1
if (so->so state & SS CANTRCVMORE)
soIsdisconnected (so) ;
tp->t_state - TCPS_FIN_WAIT_2:

1*

* In ESTABLISHED state: drop duplicate ACKs; ACK out of range
* ACKs. If the ack is in the range
tp->snd una < ti->ti ack <= tp->snd max

break;

1*

* then advance- tp->snd una to ti->ti ack and drop
* data from the retransmission queue-:- If this ACK reflects
* more up to date window information we update our window information.
*1
case TCPS_ESTABLISHED:
case TCPS_FIN_WAIT_l:
case TCPS_FIN_WAIT_2:
case TCPS_CLOSE_WAIT:
case TCPS_CLOSING:
case TCPS_LAST_ACK:
case TCPS TIME WAIT:
tdefine ourfinisa-;;ked - (acked > 0)

*

In CLOSING STATE in addition to the processing for

* the ESTABLISHED state if the ACK acknowledges our FIN
* then enter the TIME-WAIT state, otherwise ignore

*

the segment.

*1
case TCPS CLOSING:
if (ourfinisacked)
tp->t state = TCPS TIME WAIT;
tcp canceltimers (tp) ; tp->t timer [TCPT 2MSL] = 2 * TCPTV_MSL:
soisdIsconnected(so) :
break;

i f (SEQ_LEQ(ti->ti_ack, tp->snd_una»
break;
i f (SEQ GT (ti->ti ack, tp->snd max»
- goto dropafterack;
acked = ti->ti_ack - tp->snd_una;

1*

*
*

The only thing that can arrive in LAST_ ACK state
is an acknowledgment of our FIN. If our FIN is now
* acknowledged, delete the TCB, enter the closed state
* and return.

1*
* If transmit timer is running and timed sequence
* number was acked, update smoothed round trip time.
*1
i f (tp->t rtt && SEQ GT(ti->ti ack, tp->t rtseq»
if (tp->t_srtt - 0) tp->t_srtt - tp->t_rtt * 10;
else
tp->t srtt (tcp alpha * tp->t srtt) I 10 +
(10 = tcp alpha) *-tp->t rtt;
1* printf(lIrtt %d srtt(*10) now %d\n", tp->t_itt, tp->t_srtt); *1
tp->t_rtt - 0;

*1
case TCPS LAST ACK:
if (ouifinisacked)
tcp_close (tp):
tp - 0:
goto drop:

1*

*

*1
case TCPS TIME WAIT:
tp->t timer [TCPT 2MSL] - 2 * TCPTV_MSL;
goto dropafterack:

if (ti->ti ack -- tp->snd max)
tp=>t_timer[TCPTjU:XMTJ - 0;
else (

In TIME WAIT state the only thing that should arrive
Acknowledge

* is a retransmission of the remote FIN.
* it and restart the finack timer.

tundef ourfinisacked
TCPT RMfGESET (tp->t timer [TCPT REXMTJ,
(tcp beta * tp->t srtt) 1100, TCPTV MIN, TCPTV_MAX);
tp->t rtt - 1;
tp->t:=rxt.shift - 0;

)

step6:
/

.

* Update window information.

Fri Sep

5

5 19:09:39 1986

tp->t_flags 1- TF_ACKNOW:
tp->rcv_nxt++;

*/
i f (SEQ_LT(tp->snd_wl1, ti->ti_seq) II tp->snd_wll -- ti->ti_seq
(SEQ LT (tp->snd w12, ti->ti ackl I I
tp->snd w12 --ti->ti ack && ti->ti win> tp->snd_wnd»
{
tp->snd wnd - ti->ti win;
to->snd-wll - ti->ti-sea;
tp..>snd-w12 - ti->ti-ack;
/*
i f (tp->snd_wnd > 0)

&&

switch (tp->t_state) (

1*

* In SYN_RECElVED and ESTABLISHED STATES
" enter the CLOSE WAIT state.

*/

-

case TCPS_SYN_RECElVED:
case TCPS_ESTABLISHED:
tp->t state = TCPS_CLOSE_WAIT;
break:

*/
i f (tp->snd wnd != 0)
tp->t_timer[TCPT_PERSIST] - 0;

/*

/*

* If still in FIN WAIT 1 STATE FIN has not been acked so

* Process segments with URG.

*

*1

;*

enter the CLOSING st-;;:te.

*/

i f «tiflags & TH URG) && ti->ti urp &&
TCPS HAVERCVDFIN(tp->t state) -- 0)

-

tp->t_state - TCPS_CLOSING;
break:

*
*

If this segment advances the known urgent pointer,
then mark the data stream. This should not happen
* in CLOSE WAIT, CLOSING, LAST ACK or TIME WAIT STATES since
* a FIN has been received from-the remote side.
* In these states we ignore the URG.
*/
i f (SEQ GT (ti->ti seq+ti->ti urp, tp->rcv up) I
- tp->rcv up = ti->ti seq + ti->ti "iirp;
so->so_ ~obmark = so=>so_rcv. sb_ c-;- +
(tp->rcv up - tp->rcv nxt) - 1;
i f (so->so o~bmark - 0) so=>so_state 1- SS_RCVATMARK;
#ifdef TCPTRUEOOB

" In FIN WAIT 2 state enter the TIME WAIT state,
* starting the time-wait timer, turnIng off the other
* standard timers.
*/
case TCPS FIN WAIT 2:
t'P->t::::state - TCPS_TlME_WAIT;
tcp canceltimers (tp) :
tp->t timer [TCPT 2MSL] = 2 * TCPTV_MSL;
soisdIsconnected(so) ;
break;

#endif

1*

1*

* In TIME_WAIT state restart the 2 MSL time_wait timer.
*/
case TCPS TIME WAIT:
tp->t_timer [TCPT_ 2MSL] = 2 * TCPTVYSL;
break;

sohasoutofband (so) ;
tp->t_oobflags &- -TCPOOB_HAVEDATA;
/*

*
*
*
*

Remove out of band data so doesn' t get presented to user.
This can happen independent of advancing the URG pointer,
but if two URG's are pending at once, some out-of-band
data may creep in ... ick.

*/
if (ti->ti urp <= ti->ti len) (
tCPyUlloutofband(SO, ti);

if (so->so options & SO DEBUG)
tcp_traCe(TA_INPUT, ostate, tp, &tcp_saveti, 0);

/*

/*

* Process the segment text, merging it into the TCP sequencing queue,

*

and arranging for acknowledgment of receipt if necessary.
'" This process logically involves adjusting tp->rcv wnd as data

* is presented to the user (this happens in tcp usr"i:eq. c,
* case PRU_RCVD). If a FIN has already been re-;-eived on this
* connection then we just ignore the text.
*/

* Return any desired output.
*/
(void) tcp_output (tp) ;
tifdef SIGH
intcpinput -- ;
tendif
return:
dropafterack:

/*

* Generate an ACK dropping incoming segment if it occupies
sequence space, where the ACK reflects our state.
*/
if «tiflags&TH RST) II
tlen ~ 0 && (tiflags& (TH_SYN I TH_FIN» - 0)
goto drop;
if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
tcp_trace(TA_RESPOND, ostate, tp, &tcp_saveti, 0):
tcp_respond(tp, ti, tp->rcv_nxt, tp->snd_nxt, TH_ACK):
tifdef SIGH
intcpinput-- ;
#endif
return;

*

if «ti->ti_len II (tiflags&TH_FIN» &&
TCPS HAVERCVDFIN(tp->t state) ~ 0)
tiflags - tcp_reass (tp, ti);
if (tcpnodelack - 0)
tp->t_flags 1= TF_DELACK;
else

I else
m freem(m);
tIflags &- -TH_FIN:

1*

* If FIN is received ACK the FIN and let the user know
* that the connection is closing.

dropwi threset:
if (om)
(void) m_free (om) ;

*1
i f (tifla(,Js & TH FIN) {
i f (TCPS-HAVERCVDFIN(tp->t state) -

socantrcvmore (so) : -

/*

0) !

* Generate a RST, dropping incoming segment.
* Make ACK acceptable to originator of segment.

Fri Sep

5 19:09:39 1986

*1
if (tiflags & TH_RST)
goto drop;
i f (tiflags & TH ACK)
tcp_respond(tp, ti, Itcp_seq)O, ti->ti_ack, TH_RST);
else {

i f (tiflags & TH SYN)
ti->ti i;n++:
tcp respond(tp~ ti, ti->ti seq+ti->ti len, (tcp_seq) 0,
-TH_RST1 TH_ACK) ;
-

6
if (optlen !- 8)
continue;
seq - UCHAR(cp[2);
if (seq < UCHAR(tp->t iobseq»
seq +- 256; printf("oobdata ep[2] %d iobseq %d seq %d\n U , cp(2), tp->t_iobseq, seq);
if (seq - UCHAR(tp->t_iobseq) > 128) {
tp->t_oobflags 1- TCPOOB_OWEACK;
break;
tp->t iobseq - cp(2);
tp->t-iobc = cp[3];
bcopy(cp+4, &mark, sizeof mark);

Hfdef SIGH
intcpinput -- :
tendif
return:

lifndef WATCHOUT

drop:

tendif

mark

1*
* Drop space held by incoming segment and return.

*1
if (tp

&& (tp->t_inpcb->inp_socket->so_options & SO_DEBUG»
tcp trace (TA DROP, ostate, tp, &tcp saveti, 0);
m....freem(m); tifdef SIGH
intcpinput--:
tendif
return:

=

ntohl (mark) ;

so->so oobmark ~ so->so rev. sb ce + (mark-tp->rcv nxt);
if (so=>so oobmark ~ 0)
so=>so state 1= SS RCVATMARK;
printf(fttake oob data %x input iobseq now %x\n", tp->t_iobC, tp->t_iobseql;
soha souto fband (so) ;
break;

case TCPOPT OOBACK:
int-seq;
if (optlen !- 4)
continue:
if (tp->t_oobseq !- cp[2])

tcp dooptions (tp, om)
register struct tcpcb *tp:
register struct mbuf *om:

printf(lIwrong ack\n");
break;

register u char *cp;
register iilt opt, optlen, cnt;
MAPSAVE() ;
cp - mtod(om, u_char *);
cnt - om->m len:
for (; cnt > 0: cnt -- opt len, cp += optlen) {
opt - UCP.AR (cp[O]):
if (opt = TCPOPT_EOL)
break;
if (opt = TCPOPT NOP)
optlen = 1;
else
optlen = UCHAR(cp[l);
switch (opt) {
default:
break;

printf("take oob ack %x and cancel rexmt\n", cp[2]);
tp->t oobflags &- -TCPOOB NEEDACK;
tp->t=timer[TCPT_OOBREXMTl = 0;
break:
tendif TCPTRUEOOB
}
)

(void) m_free(om);
MAPREST(I;

1*
*
*
*
*

Pullout of band byte out of a segment so
it doesn't appear in the user's data queue.
I t is still reflected in the segment length for
sequencing purposes.

*1
case TCPOPT MAXSEG:
if (oPtlen != 4)
continue;
bcopy( (caddr_t) (cp+2),

tcpyulloutofband(so, til
register struct socket *so;
register struct tcpiphdr *ti;
(caddr_t) &tp->t_maxseg, 2);

tifdef SMALLTCP
tp->t_maxseg

=

256;

tendif
Hfndef WATCHOUT
tendif
break;
tifdef TCPTRUEOOB
case TCPOPT_WILLOOB:
tp->t flags 1- TF_DoooB;
printf("tp Ilx dooob\:'l", tp): break;
case TCPOPT OOBDATA:
int-seq;
register struct socket *90 - tp->t_inpcb->inp_socket.:
tep_seq mark;

register struct mbuf *m;
register int cnt - ti->ti_urp - 1;
MAPSAVE() ;
m - dtom(ti);
while (cnt >- 0) {
if (m->m_len > cnt) {
char *cp - mtod (m, caddr t) + cnt;
struct tcpcb *tp - sototcpcb (so);
tp->t iobc - *cp;
tp->t=oobflags 1- TCPOOB_HAVEDATA;
bcopy(cpt1, ep, (int) (m->m_len - cnt - 1»;
m->m_len--;
goto out:
ent -- m->m_len;
m - m->m next;
i f (m --0)
break;

Fri Sep

5 19:09:39 1986

7
if (i <= 0)
break;
if (i < q->ti len)
q->ti-seq +- i;
q->ti-Ien -- i;
m adj(DTOM(O), i);
break;
-

panic ("tcpyulloutofband") ;
out:
MAPREST() ;

tifdef WATCHOUT
/* this is for the 11 */
tdefine ti mbuf ti sum
tdefine DTDM(d) «struct mbuf *) «d)->ti_mbufl
tdefine INSQUE (i, p) { \
struct tcpiphdr *tii; \
MSGET (tii, struct tcpiphdr 0): if (tii ..... 0) gato drop; \
insque (tii, pI; \
tii->ti_Ien - (i)->ti_Ien; tii->ti_seq - (i)->ti_seq; \
tii->ti_flags = (i)->ti_flags; tii->ti_mbUf - mO; i = tii;
telse
tdefine DTOM(d) dtom(d)
tdefine INSQUE (i, p) insque (i, p)
tendif

qp = q;
q - (struct tcpiphdr *) q->ti_next;
m ~ DTOM(qp);
remque(qp) ;

I

Hfdef WATCHOUT
MSFREE(qp) ;
tendif

/*
* stick new segment in its place. Insque stuff can be expensive,
* so avoid if possible.
*/
if (tp->seg_next ~ (struct tcpiphdr *)tp)
/* queue was empty */
empty++;
else
INSQUE(ti, q->tiyrev);

/*

* Insert segment ti into reassembly queue of tcp with
* control block tp. Return TH FIN if reassembly now includes
* a segment with FIN.
*/
tcp reass (tp, til
register struct tcpcb *tp;
register struct tcpiphdr *ti;
register
register
register
register

present:

/*
" Present data to user, advancing rcv_nxt through
'" completed sequence space.
*/
if (TCPS HAVERCVDSYN (tp->t state)
0)
goto out;
if (!empty) ti = tp->seg_next;
if (ti (struct tcpiphdr ")tp II ti->ti_seq !- tp->rcv_nxt)
goto out;
if (tp->t state = TCPS SYN RECEIVED && ti->ti_Ien)
goto out;
-if (empty) {
to->rcv nxt +- ti->ti len;
fiags --ti->ti_flags "& TH_FIN;
if (so->so state & SS CANTRCVMORE)
m_freem(mO); else
sbappend (&so->so_ rcv, mO);

struct tcpiphdr *q, *qp;
struct socket *so = tp->t inpcb->inp socket;
struct mbuf *m, *mO;
int cnt,flags,empty = 0;

/*
'" Call with ti=O after become established to
* force pre-ESTABLISHED data up to user socket.
*/
if (ti - 0)
goto present;
mO = dtom(ti);
/*
" Find a segment which begins after this one does.

"/
for (q = tp->seg_next; q !- (struct tcpiphdr *)tp;
q = (struct tcpiphdr *)q->ti next)
i f (SEQ_GT(q->ti_seq, ti=>ti_seq) 1
break;
1*
* If there is a preceding segment, it may provide some of
" our data already. If so, drop the data from the incoming
* segment. If it provides all of our data, drop us.
"/
if «struct tcpiphdr *)q->tiyrev != (struct tcpiphdr *)tpl {
register int i;
q - (struct tcpiphdr *) q->tiyrev;
/* conversion to int (in il handles seq wraparound */
i - q->ti seq + q->ti len - ti->ti seq;
if (i > 01 {
i f (i >- ti->ti len)
goto drop;
m adj (mO, i):
tI->ti len -- i;
ti->ti':::seq += i;
q - (struct tcpiphdr *1 (q->ti_next);

sorwakeup(so) :
return (flags);
do
tp->rcv_nxt +- ti->ti_len;
flags - ti->ti_flags & TH_FIN;
remque (ti) ;
m - DTOM(ti);
qp - ti;
ti - (struct tcpiphdr *)ti->ti_next;
tifdef WATCHOUT
MSFREE (qp) ;
tendif
if (so->so state & SS_CANTRCVMOREI
m_ freem (m) ;
else
sbappend(&so->so_rcv, ml;
) while (ti !- (struct tcpiphdr *Itp && ti->ti_seq =
sorwakeup(so) ;
return (flags);

tp->rcv_nxtl;

drop:
m_freem(mO) ;
return (01;

/*
" While we overlap succeeding segments trim them or,
• if they are completely covered, dequeue them.

*i
while (q

(struct tcpiphdr .. 1tpl {
register int i - (ti->ti_seq + ti->ti_len) - q->ti_seq;
J-

out:
i f (emptYI INSQUE (ti, tpl;

/*

* If there are more than 10 tcp segments already queued,
* drop the oldest one from the queue. This sometimes happens
" when we get flooded with packets from unbuffered writes and

Fri Sep

5 19:09:39 1986

* there are gaps in the sequence numbers. (Why are gaps so likely
.. with unbuffered writes'll A retransmit (covering all the
.. one byte segments queued) will occur in a moment.
*;
cnt - 0;
for {q = tp->seg_next; q !- (struct tcpiphdr *)tp;
q - (struct tcpiphdr *) q->ti_next)
cnt++;
i f (cnt > 10) {
q - tp->seg next;
m

=

DTOM(q)7

rern..que lq),·

Hfdef WATCHOUT
MSFREE(q) ;

iendif

return (0);

8

Fri Sep
1*

%M%

U%

%E%

5 19:09:44 1986

1
if (len> tp->t maxseq) {
len - tii->t maxseg;
sendalot - "1;

*/

+include "sys/param.h"
+include ·sys/config .h"
tinclude "sys/errno.h"
tinclude "sys/t":ipes .h M
finclude ·sys/systm.h"
finclude "net/misc.h u
finclude "net/mbuf .h"
finclude "net/protosw. hOI
finclude "net/socket.h"
finclude "net/socketvar .hl.
finclude "net/in.h"
finclude "net/route.h"
finclude Hnet/inJ>Cb.h tl
finclude "net/in_systm.h tl
tinclude "net/ip.h"
tinclude "net/ip var.htl
finclude "net/tcp.h tl
Mefine TCPOUTFLAGS
finclude "net/tcp fsm.hOl
finclude Itnet/tcp-seq.h"
finclude "net/tcp-timer.h tl
finclude "net/tcp- var. htl
finclude "net/tcpIp.h tl
tinclude "net/tcp debug .htl
finclude "errno.h"

flags - tcp outflags [tp->t state);
if ( SEQ LT«tp->snd nxt +-len), (tp->snd una + so->so_snd.sb_cc»
flags &- -TH-FIN;
i f (flags & (TH SYN ITH RST I TH FIN»
goto send;
if (SEQ_GT(tp->snd_up, tp->snd_una»
goto send;

1*

* Sender silly window avoidance. If can send all data,
* a maximum segment, at least 1/4 of window do it,
* or are forced, do it; otherwise don't bother.

*1
if (len) {
i f (len

tp->t maxseg II off+len >= so->so_ snd. sb_ cc)
goto send;
* 4 >= tp->snd wnd)
1* a lot *1
goto send;
if (tp->t force)
geto send;
~

if (len

1*
char *tcpstates [); 1* XXX * I
fdefine returnerr{e) { error -

*

Send if we owe peer an ACK.

*1

(e); goto out; I

if (tp->t flags&TF ACKNOW)
geto send;-

1*
* Initial options: indicate max segment length 1/2 of space
" allocated for receive; if TCPTRUEOOB is defined, indicate
* willingness to do true out-of-band.
*I
fifndef TCPTRUEOOB
u char tcp_in it opt [4) - { TCPOPT_MAXSEG, 4, OxO, OxO, I;
felse
TCPOPT_MAXSEG, 4, OxO, OxO, TCPOPT_WILLOOB, 2 I;
iendif

1*
* Tcp output routine: figure out what should be sent and send it.

*1
tcp output (tp)
register struct tcpcb *tp;
register
register
register
int off,
register
register
register
register
register

struct socket *so - tp->t_inpcb->inp_socket;
int len;
struct mbuf *mO;
flags, win, error;
struct mbuf *m;
struct tcpiphdr *ti;
u char *opt ~ a;
unsigned opt len = a;
int sendalot;

1*
* Determine length of data that should be transmitted,
* and flags that will be used.
* If there is some data or critical controls (SYN, RST)
* to send, then transmit; otherwise, investigate further.

*1
fifdef SIGH
{ extern int intcpoutput; }
{if (intcpoutput) printf(tlintcpoutput. .. "); intcpoutput++; I
tendit:
again:
sendalot - a;
off - tp->snd nxt - tp->snd una;
len - MIN(so->so snd.sb cc,-tp->snd wnd+tp->t force) - off;
i f (len < a) { ret urnerr ( 0) ;
1* past FIN *1
1* 121 *1

tifdef TCPTRUEOOB

1*
* Send if an out of band data or ack should be transmitted.

*/
i f (tp->t oobflags& (TCPOOB OWEACK I TCPOOB NEEDACK»)
geto send;
-

tendif

1*
* Calculate available window, and also amount
* of window known to peer (as advertised window less
1< next expected input.)
If this is 35% or more of the
* maximum possible window, then want to send a segment to peer.
1<1
win = sbspace (&so->so_rcv);
if (win> a &&
«(lOO* (win- (tp->rcv_adv-tp->rcv_nxt» Iso->so_rcv. sb hiwat) >- 35»
qoto send;

1*
* TCP window updates are not reliable, rather a polling protocol
* using "persist" packets is used to insure receipt of window
* updates. The three "states" for the output side are:
idle
not doinq retransmits or persists
persisting
to move a zero window
(re) transmitting
and thereby not persisting

* tp->t timer [TCPT PERSIST)

*
*
*

Is set when-we are
tp->t force
Is set when we are
tp->t timer [TCPT REXMT)
Is set when-we are
The output side is idle

in persist state.
called to send a persist packet.
retransmitting
when both timers are zero.

* If

send window is closed, there is data to transmit, and no
retransmit or persist is pendinq, then go to persist state,
arranqinq to force out a byte to get more current window information
* if nothing happens soon.
1<

1<

*1
if (tp->snd wnd - a && so->so snd. sb cc &&
tp->t timer[TCPT REXMTJ ---0 " tp->t timer[TCPT PERSISTj
tp->t_rxtshift - 0;
-

-=

OJ

.;

Fri Sep

5 19:09:44 1986

2
m->m next - m get (M DONTWAIT);
if (m->m next-= O)-{
(void) m free (m) :
m_freem(mO) :
returnerr (ENOBUFS) ;

tcp_setpersist (tp);

/*

* No reason to send a segment, just return.

*I

m->m next->m next = mO;
mO --m->m_next;
mO->m_off - MMINOFF;
mO->m_Ien - optlen;

returnerr (0) ;
send:
/*
* Grab a header mbuf, attaching a copy of data to
* be transmitted., and initialize the header from
* the template for sends on this connection.
*/
MGET(m, 0);
if 1m ~ 0)
Hfdef SIGH
printf ("cant get header in tcpoutput\n-);
fendif
returnerr (ENOBUFS) ;
m->m off = MMAXOFF - sizeof (struct tcpiphdr);
m->m::::len = sizeof (struct tcpiphdr);
if (len) {
m->m next = m copylso->so snd.sb rob, off, len);
if (in->m next~ 0)
-

len

=

0;

ti - mtod (m, struct tcpiphdr *);
if (tp->t template ~ 0)
panic(lttcp output");
bcopy( (Caddr_tltp->t_template, (caddr_t)ti, sizeof (struct tcpiphdr»;

/*
* Fill in fields, remembering maximum advertised
* window for use in delaying messages about window sizes.

*/
ti->ti seq = tp->snd nxt;
ti->ti- ack = tp->rcv- nxt;
Hfndef WATCHOUT
ti->ti seq = htonl (ti->ti seq);
ti->ti::::ack - htonl(ti->ti::::aCk);
tendif
/*
* Before ESTABLISHED, force sending of initial options
* unless TCP set to not do any options.
*/
if (tp->t state < TCPS ESTABLISHED)
if (tp->t_flagS&TF_NOOPTI
goto noopt;
opt = tcp ini topt;
optlen - sizeof (tcp initopt);
* (u_short *1 (opt + 2) = so->so_rcv. sb_hiwat I 2;
tifdef SMALLTCP
* (u_short *) (opt + 2) - 256;
fendif
tifdef TCPACKMOST
fendif
tifndef WATCHOUT
*(u_short *1 (opt + 21

=

fifdef WATCHOUT
if (opt

tcp initoptl
bcopy «caddr_ t) opt, mtod (mO, caddr_tl, (inti optlen) :
MBCOPY(tp->t_tcpopt, 0, mO, 0, (int)optlen):

{else
bcopy( (caddr_tl opt, mtod(mO, caddr_t), (int) optlenl;
tendif
opt = (u char 1<) (mtod (mO, caddr t) + optlen):
Hfdef TCPTRUEOOB
if (tp->t oobflags&TCPOOB OWEACKI {
printf(OItp %x send OOBACK-for %x\n", tp->t iobseq);
*opt++ = TCPOPT_OOBACK;
*opt++ = 3:
*opt++ = tp->t iobseq:
mO->m len +tp->t-oobflags &= -TCPOOB OWEACK;
/* sender should rexmt oOb to force ack repeat */

3;-

if (tp->t oobflags&TCPOOB NEEDACK) {
tcp seq oobseq: printf("tp %x send OOBDATA seq %x data %x\n Ol , tp->t_oobseq, tp->t_oObc);
*opt++ - TCPOPT_OOBDATA;
*opt++ - 8;
*opt++ - tp->t_oobseq;
*opt++ = tp->t 0000;
oobseq - tp->t::::oobmark - tp->snd_nxt:
tifndef WATCHOUT
oobseq - htonl (oobseq) ;
tendif
bcopy ( (caddr_ t) &oobseq, opt, sizeof oobseq);
mO->m len +- 8:
TCPT RANGESET (tp->t timer [TCPT OOBREXMT],
(tcp_beta*tp->t::::srtt) /100, - TCPTV_MIN, TCPTV_MAX):
tendif
while (mO->m_Ien & Ox3) {
*opt++ - TCPOPT EOL:
mO->m_Ien++;
optlen = mO->m len;
ti = mtod (m, struct tcpiphdr *):
/ * needed for 11 * /
ti->ti_off - (sizeof (struct tcphdr) + optlen) » 2;
noopt:
ti->ti flags - flags;
win - sbspace(&so->so rcv);
Hfndef TCPACKHOST
if (win < so->so_rcv.sb_hiwat
telse

4)

/* avoid silly window */

1* avoid silly window *1

htons(*(u_short *) (opt + 2));

tendif

~

else

tendif
} else {

if (tp->t_tcpopt -- 0)
goto noopt;
opt - mtod (tp->t tcpopt, u char *);
optlen - tp->t_tcpopt->m_Ien:

win - 0;
if (win> 0)
tifndef WATCHOUT
ti->ti_win - htons «u short) win) ;
telse
tendif

Hfndef TCPTRUEOOB
if (opt)
telse
if (opt II (tp->t_oobflags&(TCPOOB_OWEACKITCPOOB_NEEDACK))
tend i f

if (SEQ GT (tp->snd up, tp->snd nxt»
-ti->ti urp-- tp->snd up - tp->snd nxt;
tifndef WATCHOUT
ti->ti_urp - htons (ti->ti_urp);
tendif
) else

Fri Sep

5 19:09:44 1986

3

/*

*

If no urgent pointer to send, then we pull
the urgent pointer to the left edge of the send window
so that it doesn't drift into the send window on sequence
* number wraparound.
*/
/* drag it along *1
tp->snd_up - tp->snd_una;

*
*

1*

*
*

If anything to send and we can send it all, set PUSH.
(This will keep happy those implementations which only
* give data to the user when a buffer fills or a PUSH comes in.

I"
" Fill in IP length and desired time to live and

* send to IP level.
*/
«struct ip *)ti)->ip len - sizeof (struct tcpiphdr) + optlen + len;
«struct ip ")ti)->ip-ttl = TCP TTL;
if (error = ip output("m, tp->t Ipopt, (so->so options & SO_DONTROUTE)
&routetoif-: &tp->t_inpcb->inp_route, O»-{
returnerr (error);

*/
if (len

&& off+len ~ so->so snd. sb cc)
ti->ti_flags 1= TH_PUSH;
-

1*

* Put TCP length in
" checksum extended
*1
if (len + optlen) {
ti->ti len =
tifndef WATCHOUT
ti->ti_len tendif

extended header, and then
header and data.
sizeof (struct tcphdr) + optlen + len;
htons( (u_short)ti->ti_len);

/"
" Data sent (as far as we can tell) .
" If this advertises a larger window than any other segment,
* then remember the size of the advertised window.
* Drop send for purpose of ACK requirements.

,,/

if (win> 0 && SEQ GT (tp->rcv nxt+win, tp->rcv adv»
tp->rcv adv - tp->rcv-nxt + win;
tp->t flags &= =(TF ACKNOWITF-DELACK);
if (sendalot && tp->t force ~-: 0)
goto again; returnerr ( 0) ;

mbprint (m, "before tout ck");
ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + (int) optlen + len);
npr int f (-tout sum%x len%x \n ", ti ->ti_sum, si zeo f (struct tcpiphdr )+optlen +len) ;
1*
" In transmit state, time the transmission and arrange for
* the retransmit. In persist state, reset persist time for
* next persist.
*1
if (tp->t force ~ 0) {

out:
tifdef SIGH
intcpoutput-- ;
tendif
return (error);
tcp setpersist (tp)
register struct tcpcb "tp;

i*

* Advance snd_nxt over sequence space of this segment.
*I

if (flags & (TH_SYNITH_FIN»
tp->snd_nxt++;
tp->snd_nxt += len;

1*

* Time this transmission if not a retransmission and
* not currently timing anything.
*1
if (SEQ GT (tp->snd nxt, tp->snd max) && tp->t_rtt ~ 0) {
-tp->t rtt :: 1;
tp->t=:rtseq - tp->snd_nxt - len;

if (SEQ GT (tp->snd nxt, tp->snd max»
-tp->snd_max - tp->snd_nXt;

1*

* Set retransmit timer if not currently set.

*

Initial value for retransmit timer to tcp beta"tp->t srtt.
" Initialize shift counter which is used for exponent{~·l
" backoff of retransmit time.

"I
if (tp->t timer [TCPT REXMT] - 0 &&
tp->snd nxt !~ tp->snd una) {
TCPT RANGESET (tp->t timer [TCPT REXMT],
("tcp beta*tp->t-srtt) 1100, -TCPTV HIN, TCPTV_MAX);
tp->t_rxtshift - 0;tp->t_timer[TCPT_PERSIST] - 0;
} else {
if (SEQ GT(tp->soo una+l, tp->snd maxI I
-tp->snd_max - tp->snd_una+l;

/"
" Trace.
"I
if (so->so_options

&

SO_DEBUG)

if (tp->t timer [TCPT REXMT])
p-;nic("tcp_output REXMT");
/*
" Start/restart persistance timer.
*/
TCPT RANGESET (tp->t timer [TCPT PERSIST],
(" (tcp_beta * tp=>t_srtt) /1(0) « tp->t_rxtshift,
TCPTV PERSHIN, TCPTV MAX);
tp->t rxtshift++;
if (tp->t rxtshift >= TCP HAXRXTSHIFT)
tp->t_rxtshift - 0;

Fri Sep
1*

4.27

#include
#include
+include
tinclude
#include
#include
finclude
#include
finclude
finclude
+include
#include
#include
finclude
finclude
finclude
+include
#include
#include
#include
#include
+include
#include
#include
finclude

82/06/20

5 19:09:45 1986
*1

sys/param. h"
Hsys/config. h"
"sys/errno.hu
H

Wsys/types .hH

"sys/systm.h"
"net/misc.h"
"net/mbuf . h"
"netl socket. h"
"net I socket var . h"
"net/protosw.h"
nnet/in.h"
"net/route. h"
Hnet/inJ>Cb. h"
"net/in_systm.h"
"net/if .h"
"net/ip.h"
"net/ip var.h"
"net/ip::::icmp.h ll
"net/tcp.h"
"net/tcp_fsm.h H
"net/tcp_seq. h"
"net/tcp_timer. h"
"net/tcp var.hH
"net/tcpIp.h"
"errno.h"

/*
" Tcp initialization

*1
tcp init()

-

{

tcp iss - 1;
1* wrong "I
tcb~inp next = tcb.inp prey - &tcb;
tcp alpha - TCP ALPHA;tcp::::oota - TcPj3ETA;

1*
* create template to be used to send tcp packets on a connection.
Call after host entry created, allocates an mbuf and fills
" in a skeletal tcp/ip header, minimizing the amount of work
" necessary when the connection is used.
"I
struct tcpiphdr *
tcp template (tp)
register struct tcpcb *tp;

1
* In any case the ack and sequence number of the transmitted
* segment are as specified by the parameters.

*1
tcp respond(tp, ti, ack, seq, flags)
register struct tcpcb *tp;
register struct tcpiphdr "ti;
register tcp seq ack, seq;
register int-flags;
register struct mbuf ·m;
register int win - 0, tlen;
register struct route *ro - 0;
i f (tp)

win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
ro = &tp->t_inpcb->inp_route;
i f (flags ~ 0) {
m = m get (M DONTWAIT);
i f (m-~ 01return;
m->m off - MMINOFF;
m->m-len - sizeof (struct tcpiphdr) + 1;
bcoPy «caddr t) ti, mtod (m, caddr t), sizeof *til;
ti = mtod (m, - struct tcpiphdr "1;flags - TH ACK;
tlen = 1; } else {
m = dtom(ti);
m_freem(m->m_next) ;
m->m next - 0;
fifndef newmbufs
m->m_off - (int)ti - (intlm:
felse
m->m_off - (intlti - mtobuf(m, intI;
fendif
m->m len = sizeof (struct tcpiphdr);
fdefine Kchg(a,b,type) { type t; t=a; a=b; b-t; }
xchg(ti->ti dst.s addr, ti->ti src.s addr, ~long);
xchg(ti->ti::::dport:- ti->ti_sport, u_short);
fundef xchg
tlen = 0;

*

register struct inpcb *inp - tp->t inpcb;
register struct tcpiphdr *n;
MSGET (n, struct tcpiphdr, 1);
i f (n ~ 0)
return (O);
n->tiyr - IPPROTO_TCP;
n->ti len - htons (sizeof (struct tcpiphdr) - sizeof (struct ip»;
n->ti- src - inp->inp laddr;
n->ti-dst - inp->inp-faddr;
n->ti-sport - inp->inp Iport;
n->ti-dport - inp->inp-fport;
n->ti::::off - 5;
return (n);

ti->ti_next = ti->tiyrev = 0;
ti->ti xl = 0;
ti->ti-len = sizeof (struct tcphdr) + tlen;
ti->ti-seq = seq;
ti->ti-ack - ack;
fifndef WATCHOUT
ti->ti len - htons «u short) ti->ti len);
ti->ti-seq = htonl (ti-=>ti seq);
ti->ti::::ack = htonl (ti->ti::::aCk);
fendif
ti->ti x2 - 0;
ti->ti-off = sizeof (struct tcphdr) » 2;
ti->ti-flags - flags;
ti->ti-win - win;
fifndef WATCHOUT
ti->ti_win - htons(ti->ti_win);
fendif

1* billn
ti->ti sum - 0;
*1
ti->ti sum - in cksum(m, sizeof (struct tcpiphdrl + tlen);
( (struct ip *) tI) ->ip len - sizeof (struct tcpiphdr) + tlen;
«struct ip *)ti)->ip-ttl - TCP TTL;
(void) ip_output(m, (struct mbuf *)0, ro, 0);

I"

* Send a single message to the TCP at address specified by

•
"
•
"
"
•

the given TCP lIP header. If !lags--O, then we make a copy
of the tcpiphdr at ti and send directly to the addressed host.
This is used to force keep alive messages out using the TCP
template for a connection tp->t template. If flags are given
then we send a message back to the TCP which originated the
segment ti, and discard the mbuf containing it and any other
* attached mbufs.

/"

* Create a new TCP control block, makinq an
• empty reassembly queue and hooking it to the argument
•

pz:otoco~ ,CQ.D.t.Z:,a,l

hl.ack.

Fri Sep

5 19:09:45 1986

*1

struct tcpcb *
tcp newtcpcb(inp)
register struct inpcb *inp;

2
tend if
}

if (tp->t template)
MSFREE (tp->t template):
if (tp->t tcpopt)
(;oid) m free (tp->t tcpopt;;
i f (tp->t ipopt) {void) m_free (tp->t_ipopt);
MSFREE Itp) ;
inp->inp-PPCD - 0;
soisdisconnected ! so) ;
inJlcbdetach(inp) :

reqister struct tcpcb *tp;

MSGET (tp, struct tcpcb, 1);
if !tp = 0)
return (0);
tp->seg next - tp->segJlrev = (struct tcpiphdr *)tp;
1* cor-;;ection from Dan@sri-tsc
tp->t rnaxseg - 576;
1* satisfy the rest of the world */
tp->t-rnaxseg - 512;
/* satisfy the rest of the world */
tp->t-flags = 0;
/* sends options! *1
tp->t-inpcb = inp;
inp->InpJlPcb = (caddr_t)tp;
return (tp);

1*
* Drop a TCP connection, reporting
* the specified error. I f connection is synchronized,
then send a RST to peer.
*/
tcp drop(tp, errno)
register struct tcpcb *tp;
register int errno;
1<

tcp drain!)
{

-

tcp ctlinput (emd, arg)
register int emd;
register caddr_ t arg;
register struct in addr *sin;
extern u_char inetctlerrrnap [ ] ;
if (emd < 0 II emd > PRC_NCMDS)
return;
switch (emd) {

struct socket *so - tp->t_inpcb->inp_socket;
if (TCPS HAVERCVDSYN (tp->t state)
tp->t state = TCPS-CLOSED;
(void) tcp_output (tp);
so->so error - errno;
tcp_close (tp) ;
tcp abort (inp)
register struct inpcb *inp;
tcp_close( (struct tcpcb *)inp->inPJlPcb);

case PRC_ROUTEDEAD:
break;
case PRC_QUENCH:
break;
/* these are handled by ip *1
case PRC_ IFJ:lOWN:
case PRC_ HOSTDEAD:
case PRC HOSTUNREACH:
break;
default:
sin = &«struct iemp *)arg)->iemp ip.ip dst;
inJ)Cbnotify(&tcb, sin, inetctlerrmap[cmd], tcp_abort);

tifdef WATCHOUT
tdefine ti_rnbuf ti_sum
ide fine DTOM(d) ( (struct rnbuf *) «d)->ti_rnbuf)
telse
tdefine DTOM(d) dtom(d)
tendif

1*
* Close a TCP control block:
discard all space held by the tcp
discard internet protocol block
wake up any sleepers
*/
tcp close (tp)
register struct tcpcb *tp:
register
tifdef WATCHOUT
register
tendif
register
register

struct tcpiphdr *t;
struct tcpiphdr ·to;
struct inpcb *inp - tp->t inpcb;
struct socket *so - inp->Inp_socket;

for It - tp->seg next; t !- (struct tcpip!ldr *1 tp; I
m_freem(DTOM(t)) ;
Hfdef WATCHOUT
to - t;
tendif
t - fstruct tcpiphdr *)t->ti_next;
Hfdef WATCHOUT
MSFREE (to) ;

Fri Sep
4.23

1*
'include
'include
'include
'include
'include
'include
'include
'include
'include
'include
'include
'include
'include
.include
tinclude
'include
'include
.include
tinclude
'include
'include
tinclude
tinclude
tinclude

82/06/20

5 19:09:46 1986
*/

"sys/param.h"
Usys/config .h"
"sys/errno.h u
·sys/types.h"
"sys/systm.h R
"net/misc.h"
"net/mbuf .h"
"net/socket.h"
"net/socketvar .h"
"net/protosw. h"
"net/in.h u
"net/route.h"
"net/in--'pcb.h"
"net/in systm.hu
"net/if~hlt
"net/ip.h"
"net/ip var.h"
"net/tcp.h"
-net/tcp fsm.h"
"net/tcp-seq.h"
Itnet/tcp-timer. hit
"net/tcp-var.h"
"net/tcpIp.h"
Herrno .h"

1
'endif
ip ~ tcb.inp next;
if (ip - O)-{
splx(s) ;
.ifdef SIGH
inslowtimo-- ;
'endif
return;
while (ip !- &tcb) {
tp - intotcpcb (ip) ;
i f (tp = 0)
continue;
ipnxt - ip->inp next;
for (i = 0; i <-TCPT NTIMERS; iH) {
if (tp->t_timer[il && --tp->t_timer[i] -= 0) {
(void) tcp usrreq (tp->t inpcb->inp socket,
PRU Sr.OwTIMO, (struct mbuf *) 0-;
(caddr t) i) ;
if (ipnxt->inp_prev !- ip)
goto tpgone;

tp->t idle++;
if (tp..>t rtt)
tp->t_rtt++:
tpgone:
ip

ipnxt;

int
tcpnodelack = 0;
.ifdef SIGH
int
infasttimo = 0;
int
inslowtimo - 0;
'endif
/*
* Fast timeout routine for processing delayed acks
*1
tcp_fasttimo ()

tcp_iss += TCP_ISSINCR/PR_SLOWHZ;
splx(s) ;
.ifdef SIGH
inslowtimo-- ;
'endif

{

/*
register struct inpcb *inp;
register struct tcpcb *tp;
register int s = spInet () ;

=

/* increment iss */

)

* Cancel all timers for TCP tp.
it/
tcp cancel timers (tp)
register struct tcpcb "tp;

tifdef SIGH
if (infasttimo) printf("infasttimo ... 11); else infasttimo++;

register int i;

'endif
inp - tcb.inp next;
if (inp)
for (; inp != &tcb; inp = inp->inp next)
if «tp ~ (struct tcpcb ") Inp->inp.J>pcb) &&
(tp->t flags & TF DELACK) {
tP:->t flags ,:: -TF DELACK;
tp->t-flags 1- TF ACKNOW;
(void) tcp_output(tP);

for (i - 0; i < TCPT NTIMERS; i++)
tp->t_timer[I] - 0;

int
int
int

tcp backoff[TCP MAXRXTSHIFT] =
/* scaled by 10 */
10, 12, 14, 17, 20, 30, 50, 80, 160, 320 );
tcprexmtprint - 1;
tcpexprexmtbackoff = 0;

/*
tifdef SIGH
infasttimo-- ;
'endif
splx (sl;

/*
* Tcp protocol timeout routine called every 500 ms.
it Updates the timers in all active tcb's and
* causes finite state machine actions if timers expire.
*/
tcp_slowtimo (I

* TCP timer processing.
*/
tcp timers (tp, timer)
register struct tcpcb *tp;
register int timer;

switch (timer) {

/*

* 2 MSL timeout in shutdown went off.
* control block.

Delete connection

*/

{

register
register
register
register

struct inpcb Kip, *ipnxt;
struct tcpcb *tp;
int s - spInet ( ) :
int i;

case TCPT_2MSL:
tcp_close (tp);
return;
/*

1*
1<

1<

Search through tcb's and update active timers.

1< /

tifdef SIGH
if (inslowtimo) printf("inslowtimo ... "); else inslowtimo++:

*
1<

*
it/

Retransmission timer went off. Message has not
been acked within retransmit interval. Back off
to a longer retransmit interva1. and retransmit all
unacknowledged lIIessaqes in the window.

Fri Sep

5 19:09:46 1986

case TCPT REXMT:
tp->t rxtshift++;
if (tp->t rxtshift > TCP_MAXRXTSHIFT)
tcp_drop(tp, ETIMEDOUT):
return;
}

TCPT RANGESET (tp->t timer [TCPT REXMTJ,
(int)tp->t srtt710, TCPTV MIN, TCPTV MAX);
if (tcpexprexmtbackoff) { TCPT RANGESET(tp->t timer[TCPT REXMTJ,
tp->t_timer [TCPT_REXMTJ «-tp->t_rxtshift,
TCPTV_MIN, TCPTV_MAX);
} else {
TCPT RANGESET (tp->t timer [TCPT REXMTJ,
(tp->t timer[TCPT REXMTJ *tcp backoff[tp->t rxtshift - 1]) /10,
TCPTV_MIN, TCPTV_MAX);
}

if (tcprexmtprint)
printf(Urexmt set to %d\n", tp->t timer[TCPT REXMT]);
tp->snd nxt - tp->snd una; /* this-only transmits one segment! */
(void) tcp_output (tp);
return;

/*

* Persistance timer into zero window.
* Force a byte to be output, if possible.
*/
case TCPT PERSIST:
tcp setpersist (tp);
tp->t force = 1;
(void) tcp output (tp) ;
tP->t_force = 0;
return;
/*

*
*

Keep-alive timer went off; send something
or drop connection if idle for too long.

*/
if (tp->t state < TCPS ESTABLISHED)
g;to dropit;
if (tp->t inpcb->inp socket->so options & SO_KEEPALIVE)
if (tp->t idle >= TCPTV-MAXIDLE)
g;to dropit;
/*
* saying tp->rcv nxt-1 lies about what
* we have received, and by the protocol spec
* requires the correspondent TCP to respond.
* Saying tp->snd una-1 causes the transmitted
* byte to lie outside the receive window; this
* is important because we don't necessarily
* have a byte in the window to send (consider
* a one-way stream!)
*/
tcp respond (tp,
-tp->t_template, tp->rcv_nxt-1, tp->snd_una-1, 0);
} else
tp->t idle = 0;
tp->t timer [TCPT KEEP] - TCPTV KEEP;
return;
dropit:
tcp drop (tp, ETIMEDOUT);
ret~rn;

.ifdef TCPTRUEOOB

/*

* out-of-band data retransmit timer.
*/
case TCPT OOBREXMT:
if (tp->t flags & TF_NOOPT)
return;
(void) tcp output (tp) ;
TCPT RANGESET (tp->t timer [TCPT OOBREXMT],
(2 * tp->t_srtt)/lO, TCP TV::::MI N, TCPTV_MAX);

2
return;
tenciif

Fri Sep
1*

tcp_usrreq. c

1. 59

82/06/20

5 19:09:48 1986
*1

1
tendif
ostate - tp->t_state;

tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
Hnclude
tinclude
tinclude
tinclude
tinclude
+include
tinclude
tinclude
tinclude
+include
tinclude
tinclude
tinclude
tinclude

"sys/param.h H
"sys/config. hIt
"sys/errno.h"
"svs/tvnes .hH

switch (req) {

1*

"sYs/sY~tm.hH

" TCP attaches to socket via PRU ATTACH, reserving space,
* and internet and TCP control blocks.
* If the socket is to receive connections,
* then the LISTEN state is entered.

"net/misc.h"
"net/mbuf .h"
"net/socket.h"
.net/socketvar .h H
"net/protosw. hOI
"net/in.h"
"net I route. h II
"net/inJ>Cb.h"
"net/in_systm.h"
"net/if .h"
"net/ip.h"
"net/ip_var.h"
"net/tcp.h"
"net/tcp_fsm.h R
"net/tcp_seq.h"
"net/tcp_timer. h"
"net/tcp var. h"
"net/tcpIp.h ll
"net/tcp_debug. h"
"errno.h"

*1
ca.se PRU ATTACH:

If (inp)
error - EISCONN;
break;
error = tcp_attach(so, (struct sockaddr *)addr);
if (error)
break;
if «so->so options & SO DONTLINGERJ
OJ
so->so_linger = TCP_LINGERTIME;
tp - sototcpcb ( so) ;
break;

/*
*
"
"
*

PRU DETACH detaches the TCP protocol from the socket.
If the protocol state is non-embryonic, then can't
do this directly: have to initiate a PRU DISCONNECT,
which may finish later; embryonic TCB's can just
" be discarded here.

1*
" TCP protocol interface to socket abstraction.

*1
extern
struct

*1
char *tcpstates [] ;
tcpcb *tcp_newtcpcbO;

case PRU DETACH:
tp - tcp_disconnect (tp);
break;

1*
* Process a TCP user request for TCP tb. If this is a send request
* then m is the mbuf chain of send data. If this is a timer expiration
* (called from the software clock routine), then timertype tells which timer.

*1
tcp usrreq(so, req, m, addr)
struct socket *so:
int req;
struct mbuf *m:
caddr_ t addr;
register struct inpcb
register struct tcpcb
int s = spInet ();
int error - 0;
int ostate - 0;
extern struct tcpcb "
extern struct tcpcb *

1*
"
"
"
*
±

Initiate connection to peer.
Create a template for use in transmissions on this connection.
Enter SYN SENT state, and mark socket as connecting.
Start keep-alive timer, and seed output sequence space.
Send initial segment on connection.

*1

*inp = sotoinpcb(so):
*tp;

tcp disconnect () ;
tcp::::usrclosed ( ) ;

case PRU CONNECT:
error - inJ>Cbconnect (inp, (struct sockaddr_in *) addr) ;
if (error)
break;
tp->t template = tcp template (tp) ;
i f (tp->t template":: 0) (
inycbdisconnect (inp);
error - ENOBUFS;
break;
soisconnecting (so) ;
tp->t state = TCPS SYN SENT;
tp->t-timer[TCPT KEEP]-- TCPTV KEEP;
tp->iss - tcp iss; tcp iss +- TCP ISSINCR/2;
tcp sendseqinIt (tp); error = tcp output (tp) ;
break;
-

/*
*
*
*
*

When a TCP is attached to a socket, then there will be
a (struct inpcb) pointed at by the socket, and this
structure will point at a subsidary (struct tcpcb).
The normal sequence of events is:
PRU_ATTACH
creating these structures
PRU_CONNECT
connecting to a remote peer
(PRU_SENDIPRU_RCVD)*
exchanging data
PRU_DISCONNECT
disconnecting from remote peer
PRU DETACH
deleting the structures
* With the-operations from PRU CONNECT through PRU DISCONNECT
* possible repeated several tbiies.
* MULTIPLE CONNECTS ARE NOT YET IMPLEMENTED.

if (inp) (
tp - intotcpcb(inp);
tifdef KPROF
tcp_acounts [tp->t_state] [req] ++;

*
*
"
"
*

*

*

*1
if (inp - 0 " req !- PRU ATTACH)
splx(s);
return (EINVAL);

1*

/* XXX */

Initiate disconnect from peer.
If connection never passed embryonic stage, just drop;
else if don't need to let data drain, then can just drop anyways,
else have to begin TCP shutdown process: mark socket disconnecting,
drain unread data, state switch to reflect user close, and
send segment (e.g. FIN) to peer. Socket will be really disconnected
when peer sends FIN and acks ours.

* SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB.
*1
case PRU DISCONNECT:
tp - tcp_disconnect (tp) ;
break;
/*

Fri Sep

5 19:09:48 1986

* Accept a connection. Essentially all the work is
,. done at higher levels: just return the address
* of the peer, storing through addr.
*/
case PRU_ACCEPT: {
struct sockaddr_in * sin = (struct sockaddr_in

*) addr;

if (sin) {
bzero«caddr t)sin, sizeof (*sin»;
sin->sin family - AF INET:
sin->sin~rt = inp->inp_fport;
sin->sin_addr = inp->inp_faddr;

2
case PRU_SENDOOB:
tifdef TCPTRUEOOB
if (tp->t flags & TF ooooB) {
tp->t oobseq++:
tP->(~oobc ~ *mtod(m, caddr_t):
tp->t oob.uark = tp->snd una + so->so snd.sb cc;
printf("sendoob seq now %x OObe %x\n", tp->t oobseq, tp->t oobc): tp->t oobflags ,- TCPOOB NEEDACK; /* what to do ... 1 */
if (error - tcp_output (tp»
break;
tendif
if (sbspace(&so->so_snd) < -512) {
error - ENOBUFS:
break:

break;
/*

* Mark the connection as being incapable of further output.
*/
case PRU_SHUTDOWN:
socant sendmore ( so) ;
i f (tp = tcp_usrclosed(tp»
error = tcp_output(tp);
break;
1*
* After a receive, possibly send window update to peer.
*1
case PRU RCVD:
(void) tcp_output (tp);
break:
1*
" Do a send by putting data in output queue and updating urgent
* marker if URG set. Possibly send more data.
*1
case PRU SEND:
sbappend (&So->so_snd, m);
Ufdef notdef
i f (tp->t flags & TF PUSH)
tp->snd_end
tp->snd_una + so->so_snd.sb_cc;
tendif
error - tcp output (tp) ;
break;
-

=

* Abort the TCP.

*1
case PRU_ABORT:
tcp drop (tp, ECONNABORTED);
tp :: 0;
break;

case PRU_SENSE:
error - EOPNOTSUPP;
break;
1* END UNIMPLEMENTED HOOKS "/

tp->t_iobc;

=

tendif

tp->t force = 1;
error-= tcp output (tp) ;
tp->t force- = 0;
break;
case PRU SOCKADDR:
in_setsockaddr «struct sockaddr_in
break;

*)

addr, inp);

1*

*
*

TCP slow timer went off; going through this
routine for tracing's sake.

*1
case PRU SLOWTIMO:
tcp timers (tp, (int) addr) ;
req-,- (int)addr « 8;
break;

1* for debug's sake * /

default:

register struct tcpeb *tp;
struct inpcb * inp;
int error;
Q)

i f ((tp->t_oobflags & TCPOOB_HAVEDATA)
error - EWOULDBLOCK;
break;
=

i f (tp->t flags & TF PUSH)
tp->snd_end
tp->snd_una + so->so_snd.sb_cc;

tcp sendspace = 1024*2;
int
int
tcp::::recvspace - 1024*2;
1*
* Attach TCP protocol to socket, allocating
* internet protocol control block, tcp control block,
" bufer space, and entering LISTEN state if to accept connections.
*/
tcp_attach(so, sa)
struct socket *so;
struct sockaddr * sa;

1* SOME AS YET UNIMPLEMENTED HOOKS */
case PRU_CONTROL:
error - EOPNOTSUPP;
break;

*mtod 1m, caddr_t)
break;

tifdef notdef

if (so->so_options & SO_DEBUG)
tcp_trace(TA_USER, ostate, tp, (struct tcpiphdr *)0, req);
splx(s) ;
return (error):

1*

case PRU RCVOOB:
if (so->so_oobrnark -- a &.Ii
(so->so_state & SS_RCVATMARK) -error - EINVAL;
break;

tp->snd up = tp->snd una + so->so_snd.sb_cc + 1;
sbappend(&so->so_snd~ m):

{

==

0) {

error - inycbattach(so, &tcb,
tcp sendspace, tcp recvspace, (struct sockaddr_in
i f (error)
return (error);
inp - I struct inpcb *) so-> soycb;
tp - tcp newtcpcb(inp);
i f Itp -:: 0) {
inycbdetach(inp) ;
return (ENOBUFS):
if (So->so_options & SO_ACCEPTCONN)

*)

sa);

Fri Sep

5 19:09:48 1986

else
tp->t state
return (0); -

~

TCPS_CLOSED;

/*
" Initiate (or continue) disconnect.
" If embryonic state, just send reset (once).
* If not in "let data drain" option, just drop.
* Otherwise (hard), mark socket disconnecting and drop
" current input data; switch states based on user close, and
" send segment to peer (with FIN) .
*/
struct tcpcb *
tcp disconnect (tp)
struct tcpcb "tp;
struct socket *so - tp->t_inpcb->inp_socket;
i f (tp->t state <~ TCPS LISTEN) {
tcp_close(tp); tp = 0;
) else if (so->so linger = 0) {
tcp drop(tp, 0);
tp:;; 0;
} else {
soisdisconnecting (so) ;
sbflush(&so->so rcv);
i f (tp - tcp usrclosed (tp) )
(VOld) tcp_output (tp);

return (tp);

/*

* User issued close, and wish to trail through shutdown states:
" if never received SYR, just forget it. If got a SYN from peer,
" but haven't sent FIN, then go to FIN WAIT 1 state to send peer a FIN.
" If already got a FIN from peer, then-almost done; go to LAST_ACK
* state. In all other cases, have already sent FIN to peer (e. g.
" after PRU SHUTDOWN), and just have to play tedious game waiting
" for peer to send FIN or not respond to keep-alives, etc.
" We can let the user exit from the close as soon as the FIN is aCked.
,,/
struct tcpcb "
tcp_usrclosed (tp)
struct tcpcb "tp;
switch (tp->t_state)
case TCPS_LISTEN:
case TCPS_SYN_SENT:
tp->t state - TCPS_CLOSED;
tcp close (tp) ;
tp -= 0;
break;
case TCPS_SYN_RECEIVED:
ca se TCP S_ ES TABLI SHED:
tp->t state - TCPS_FIN_WAIT_l;
break:
case TCPS_CLOSE_WAIT:
tp->t state - TCPS_LAST_ACK;
break:
i f (tp

&& tp->t state >- TCPS FIN NAIT 2)
soisdisconnected (tp->t inpcb->Inp socket);
return (tp);
- -

3

tecmar.c

Fri Sep

5 19:09:15 1986

1
extern char te dparam[lJ;
extern char te-modem [1) ;
extern int te_cnt:

1*
Lisa INSS250A device driver
Copyright 19S4 UniSoft Corporation

*1
#include
#include
#include
#include
tinclude
tinclude
#include
#include
#include
+include
tinclude
tinclude
tinclude
Hnclude
tinclude
+include
tinclude
#include
int

"sys/param.h"
"sys/config .h"
·sys/types. h"
·sys/systm.h"
·sys/dir.h"
·sys/signal.h"
·sys/user.h"
"sys/errno.h"
"sys/file.h"
·sys/tty.h u
·sys/termio. h"
·sys/conf.h"
·sys/sysinfo.h"
"sys/var.h"
·setjmp.h"
·sys/reg.h"
·sys/mmu.h"
·sys/proc.h"

teproc() ;

1*

*

structure to access Tecmar device registers

*1
struct tedevice {
char
filll;

/*
fdefine te dvlsb te rbr
char
fil12;
char
te ier;
fdefine te dvmsb t; ier
char
fil13;
char
te iir;
fill4;
char
char
te lcr;
char
fil15:
char
te mcr:
fil16;
char
te Isr;
char
fil17;
char
char
te msr:
fillS;
char
char
te scrat;
char
fill [Ox200-16);

/*

+1 data register * I
Isb of divisor latch *1

/* +3 interrupt enable register */
/*
msb of divisor latch */
/* +5 interrupt id register */

tdefine MODEM
tdefine tedev (dl

Ox80
( (d)&Ox7f)

tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

2304
1356
1047
857
768
384
192
96
64
58
4S
32
24
16
12

/* +9 modem control register *1

};

tdefine
tdefine
tdefine
tdefine

/* Interrupt enable register bits *1
ERBFI
OxOl
/* Enable received data available interrupt */
ETBEI
Ox02
1* Enable transmitter enable holding register empty interrupt */
ELSI
Ox04
/* Enable receiver line status interrupt *1
EDSSI
OxOS
/* Enable modem status interrupt */

tdefine
tdefine
tdefine
tdefine

/* Interrupt ident register bits * /
IRQ
Ox01
1* Interrupt request, o if interrupt pending */
THE
Ox02
1* Transmitter holding register empty *1
IID
Ox06
1* Interrupt ID bit mask *1
RID
Ox04
1* Interrupt receive bit mask *1

tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

1* Line
BITSS
BITS6
BITS7
BITSS
STOPl
STOP2
PEN
EPS
SPS
SBRK
DLAB

1* +13 modem status register * /
/* +15 scratch register (S250-A only) *1
1* sized to make tedevice be Ox200 long *1

}:

/*
* structure to access the interrupt reset bit
*/
struct teidevice {
struct tedevice fill[7]:I* filler */
skip;
char
char
te_intr:
1* interrupt reset location *1
};

/*

* array used to remap ivec interrupt board slot number to tty slot
"/
int te_remap[3];
/*

* Slot id to interrupt reset address
*I
struct teidevice *te idevice[3) - {
(struct teid;vice .) (STDIOI,
(struct teidevice *1 (STDIO+Ox40001,
(struct teidevice *) (STDIO+OxSOOO)
};

extern struct tty te tty[lJ;
extern struct ttyptr-te_ttptr[l];

6

/* -1 means hangup, -2 means invalid */
int
tebaudmap [J - {
-1, BAUDSO, BAUD75, BAUDllO, BAUD134, BAUD1S0, BAUD134,
BAUD300, BAUD600, BAUD1200, BAUD1S00, BAUD2400,
BAUD4800, BAUD9600, BAUD19200, BAUD3S400

1* +7 line control register *1

1* +11 line status register */

BAUDSO
BAUD7S
BAUDllO
BAUD134
BAUD1SO
BAUD300
BAUD600
BAUD1200
BAUD1800
BAUD2000
BAUD2400
BAUD3600
BAUD4800
BAUD7200
BAUD9600
BAUD19200
BAUD38400
BAUD56000

1* modem control on bit */
1* from unix device nU!!IDer to device *1

control
OxOO
ox01
ox02
ox03
OxOO
Ox04
Ox08
OxlO
ox20
Ox40
Ox80

register bits *1
5 bits */
6 bits *1
7 bits *1
8 bits *1
One stop bit *1
Two stop bit * I
Parity enable *1
Even parity select *1
stick parity *1
set break * /
Divisor latch access. ilo direction bit *1

1*
1*
1*
/*
1*
1*
1*
1*
1*
1*
1*

1* Modem control register bits */
tdefine DTR
ox01
1* Data terminal ready */
tdefine RTS
Ox02
1* Request to send *1
status register bits */
OxOl
/* Data ready *1
Ox02
/* OVerrun error on receiver */
Ox04
/* Parity error */
Ox08
/* Framing error *1
OxlO
/* Break interrupt */
ox20
/* Trammdtter holding register
Ox40
/* Transmitter empty */

tdefine
tdefine
tdefine
tdefine
tdefine
'define
'define

/* Line
DATARDY
OV ERR
PE-ERR
FR-ERR
BR- INT
THRE
TEMT

'define
tdefine
tdefine
tdefine

/* Modem status
DCTS
OxOl
DDSR
ax02
TERI
Ox04
DDCD
OxOS

register bits

.,

*/

1* Delta clear to send */
1* Delta data set ready */
/* Trailing edge ring indicator */
/* Delta data carrier detect *1

Fri Sep

tecmar.c
tdefine
tdefine
tdefine
tdefine

CTS
DSR
RI
DCD

I*
1*
1*
1*

Oxl0
Ox20
Ox40
Ox80

5 19:09:15 1986

2

Clear to send * I
Data set ready *1
Ring indicator *1
Data carrier detect *1

if

(!

tp->t state &= -CARR ON:
(flag & FNDELAY»
while «tp->t state&CARR ON) == 0) (
tp->t-state I~ wOPEN:
(void) sleep ( (caddr_t) &tp->t_rawq, TTOPRI):

int teslotsused - 0:
SPLOO:
(*linesw[tp->t_line] .l_open) (tp):

1*
* Initialize the baud rate
slot - 0, 1, or 2
*/
teinit (slot)

1* ARGSUSED */
teclose (dev, flaq)
dey t dey:
int-flag;

{

register i, val;

(

*addr;

if (teslotsused+4 > te cnt) (
printf("\n\nsystem only confiqured for %d tecmar ports\n\n", te_cnt):
return (1) :

register struct tedevice
register struct tty *tp;
register d;

te remap [slot] - tes1otsused;
val - STDIO + slot*Ox4000 + Ox200;
for (i = teslotsused; i < teslotsused+4; i++) (
te ttptr[i].tt addr - val;
te-ttptr[i].tt-tty = &te tty[i];
val +- Ox200; -

d - tedev{dev);
tp - te ttptr[d].tt tty;
(*linesw [tp->t line].1 close) (tp) ;
if ItP->t cflag&HUPCL)-{
addr - (struct tedevice *)te_ttptr[d].tt_addr;
d - 0;

addr->te_mcr - d;
teslotsused
return(O) ;

+~

4;

1* ARGSUSED * I
teopen(dev, flag)
dey t dey;
( register struct tedevice *addr:
register struct tty *tp;
register d;
Hfdef SINGLEUSER
register struct proc *p;
tendif SINGLEUSER

teread (dev)
dey t dey;
(

-

register struct tty *tp;
tp - te ttptr[tedev(dev) ].tt tty;
(*linesw[tp->t_line] .l_read)(tp);

tewrite (dev)
dev_t dey:
(

d

tedev (dev);
i f (d >= te_cnt)
u.u_error
return;

register struct tty *tp;

=

=

tp ~ te ttptr [tedev (dev) ].tt tty;
(*linesw[tp->t_line].l_write) (tp);

ENXIO;

tp - te_ttptr[d].tt_tty;
tifdef SINGLEUSER
p - u.uyrocp;
i f 11p->pyid - p->pygrp)
&& lu. u ttyp -- NULL)
&& (tp->tygrp == 0»
{
u.u_error ~ ENOTTY:
return;

teproc (tp, cmd)
register struct tty *tp;
(

register struct ccblock *tbuf;
register struct tedevice *addr;
register dev_t dey;
int s;
extern ttrstrt () ;

tendif SINGLEUSER
addr - (struct tedevice *)te ttptr[d].tt addr;
i f (tp 0 II addr ~ 0) ( u.u_error - ENXIO;
return;

s - spltty();
dey - tp->t index;
addr = (struct tedevice *)te_ttptr[dev].tt_addr;
switch (cmd) (

tp->t index - d:
SPLS I);
i f l(tp->t_state&(ISOPENIIfOPEN» ~ 0) (
tp->tyroc - teproc;
ttinit (tp);
tp->t iflag - ICRNL I ISTRIP;
tp->t-oflag - OPOST I ONLCR I TAB3;
tp->t-lflag - ISIG I ICANON I ECHO I ECHOK;
tp->t-cflag - sspeed I CS8 I CREAn I HUPCL;
teparam(dev) ;
te modem [d] - dey & MODEM;
if- «dev&MODEM)--O I I addr->te msr&DSR)
tp->t_state 1- CARR_ON:
else

case T_TlME:
tp->t_ state
goto start;

&-

-TIMEOUT;

case T_HFLUSH:
tbuf - &tp->t tbuf;
tbuf->c size
tbuf->c count;
tbuf->C-count - 0:
I .. fall-through * I
case T_RESUME:
tp->t_state &- -TTSTOP;
goto start:

=-

case T_OUTPUT:
start:

Fri Sep

tecmar.c

5 19:09:15 1986

3

i f (tp->t state & (TTSTOP 1TIMEOUT 1BUSY)) {
/* i f «tp->t_state & BUSY) ~ 0) {
addr - (struct tedevice *) «int)addr & OxFCeOOOj;
( (struct teidevice *) addr) ->te_ intr - dev;

tp - te ttptr[tedev(dev) J.tt tty;
addr - t_cflag & CBAUD]) = -2) {
u.u_error - EINVAL;
return;

} "I
break;
}

i f (tp->t state & TTXOFF) {
tp->t state &- -TTXOFF;
tp->t-state 1- BUSY;
addr->te_rbr = eSTOP:
break:

s

=

0:

1*
" hanqup the line

"I
i f (speed ~ -1) {
addr->te_mcr - s;
return:

}

i f (tp->t state & TTXON)
tp->t state &= -TTXON:
tp->t-state 1- BUSY:
addr->te_rbr - eSTART:
break:

i f (tp->t_state & BUSY) (
te_dparam[tedev(dev)] = 1:
return:

tbuf = &tp->t tbuf:
i f «tbuf->cytr = 0) 1 1 (tbuf->c count == 0)) {
i f (tbuf->cytr)
tbuf->cytr -- tbuf->c_size - tbuf->c_count:
i f (! (ePRES & (*linesw[tp->t line].l output) (tp»)) (
break:
--

1*

*

set new speed

*1
oldpri = spltty () :
addr->te lcr = DLAB:
addr->te-dvlsb = speed;
addr->te::::dvmsb - speed »
addr->te_lcr - s;

tp->t state 1= BUSY;
addr->te_ier = ERBFI 1 ETBEI 1 ELSI 1 EDSSI;
addr->te_rbr - *tbuf->cytr++:
tbuf->c_count--:
break:

8;

/*

*

case T_SUSPEND:
tp->t_state 1= TTSTOP;
break:

set line control information

*1
i f «tp->t_cflaq & CSIZE) - eS8)
s 1- BITS8:
else if «tp->t cflag & CSIZE)
eS7)
s 1= BITS7:
else i f «tp->t cflag & CSIZE)
eS6)
s 1= BITS6;
else if «tp->t_cflag & eSIZE) = eSS)
s 1= BITSS:
i f (tp->t cflag & CSTOPB)
s-I= STOP2:
i f (tp->t cflag & PARENB)
if «tp->t_cflag & PARODD)
0)
s 1= PENIEPS;
addr->te_lcr - s;

case T_BLOCK:
tp->t state &- -TTXON;
tp->t-state 1= TBLOCK:
tp->t::::state 1= TTXOFF;
goto start:
case T_ RFLUSH:
i f (! (tp->t state&TBLOCK)
break;
1* fall through */
case T_UNBLOCK:
tp->t state &= - (TTXOFF 1TBLOCK);
tp->t-state 1= TTXON;
goto ~tart;

/*
" set modem control information
*1
addr->te_mcr - DTR
RTS;

case T_BREAK:
tp->t state 1- TIMEOUT;
timeout (ttrstrt, (caddr_t)tp, v.v_hz»2);
break;

/*
* enable interrupts

*/
addr->te_ier

=

ERBFI 1 ETBEI 1 ELSI 1 EDSSI;

splx(s) ;

1*
* reset pending interrupts
teioctl (dev, cmd, arg, mode)
dey t dey;
{

*1
c - addr->te_ rbr;
c = addr->te_lsr;
c - addr->te msr:
c - addr->te::::iir;

-

if (ttiocom(te_ttptr[tedev(dev)].tt_tty, cmd, arg, mode)
teparam(dev) ;

splx (oldpri) ;
tepararn (dev)
regist:er dey t: dey;
{
register struct tty *tp;
register struct tedevice *addr;
register int s, speed, oldpri;
char c;

/* VARARGS */
teintr (ap)
struct arqs *ap;
{

register struct t.edevice • addr;

Fri Sep

tecmar.c

5 19:09:15 1986

4
any++;
goto restart;

register struct ccblock *cbp;
register struct tty *tp;
register int c, lent, flg, iir, Isr;
register char ctmp;
int i, any;
struct teidevice * iaddr;
int index, s;
char Ibuf[3];

I
i f (flg&PARMRK)
Ibuf[2] - 0377;
Ibuf[l] = 0;
lcnt - 3;
sysinfo.rawch += 2;
else
c ~ 0;

s - splS ();
index - te_remap[ap->a_dev];
iaddr = te idevice [ap->a dev];
c = 0;
iaddr->te_intr - c;
/* reset master interrupt */

I else
i f (flg&ISTRIP)
c &- 0177;
else {
i f (c ~ 0377 && flg&PARMRK)
Ibuf[l] - 0377;
lent ~ 2;

again:
any = 0;
for (i = index; i < index+4; i++) {
addr = (struct tedevice *)te_ttptr[i].tt_addr;
restart:
iir - addr->te iir;
i f (iir & IRQ)continue;
tp = te ttptr[i].tt tty;
Isr - addr->te Isr;i f (iir & RID)-{
sysinfo. rcvint ++;
c - addr->te_rbr & OxFF;
i f (tp->t_rbuf.cytr - NULL)
any++;
goto restart;
I
i f «lsr & DATARDY) ~ 0)
c - 0;
i f (tp->t iflag & IXON) {
ctmp = c & 0177;
i f (tp->t state & TTSTOP) {
if (ctmp - CSTART I I tp->t iflag & IXANY)
(*tp->tyroc) (tp, T_RESUME);
I else {
i f (ctmp - CSTOP)
(*tp->tyroc) (tp, T_SUSPEND);

/*
." Stash character in r_buf
*/
cbp = &tp->t rbuf;
i f (Cbp->cytr ~ NULL)
any++;
goto restart:
i f (lent !- 1) {
Ibuf[O] - c;
while (lent)
*cbp->c ptr++ = Ibuf[--lent];
i f (--cbp->c count - 0) {
Cbp->cytr -- cbp->c_size;
(*linesw[tp->t_line] .l_input) (tp);

if (cbp->c size !- cbp->c count) {
Cbp->cytr -= cbp=>c_size - cbp->c count;
l*linesw[tp->t_line].l_input) (tp);
}

i f (ctmp

~ CSTART II ctmp
any++;
goto restart;

~

} else {
*cbp->cytr ~ c:
cbp->c count--:
(*linesw[tp->t_line].l_input) (tp);

CSTOP) {

any++;
goto restart;

/*

*

Check for errors
*/
lcnt = 1;
flg = tp->t iflag;
i f (lsr & (PE ERRIFR ERRIOV ERRIBR INT»
{
i f (clsr & PE_ERR) && (flg-& INPCK»
c 1- PERROR;
i f (lsr & OV_ERR)
c 1- OVERRUN;
i f (lsr & FR_ERR)
c 1- FRERROR;
i f (lsr & BR_INT)
/ * reset char on a break * I
c - OVERRUN;
I
i f (C& (FRERROR IPERRORI OVERRUN) )
i f «c&0377) - 0) {
i f (flg&IGNBRK)
any++;
goto restart:
I
i f (flg&BRKINT) {
signal (tp->t pgrp, SIGINT);
tty flush (tp, - (FREAD IFWRITE) ) ;
any++;
goto restart;
}

else {

i f (iir&THE) {
sysinfo.xmtint++;
tp->t state &- -BUSY;
i f (t~ dparam[i]) {
- te dparam[i] - 0;
teparam(i) ;

teproc(tp, T_OUTPUT);
} else {
/*
.. must be a modem transition interrupt
*/
temodem(tp, addr->te_msr):
any++:
goto restart;
I
i f (any !- 0)
goto again;
spIx(s) ;
temodem(tp, msr)
register struct tty *tp;
{

i f (flg&IGNPAR)

!

if «tp->t_state& (ISOPENI WOPEN) )--0)

Fri Sep

tecmar.c
i f (msr

return;
& DSR "

5 19:09:15 1986

te mode.ln[tp->t index] -- 0) {

i f «tp->t -;tate&CARR ON) ~ 0) {

tp=>t state ,:; CARR ON;
i f (tp->t state&WOPEN)
1L/;keup( (caddr_t) ftp->t_rawq);

I
I else {
i f (tp->t state&CARR ON) {
tp->t state &- -CARR ON;
i f (tp->t_ rbuf. cytr- ! - NULL)
ttyflush (tp, FREAD! FWRITE) ;
signal (tp->tyqrp, SIGHUP);

5

tecmar. su. c:;

Fri Sep

5 19:09:06 1986

I"
Lisa INS8250A device driver

1
extern char te dparam[l):
extern char te-modem (1] :
extern int te_cnt;

Copyright 1984 UniSoft Corporation

"I
tinclude
#include
tinclude
#include
tinclude
#include
#include
#include
#include
tinclude
tinclude
tinclude
tinclude
#include
#include
#include
tinclude
#include
int

"sys/param.h"
"sys/config. h"
"sys/types .h Ol
"sys/systm.hu
"sys/dir.h"
·sys/signal.h"
·sys/user.h"
·sys/errno.h"
·sys/file.h"
·sys/tty.h"
"sys/termio.h u
·sys/conf .h"
• sysl sysinfo. h"
·sys/var.h"
·setjmp.h"
"sys/reg.h"
"sys/mmu.h"
"sys/proc.h"
teproc() ;

I"
" structure to access Tecmar device registers
*1
struct tedevice {
char
fil11:
char
te rbr;
I" +1 data register * I
tdefine te dvlsb te rbr
1*
Isb of divisor latch *1
char
fi112:
char
te ier;
1* +3 interrupt enable register */
tdefine te dvmsb te ier
1*
msb of divisor latch *1
char
fi113;
te iir;
char
/* +5 interrupt id register */
fil14;
char
char
te lcr;
/* +7 line control register */
char
fillS;
te mcr;
char
/* +9 modem control register */
fil16;
char
char
te lsr:
/* +11 line status register */
char
fil17:
char
te msr;
/* +13 modem status register */
char
fil18:
char
te scrat;
/* +15 scratch register (8250-A only) *1
fill (Ox200-l6) ; 1* sized to make tedevice be Ox200 long *1
char
}:

/*

* structure to access the interrupt reset bit
*/
struct teidevice {
struct tedevice fill (7) ; /* filler * I
char
skip;
char
te_intr;
1* interrupt reset location *1
};

1*

* array used to remap ivec interrupt board slot number to tty slot

tdefine MJDEM
tdefine tedev(d)

Ox80
«d) fOx7f)

tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

2304
1356
1047
857
768
384
192
96
64
58
48
32
24
16
12
6

1* -1 means hangup, -2 means invalid *1
int

1*

* Slot id to interrupt reset address
*I
struct teidevice *te idevice [3] - {
(struct teidevice *) (STOIC),
(struct teidevice ") (STDIO+Ox4000),
(struct teidevice *1 (STDIO+Ox80001
);

ext.ern struct tt.y te t.t.y [1] ;
extern struct ttyptr- te_ ttptr [1] ;

tebaudmap () = {
-1, BAUD50, BAUD75, BAUDllO, BAUD 1 34, BAUD150, BAUD134,
BAUD300, BAUD600, BAUD1200, BAUD1800, BAUD2400,
BAUD4800, BAUD9600, BAUD19200, BAUD38400
};

tdefine
tdefine
tdefine
tdefine

I * Interrupt enable register bits *1
/* Enable received data available interrupt *1
ERBFI
OxOI
1* Enable transmitter enable holding register empty interrupt */
ETBEI
Ox02
1* Enable receiver line status interrupt */
ELSI
Ox04
EDSSI
Ox08
/* Enable modem status interrupt * I

tdefine
tdefine
tdefine
tdefine

IRQ
THE
!ID
RID

tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

1* Line
BITS5
BITS6
BITS7
BITS8
STOPl
STOP2
PEN
EPS
SPS
SBRK
DLAB

1* Interrupt ident
/*
OxOl
1*
Ox02
/*
Ox06
1*
Ox04
control
OxOO
OxOl
Ox02
Ox03
OxOO
ox04
axa8
axla
ax20
ax4a
ax8a

register bits * /
Interrupt request, 0 if interrupt pending */
Transmitter holding register empty *1
Interrupt ID bit mask *1
Interrupt receive bit mask */

register bits *1
/* 5 bits *1
1* 6 bits */
1* 7 bits *1
/* 8 bits */
/* One stop bit *1
1* Two stop bit */
/* Parity enable */
/* Even parity select */
/* Stick parity *1
/* set break *1
/* Divisor latch access. i/o direction bit */

/* Modem control register bits */
tdefine DTR
axal
/* Data terminal ready */
tdefine RTS
ax02
1* Request to send */

*1
int te_remap(3];

BAUD50
BAUD75
BAUD110
BAUD134
BAUD150
BAUD300
BAUD600
BAUD1200
BAUD1800
BAUD2000
BAUD2400
BAUD3600
BAUD4800
BAUD7200
BAUD9600
BAUD19200
BAUD38400
BAUD56000

/* modem control on bit *1
1* from u.."lix device n1..L~r to device *1

tdefine
tdefine
tdefine
tdefine
tdefine
tdefine
tdefine

tdefine
tdefine
tdefine
tdefine

1* Line
DATARDY
OV ERR
PE-ERR
FR-ERR
BR- INT

THR!
TEMT

status register bits */
OxOl
1* Data ready */
Ox02
1* OVerrun error on receiver *1
Ox04
/* Parity error */
axas
/* Framing error * I
OxlO
1* Break interrupt * /
Ox20
/* Transmitter holding register *1
ax4a
/* Transmitter empty *1

1* Modem status register bits *1
DCTS
axOl
1* Delta clear to send "/
DDSR
ax02
/ * Delta data set ready • /
TERI
ax04
/ * TrailinlJ edlJe ring indicator
DDCD
OxOS
/* Delta data carrier detect *1

*I

Fri Sep

tecmar.su.c
"define
"define
tdefine
tdefine

CTS
DSR
RI
DCD

int teslotsused

OxlO
Ox20
Ox40
oxao
=

5 19:09:06 1986

2

Clear to send * /
Data set ready "/
Ring indicator * /
Data carrier detect */

/*
/"
/"
/*

if

(!

tp->t state &~ -CARR ON;
(flag & FNDELAY»
while «tp->t state&CARR ON) ~ 0) !
tp->t-state 1- wOPEN;
(void) sleep( (caddr_t) &tp->t_rawq, TTOPRI);

0;
SPLO () ;
("linesw[tp->t_line].l_open) (tp);

/"
" Initialize the baud rate
slot ~ 0, 1, or 2

/" ARGSUSED * I
teclose (dev, flag)
dey t dey;
int-flag;

"/
teinit (slot)
{

register i, val;

{

if (teslotsused+4 > te cnt) {
printf("\n\nSy"item only configured for %d tecmar ports\n\n", te_cnt):
return(l) :

register struct tedevice "addr:
register struct tty "tp;
register d;

te remap [slot] = teslotsused:
val - STDIO + slot"Ox4000 + Ox200:
for (i = teslotsused: i < teslotsused+4: i++) {
te ttptr[i] .tt addr = val;
te-ttptr[i].tt-tty = &te tty[i];
val +- Ox200; -

d = tedev(dev);
tp = te ttptr[d].tt tty;
(*linesw[tp->t lineT.l close) (tp);
if (tp->t_cflag&HUPCL)-{
addr = (struct tedevice *)te_ttptr[d].tt_addr;
d = 0;

addr->te_mcr

=

d:

teslotsused +- 4;
return (0) ;
teread (dev)
dev_t dey:

/" ARGSUSED "I
teopen(dev, flag)
dev_t dey:

{

register struct tty *tp:

{

register struct tedevice *addr;
register struct tty "tp:
register d;
tifdef SINGLEUSER
register struct proc *p:
tendif SINGLEUSER

tp - te ttptr[tedev(devl].tt tty;
("linesw[tp->t_line].l_read)(tp) :

tewrite (dev)
dev_t dey;

!
d = tedev(dev);
if (d >= te_cnt)
u.u_error
return;

register struct tty *tp:
=

ENXIO;

tp = te_ttptr[d].tt_tty;
tifdef SINGLEUSER
p - u.uyrocp;
if «p->pyid - p->pygrpl
&& (u.u ttyp NULL)
&& (tp->tygrp ~ 0» {
u. u_error = ENOTTY;
return:

tp - te_ttptr[tedev(dev)].tt_tty:
(*linesw[tp->t_line].l_write) (tp);

teproc (tp, cmd)
register struct tty *tp;
{

register struct ccblock *tbuf;
register struct tedevice "addr;
register dey_ t dev;
int s:
extern ttrstrt (I :

tendif SINGLEUSER
addr - (struct tedevice *Ite ttptr[d].tt addr;
if (tp -- a II addr - 01 ! u.u_error - ENXIO:
return:

s - spltty () :
dey = tp->t index:
addr - (struct tedevice "I te_ ttptr [dev] . tt_ addr;
switch (cmdl !

tp->t index - d;
SPL5 ():
if «tp->t state& (ISOPEN IIfOPEN) 1 -= 01 !
tp=>tyroc - teproc:
ttinit (tp) :
tp->t_iflag = ICRNL I ISTRIP:
tp->t_oflag - OPOST I ONLCR I TAB3:
tp->t lflag - ISIG I ICANON I ECHO I BCHOK;
tp->t=cflag - sspeed I csa I CREAn 1 HUPCL;

case T_TlME:
tp->t state &= -TIMEOUT:
goto "itart:
case T_NFLUSH:
tbuf - &tp->t tbuf;
tbuf->c size
tbuf->c count;
t!::IUf->c- count - 0;
I * fall-through "/
case T_RESUME:
tp->t state &- -TTSTOP;
goto start:

=-

tepa ram (dev) ;

te modem[d] - dey & MODEM;
if- «dev&MODEMI--O 1 1 addr->te msr&DSRI
tp->t_state 1- CARR_ON:
else

start:

tecmar.su.c

Fri Sep

5 19:09:06 1986

3
tp - te ttptr[tedev(dev)].tt tty;
addr - t_cflag & CBAUD]) ~ -2) {
u.u_error - EINVAL;
return;

if (tp->t state & (TTSTOP I TIMEOUT IBUSY»
{
i* i f «tp->t state & BUSY) -- 0) {
addr -= (struct tedevice *) «int)addr & OxFCCOOO);
«struct teidevice *) addr) ->te_intr = dey;
I *1
break;
I
i f (tp->t_state & TTXOFF) {
tp->t state &= -TTXOFF;
tp->t-state 1- BUSY;
addr->te_ rbr = CSTOP;
break:

s

=

0;

1*

*

hangup the line
*/
i f (speed - -1) {
addr->te_ mcr
return;

i f (tp->t_state & TTXON)
tp->t_state &- -TTXON;
tp->t state 1- BUSY;
addr->te_rbr - CSTART;
break;

=

s;

i f (tp->t state & BUSY) {
te_dparam[tedev(dev)] - 1;
return;

tbuf = &tp->t tbuf;
i f «tbuf->cytr = 0) II (tbuf->c count == 0»
{
i f (tbuf->cytr)
tbuf->cytr -= tbuf->c_size - tbuf->c_count;
i f (!(CPRES & (*linesw[tp->t line].l output) (tp»)
break;
--

1*

*

set new speed

*1
oldpri = spltty () ;
addr->te lcr - DLA8;
addr->te- dvlsb - speed;
addr->te=:dvmsb - speed »
addr->te_Icr - s;

tp->t state I= BUSY;
addr->te_ier = ERBFI I ETBEI I ELSI I EDSSI;
addr->te_ rbr - *tbuf->cytr++;
tbuf->c count--;
break; -

8:

1*

*

case T_SUSPEND:
tp->t_state 1= TTSTOP:
break;

set line control information

*1
i f «tp->t_cflag & CSIZE) -- CS8)
s 1- BITS8:
else if «tp->t cflag & CSIZE)
CS?)
s I- BITS?;
else if «tp->t cflag & CSIZE)
CS6)
s 1= BITS6:
else if «tp->t_cflag & CSIZE) = CS5)
s 1- BITS5;
i f (tp->t cflag & CSTOPB)
s-I= STOP2;
i f (tp->t cflag & PARENS)
if «tp->t cflag & PARODD) -- 0)
s 1= PENIEPS;
addr->te_Icr = s;

case T_BLOCK:
tp->t state &= -TTXON;
tp->t-state 1= TBLOCK;
tp->t=:state 1= TTXOFF;
goto start;
case T_RFLUSH:
if (! (tp->t state&TBLOCK»
break;
1* fall through *1
case T_UNBLOCK:
tp->t state &- -(TTXOFFI TBLOCK) ;
tp->t-state 1= TTXON;
goto start;

1*

*

set modem control information

*1
addr->te_mcr - DTR

case T_BREAK:
tp->t state 1- TIMEOUT:
timeout (ttrstrt, (caddr_tltp, v.v_hz»21;
break;

RTS;

1*
* enable interrupts

*1
addr->te_ier

=

ERBFI I ETBEI I ELSI I EDSSI;

splx(s) :

1*
* reset pending interrupts
teioctl (dev, cmd, arg, mode I
dey t dey;
{

*1
c
c
c
c

-

if (ttiocom(te ttptr[tedev(devl].tt tty, cmd, arg, mode»)
teparai(dev);
-

-

addr->te_ rbr;
addr->te_lsr;
addr->te msr;
addr->te=:iir;

splx(oldpri) ;
teparam (dev)
register dey t dev;
{
register struct tty *tp;
register struct tedevice *addr;
register int s, speed, oldpri;
char c;

/ * VARARGS * I
teintr (ap)
struct args *ap;
{

register struct tedevice *addr;

tecmar.su.c

Fri Sep

5 19:09:06 1986

4
any++;
goto restart;

register struct ccblock *cbp;
register struct tty *tp;
register int c, lent, fIg, iir, Isr;
register char ctmp;
int i, any;
struct teidevice * iaddr ;
int index, s;
char Ibuf[3];

i f (flg&PARMRK)
Ibuf[2] = 0377;
Ibuf[1] - 0;
lcnt - 3;
sysinfo.rawch +- 2;
else
c = 0;

s - sp15();
index = te remap[ap->a dev];
iaddr = te- idevice [ap->a dev];
c = 0;
iaddr->te_intr - c;
/* reset master interrupt *1

else
i f (flg&ISTRIP)
c &- 0177;
else {
i f (c - 0377 && flg&PARMRK)
lbuf[l] - 0377;
lcnt = 2;

again:
any = 0;
for (i - index; i < index+4; iff) {
addr - (struct tedevice *)te_ttptr[i].tt_addr;
restart:
iir = addr->te iir;
i f (iir & IRQ)continue;
tp - te ttptr[i].tt tty;
Isr = addr->te Isr;i f (iir & RID)-{
sysinfo. rcvint++;
c - addr->te rbr & OxFF;
i f (tp->t_rbuf.cytr = NULL)
any++;
goto restart;

}

1*
* Stash character in r_buf

*1
cbp

=

&tp->t rbuf;

i f (Cbp->cytr

=

NULL)

any++;
goto restart;
if (lcnt != 1) {
lOOf[O] - c;
while (lcnt)
*cbp->cytr++ = lbuf[--lent];
if (--cbp->c count - 0) {
cbp->c ptr -- cbp->c size;
(*linesw[tp->t_line]-:-l_input) (tp);

}

i f «lsr & DATARDY) - 0)
c - 0;
i f (tp->t iflag & IXON) {
ctmp = C & 0177;
i f (tp->t state & TTSTOP) {
if (ctmp - CSTART 1 1 tp->t iflag & IXANY)
(*tp->tyroc) (tp, T~)ESUME);
} else
i f (ctmp = CSTOP)
(*tp->tyroc) (tp, T_SUSPEND);

}

if (cbp->c size != cbp->c count) {
Cbp->cytr -= cbp=>c_size - cbp->c_count;
(*linesw[tp->t_line] . I_input) (tp);
}

}

i f (ctmp - CSTART 1 1 ctmp any++;
goto restart;

} else {

CSTOP) {

*cbp->cytr - c;
cbp->c count--;
(*linesw[tp->t_linel.l_input) (tpl;
any++;
goto restart;

/*
* Check for errors
*1
lent = 1;
flg - tp->t iflag;
i f (lsr & {FE ERRIFR ERRIOV ERRIBR INT»
{
i f «lsr & PE_ERR) && (flg-& INPCK»
c 1- PERROR;
i f (lsr ;; OV_ERRJ
c 1 = OVERRUN;
i f (lsr & FR_ERRJ
c 1- FRERROR;
i f (lsr & BR_INT)
c = OVERRUN;
1* reset char on a break *1

)

i f (iir&THE) {

sysinfo.xmtint++;
tp->t state &= -BUSY;
i f (tEl dparam[i]) {
- te dparam[i] - 0;
teParam(i) ;
teproc(tp. T_OUTPUT);
} else (

1*
* must be a modem transition interrupt

*1
i f (c& (FRERROR 1PERROR 1OVERRUN) )
i f «c.0377) - 0) {
i f (flg&IGNBRK)
any++;
goto restart;

temodem(tp, addr->te_msr);
any++;
goto restart;
}

i f (any !- 01

}

i f (flg&BRKINT) {
signal (tp->tygrp, SIGINT);
ttyflush (tp. (FREAD 1FIVRITE) ) ;
any++;
goto restart;
}

} else {
i f (flg&IGNPAR)

qoto aqain;
splx (sl ;
temodem (tp, msr)
register struct tty *tp;
{

{

if «tp->t_state& (ISOPEN I WOPEN) ) --0)

tecmar.su.c

Fri Sep

5 19:09:06 1986

return;
i f (msr & DSR II te_modem[tp->t_indexl = 0)
i f «tp->t state&CARR ON) = 0) (
tp=>t state
CARR ON;
i f (tp..>t_state&WOPEN)

1=

)

) else {
i f (tp->t_state&CARR_ON) {
tp->t state &- -CARR ON;
i f (tp..>t_rbuf.cytr-!- NULL)
tty flush (tp. FREADIFWRITE);
signal (tp->tJ>9'rp. SIGHUP);

5

text.c

Fri Sep

5 19:08:28 1986

1

1*

@(t) text. c
1. 3 * I
tinclude usys/param. h n
tinclude Hsys/config.h"
tinclude ·sys/mmu.h"
tinclude ·sys/types.h"
iinclude "sysl sysmacros. hO!
tinclude ·sys/systm.h"
tinclude Hsys/map. h"
+include "sys/dir.h"
tinclude ·sys/signal.h"
tinclude "sys/user .h"
tinclude Hsys/proc. h"
tinclude "sys/context.h"
tinclude ·sys/text.h"
tinclude ·sys/inode.h"
tinclude ·sys/buf.h"
tinclude ·sys/seg.hu
tinclude ·sys/var .hu
tinclude "sys/sysinfo.h"
tinclude ·sys/scat.h"

if (tos < 0)
tos = 0;
tifdef NONS CAT LOAD
addr +- a;
tendif
!- 0)
panic(Uout of swap space");
a - p->p_xaddr[O);
1* for Ibin/ps *1

if

(s

} else {
tifdef NONSCATLOAD
swap ( (daddr_t)a, (int)p->p_addr, (mem_t)os, B_WRITE);
telse
tendif
p->p flag &= -SNOMMU;
i f (rf) {
tifdef NONS CAT LOAD
telse

typedef int

memfree (p->p scat);
p->p_scat = 0;

1*

tendif

" Swap out process p.
* The ff flag causes its core to be freed-* it may be off when called to create an image for a
* child process in newproc.
* On a partial swap ff is the negative number of blocks to be swapped.
" Os is the old size of the process,
" and is supplied during core expansion swaps.
*1
xswap(p, ff, os)
register struct proc .p;

cxrelse (p->p context);
p->p dkaddr :- a;
p->p- flag &= - (SLOAD I SLOCK) :
tifndef NONSCATLOAD
i f (p->p flag & SSWAPIT) (
p->p flag &= -SSWAPIT;
p->pflag 1- SCONTIG;
wake"iip( (caddr_t) scatmap);

{

tendif
register a, i, s, tos;
int addr, sz;

if (os == 0)
os = p->p size:
p->p flag 1= (SLOCK I SNOMMUl ;
xccd;c(p->p_textp) ;
cxrelse (p->p context);
a = malloc(swapmap, ctod(p->p_size»);
if (a - NULL) (
1*
" s = decreasing click size of total disk space needed
* tos - decreasing click size of process being swapped
*1
tos = os;
s - p->p size;
+ifdef NONSCATLOAD
addr - p->p_ addr;
telse
addr - p->p_scat;
tendif
for (i-O; i < NSCATSWAP; iH) {
if «a = dtoc (mallocl (swapmap)) -- NULL)
break;
if (a > s)
a - s;
p->p xaddr[i) - malloc(swapmap, (mem_t)ctod(a));
p->p-xsize[i) = a;
sz --MIN(a, tos);
if (sz) {
tifdef NONSCATLOAD

p->p time ~ 0:
if (runout) (
runout = 0;
wakeup! (caddr_t) &runout);

/*
* relinquish use of the shared text segment
* of a process.
*1
xfree()
{

register struct text *xp;
register struct inode *ip;
register struct proc *p = u. uyrocp;
= p->p_textp) ~ NULL)
return;
xlock(xp) ;
xp->x flag &= -XLOCK;
p->p textp = NULL;
u.ujitsize - 0;
ip = xp->x iptr;
i f (--xp->i_count~O && «ip->i_mode&ISVTX)-O II xp->x_flag&XERROR»
xmsave (xp) ;
xp->x_iptr - NULL;
i f (xp->x daddr)
mfree(swapmap, ctod(xp->x_size), (int)xp->x_daddr);
cxtxfree !Xp) ;
ip->i flag &- -ITEXT;
if (ip->i flag&ILOCK)
ip->i_count--;
el$8
iput(ip) ;
} else
xccdec (xp) ;
cxrelse (u. uyrocp->p_context) ;

if «xp

telse
addr = swap(p->p xaddr[i], addr,
B_WRITE);

(mem_t)sz,

tendif
s -- a;
i f (s -

0)

break;
tos -- a:

1*

{

Fri Sep

text.c

5 19:08:28 1986

2

;, Attach to a shared text segment.
* If there is no shared text, just return.
* If there is, hook up to it:
* if it is not currently being used, it has to be read
* in from the inode (ip); the written bit is set to force it
x to be written out as appropriate.
* If it is being used, but is not currently in core,
* a swap has to be done to get it back.

*/
xalloc(ip)
register struct inode *ip:
struct text *xp;
ts:
struct text ·xpl:
struct user ·up;

register
register
register
register

up = &u;
if (up->u_exdata.ux_tsize return;
xpl ~ NULL;

/*

* Assure core for text segment
• Text must be locked to keep someone else from
• freeing it in the meantime.
,. x_ ccount must be O.
*1
xexpand (xp)
register struct text *xp:
{

if (xmlink(xp» {
xp->x_ccount++;
xunlock(xp) ;
return (1) ;

0)

loop:
for (xp

if (up->u error II up->u count!~O)
xp->x_flag - XERROR;
else
xp->x_flag - XWRIT:

&text[O]; xp < (struct text *)v.ve_text; xp++) {
if (xp->x iptr ~ NULL) {
if (xpl ~ NULL)
xpl - xp;
continue;

=

if (xp->x_iptr ~ ip) (
xlock(xp) ;
xp->x count++;
up->u~rocp->p_textp = xp;
if (xp->x ccount -- 0)
(void) xexpand (xp) ;
else
xp->x_ ccount ++;
xunlock (xp) ;
return;
i f ! (xp-xpll == NULL) (
printf(nout of text\n");
syserr. textovf++;
if (xumount (NODEV»
goto loop;
psignal (up->uyrocp, SIGKILL);
return;

xp->x_flag ~ XLOADIXLOCK;
xp->x_count = 1;
xp->x ccount - 0;
xp->x-iptr = ip;
ip->i-flag 1= ITEXT;
ip->i-count++;
ts = btoc(up->u exdata.ux tsize);
xp->x size = ts7
I * if- «xp->x daddr - malloc (swapmap, ctod (ts) ») == NULL) * /
1* panic(Uout of swap space"); *1
xp->x_daddr - 0;
1* defer swap alloc til later */
up->uyrocp->p_textp - xp;
if (xexpand (xp» {
(void) estabur ( (unsigned) ts, (unsigned) 0, (unsigned) 0, 0, RW);
xp->x_flag - XWRIT;
return;
(void) estabur ( (unsigned) ts, (unsigned) 0, (unsigned) 0, 0, RW);
up->u count - up->u exdata. ux tsize;
up->u-offset - sizeof (up->u eidata);
/* up-=>u offset - up->u eXdata.ux tst.art; */
up->u base - (caddr t)v-:-v ustart;1* up-=>u_base - 0;
up->u_segflg - 2;
up->uyrocP->p_flag 1- SLOCK;
readi (ip);
up->uyrocp->p_flaq &- -SLOCK;

}

Hfdef NONSCATLOAD
if «xp->x caddr - malloc(coremap, xp->x_size»
!- NULL) {
if-«xp->x flag&XLOADI-O)
sw'iP(Xp->x daddr, (int)xp->x caddr, xp->x size, B_READ);
xp->x ccount++;
xunlo~k(xp) ;
return (0) ;
telse
if «xp->x scat = memalloc(xp->x size»
!= NULL) (
if-«xp->x flag&XLOADI--O)
(void) swap(xp->x daddr, (int)xp->x scat,
xp->x_size, B_READI;
xp->x_ ccount ++;
xunlock(xpl;
return (0) ;
tendif
if (save(u.u ssav»
(
cxtxfree (xp) ;
sureg() ;
return(O) ;
xswap(u.uyrocp, 1, 0);
xunlock(xp) ;
u. u procp->p flag 1- SSWAP;
qswtch();
tifdef lint
return (0);
tendif
}

/*
• Lock and unlock a text segment from swapping
*/
xlock(xp)
register struct text *xp;
{

while (xp->x flag&XLOCK)
xp->x flag 1- XWANT;
(void) sleep ( (caddr_t)xp, PSWP);

xunlock (xp)
register struct text *xp:
i

*' -

UP"'>I1...;.~~ -

0;

i f (xp->x flaq&XlfANT)
w'ikeup( (caddr t)xp);
xp->x_flaq ,- -(XLOCKIXWANT);

1*

Fri Sep

text.C

5 19:08:28 1986

3

* Decrement the in-core usage count of a shared text segment.
register struct inode *ip;

* When it drops to zero, free the core space.
*/
xccdec(xp)
register struct text *xp;
i
int prevlock;

xlock(xp) ;
if (xp->x_count)
xunloek ixp) :
return (0) ;

if (xp==NULL II xp->x_ccount~O)
return;
xlock(xp) ;
..! ~
(1 (prevlock = (u. uyrocp->p_flag
SLeCK) ) }
u.u-procp->p_flag 1- SLDCK;
if (--xp->x ccount-O) (
i f (xp->x flag&XWRIT) (
xp->x flag &- -XWRIT;
if (Xp->x_daddr -= 0)
xp->x_daddr - swapalloc (ctod (Xp->x_size) , 1);
fifdef NONSCATLDAD

ip = xp->x iptr;
xmfree (ip)-;
xp->x flag &- -XLDCK;
xp->x- iptr = NULL;
cxtxfree (xp) ;
i f (xp->x daddr)
mfree{swapmap, ctod(xp->x_size), (int)xp->x_daddr);
ip->i flag &= -ITEXT;
i f (ip->i fl ag&I LOCK)
ip->i_count--;
else
iput(ip) ;
return(l) ;

felse
(void) swap (xp->x daddr,
(int)xp->i:_scat, xp->x_size, B_WRITE);
fendif

/*

*

xmsave (xp) ;
cxtxfree (xp) ;

allocate swap blocks, freeing and sleeping as necessary

*/
swapalloc (size, sflg)
{

i f (!prevlock)
u.u-procp->p_flag &- -SLOCK;
xunlock(xp) ;

register addr;
for (;;) {
if (addr

= malloc(swapmap, size»
return (addr) :
i f (swapclu ()
(
printf("\nWARNING: swap space running out\n U ) ;
printf(" needed 'lid blocks\n", size):
continue;

/"
" free the swap image of all unused saved-text text segments
" which are from device dev (used by umount system call) .
*1
xumount (dev)
register dev_t dev;

}

printf("\nDANGER: out of swap space\nA);
printf(" needed 'lid blocks\n", size);
i f (sflg) {
mapwant (swapmap) ++;
(void) sleep «caddr_t) swapmap, PSWP);
} else
return (0) ;

{

register struct inode *ip;
register struct text "xp;
register count = 0;
for (xp - &text[O]; xp < (struct text "lv.ve_text; xp++l {
i f «ip = xp->x iptr) = NULL)
continue;
if (dev !- NODEV && dev != ip->i_dev)
continue;
i f (xuntext (xp) )
count++;
return (count) ;

/"

* clean up swap used by text
"I
swapclu()
(

register struct text "xp;
register ans - 0;

/*

* remove a shared text segment from the text table, if possible.
*/
xrele lip)
register struct inode "ip;
{

register struct text "xp;
i f «ip->i flag&ITEXT) -

0)

return;
for (xp - &text[O]; xp < (struct text *)v.ve_text; xp++)
i f (ip--xp->x iptr)
(void) xuntext (xp) ;

/*

* remove text image from the text table.
" the use count must be zero.
*/
xuntext (xp)
reQister struct text *xp;

for (xp - text; xp < (struct text *) v. ve_text; xp++) {
i f (xp->x iptr = NULL)
continue;
i f (xp->x flag&XLOCK)
continue;
i f (xp->x daddr -- 0)
continue;
if (xp->x count) {
if (xp->x ccount)
mfree (swapmap, ctod (xp->x_ size) ,
(int)xp->x_daddr) ;
xp->x flag 1- XWRIT;
xp->x::::daddr
0;
ans++;
I
I else {
(void) xuntext (xp) ;
ans++;

Fri Sep

text.c

5 19:08:28 1986

4

return (ans) ;

tifdef NONSCATLOAD
mfree(coremap, tsvx->x_svsize,

(mem_t)tsvx->x_svcaddr);

telse
memfree «mem_t)tsvx->x_svscat);

/*
" free the saved text area associated with an inode

tendif
tsvx->x svflag
return(!) ;

*1
xmfree(ip)
register struct inode *ip;

&~

-XSVBUSY:

{

register struct svtext "svx:
fer (svx - &svtext [0]: svx < (struct s\rtext *) v. "''''2 s\r~ext; svx++) {
if (svx->x svflag&XSVBUSY &.Ii ip->i number":;;;:svx->x svnumber &&
ip->i dev=svx->x svdev) { svx->x_ svflag- &- -XSVBUSY;
tifdef NONS CAT LOAD
mfree (coremap, svx->x_svsize, (mem_ t) svx->x_ svcaddr) :
telse
memfree «mem_t) svx->x_svscat):
tendif
break;

/*

*

Save the memory of a text region of a shared process
*/
xmsave(xp)
register struct text *xp;
{

register struct svtext *svx, *tsvx;
register struct inode *ip;
tsvx = NULL:
ip - xp->x iptr:
for (svx =-&svtext[O); svx < (struct svtext *)v.ve_svtext; svx++) {
if «svx->x svflag&XSVBUSY) ~- 0) {
if (tsvx ~ NULL)
tsvx - svx;
continue;

/*
* link up to a text region already in memory

if (ip->i number=svx->x svnumber && ip->i dev--svx->x svdev)
printf("xmrelse:memory saved more than once\n");
tsvx = NULL;
break;

*/
xmlink(xp)
register struct text *xp;
I
register struct svtext *svx;
register struct inode *ip:
ip = xp->x_ iptr;
for (svx = &svtext[Oj; svx < (struct svtext ")v.ve_svtext; svx++) {
if (svx->x svflag&XSVBUSY &.Ii ip->i number=svx->x svnumber &&
ip->i dev-svx->x svdev) { svx->x_ svflag- &- -XSVBUSY;
tifdef NONS CAT LOAD
xp->x_ caddr - svx->x_ svcaddr:
telse
tendif
tifdef TEXTTRACE
printf(Ulinking to text caddr Ox%x\n U, svx->x_svcaddr);
tendif

/*
" No space left in table
*1
if (xp->x flag&XERROR I I tsvx - NULL)
tifdef NONSCATLOAD
mfree(coremap, xp->x_size, (mem_tlxp->x_caddr);
telse
iendif
} else
tsvx->x svflag 1= XSVBUSY;
tsvx->x- svsize = xp->x size;
tifdef NONSCATLOAD
tsvx->x_ svcaddr - xp->x_caddr;
telse

return (1) ;
tendif
tsvx->x svdev - ip->i dey;
tsvx->x:::svnumber - ip=>i_number:

return(O) ;
Hfdef TEXTTRACE

printf(Usaving %d segments at text caddr Ox%x\n",
tsvx->x_svsize, tsvx->x_svcaddr);

/*

*

Release a shared text segment in the text area space.

*/
xmrelse ()
{

register struct svtext *svx, *tsvx;
register n;
n - «unsigned) -1) » 1;
tsvx - NULL;
for (svx - &svtext[O); svx < (struct svtext "lv.ve svtext; svx++) I
if (svx->x svflag&XSVBUSY H svx->x_svsizex svsize;
tsvx - svx;
continue;

I
i f (tsvx

~ NULL)
return(OI;

Hfdef TEXTTRACE
printf("freeing %d segments at text caddr Ox%x\r.",
tsvx->x_svsize, tsvx->x_svcaddr);
tendif

tendif

trap.c

Fri Sep

I*tdefine HOWFAR*I
I*tdefine SYSCALLS

5 19:08:06 1986

* the saved rO. See reg. h
*/
char
regloc[8+8+1+1] ~ {
RO, Rl, R2, R3, R4, R5, R6, R7,
ARO, AR1, AR2, AR3, AR4, AR5, AR6, SP, PC,
RPS

*1

/* @(t)trap.c
1.2 *1
tinclude "sys/param.h"
tinclude "sys/types .h ' ;
tinclude "sys/systm.h"
tinclude "sys/dir.h"
tinclude ·sys/signal.h"
tinclude "sys/user .h"
tinclude ·sys/errno.h"
iinclude "sys/proc.h"
tinclude ·sys/reg.h"
tinclude ·sys/psl. h"
tinclude ·sys/trap.h R
tifdef mc68881
tinclude "sys/fptrap.h"
tendif mc68881
tinclude "sysl seg. h OO
tinclude "sys/sysinfo. h"
tifndef VIRTUAL451
tinclude "sys/buserr.h"
tendif
tdefine EBIT
tdefine USER
Oxl000
tdefine NSYSENT 128

};

1*
* Called from the trap handler when a processor trap occurs.
*/
trap (number, regs;
short number;
{

register struct user *up;
extern int parityno;
register i;
time t syst;
int retval;
int *oldarO;
tifdef mc68881
1* MC68881 floating-point coprocessor */
extern short fp881;
1* is there an MC68881? *1
tendif mc68881

1* user error bit in PS: c-bit *1
1* user-mode flag added to number *1

tifdef SYSCALLS
static char reserved [] - "reserved";
char *callnames []
1* 0 *1

1*
1*
1*
1*
1*
1*
1*
I"
1*
1*
1*
1*
1*
1*
1*

12
16
20
24
28
32
36
40
44
48
52
56
60

*1
*1
*1
*1
*1
*1
*1
"I
*1
*1
*1
*1
*1
*1
*1

1* 64 *1
Hfdef UCB_NET
1* 68 *1

-

1

{

"indir", "exit", "fork", "read",
"write", "open", ·close", "wait",
"creat··, "link", "unlink", "exec",
"chdir", "time", "mknod", "chmod",
"chown", "break", "stat", "seek",
"getpid", -mount", "umount", "setuid",
"getuid", "stime", "ptrace", Malarm'l,
"fstat", "pause", "utime ll , "stty",
"gtty", uaccess", "nice", "sleepu,
• sync", "kill", "CSWU, "setpgrp",
"tell", "dup", "pipe", "times",
"prof", "lock", "setgid", Ugetgid",
·sig", "msgsys", reserved, "acct",
"shmsys", "semsys", "ioctl", "phys",
"locking", "utssys", reserved, "exece",
-um.ask ll , "chroot", "fentl", "ulimit",

up ~ &u;
retval = 0;
syst = up->u_stime;
tifdef FLOAT
1* sky floating point board */
up->u_fpsaved ~ 0;
tendif
oldarO = up->u_arO;
up->u arO ~ ®s;
i f (USERMODE(up->u arO[RPSJ)
number I = USER;
tifdef HOWFAR
if (number != RESCHED && number != RESCHED+USER) (
printf("trap number~Ox%x ps-Ox%x\n", number,
up->u_arO [RPS] &OxFFFF);
showregs (I) ;
tendif

1*

*

Handle parity specially to make it processor independent

*1
if (number-parityno I I number- (parityno I USER)) {
if «i - parityerror() - 0) (
logparity «paddr_t) &up->u_arO [PC]) ;
goto out;
if (i >

"reboot", reserved, reserved, reserved,

1* 72 *1
1* 76 *1

reserved, reserved, "select", "gethostname" ,
"sethostname" , "socket", "accept", "connect·,
"receive", "send", "socketaddr" , "netreset" ,

1* 68 *1
1* 72 *1
/* 76 */

reserved, reserved, reserved, reserved,
reserved, reserved, reserved, reserved,
reserved, reserved, reserved, reserved,

80 */
84 */
88 */
92 */
96 */
100 *1
104 *1
108 */
112 *1
116 *1
120 *1
/* 124 */

reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,

,.

reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,

};

showbus() ;
panic("kernel parity error");
}

} else (
sw:
switch (number)

1*

* Trap not expected.
* Usually a kernel mode

bus error.

*1

Jendif

default:
i f ((number " \JSER) =- a i i
panicstr - "trap";

;"
• Offset.s a.t:tb.e user's .regist.ers reJ.a.tiv,e

reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved

I (number & USER);

}

tendif
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,
reserved,

(

i f (number & USER) (
logparity( (paddr_t) &up->u_arO [PC]);
i - SIGBUS;
} else (
i f (nofault)
up->u arO - oldarO;
longj;p(nofault, -1):

telse

/*
/*
/*
1*
/*
/*
1*
/*
1*
1*

0)

number goto sw;

tQ

ifX"J.llitf4.~t.iI:-.p

1* fake it for printfs *1

.t.ype 'Q\D,... nwlIber.;

trap.c

Fri Sep

5 19:08:06 1986

2
* of the stack segment, then grow the

showregs (1);
panic ("unexpected kernel trap");

case
case
case
case
case
case
case
case
case
case
case
case
case
case
case
case
case
case

CHK + USER:
TRAPV + USER:
PRIWIO + USER:
L1010 + USER:
L1111 + USER:
TRAP4 + USER:
TRAPS + USER:
TRAP6 + USER:
TRAP7 + USER:
TRAP8 + USER:
TRAP9 + USER:
TRAP10 + USER:
TRAP11 + USER:
TRAP12 + USER:
TRAP13 + USER:
TRAP14 + USER:
TRAP1S + USER:
ILLINST + USER:
i = SIGILL;
break;

case DIVZERO + USER:
i = SIGFPE;
break;

*

stack automatically.
*/
case ADDRERR + USER:
1* bus error - address error
i - SIGBUS;
rei:val - 1;
trapaddr «struct buserr *) ®s);
break;

/* CHK instruction */
/ * TRAPV instruction "/
/* priviledge violation */
/" Line 1010 emulator */
/* Line 1111 emulator */

*/

case BUSERR + USER:
/* memory management error - bus error */
if(pagein«int) «(struct buserr ")®S)->ber_faddr») {
up->u arO = oldarO;
return(O) ;
i = SIGSEGV;
retval - 1;
trapaddr «struct buserr *) ®s);
break;
case ADDRERR:
1* bus error - address error *1
trapaddr «struct buserr ") ®s);
printf("kernel address error\n");
showbus() ;
panic("kernel memory management error");

/* illegal instruction */

case BUSERR:
/* memory management error - bus error in kernel */
if (nofault) {
up->u arO = oldarO;
longjmp{nofault, -1);

/* zero divide */

Hfdef mc68881
/* MC68881 floating-point coprocessor */
case FPBSUN + USER:
/* Branch or Set on Unordered condition "/
case FPINEX + USER:
/* Inexact Result */
case FPDZ + USER:
/* Floating Point Divide by Zero */
case FPUNFL + USER:
/* Underflow ,,/
case FPOPERR + USER:
/* Operand Error */
case FPOVFL + USER:
/* OVerflow */
case FPSNAN + USER:
/* Signalling NAN (Not-A-Number) */
up->u_fpexc - nwnber & OxFF;
i - SIGFPE;
break;
iendif mc68881

trapaddr( (struct buserr *) ®s);
berdump( (struct buserr *) ®s):
printf(-kernel bus error\n", ;
showbus() ;
panic(Ukernel memory management error");
.else

/*

* If the user SP is below the stack segment,
" grow the stack automatically.
This relies on the ability of the hardware
" to restart a half executed instruction.
" On the 68000 this is not the case and
* the routine machdep/backup () will fail.
*/
K

case TRCTRAP:
1* trace out of kernel mode - * /
up->u arO - oldarO;
return (retval); /* this is happens when a trap instruction *1
/* is executed with the trace bit set */
case TRCTRAP + USER:
/* trace */
case TRAP 1 + USER:
/* bpt - trap
i - SIGTRAP;
up->u_arO [RPSj &= -PS_T;
break;

n

case ADDRERR + USER:
/* bus error - address error */
i - SIGBUS;
retval - 1;
trapaddr ( (struct buserr *) ®s) ;
break;

*/

case TRAP 2 + USER:
i - SIGIOT;
break;

/* iot - trap .2 */

case TRAP 3 + USER:
i - SIGEMT;
break;

/* emt - trap .3 */

case BUSERR + USER:
/* memory management error - bus error */
if (i - backup(up->u arO»
if (grow{ (unsigned) (up->u_arO [SP] +i»)
goto out;
i - SIGSEGV;
retval = 1;
trapaddr ( (struct buserr *) ®s) ;
break;

case SYSCALL + USER:
/* sys call - trap to */
panic (ltsyscall \n");

case ADDRERR:
/* kernel address error */
case BUSERR:
/ * kernel bus error * /
if (nofault)
longjmp(nofault, -1);
trapaddr «struct buserr *) ®s);
showbus ();
panic("kernel memory management error\nlt);

/*

* Allow process switch
*1
case RESCHED + USER:
case RESCHED:
qswtch() ;
goto out;
Hfdef VIRTUAL4S1
/*
" If the user SP is below the stack: segment
* an~IIiith.in. s.~ cl.icks. OL t.b/iII bQttco

'end::.f

1*

* Unused trap vectors generate this trap type.
* Reciept of this trap is a

.. symptom of hardware problems and may
* represent a real interrupt that got
.. sent tot.he. wZODg .pLace.. iiatch out

trap.c

Fri Sep

5 19:08:06 1986

3

* for hangs on disk completion if this message appears.

up->u_error

(" (sysent[i].sy_call»

case SPURINT:
case SPURINT + USER:
printf ("\nRandom interrupt ignored\n");
up->u arO - oldarO:
return (retval);

EINTR;

*1

out::

();

}

if (up->u_error) {
regp[ROj - up->u_error;
regp[RPS] 1- PS C;
if (++up->u errent > 16) {
up->u_errcnt - 0;
runrun++;

}

}
I" end else ...
psignal (up->uyrocp, i);

=

else {

*1

1* carry bit *1

tifdef SYSCALLS

if (up->uyrocp->p_sig && issigO)
psig() ;
if (up->uyroLpr scale)
addupc( (unsigned)up->u arO [PC), &Up->u prof, (int) (up->u_stime-syst);
tifdef FLOAT
1* sky floating point board
if (up->u fpinuse && up->u fpsaved)
restfp();
tendif
Hfdef mc68881
1* MC68881 floating-point coprocessor *1
if (fp881)
fprestO;
tendif mc68881
up->u_arO = oldarO:
return (retval);

*r

1*
* process a system call

*1
syscall (regs)
(

register struct proc "pp:
register struct user "up;
register "regp, *argp;
register ~:
int *oldarO;
Hfdef mc68881
I" MC68881 floating-point coprocessor */
extern short fp881:
1* is there an MC68881? *1
tendif mc68881
up = &u;
sysinfo. syscall ++:
up->u error = 0;
Hfdef FLOAT 1* sky floating point board *1
up->u_fpsaved = 0;
tendif
oldarO - up->u arO;
up->u_arO = re@ - ®s;
up->u_ap ~ argp = up->u_arg;
i = regp[RO] & 0377;
if Ii >- NSYSENT)
i = 0;
argp[O) - regp[ARO];
argp[l] - regp[Rl];
argp[2] - regp[ARl];
argp[3] = regp[R2];
argp[4] - regp[AR2];
argp[5] - regp[R3];
tifdef SYSCALLS
printfl""*"" %s: %x %x %x %x\n", callnames[i),
argp[O], argp[I], argp[2], argp[3], argp[4], argp(5):
tendif
up->u_dirp - (caddr_t)argp[O];
up->u rvall - 0:
up->u:=rva12 - regp [Rl] :
i1" (qsave (up->u qsav»
{
I"
" restore registers not saved by qsave
"I
up - &U;
regp - ®s;
argp - up->u arg;
it, .(,i.lp...,>u-,llIt:r.ot:...-O.)

printf!"

syscall error = %d, pc - Ox\x\n",
up->u_error, regp[PC]);

printf("

syscall success, pc
regp[PC]) ;

tendif
} else (
tifdef SYSCALLS
=

Ox%x\n H ,

tendif
regp[RPS] &- -ps_c;
regp[RO] = up->u_rval1;
regp[Rl] = up->u_rva12;

1* carry bit *1

pp - up->uyrocp;

1*
* Test if the trap instruction was executed with the
" trace bit set (the trace trap was already ignored)
" and set the trace signal to avoid missing the trace
* on the trap instruction.
"I
pp->p_pri ~ (pp->p_cpu»l) + (PUSER - NZERO) + pp->p_nice:
curpri - pp->pyri;
if (pp->p sig && issig () )
p-;ig ();
up->u arO - oldarO;
if (runrun)
qswtch() ;
Hfdef FLOAT
I" sky floating point board *1
if (up->u fpinuse && up->u fpsaved)
restfpO;
tendif
Hfdef mc68881
I" MC68881 floating-point coprocessor *1
if (fp881)
fprest() :
tendif mc68881
}

1*
" nonexistent system call-- signal bad system call.
"I
nosys()
(

psignal lu. uyrocp, SIGSYS);

1*
" Ignored system call

"I
nullsysl)
{
}

stray I addr I
physadr addr:
(

logstray (addrl ;
printf I"stray interrupt at \x\n", addrl;

1*
" trapaddr - Save the info from a 68010 bus or address error.

*1

trapaddr lap)
register struct buserr *ap;

,

trap.c

Fri Sep

5 19:08:06 1986

4
while (ip < (unsigned short "I «int) &u+ctob(v. v usize»)
i f «(int)ip & 31) =- 0)
printf("\n%x 0 , ip);
printf(" %X", *ip++);

extern int cputype;
if (cputype ~ 0)
return;
u.u_fcode - ap->ber_sstat;
u.u aaddr = ap->ber faddr;
u.u:::ireg - ap->ber_'Iib;

1*

printf ("\n ii ) ;
i f (ret !- 0)
panic(U,,*** ABORTING *"*"");

* showbus - print out status on mmqt error
*/
showbus ()

lir

{

dumpustack (max)
unsigned max;

register struct user "up;

* dump the present contents of the user stack

*1
{

up = &u;
printf(Uvaddr = Ox%x paddr = Ox%x ireg - Ox%x fcode - Ox%x\n",
up->u aaddr, vtop( (caddr t)up->u aaddr), up->u_ireg&OxFFFF,
up->u-fcode&OxF);
showregs (1); -

register unsigned short *ip, *jp;
register unsigned i, n;
ip = (unsigned short *) (u.u arO[SP) - 20);
jp = ip + 64;
if (jp < (unsigned short *)max)
jp = (unsigned short *)max;
if (jp > (unsigned short *)v.v uend)
jp = (unsigned short *)v.v uend;
printf("\n%x ", ip);
while (ip < jp) {
i = (fuword(ip++) » 16) & OxFFFF;
i f «(intlip & 31) = 0)
printf(U\n%x ., ip);
printf(" %X U, i);

1*
* Show a processes registers
*/
showregs (mmuf1g)
int mmuflg;
{

register struct user *up;
register int i, j;
char command [DIRSIZ+1) ;

printf("\n") ;
up - &u;
Hfdef HOWFAR
i f (mmuflg)
dumpmm(-l) ;
tendif HOWFAR
tifdef lint
dumpmm(mmuflg) ;
tendif lint
for (i=O; iu comm[i);
if (j<-' ,. II j>-Ox7F)
break;
command [i) - j;
command [i)

~

0;

1*
* separate prints in case up or uyrocp trashed

*1
printf ("pc = Ox%x sr - Ox%x up->uyrocp - Ox%x",
up->u_arO [PC], up->u_arO [RPS) &OxFFFF, up->uyrocp);
printf(" pid = %d exec - '%s'\n·, up->uyrocp->pyid, command);
for (i - 0; i < 16; i++) {
printf ("OX%X ., up->u arO [i);
if (i - 7 II i =- 15) printf("\n");

Hfdef DUMPSTK
tinclude 
Hfndef VIRTUAL451
Hnclude 
tendif
tinclude 
/*
* dump the present contents of the stack
*/
dumpstack (ret I
{

register unsigned short *ip;
ip - (unsigned short *) &ret;
ip -- 4;
pxint!'"\n.b ", ip,):

tendif

Fri Sep

ttO.c
1* @(t)tto.c
1*

5 19:08:07 1986

1
reqister struct cblock *cp;

1.4 *1

i f «cp - qetcb(tq» - NULL)
break:
n = min(up->u count,
(unsigned) (cp->c last - cp->c first»;
i f (copyout «caddr t) &Cp=>c data [cp->c first],
(caddr t)UP->u base-; n)
up->u error ~ EFAULT;
putcf ( (struct- cblock ") cp) ;
up->u_base += n;
up->u count ~ n;
} else {
reqister c;

* Line discipline 0
* Includes Terminal Handling

*1
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

IIsys/param. h"
II sys/types. h"
"sys/systm.h"
"sys/conf .h"
"sys/dir.h"
"sys/signal.h"
"sys/user.h"
"sys/errno.h"
"sys/proc.h"
"sys/file.h"
"sys/tty.h"
·sys/termio .h"
·sys/crtctl.h u
·sys/sysinfo.h"
·sys/var.h"

qetc(tq» < 0)
break:
if (subyte (up->u base++, c»
up->u error = EFAULT;
up->u_count---;-

i f «c

=

)

i f (tp->t state&TBLOCK)
if (tp->t rawq.c cctyroc) (tp, T_UNBLOCK);

extern char partab [] ;
char colsave, rowsave:
struct clist tempq;

1* temp save for high queue restore "/
/* temp for echo during high queue *1

/*
* routine called on first teletype open.
" establishes a process group for distribution
* of quits and interrupts from the tty.

1*
* Called from device's write routine after it has
" calculated the tty-structure qiven as argument.

*/
ttopen(tp)
register struct tty "tp;

*1
ttwrite (tp)
reqister struct tty *tp;

(

register struct proc *pp;

(

pp = u.uyrocp;
i f «pp->pyid ~ pp->p_pgrp)
&& (u. u ttyp NULL)
&& (tp->tJ>qrp =
0)
(
u.u_ttyp - &tp->tJ>qrp;
tp->tygrp = pp->pygrp;
ttioctl(tp, LOOPEN, 0, 0);
tp->t state &- -WOPEN:
tp->t::::state 1- ISOPEN;
ttclose (tp)
register struct tty *tp:
(

i f «tp->t_state&ISOPEN) -

0)

return;
tp->t state &= -ISOPEN;
tp->tygrp = 0:
ttioctl (tp, LDCLOSE, 0, 0):

reqister struct user "up;
int hqflaq;
int col, row;
up - &u:
qwait:
spltty() ;
while(tp->t_tmflaq & QLOCKB) (
tp->t state 1- OASLP;
(void) sleep ( (caddr_t) &tp->t_outq, TTOPRI);
SPLO ();
if (! (tp->t_state&CARR_ON»
return;
hqflag = 0;
while (up->u count) {
i f (tp->t outq. c cc > tthiwat [tp->t_ cflaq&CBAUD] )
if (hqfiiq ) (
col - tp->t col;
row - tp->t::::row;
hqrelse (tp) ;
)

1*
* Called from device's read routine after it has
" calculated the tty-structure given as argument.

"I

ttread(tp)
reqister struct tty *tp;
(

spltty() ;
(*tp->tyroc) (tp, T_OUTPUT);
while (tp->t_outq.c_cc > tthiwat[tp->t_cflaq&CBAUD])
tp->t state 1- OASLP;
i f (sleep ( (caddr t) &tp->t outq,
hqflaq ?-PZERO : (TTOPRIIPCATCH»)
SPLO II;
qoto out;

reqister struct user *up;
reqister struct clist *tq;
up - &u;
tq - &tp->t canq;
i f (tq->c_cc 0)
canon (tp) ;
while (up->u count! -0 && :lp->u e==or=~C)
i f (Up->u count >- CLSIZE) {
:Z:Sqister n:

SPLO 0;
i f (hqflaq)
tp->t tmflaq 1- QLOCKI;
cOlsave - tp->t col;
rowsave - tp->t-row;
ttyctl (LCA, tp, -col, row):
continue;

ttO.c

Fri Sep

5 19:08:07 1986

2

i f (tp->t_tmflag & QLOCKB)
goto qwait:
i f (up->u count >= (CLSIZE/2) && tp->t term register n;
register struct cblock wcp:

/*

* Place a character on raw TTY input queue, putting in delimiters
* and waking up top half as needed.
" Also echo if required.
""/
tdefine LCLESC 0400

0) {

i f «cp - getcf (» ~ NULL)
break:
n - min(up->u_count, (unsigned)cp->c_last):
if (copyin «caddr_t) up->u_base, (caddr_t) cp->c_data,
nl) {
up->u error = EFAULT:
putc£"( (struct cblock ") cp) :
break:

ttin(tp)
register struct tty *tp;
{

register c:
register flg:
register char *cp;
ushort nchar, nc:
nchar = tp->t rbuf. c size - tp->t rbuf. c count:
1* reinit rx control-block *1
tp->t rbuf. c count = tp->t rbuf. c size:
i f (nC'har-O")
-return;
flg - tp->t iflag;
1* !t state&EXTPROC)
fIg &= IXOFF;
nc - nchar;
cp - tp->t_rbuf.cytr;
i f (nc < cfreelist.c size II (flg & (INLCRIIGNCRIICRNLIIUCLC»
I I tp->t term) {
/* must do per character processing */
for ( ;nc--; cp++) {
c = *cp;
i f (tp->t term)

up->u_base += n:
up->u count -- n;
cp->c:)ast = n;
ttxput (tp, cp, n):
} else {
register c;
c = fubyte(up->u base++):
i f (cu error = EFAULT:
break;
up->u count--:
i f (c-== ESC && tp->t term) {
switch Ic = cPass (»
int col:

C-&= 0177:
i f «c = (*termsw[tp->t_term] .t_inputl

case -1:
continue:
case ESC:
goto norm;
case HIQ:
i f (hqflag++)
continue;
tp->t_tmflag I- QLOCKBIQLOCKI:
tp->t hqcnt++:
cOlsave = tp->t_col;
rowsave = tp->t row;
continue;
case LCA:
case SVID:
case DVID:
case CVID:
col - cpass () :
default:
ttyctl (c, tp, col, c==LCA ? cpass ()

== -1)

i f (c &

if (c == , \n' && flg&INLCR)
*cp = c = , \r' ;
else if (c == '\r')
i f (flg&IGNCR)
continue;
else i f (flg& ICRNL)
*cp - c = , \n' ;
if (flg&IUCLC && 'A' <- c && c <= , Z')
c+-'a'-'A';
i f (putc(c, &tp->t rawq»
continue; sysinfo. rawch++;

0) ;

}

} else {
norm:
ttxput (tp, c,

continue:
CPRES) {
(void) putc (ESC, &tp->t rawq);
(void) putc (c, &tp->t r-;;:wq):
continue;
-

0);

cp
} else {

=

tp->t_rbuf.cytr;

1* may do block processing *1
i f (hqflag)
hqrelse (tp) ;
(void) putc(QESC, &tp->t_outq);
(void) putc(HQEND, &tp->t_outq);
spltty() ;
if (tp->t_state & OASLP) {
tp->t state &- -QASLP;
wakeup ( (caddr_t) &tp->t_outq);

SPLO (I;

putcb(CMATCH«struct cblock ")cp), &tp->t_rawq):
sysinfo.rawch +- nc;
1* allocate new rx buffer *1
i f «tp->t_rbuf.cytr = getcf()->c_data)
«struct cblock *)NULL)->c_data)
tp->t_rbuf.cytr - NULL;
return;
tp->t rbuf. c count - cfreelist. c size;
tp->t::::rbuf .c::::size - cfreelist.c_'iize;

out:
tp->t tmflag &- -(QLOCKBIQLOCKI);
splttYIl ;
(*tp->tyroc) (tp, T_OU7?tr7);
SPLOO:

if (tp->t rawq.c cc > TTXOHI) I
if (flg&IXOFF && ! (tp->t state&TBLOCK»
(*tp->t proc) (tp; T BLOCK);
iL ,tp-~t.....:z:a.wq_c._cc> TT~{

(c,tp»

Fri Sep

ttO.c

5 19:08:07 1986

3

tty flush (tp, FREAD);
return;

I
flg = lobyte (tp->t lflag);
i f (tp->t_outq.c_c; > (tthiwat [tp->t_cflag&CBAUD) + TTECHI»
flg &- - (ECHO I ECHOK I ECHONL I ECHOE) ;
i f (flg) while (nchar--) {
c = *cp++;
i f (flg&ISIG) {
i f (c - tp->t cc[VINTRj) (
signai(tp->t-P9'rp, SIGINI);
i f (! (flg&NOFLSH) && tp->t hqcnt-O)
tty flush (tp, (FREAD I FWRITE) ) ;
continue;
i f (c

~

tp->t cc[VQUITj)
signai"(tp->tJX1rp, SIGQUIT);
i f (! (flg&NOFLSH) && tp->t hqcnt-O)
ttyflush (tp, (FREAD I FWRITE) ) ;
continue;

i f (flg&ICANON)

if (tp->t_state&cLESC) (
flg 1= LCLESC;
tp->t_state &= -CLESC;
)

i f (c == '\n') (
i f (flg&ECHONL)
flg I- ECHO;
tp->t delct++;
) else i f (c ;;;.. , \ \') (
tp->t state 1= CLESC;
i f (fIg&XCASE) {
c 1= QESC;
i f (flg&LCLESC)
tp->t_state &= -CLESC;

) else i f (c = tp->t_cc[VEOLj II c =- tp->t_CC[VEOL2])
tp->t_delct++:
(! (flg&LCLESC»
(
i f (c ~ tp->t cc[VERASEj && flg&ECHOE)
i f (flg&ECHO)
ttxputi (tp, , \b' ) :
flg 1- ECHO:
ttxputi (tp, , '):
c = '\b':
) else i f (c -- tp->t cc[VKILL] && flg&ECHOK) (
i f (flg&ECHO)ttxputi (tp, c):
flg 1- ECHO;
c - '\n';
) else i f (c = tp->t_cc[VEOFj)
flg &= -ECHO:
tp->t_delct++:

else i f

i f (flg&ECHO) {
ttxputi (tp, c);
(*tp->tyroc) (tp, T_OUTPUT);
)

i f (! (flg&ICANON»
tp->t state &- -RTO;
i f (tp->t rawq. c cc >- tp->t ee [VMINj)
tp->t delct - 1:
else i f (tp->t ee iVTlMEJ) i
i f (! (tp->t state&TACT»
tttImeo (tp) :
}

i f (tp->t delet && (tp->t state&IASLP»

tp->t state i - -IAsLP:

wakeuP ( 4ca.ddx:_ t) "tp->~x:a.wq) ;

/*
.. Interrupt interface to ttxput.
" Checks for High Queue write in progress, and saves characters to be echoed.
,,/
ttxputi (tp, c)
register struct tty *tp;
(

i f (tp->t tmflag & QLOCKI) (
i;oidi putcic,&tempq);
return;
) else
ttxput (tp, c, 0);

/"
* Put character (s) on TTY output queue, adding delays,
* expanding tabs, and handling the CR/NL bit.
* It is called both from the base level for output, and from
* interrupt level for echoing.
*/
/" VARARGSl */
ttxput (tp, ucp, ncode)
register struct tty *tp;
union {
/ * machine dependent union * /
struct ch {
char dum[3j:
unsigned char theaddr:
} ch;
int thechar:
struct cblock *ptr:
ucp:
register c:
register flg;
register unsigned char *cp:
register char *colp:
int ctype:
int cs:
struct cblock * scf :

/* KMC does all but XCASE, virt term needs CR info for t_col * /
i f (tp->t state&EXTPROC) (
if (tp->t term I I tp->t lflag&XCASE)
fIg - tp->t_o flag &(OPOST I OLCUC I ONLRET I ONLCR) :
else
flg = 0:
) else
flg = tp->t oflag:
i f (ncode - 0) ( ncode++:
i f (! (flg&OPOST»
sysinfo. outch++:
(void) putc(ucp.thechar, &tp->t_outq):
return;
cp - (unsigned char ") &ucp. ch. theaddr:
scf - NULL:

I else (
i f (! (flg&OPOST) )

sysinfo.outch +- neode:
putcb(uep.ptr, &tp->t_outq):
return:
ep = (unsigned char
sef - ucp.ptr:

w)

&uep.ptr->e_data[uep.ptr->e_firstl;

while (ncode--) {
c - *cp++:
i f (c >- 0200)
/* splS-O */
if ie ~ OESC && ! (tp->t state&EXTPROC))
(void) putc (QE9C~ &tp->t_ outq) :
IJY,IJl.nt"G .00000ch++:

Fri Sep

ttO.c

5 19:08:07 1986

4
i f (! (tp->t_state&EXTPROC»

{
ctype - flg&TABDLY:
TABO) {
c - 0:
} else i f (ctype - TAB1)
i f (c < 5)
c - 0;
else i f (ctype = TAB2)
c = 2;
else i f (ctype - TAB3)
sysinfo.outch +- c;
do
(void) putc(' "
while (--c):
continue;

(void) putc (c, &tp->t_outq);
continue;
I
/*
* Generate escapes for upper-case-only terminals.
"I
i f (tp->t Iflag&XCASE) {
colp - "(0 I! I
while (*colp++)
i f (c "colp++) {
ttxput (tp, , \\' 10200, 0):
c = colp[-2j:
break:

i f (ctype -

A

-,,\\\\,,:

if ('A' <= c && C <= 'Z')
ttxput(tp, '\\' 10200, 0):
if (flg&OLCUC && 'a' <= c && c <- 'z'l
C += 'A' - , a' ;
cs - c:

/"
" Calculate delays.
* The numbers here represent clock ticks
* and are not necessarily opti1llal for all terminals.
* The delays are indicated by characters above 0200.
*1
ctype = partab[c];
colp = &tp->t col;
c ~ 0:
switch (ctype&077)

&tp->t_outq):

break;
case 5: I * vertical tab * I
if (flg&VTDLY)
c - 0177;
break:
case 6: 1* carriage return "I
i f (flg&OCRNL) {
cs - '\n';
goto nl;
i f (flg&ONOCR && *colp

~

0)

continue;
case 0: / * ordinary
(*colp) ++:

cr:

1< /

i f (! (tp->t state&EXTPROC»

ctYiie - flg&CRDLY;
i f (ctype = CRl) {
i f (*colp)

case 1: /* non-printing */
break:

c - max ( (unsigned) «*colp»4) +3), 6):
else i f (ctype - CR2) {
c - 5;
else i f (ctype = CR3)
c = 9:

case 2: /* backspace */
i f (flg&BSDLY)
c = 2:
i f (*colp)
(*colp)--;
break;
*colp - 0;
break;

case 3: /" line feed */
top:
i f (tp->t term)

if (tp->t vrow && tp->t row >- tp->t_lrow) {
ttyctl (UVSCN, tp):
continue;
i f (tp->t tmflag & SNL)

ttyctl (NL, tp):
continue;
i f (flg&ONLRET)

goto cr;
if (tp->t_row < tp->t_lrow)
tp->t row++:
i f (flg&ONLCR) {
i f «! (tp->t state&EXTPROC» &&
! (flg&ONOCR && "colp==O»
sysinfo. outch++:
(void) putc(' \r', &tp->t_outq):
goto cr:

case 7: 1* form feed */
i f (flg&FFDLY)
c - 0177;
break:
sysinfo. outch++:
if (tp->t_term && "colp >- 80 && tp->t_row >- tp->t_lrow
&& tp->t tmflag & LCF) {
ttyctl (WOMB, tp):
ttyctl (DL, tp);
ttyctl(LCA, tp, 79, tp->t_lrow-l);
(*colp)++;
i f (tp->t term-Oj

(void) putc(cs, &tp->t_outq):
else
qputc(cs, &tp->t outq);
i f (! (tp->t state&EXTPROC»
{
i f (c) {
i f «c < 32) && flg&OFILL)
i f (flg&OFDEL)

cs - 0177:

n:",

else
i f (flg&NLDLY)

c - 5;
break;
cas.", 4: 1* tab * /
c - 8 - «*colp)&07);
"colp +- .0.

cs - 0;
(void) putc(cs, &tp->t_outq):
i f (c > 3)
(void) putc(cs, &tp->t_outq);
i e:"se {
(void) putc (QESC, &tp->t outq);
•.¥oii.~ P'ltc,ol~a~O .. "tp->t.:..Q¥UO I

Fri Sep

ttO.c

5 19:08:07 1986

5
if (c -- HQEND) {
i f (tp->t tenn)
tp->t hqcnt--;
continue;
-

)

if (*colp >- 80 && tp->t term && tp->t tmflag&ANL)
i f (tp->t tmflag&LCF)
ttyctl{LCA, tp, 0, tp->t_row+lj;
else (
i f «flg&ONLCR) - 0)
ttxputi (tp,' \r' ) ;
cs = , \n';
goto top;

if (c > 0200 && ! (tp->t state&EXTPROC»
hibyte (tp->t lflag) - c;
if (! retval) goto delay;
break;

retval = CPRES;
*cptr++ - c;
tbuf->c count++;
if (tbuf->c count >- cfreelist.c_size)
break;

i f (scf ! - NULL)
putcf(scf) ;

/*

* Get next packet from output queue.

* Called
*/

from xmit interrupt complete.
if (tp->t state&OASLP &&
tP->t_outq.c_cc<-ttlowat [tp->t_cflag&CBAUD])
tp->t state &- -OASLP;
wakeup ( (caddr_ t) &tp->t_ outq) ;

ttout(tp)
register struct tty *tp;
(

register
register
register
register

struct ccblock "tbuf;
c;
char *cptr;
retval;

return (retval) ;

tttimeo (tp)
register struct tty *tp:

extern ttrstrt () ;

{

if (tp->t state&TTIOW && tp->t outq.c cc=O)
tp->t state &- -TTIOW; wakeup ( (caddr_t) &tp->t_oflag);

tp->t state &= -TACT;
i f (tp->t lflag&ICANON II tp->t_cc[VTlMEJ -- 0)
return:
if (tp->t_rawq.c_cc ~ 0 && tp->t_CC[VMINJ)
return;
i f (tp->t_state&RTO) (
tp->t delct = I;
i f (tp->t_state&IASLP)
tp->t state &= -IASLP;
wakeup ( (caddr_t) &tp->t_rawq);

delay:
tbuf = &tp->t tbuf;
i f (hibyte (tp=>t lflag»
i f (tbuf=>cytr)
putcf(CMATCH( (struct cblock ")tbuf->cytr»;
tbuf->cytr = NULL;

)

tp->t state 1- TIMEOUT;
timeout (ttrstrt, (caddr t) tp,
(int) «hibyte (tp->t lflag) &0177) +6»;
hibyte (tp->t_lflag) = 0;
return(O) ;
retval = 0;
i f « (tp->t_state&EXTPROC) II (! (tp->t_oflag&OPOST») &&
tp->t term-D) {
i f (tbUf->cytr)
putcf (CMATCH( (struct cblock *)tbuf->cytr»;
i f «tbuf->cytr = (char *)getcb(&tp->t_outq» -= NULL)
return (0);
tbuf->c_count = «struct cblock *)tbuf->cytr)->c_last «struct cblock *)tbuf->cytr)->c_first;
tbuf->c size - tbuf->c count;
tbuf->c- ptr - &( (struct cblock *) tbuf->c ptr) ->c data
[( (struct cblock *)tbUf->cytr) ->c_firstl;
retval - CPRES;
) else {
/* watch for timing
*/
i f (tbuf->cytr - NULL) {
i f «tbuf->cytr - qetcf()->c_data)
«struct cblock *)NULL)->c data)
tbuf->c ptr - NULL;
return (D) ;
/* Add restart'1 */
tbuf->c_count - 0;
cptr - tbuf->cytr;
while «c-qetc(&tp->t outq»
i f {c -

/*

* I/O control interface
*/
/* ARGSUSED * /
ttioctl (tp, cmd, arg, mode)
register struct tty *tp;
(

ushort chg;
struct tenncb termblk;
register struct tenncb *tbp;
switch (cmd) {
case LDOPEN:
i f (tp->t_rbuLcytr = NULL) {
/* allocate RX buffer */
while ( (tp->t_rbuLc_ptr - getcf()->c_data)
«struct cblock *)NULL)->c_data)
tp->t_rbuLc_ptr - NULL;
cfreelist. c flaq - 1;
(void) sleep( (caddr_t) 'cfreelist, TTOPRI):
tp->t_rbuf. c_count - cfreelist. c_size;
tp->t_rbuf. c_size - cfreelist. c_size;
(*tp->tyroc) (tp, T_INPUT);

>- 0) {

QEscT {
i f «c - qetc(Up->t outq»
break,;
-

} else {
tp->t state 1= RTO I TACT;
timeout (tttimeo, (caddr t)tp,
(int) (tp->t_cc [VTlMEl * (short) «short) v. v_hz/IO») ;

< 0)

ttO.c

Fri Sep

5 19:08:07 1986

case LDCLOSE:
spltty() ;
(*tp->tyroc) (tp, T_RESUME);
SPLO ();
ttywait (tpi;
ttyflush (tp, (FREAD I FWRITE) ) ;
i f (tp->t tbuLcytr) {
putcf(CMATCH( (struct cblock *ltp->t_tbuf .cytr»;
tp->t_ tbuL cytr - NULL;
tp->t tbuLc count = 0;
tp->t=tbUf.c=size = 0;
I
i f (tp->t_rbuLcytr) {
putcf(CMATCH( (struct cblock *)tp->t_rbuLc_ptr»;
tp->t_rbuf.cytr - NULL;
tp->t rbuf. c count = 0;
tp->t=rbuLc=:size - 0;

6
tp->t state &- -CLESC;
break;
default:
break;

1************** ADDITIONS FOR TERMINAL HANDLERS **********************1
1*
* release the high priority queue for interrupts.
;, copy over any received characters while queue was locked.

;,1
hqrelse (tp)
register struct tty *tp;
{

register c;
ttyctl (LCA, tp, col save, rowsave);
splttyO;
while «c - getc(&tempq» >- 0)
ttxput (tp, c, 0);
tp->t_tmflag &= -QLOCKI;
SPLO ();

tp->t tmflag - 0;
break;
case LDCHG:
chg = tp->t IflagAarg;
i f (! (chg&ICANON»
break;
spltty() ;
if (tp->t canq.c cc)
if (tp->t_rawq.c_cc)
tp->t canq.c cc += tp->t rawq.c cc;
tp->t=:canq.c=:cl->c_next ;;; tp->t=:rawq.c_cf;
tp->t_canq.c_cl = tp->t_rawq.c_cl;
tp->t rawq
tp->t=:canq

=
=

tp->t canq;
ttnulq;

1*
* put a character on the output queue,
;, checking first to see if it is a ESC.

*1
qputc (c, qp)
register c;
struct clist *qp;
{

i f (c -

ESC)
(void) putc(c, qp);
(void) putc(c, qp);

tp->t delct - tp->t_rawq.c_cc;
SPLO();
break;
case LDGETT:
tbp - &termblk;
tbp->st flgs - tp->t tmflag;
tbp->st-termt = tp->t term;
tbp->st-crow = tp->t row;
tbp->st-ccol = tp->t-col;
tbp->st-vrow = tp->t-vrow:
tbp->st-lrow - tp->t-lrow;
i f (copyout( (caddr_t)tbp, (caddr_tlarg, sizeof(termblk»)
u.u_error = EFAULT;
break;
case LDSETT:
tbp - &termblk;
if (copyin( (caddr_t)arg, (caddr_t)tbp, sizeof(termblk») {
u. u error - EFAULT;
break;
if «unsigned) tbp->st_termt >- termcnt) {
u. u error - ENXIO;
break;
i f (tbp->st termt)
(*termsw[tbp->st termtJ.t ioctl)
(tp,
tp->t term-tbp->st termt ? LDCHG
LDOPEN,
tbp->st vrow);
i f (u. u error)
-break;
tp->t vrow - tbp->st vrow;
tp->t-term - tbp->st-termt;
i f (tbp->st flgS&TM SET)
tP->t_tmflaq - tbp->st_flgs & -TM_SET;
else

tifdef notdef
1* simulate Up Variable SCreeN as common routine *1
ttuvscn (tp)
register struct tty *tp;
{

ttyctl (VHOME, tp);
ttyctl (DL, tp);
ttyctl(LCA, tp, 0, tp->t_lrow);

1* simulate Down Variable SCreeN as common routine *1
ttdvscn (tp)
register struct tty *tp;
{

ttyctl (VHOME, tp);
ttyctl (IL, tp);
I
tendif

char colpres, rowpres;
1* VARARGS * I
ttyctl (ac, tp, acol, arow)
register struct tty *tp;
{

reqister char *colp;
reqister c;
int sps;
c - ac;
colp - &tp->t_col:
sps - splttyO;
co.;.pres = *colp;
rowpres - tp->t row;
_i.t.Gb~o. f
-

ttO.c

Fri Sep

5 19:08:07 1986

case CUP:
case DSCRL:
i f (tp->t row ~ 0)
gate out;
tp->t_ row--;
break;
case CDN:
case USCRL:
if (tp->t_row >~ tp->t_Irow)
goto out;
tp->t_ row++;
break;
case UVSCN:
*colp = 0;
tp->t row = tp->t Irow;
break:
case DVSCN:
*eolp - 0;
tp->t row = tp->t vrow;
break:
case CRr:
case STB:
case SPB:
i f (*eolp >~ 79)
goto out;
(*eolp)++;
break;
case CLE:
i f I*eolp ~ 0)
goto out;
(*colp)--;
break;
case HOME:
case CS:
case CM:
tp->t_row = 0;
case DL:
case IL:
*eolp - 0;
break;
case VHOME:
*eolp = 0;
tp->t row = tp->t vrow;
e - LeA;
break;
case LCA:
*eolp - aeol;
tp->t row - arow;
break:
case ASEG:
tp->t row - (short) (tp->t_row+24) 'I; (short) (tp->t_Irow+l);
break:
case NL:
if (tp->t row < tp->t Irow)
tp->t_row++; case CRTN:
*eolp - 0;
break;
case SVID:
tp->t dstat 1- acol;
e - DVID;
break;
case CVID:
tp->t_dstat &- -aeol;
e - DVID;
break;
case DVID:
tp->t_dstat - aeol;
break:
(*termsw[tp->t_term] .t_outputJ (e, tp):
out:
spIx (sps);

7

Fri Sep

tt1.c
1* @(t)tt1.c
I"

5 19:08:09 1986

1
break;
n - MIN (up->u count,
(unsi~ed) (cp->c last - cp->c first));
i f (copyout «caddr t) &Cp=>c data [cp->c first],
(caddr_t)Up->u_base-; n»
up->u error = EFAULT;
putcf ( (struct- cblock *) cp) ;
up->u base +- n;
up->u-count -- n;
} else {
register c;

1.4 *1

* Line discipline 0

*

No Virtual Terminal Handling

*1
tinclude
+include
tinclude
tinclude
tinclude
tinclude
Hnclude
tinclude
+include
tinclude
tinclude
+include
+include
tinclude
tinclude

"sys/param.h"
"sys/types.h"
"sys/systm.h"
·sys/conf.h"
"sys/dir.h ll
"sys/siqnal.h u
·sys/user.h"
·sys/errno.h"
"sys/proc.h"
·sys/file.h"
·sys/tty.h"
"sys/termio.h"
·sys/sysinfo.h n
"sys/var.h"
"sys/reg.h"

i f «c - getc(tq) < 0)
break;
if (subyte (up->u base++, c»
up->u error - EFAULT;
up->u_count--;
}

i f (tp->t state&TBLOCK) (
if (tp->t rawq.c cctyroc) (tp, T_UNBLOCK);

extern char partab [ ] ;

1*
" routine called on first teletype open.
" establishes a process group for distribution
" of quits and interrupts from the tty.
*1
ttopen(tp}
register struct tty *tp;

I"
* Called from device's write routine after it has
* calculated the tty-structure given as argument.

"I
ttwrite (tp)
register struct tty *tp;

{

register struct proc *pp;

{

register struct cblock "cp;
register struct user "up;
register a, n;

pp - u.uyrocp;
i f «pp->pyid ~ pp->pygrp)
&& (u.u ttyp = NULL)
&& (tp->tygrp - 0)) {
u.u_ttyp - &tp->tygrp;
tp->tyqrp = pp->pygrp;

i f (! (tp->t_state&CARR_ON»)
return;
up - &u;
a - tthiwat[tp->t_cflag&CBAUD];
i f (up->u count <= 4 && up->u arO [RO] & Ox80000000) {
n-= up->u arg[3];
SPL6 (); while (tp->t outq.c cc > a) (
I*tp=>tyroc) (tp, T_OUTPUT);

;
ttioctl (tp, LDOPEN, 0, 0);
tp->t state &= -NOPEN;
tp->t::::state I~ ISOPEN;
ttclose (tp)
register struct tty *tp;
!
i f «tp->t_state&ISOPEN) =
return;
tp->t state &- -ISOPEN;
tp->tJ>grp - 0;
ttioctl (tp, LDCLOSE, 0, 0);

/*
" For non-interrupting output devices sleep
" only when characters are still pending.
*1
i f (tp->t_state& (TIMEOUT I TTSTOP I BUSY) ) {
tp->t state I~ OASLP;
(void) sleep { (caddr_t) &tp->t_outq, TTOPRI);

0)

}

1*
* Called from device's read routine after it has
" calculated the tty-structure given as argument.
*/
ttread(tp)
register struct tty "tp;
!
register struct user *up;
register struct clist *tq;
up - &u;
tq - &tp->t canq;
i f (tq->c_cc -- 0)
canon (tp) ;
while (up->u count! -0 " up->u error--O)
i f (~p->u count >- CLSIZE) (
r;gister n;
register struct cblock *cp;
i f {{cp - Qliltc:b (tqll -

HULL)

SPLO ();
while (up->u count) {
ttxp~t (tp, n&OxFF, 0);
up->u_base++;
up->u count--;
n »--8;
} else
while (up->u_count)
SPL6() ;
while (tp->t outq.c cc > a) {
("tp=>t proc) (tp, T OUTPUT);
1*
* For non-interrupting output devices sleep
* only when characters are still pending.

*'

i f (tp->t state& (TIMEOUT I TTSTOP I BUSY») (
tp->t state 1- OASLP;
(void) sleep( (caddr_t) &t.p->t_outq, TTOPRI);

tt1.c

Fri Sep

2

5 19:08:09 1986

SPLO ():

cp - tp->t_rbuf.c-ptr:

i f (up->u count >- (CLSIZE/4»)

{
if «cp - getcf () ~ NULL)
break:
n - MIN (up->u count, (unsigned) cp->c last):
i f (copyin( (c:iddr tlllP->ll base, (caddr ticp->c data,
n») ( -up->u error = EFAULT:
putcf( (struct cblock ") cp) :
break:

/"
" Put trailing , \n' in a separate cblock
,,/
if (n~up->u_count && cp->c_data [n-l]-' \n'

} else (
/" may do block processing "/
putcb(CMATCH«struct cblock ")cp), &tp->t_rawq):
sysinfo. rawch +- nc:
/" allocate new rx buffer ,,/
i f «tp->t_rbuf.c-ptr - getcf() ->c_data)
-- «struct cblock ")NULL)->c data)
tp->t_rbuf.c-ptr = NULL:
return:
tp->t rbuf.c count = cfreelist.c size:
tp->t=:rbuf.c=:size - cfreelist.c_size:

&&

n--:
up->u_base +~ n:
up->u count -- n:
cp->c-last - n:
ttxput (tp, cp, n):

I else (
n = fubyte (up->u base++):
i f (nu error = EFAULT:
break~

n>=3)
i f (tp->t rawq.c cc > TTXOHI) (
if (flg&IXOFF && ! (tp->t state&TBLOCK»
("tp->t-proc) (tp-;- T_BLOCK) :
if (tp->t rawq.c cc > TTYHOG) (
ttyflush(tp, FREAD):
return:

I
flg - lobyte (tp->t lflag):
i f (tp->t outq.c cc > (tthiwat[tp->t cflag&CBAUD] + TTECHI)

up->u count--:
ttxput (tp, n, 0):

fIg &= -(ECHO I ECHOKI ECHONL IECHOE) :
i f (flg) while (nchar--) {

c - "cp++:
i f (flg&ISIG) {
i f (c -

spltty() ;
i f (! (tp->t state&BUSY»
("tp->t-proc) (tp, T_OUTPUT):
SPLO () :

i f (c -

/"
" Place a character on raw TTY input queue, putting in delimiters
" and waking up top half as needed.
" Also echo if required.
"!
tdefine LCLESC 0400
ttin(tp)
register struct tty "tp;
{

register c:
register fIg:
register char "cp:
ushort nchar, nc:
nchar - tp->t rbuf. c size - tp->t rbuf. c count;
/" reinit rx control-block ,,/
tp->t rbuf. c count - tp->t rbuf. c size:
i f (nchar-O")
-return:
flg - tp->t_iflag:
nc - nchar;
cp - tp->t_rbuf.c-ptr;
i f (nc < cfreelist.c size II (flg & (INLCRIIGNCRIICRNLIIUCLC»)
1* must do per character processing */
for ( ;nc--: cp++) {
c = *cp;
i f (c , \n' && flg&INLCR)
"cp - c = , \r' ;
else if (c - '\r')
i f (flg&IGNCR)
continue:
else i f (flg&ICRNL)
*cp - c - , \n' :
if (flg&IUCLC && 'A' <- c " c <- 'Z')
c+-'a'-'A';
if (putc(c, &tp->t rawq»
continue: sysinfo. rawch++;

tp->t cc [VINTR]) (
signal(tp->tJXJrp, SIGINT):
i f (! (flg&NOFLSH»
tty flush (tp, (FREAD IFWRITE) ) :
continue:
tp->t cc[VQUIT]) (
signal(tp->t-P9'rp, SIGQUIT):
i f (! (flg&NOFLSH»
tty flush (tp, (FREADIFWRITE»:
continue:

Hfdef notdef
i f (flg&ICANON) {
i f (tp->t state&CLESC)
fIg 1= LCLESC;
tp->t_state &= -CLESC;

if (c

~

, \n')

{

i f (flg&ECHONL)
flg 1- ECHO:
tp->t delct++;
I else i f (c:"'\\') (
tp->t state 1- CLESC;
i f (flg&XCASE) (
c 1- QESC;
i f (flg&LCLESC)
tp->t_state

&- -CLESC;
I
} else i f (c ~ tp->t_cC[VEOL] II c -- tp->t_cc[VEOL2])
tp->t delct++:
else i f (! (flg&LCLESC» (
i f (c - tp->t cc[VERASE] && flg&ECHOE)
i f (flg&ECHO)
ttxput (tp, , \b', 0):
flg 1- ECHO:
ttxput (tp, , " 0);
c - , \b';
J else i f (c - tp->t cc [VKILLl && flg&ECHOK) (
i f (flg&ECHO)ttxput(tp, c, 0);
flg 1- ECHO;
C ~ '\n';
} else if Ic - tp->t cc [VEOF] )

fJ.q ,... -:B.CHO:-

Fri Sep

tt1.c

5 19:08:09 1986

3
c - partab[c] & 077;
i f (c ~ 0)
n++;
else if (c !- 1)
return (-1) ;
while (--ncode !~ -1);
return(n) ;

}

i f (flg&ECHO)
ttxput (tp,. c,. OJ:

felse
i f (flg&ICANON) {
if (c == '\n'l

if (flq&ECHONL)
flg 1= ECHO;
tp->t delct++;
) else i f (c ~ tp->t cc[VEOLJ II c = tp->t_cc[VEOL2])
tp->t delct++;
i f (! (tp->t state&CLESC)) !
if(c~'\\')
tp->t_state I- CLESC:
i f (c ~ tp->t cc [VERASE] && flg&ECHOE)
if (flg&ECHO)
ttxput (tp, , \b', 0):
flg 1- ECHO;
ttxput (tp, , " 0);
c - '\b';
} else i f (c ~ tp->t cc[VKILLJ && flg&ECHOK) (
if (flg&ECHO)ttxput(tp, c, 0);
flg 1= ECHO;
c = '\n';
} else if (c -- tp->t cc[VEOF])
flg &- -ECHO;tp->t_delct++;
)

} else (
i f (c !='\\' II (flg&XClISE))
tp->t_state &- -CLESC;

if (flg&ECHO)
ttxput(tp, c, 0);
(*tp->tyroc) (tp, T_OUTPUT):
tendif
i f (! (flg&ICANON)) !
tp->t state &- -RTO;
if (tp->t rawq.c cc >- tp->t cc[VMIN])
tp->t delct - 1:
else if (tp->t cc [VTIME]) {
i f (! (tp->t state&TACT))
tttImeo (tp) ;

1*

* Put character (s) on TTY output queue, adding delays,
" expanding tabs, and handling the CR/NL bit.
" It is called both from the base level for output, and from
* interrupt level for echoing.

*1
1* VARARGSI *1
ttxput (tp, ucp, ncode)
register struct tty *tp;
register ncode;
union {
struct ch
I" machine dependent union * I
char dum[3]:
unsigned char theaddr;
} ch;
int thechar;
struct cblock ·ptr;
ucp;
register struct clist *outqp;
register unsigned char *cp;
register c, fIg, ctype;
register char *colp;
struct cblock "scf;
int cs;
flg = tp->t oflag;
outqp - &tp::>t outq;
i f (ncode - 0) {
i f (! (flg&OPOST))
sysinfo. outch++;
(void) putc(ucp.thechar, outqp);
return;
ncode++;
cp = (unsigned char *) &ucp. ch . theaddr ;
scf = NULL:
} else {
if (! (flg&OPOST))
sysinfo.outch +- ncode;
putcb(ucp.ptr, outqp);
return;
cp - (unsigned char ") &ucp. ptr->c_data [ucp. ptr->c_first] ;
scf - ucp.ptr;

}

i f (tp->t delct && (tp->t state&IASLP»
tp->t state &= -IAsLP:
wakeup ( (caddr_t) &tp->t_rawq);

/*
" Scan a list of characters and assure that they require no
" post processing
"/
ttxchk (ncode, cp)
register short ncode;
register unsigned char *cp;
!
register c, n;
n - 0;

ncode--;
do {
c - *cp++:
i f (c , 0200)
return (-1) ;

}

if

«tp->t_lflag&XClISE)~O

&& (flg&OLCUC)-O) {
colp = &tp->t col;
if (ncode > 1-&& (c - ttxchk(ncode, cp»
(*colp) +- c;
sysinfo.outch +- ncode;
putcb(ucp.ptr, outqp);
return;
}

while (ncode--)
ctype - partab[c - *cp++] & 077;
i f (ctype-O) {
("colp)++;
sysinfo. outch++:
(void) putc (c, OU1:qp);
continue;
else i f (ctype-l)
sysinfo. outch++;
(void) pute Ie, outqp);
continue;

>=

0)

(

tt1.c

Fri Sep

5 19:08:09 1986

4

i f (c >= 0200) (
i f (c - QESC)
(void) putc (QESC, outqp);
sysinfo. outch++;
(void) putc(c, outqp);
continue:

continue;
qcr:
ctype - flg&CRDLY;
i f (ctype - CRl) (
i f ("colp)
c - max((unsiqned) «*colp»4) + 3), 6);
else if (ctype ~ CR2) (
c - 5;
else i f (ctype = CR3)
c = 9;

cs = c;
/"
" Calculate delays.
" The numbers here represent clock ticks
11: and are net necessarily optimal for all terruinals.
* The delays are indicated by characters above 0200.

*colp - 0;
break;

,,/

case 7: /" form feed */
i f (flg&FFDLY)
c = 0177;
break;

c - 0:
switch (ctype) (
case 0: /* ordinary * /
(*colp)++;

sysinfo. outch++;
(void) putc(cs, outqp);
i f Ic) {
i f «c < 32) && flg&OFILL)
i f (flg&OFDEL)
cs = 0177;
else
cs - 0;
(void) putc(cs, outqp);
i f (c > 3)
(void) putc(cs, outqp);
} else (
(void) putc(QESC, outqp);
(void) putc (c 10200, outqp);

case 1: /* non-printing * /
break;
case 2: /* backspace */
i f (flg&BSDLY)
c - 2:
i f (*colp)
(*colp)--;
break:
case 3: /* line feed "/
i f (flg&ONLRET)
goto qcr;
i f (flg&ONLCR) (
i f (! (flg&ONOCR && *colp-=O»
(
sysinfo. outch++:
(void) putc(' \r', outqp);
goto qcr:

qnl:
i f (flg&NLDLY)
c - 5;
break;
case 4: /* tab */
c = 8 - ("colp)&07);
"colp +- c:
ctype = flg&TABDLY;
i f (ctype =- TABO) {
c = 0;
} else i f (ctype =- TABl)
i f (c < 5)
c = 0;
else i f (ctype =- TAB2)
c - 2:
else i f (ctype -- TAB3)
sysinfo.outch +- c;
do
(void) putc (' "
while (--c);
continue;

} else
while (ncode--)
c - *cp++;
i f (c >= 0200)
/* sp15-0 "/
i f (c ~ QESC)
(void) putc (QESC, outqp);
sysinfo. outch++ ;
(void) putc(c, outqp);
continue;
/*
" Generate escapes for upper-case-only terminals.

*/
i f (tp->t Iflag&XCASE) {
colp = II ({)}! I A_"\\ \\H:
while (*colp++)
if (c -- "colp++) {
ttxput (tp, , \\' 10200, 0);
c - colp[-2];
break;
if ('A' <- c && c <- 'Z')
ttxput (tp, , \\' 10200, 0):

outqp);
}

ca se 5: I * vertical tab "/
i f (flg&VTDLY)
c-Ol77:
break;

if (flg&OLCUC && ' a' <- c && c <- , z' I
c+-'A'-'a';
cs = c;
/"
* Calculate delays.
" The numbers here represent clock ticks
* and are not necessarily optimal for all terminals.
" The delays are indicated by characters above 0200.

case 6: /" carriage return */
i f (flg&OCRNL) {
cs - '\n';
goto qnl;

ctype - partab[c];
colp - &tp->t col;
c - 0;
switch (ctype&077)

break;

*/

i f (flg&QNOCR &." "colp -

0)

oaaa Ih 1* orciiaary· * I

Fri Sep

tt1.c

5 19:08:09 1986

5

("colp)++;
sysinfo. outch++;
(void) putc(cs, outqp);
i f (c) (
i f «c < 32) && flg&OFILL)
i f (flg&OFDEL)
cs = 0177;
else
cs = 0;
(void) putc(cs, outqp);
i f (c > 3)
(void) putc (cs, outqpi;
} else (
(void) putc (QESC, outqp);
(void) putc(cI0200, outqp);

case 1: /" non-printing */
break;
case 2: I" backspace *1
i f (flg&BSDLY)
c = 2;
i f (*colpl
("colpl--;
break;
case 3: /" line feed */
i f (flg&ONLRET)
goto cr;
i f (flg&ONLCR) (
i f (! (flg&ONOCR && *colp=O» {
sysinfo. outch++;
(void) putc (' \r', outqp);

}

i f (scf != NULL)
putcf(scf) ;

goto cr;
nl:
i f (flg&NLDLY)
c - 5;

I"
" Get next packet from output queue.
" Called from xmit interrupt complete.
*/

break;
case 4: /* tab ,,/
c = 8 - «"colp) &07);
"colp +- c;
ctype = flg&TABDLY;
i f (ctype = TABO) {

c

ttout(tp)
register struct tty "tp;
(

register struct ccblock "tbuf;
register c;
register char *cptr;
register retval;
register struct clist "outqp;
extern ttrstrt () ;

= 0;

} else i f (ctype =

TAB1)

i f (c < 5)

c

=

0;

else i f (ctype = TAB2)
c ~ 2;
else i f (ctype = TAB3)
sysinfo.outch +- c;
do
(void) putc('
while (--c);
continue;

I,

outqp - &tp->t outq;
if (tp->t state&TTIOW && outqp->c cc~O)
tp..>t_state &- -TTIOW;
wakeup ( (caddr_t)&tp->t_oflag);

outqp);
delay:

tbuf
break;

tp->t state I= TIMEOUT;
timeout (ttrstrt, (caddr t) tp,
(int) «hibyte (tp->t_lflag) &0177) +6» ;
hibyte(tp->t_lflag) - 0;
return(O) ;

case 6: /* carriage return */
i f (flg&OCRNL) (
cs = , \n';
goto nl;
0)

cr:
ctype = flg&CRDLY;
i f (ctype - CRl) (
i f ("colp)
c = max«unsigned) «*colp»4) + 3), 6);
else i f (ctype -- CR2) (
c - 5;
else i f (ctype -- CR3)
c - 9;
"colp - 0;
break;
case 7: /" form feed "/
i f (flg&FFDLY)
c - 0177;
break;

&tp->t tbuf;
putcf(CMATCH( (struct cblock ")tbuf->cytr»;
tbuf->cytr = NULL;

case 5: /" vertical tab "/
i f (flg&VTDLY)
c = 0177;
break;

i f (flg&ONOCR && "colp -continue;

=

i f (hibyte (tp=>t lflag»
i f (tbuf=>cytr)

retval = 0;
i f (! (tp->t oflag&OPOST»
{
i f (tbUf->cJltr)
putcf(CMATCH( (struct cblock *)tbuf->cytr»;
i f «tbuf->cJltr - (char ,,) getcb(outqpll = NULL)
goto out;
1* return(O); ,,/
tbuf->c count - «struct cblock *ltbuf->cJltr)->c_last ( (struct cblock ") tbuf->cJltr )->c_ fir st;
tbuf->c size - tbuf->c count;
tbuf->cytr - &«struct cblock *)tbuf->cJltrl->c_data
[( (struct cblock ") tbuf->cJltr)->c_firstl ;
ret val - CPRES;
I else {
/* watch for timing
*/
i f (tbuf->cytr - NULL) (
if «tbuf->cytr - getcf () ->c_data)
«struct cblock *)NULL)->c data)
tbuf->cJltr - NULL;
goto out;
I" rebl.rn40);
I" Acid r_tart?

*'

Fri Sep

tt1.c

5 19:08:09 1986

6
break:

tbuf->c count - 0;
cptr - tbuf->cytr;
while «c-getc(outqp» >= 0) {
~~ (c =
QESC) {
i f «c = qetc(outqp» < 0)
break;
i f (c > 0200) {
hibyte (tp->t lflaq)
i f (!retval)qoto delay;
break;

case LDCLOSE:
spltty() ;
(*tp->tyroc) (tp, T_RESUME):
SPLO (j:

=

ttywait (tp) :
ttyflush(tp, (FREADIFWRITE»;
i f (tp->t_tbuf.cytr) {
putcf(CMATCH( (struct cblock *)tp->t_tbuf.cytr»;
tp->t_tbuf.cytr - NULL;

c;

tp->t tbuf. c count -

0;

tp->(~tbuf.c:=size - 0;

i f (tp->t_rbuf.cytr) {
putcf(CMATCH( (struct cblock *)tp->t_rbuf.cytr»;
tp->t_ rbuf. cytr - NULL;
tp->t rbuf. c count = 0;
tp->t:=rbuf.c:=size = 0;

retval = CPRES;
*cptr++ - c;
tbuf->c count++;
if (tbuf->c count >= cfreelist.c_size)
break;

tp->t tmflag - 0;
break:
out:
if (tp->t state&OASLP &&
outqp->c cc<=ttlowat [tp->t cflaq&CBAUDJ)
tp->t state &- -OASLP;
wakeup ( (caddr_t) outqp);
return (retval) ;

case LDCHG:
chg = tp->t lflag~arq;
i f (! (chg&ICANONI J
break;
spltty() ;
if (tp->t canq. c ccl {
if (tp->t rawq.c ccl
tp->t canq.c cc +- tp->t rawq.c cc;
tp->t:=canq.c:=cl->c_next
tp->t:=rawq.c_cf;
tp->t_canq.c_cl - tp->t_rawq.c_cl;

=

tttimeo (tp)
reqister struct tty *tp:

tp->t_rawq - tp->t_canq;
tp->t_canq = ttnulq;

{

tp->t state &- -TACT:
i f (tp->t_lflag&ICANON i 1 tp->t_cc[VTlMEJ = 0)
return;
if (tp->t_rawq.c_cc = 0 && tp->t_cc[VMINJ)
return;
i f (tp->t_state&RTO) (
tp->t delct = 1;
i f (tp->t state&IASLP)
tp->t state &- -IASLP;
wakeup ( (caddr_t) &tp->t_rawq);
}

) else {
tp->t state 1- RTO 1TACT;
timeout (tttimeo, (caddr t) tp,
(int) (tp->t_CC[VTlMEJ * (short) «short)v.v_hz/lO»);

1*

* I/O control interface

*1
1* ARGSUSED * I
ttioctl (tp, cmd, arg, mode)
register struct tty *tp;
{

ushort

chg;

switch (cmd) {
case LOOPEN:
i f (tp->t_rbuf.cytr - NULL) {
1* allocate RX buffer * I
while «tp->t rbuf. c ptr - getcf () ->c data)
«struct-cblock *)NULL)->C data)
tp->t_rbuf.cJltr = NULL;
cfreelist. c flag - 1;
(void) sleep ( (caddr_t) &cfreelist, TTOPRI);
tp->t rbuf. c count - cfreelist. c size;
tp->t-rbuf,c-size - cfreelist.c-size;
(*tp->tyrOC) (tp, T_INPUTI;
-

tp->t delct
SPLO();
break;
default:
break;

=

tp->t rawq.c cc:
--

tty.c

Fri Sep

5 19:08:12 1986

/* @(t)tty.c
1.2 "I
/*
* general TTY subroutines
*/
tinclude ·sys!param.h"
tinclude ·sys/types .hM
tinclude ·sys/systm.h M
tinclude ·sys!dir.h"
tinclude ·sys!signal.h"
tinclude ·sys!user.h"
t incl ude • sys! errno . h·
tinclude ·sys!tty.h"
tinclude ·sys!ttold.h·
tinclude ·sys/proc.h"
tinclude ·sys!file. hit
tinclude ·sys!conf. hOI
tinclude ·sys/termio .h"
tinclude ·sys/sysinfo.h"
tinclude ·sys/var.h"
extern
extern
extern
extern

1
case TCSETAF:
ttywait (tp);
if (cmd ~ TCSETAF)
tty flush (tp, (FREAD I FWRITE) ) ;
case TCSETA:
cbp - 5cb;
if (copyin((caddr_t)arg, (caddr_t)cbp, sizeof cb»
up->u_error - EFAULT;
break;

if (tp->t line !- cbp->c line)
if (cbp->c line "< 0 !! cbp->c_line >- linecnt)
uP:>u error = EINVAL;
break:
}

(*linesw[tp->t_line].l_ioctl) (tp, LDCLOSE, 0, mode):
flag - tp->t Iflag;
tp->t iflag :; cbp->c iflag;
tp->t- oflag - cbp->c- oflag;
tp->t-cflag - cbp->c-cflag;
tp->t_lflag = cbp->c-Iflag;
bcopy( (caddr t) cbp->c cc, (caddr t) tp->t cc, NCC);
if (tp->t li;;:e !- cbp=>c line) {t~>t_line = cbp=>c_Iine;
(*linesw[tp->t line].l ioctl) (tp, LDOPEN, 0, mode);
else if (tp->t Iflag-!- flag) {
(*linesw[tp->t_line].l_ioctl) (tp, LDCHG, flag, mode);

int sspeed;
int tthiwat [] ;
int ttlowat [] ;
char ttcchar [] ;

/* null clist header */
struct clist ttnulq;
/* canon buffer */
char
canonb[CANBSIZ];
1*

* Input mapping table-- if an entry is non-zero, when the
* corresponding character is typed preceded by "\,, the escape
* sequence is replaced by the table value. Mostly used for
* upper-case only terminals.
*/
char
maptab[] = {
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,' I' ,000,000,000,000,000,' \ f ,
, {' " }' , 000, 000, 000, 000, 000, 000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,000,000,
000,000,000,000,000,000,' -' , 000,

OOO,'A' ,'B' ,'C' I'D' ,'E' ,'F' ,'G',
I H' ,'I' ,'J' ,'K' ,'L' " M' I 'N' ,'0' ,
'P' ,'Q' ,'R',' 5', 'T', 'U' ,'V', 'W',
'X' ,'Y' ,'Z' ,000,000,000,000,000,
};

/*
" common ioctl tty code
*/
ttiocom(tp, cmd, arg, mode)
register struct tty *tp;
{

register struct user *up;
register short flag;
register struct sgttyb *tbp;
register struct termio *cbp;
struct termio cb;
struct sqttyb tb;

return (1)

case TCSETAi'I:

;

case TCGETA:
cbp = &cb;
cbp->c iflag = tp->t iflag;
cbp->c=oflag = tp->t=oflag;
cbp->c cflag - tp->t cflag:
cbp->c-Iflag - tp->t-lflag;
cbp->c-line - tp->t line;
bcopy «caddr t) tp->t cc, (caddr t) cbp->c cc, NCC);
if (copyout«caddr_t)cbp, (Caddr_t)arg, sizeof cb»
up->u_error = BFAULT;
break;
case TCSBRK:
ttywait (tp) ;
if (arg = 0)
(*tp->tyroc) (tp, T_BREAK);
break:
case TCXONC:
switch (arg) {
case 0:
(*tp->tyroc)
break;
case 1:
(*tp->tyroc)
break;
case 2:
(*tp->tyroc)
break:
case 3:
(*tp->tyroc)
break:
default:
up->u_error -

(tp, T_SUSPEND) :

(tp, T_RESUME) ;
(tp, T_BLOCK) :

(tp, T_UNBLOCK) ;

EINVAL:

break;
C2se

up - &u;
switch (cmd) {
case IOCTYPE:
up->u_rvall - TIOC;
break;

{

TCFLSH:
switch (arg)
case 0:
case 1:
case 2:
ttyflush (tp, (arg - FOPEN) & (FREAD I FWRITE) ) ;
break;

tty.c

Fri Sep

5 19:08:12 1986

2

default:

return!l) :
up->u_error

=

EINVAL;

break;

/* conversion aide only */
case TIOCSETP:
tbp - &tb;
ttywait (tp) ;
ttyflush (tp, (FREAD 1FNRITE) ) ;
i f (copyin( (caddr_t)arg, (caddr_t)tbp, sizeof(tb») (
ut)->u error = EFAULT;
break;
)

tp->t iflag - 0;
tp->t-oflag - 0;
tP->(~lflag = 0;
tp->t cflag - (tbp->sg ispeed&CBAUD) 1CREAD;
i f «tbP->sLispeed&CBAUD)~B110)
tp->t cflag 1- CSTOPB;
tp->t_CC[VERASE] ~ tbp->sg_erase;
tp->t cc[VKILL] - tbp->sg kill;
flag -: tbp->sq flags;
i f (flag&O_HUPCL)
tp->t cflag 1= HUPCL;
i f (flaq&O_XTAss)
tp->t oflag 1= TAB3;
else if (flag&O TBDELAY)
tp->t_oflaq 1- TABl:
i f (flaq&O LCASE) {
tp=>t iflaq 1= IUCLC;
tp->t-oflag 1= OLCUC;
tp->()flag 1- XCASE;
if (flag&O_ECHO)
tp->t lflag 1= ECHO;
i f (! (flag&O NOAL»
tp->t lflag 1= ECHOK;
if (flag&O CRMOD) {
tp=>t_iflag 1- ICRNL;
tp->t oflaq 1- ONLCR;
if (flag&o CRl)
tP:->t oflag 1=
if (flag&O_CR2)
tp->t_ oflag 1=
) else
tp->t_ oflag 1- ONLRET;
if (flag&O_NLl)
tp->t oflag 1if (flag&O NU)
tp=>t_ oflag 1-

case TIOCGETP:
tbp - &tb;
tbp->sg ispeed - tp->t cflag&CBAUD;
tbp->sg::::ospeed = tbp->-;g_ispeed;
tbp->sg erase - tp->t cc[VERASE];
tbp->sq::::kill - tp->t_CC[VKILL];
flag - 0;
i f (tp->t cflag&HUPCL)
flag 1- 0_HUPCL;
if (! (tp->t IflagHCAIWN»
flag 1- 0 RAW;
if (tp->t lflag&XCASE)
flag 1= 0 LCASE;
if (tp->t lflaq&ECHO)
flag 1= O_ECHO;
if (! (tp->t lflag&ECHOK»
flag 1= 0 NOAL;
if (tp->t cflaq&PARODD)
flaq I- 0 ODDP;
else if (tp->t iflaq&INPCKI
flag I:; 0_EVENP ;
else
flag 1- 0 ODDP 10 EVEN?;
i f (tp->t oflag&ONLCR) {flag 1= 0 CRMOD;
if (tp->t- oflaq&CRl)
flag 1- O_CRl:
i f (tp->t oflaq&CR2)
flaq 1= O_CR2:
) else {
i f (tp->t oflaq&CRl)
flaq 1- 0 NLl;
i f (tp->t oflag&CR2)
flag 1= O_NL2;
i f «tp->t_oflag&TABDLY)--TAB3)
flag 1- 0 XTABS;
else i f (tp->t oflag&TABl)
flag
O_TBDELAY;
i f (tp->t oflag&FFDLY)
flag 1= 0 VTDELAY;
i f (tp->t oflag&BSDLY)
flag 1- 0 BSDELAY;
tbp->sg flags - flag;
i f (copyout «caddr_t)tbp, (caddr_t) arg, sizeof{tb»)
up->u_error = EFAULT;
break;

1-:

CRl;
ONOCR 1CR2;

CRl;
CR2;

/*

*

if (flag&O_RAW) {
tp->t cc[VTIME] = 1;
tp->t-CC[VMIN] = 6;
tp->t-iflag &= -(ICRNLI IUCLC);
tp->t-cflag 1= CS8;
) else (
tp->t_cc[VEOF] = CEOF;
tp->t cc[VEOL] - 0;
tp->t- cc [VEOL2] - 0;
tp->t-iflag 1- BRKINT 1IGNPAR 1ISTRIP 1IXON 1lXANY;
tp->t::::oflag 1- OPOST;
tp->t cflag 1- CS71 PARENB;
tp->t::::lflag 1= ICAHONI ISIG;

The following ioctls were added by UniSoft

*/
/*

*

Return number of characters immediately available.

*1
case FIONREAD: {

SPL6 () ;
while (tp->t rawq.c cc && tp->t_delct)
canon (tp); SPLO () ;
nread - tp->t canq. c cc;
i f {! (tp->t lflaq &IeAHON»
nre~d += tp->t_rawq.c_cc;
if (copyout«caddr_t)&nread, (caddr_t)arq, sizeof (off_t»)
up->u_error - EFAULT;
break;

)

tp->t iflag 1- INPCK;
i f (flag&O ODDP)
H- (flaqliO EVENP)
tp=>t_iflag &- -INPCK;
else
tp->t cflag 1- PARODD;
i f (flaq&O_VTDELAYI tp->t oflag 1- FFDLY;
i f (flag&O BSDELAY)
tp=>t-,oflag 1= BSDLY;
o

)

default:
i f «cmd&IOCTVPE) LDIOC)
(*linesw[tp->t_linel.l_ioctl) (tp, cmd, arg, mode);
else

Fri Sep

tty.c

5 19:08:12 1986

3

up->u_error - EINVAL;
break:
return(O) :

ttinit(tp)
register struct tty *tp:
I
tp->t line - 0;
tp-><:)flag - 0:
tp->t oflag = 0;
tp->t:::cflag - sspeed I CS8 ICREAn IHUPCL;
tp->t lflag = 0:
bCopy«caddr_t)ttcchar, (caddr_t)tp->t_cc, NCC);

spltty() ;
if (tp->t rawq.c cc = 0)
tp..>t delct - 0:
while (tp->t_ delct ~ 0) I
if {! (tp->t_state&'CARR_ON) II
SPLOO;
return:

{u. u_fmode&FNDELAY)}

i f (! (tp->t_lflag&ICANON) && tp->t_cc[VMIN]~O)
i f (tp->t_ cc [VTlME] -0)
break:
tp->t state &- -RTO;
i f (! (tp->t state&TACT»
tttImeo (tp) ;

tp->t state 1= IASLP;
(void) sleep( (caddr_t) &tp->t_rawq, TTIPRI);

ttywait (tpJ
register struct tty *tp;
{

spltty() ;
while (tp->t outq.c cc II (tp->t_state& (BUSYITlMEOUTJ) J
tp->t state-1- TTIOW:
(void) sleep( (caddr_t) &tp->t_oflag, TTOPRIJ;
}

SPLO () ;
delay (v. v _ hz»4) ;

/*
* flush TTY queues

i f (! (tp->t lflag&ICANON»
{
i f (tp->t canq.c cc = 0) {
tp->t canq = tp->t rawq:
tp->t:::rawq - ttnulq:
} else
while (tp->t rawq.c cc)
(void) putc(getc(&tp->t_rawq), &tp->t_canq);
tp->t delct = 0:
SPLO():
return:
}

*/
ttyflush (tp, cmd)
register struct tty *tp;
{

register struct cblock *cp:
register s;
i f (cmd&FWRITE) {
while «cp = getcb(&tp->t outq»
!- NULL)
putcf(cp):
(*tp->tyroc) (tp, T_WFLUSH);
i f (tp->t state&OASLP) {
tp->t state &= -OASLP;
wakeup ( (caddr_t) &tp->t_outq):
i f (tp->t_state&TTIOW) {

tp->t state &= -TTIOW;
wakeup ( (caddr_t) &tp->t_oflag):
i f (cmd&FREAD)
while «cp - getcb(&tp->t canq»
!= NULL)
putcf(cp) ;
s = spltty () ;
while «cp - getcb(&tp->t rawq»
!- NULL)
putcf(cp):
tp->t delct - 0:
splx(s) ;
(*tp->t proc) (tp, T RFLUSH);
i f (tp->t state&IASLP) (
tp..>t state &- -IASLP:
wakeup ( (caddr_t) &tp->t_rawq):

/*
.. Transfer raw input list to canonical list,
.. doing erase-kill processing and handling escapes.

*1
canon (tpJ
register struct tty *tp;
I
register char *bp;
register c, esc:

SPLO ();
bp = canonb;
esc = 0;
while «c-getc(&tp->t_rawq» >- 0)
i f (!esc) {
i f (c == '\VI {
esc++;
} else i f (c - tp->t cc [VERASE])
i f (bp > eanoIlbI
bp--;
continue;
} else i f (e = tp->t_cc[VKILL] I
bp - eanonb;
continue;
if
(c ~ tp->t_cc[VEOF])
else
break;
}

} else {
esc =
i f (e
e
c

0;

= tp->t_ce[VERASE] II
== tp->t_cc[VKILL] II

- tp->t_cc[VEOFJ)
bp--;
else if (tp->t_lflag&XCASE)
i f «c < 0200) && rnaptab[c])
bp--;
c = rnaptab[c];
else if (c =- , \\')
continue;
} else i f (c == ' \ \ ' )
esc++;

*bp++ - c;
i f (c -- '\n' II c -- tp->t_cc[VEOL]
break;
i f (bp >- &canonb[CANBSIZ])
bp--;
t;->t 1elct--;
c - bp - canonb;
sysinfo. canch +- c;
bp = canonb;
/* faster copy '1 */
while (c--)
(void) putc(*bp++, &tp->t_canq);
return;

II c -- tp->t_cc[VEOL2] J

tty.c

Fri Sep

5 19:08:12 1986

Ix
* Restart typewriter output following a delay timeout.
* The name of the routine is passed to the timeout
* subroutine and it is called during a clock interrupt.
*/
ttrstrt (tp)
register struct tty *tp;
{

(*tp->tyroc) (tp, T_TIME);

4

Fri Sep
1*

4.45

tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude
tinclude

83/02/16

5 19:09:49 1986

1

*1

"sys/param.h"
"sys/config.h"
"sys/errno.h"
"sys/types.h"
"sys/sysmacros .h"
"sys/systm.h"
"sys/sysmacros .h"
"sys/dir.h"
"sys/signal.h"
Hsys/user. h"
"net/misc.h"
"net/mbuf.h"
"net/protosw.h"
"net/socket.h"
"netl socketvar. h"
"net/in.h"
"net/if .h"
"net/route.h"
"net/inycb.h"
"net/in_systm.h"
"net/ip.h"
"net/ip_var.h"
"net/ip_iemp.h"
"net/udp.h"
"net/udp_ var. h"
"errno.h"

1*
* Checksum extended UDP header and data.

*1
if (udpcksum

&& ui->ui SUiii) {
register u=short csum

*

(

Locate pcb for datagram.

*1
inp - inycblookup(&udb,
ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport,
INPLOOKUP WILDCARD);
i f (inp ~ 0) { 1* don't send ICMP response for broadcast packet *1
i f (in lnaof(ui->ui dst) ~ INADDR_ANY)
- go to bad; iemp_error «struct ip *)ui, ICMP_UNREACH, ICMP_UNREACH_PORT);
return;

{

1*
* Construct sockaddr format source address.
* Stuff source address and datagram in user buffer.
*1
udp_in. sinyort = ui ->ui_ sport;
udp in. sin addr = ui->ui src;
m->'i len
sizeof (stru;t udpiphdr);
m->m-off += sizeof (struct udpiphdr);
if (sbappendaddr(&inp->inp socket->so rcv, (struct sockaddr *1 &udp_in, m) == 01
goto bad;
sorwakeup(inp->inp_socket) ;
return;

udb.inp_next = udb.inp_prev = &udb;
udpcksu!n:
sockaddr_in udp_in

ui->ui_sum;

1*

1*
* UDP protocol implementation.
* Per RFC 768, August, 1980.
*1
udp_init()

int
struct

=

i f (csum == Oxffff)
csum - 0;
ui->ui_next - ui->uiyrev = 0;
ui->ui xl - 0;
u~->u~=len = htons( (u_short) len) ;
U1.->U1. sum = 0;
if (csUm !- in cksum(m, len + sizeof (struct ipl»
udpstat. udps badsum++;
m_freem(m); return;

=

-=

AF_lNET I:

udp_input (mO)
struct mbuf *mO:
register struct udpiphdr *ui;
register struct inpcb *inp:
register struct mbuf *m;
int len;

bad:
m_ freem (m) ;

1*

udp_abort (inp)
struct inpcb *inp;

* Get IP and UDP header together in first mbuf.
*I
m - mO;
if «m->m_off > MMAXOFF II m->m_len < sizeof (struct udpiphdr»
(m = myullup(m, sizeof (struct udpiphdr») == 0) {
udpsta t . udps hdrops++;
return;
ui - mtod (m, struct udpiphdr *);
i f « (struct ip *)ui)->ip_hl > (sizeof (struct ip) » 2»
ip_stripoptions«struct ip *)ui, (struct mbuf *)0);

1*
* Make mbuf data length reflect UDP length.
* If not enough data to reflect UDP length, drop.
*1
len - ntohs (Iu short) ui ->ui ulen);
i f « (struct
*)ui)->ip l;:;n !- len) (
i f (len> «struct ip *)ui)->ip_len)
udpstat.udps badlen++;
goto bad;
-

lp

m_adj (m, «struct ip *)ui)->ip_len - len);
;* (struct ip *)ui->ip_len = len; *1

struct socket *so

=

inp->inp_socket;

&&

inycbdisconnect (inpl ;
soisdisconnected(so) ;

udp ctlinput (emd, argl
int cmd;
caddr_t arg;
struct in addr *sin;
extern u_(;har inetctlerrmap [1 ;
i f (cmd < 0 II cmd > PRC_NCMDS)
return;
switch (cmdl {

case PRC_ROUTEDEAD:
break;
case PRC_CUENCH:
break;

Fri Sep

5 19:09:49 1986

2
int req;
struct mbuf *m, *nam;

/* these are handled by ip */
case PRC_IFDOWN:
case PRC_HOSTDEAD:
case PRC_HOSTUNREACH:
break;

struct inpcb *inp - sotoinpcb(sol;
int error = 0;
if (inp

default:
sin - &«struct icmp X) arg) ->icmp ip. ip dst;
inycbnotify (&udb, sin, (int) inetctlernnap [cmd], udp_abort) ;

NULL && req != PRU_ATTACH)
error = EINVAL;
goto release;

=

switch (req)
case PRU ATTACH:
If (inp != NULL)
error = EINVAL;
break:

udp output (inp, mOl
struct inpcb *inp;
struct mbuf "'mO;
register
register
register
register

struct mbuf *m;
struct udpiphdr "ui;
struct socket *so;
int len = 0;

/*

* Calculate data length and get a mbuf
" for UDP and IP headers.
*/
for (m = mO: m; m - m->m next)
len += m->m len:/* we don't have MT~)EADERI s (yet'?)
m ~ m get(M DONTWAIT, MT HEADER);
*/
m - m get (M DONTWAIT);
if (m-~ 0)-(
m_freem(mO) ;
return (ENOBUFS):

* Fill in mbuf with extended UDP header
" and addresses and length put into network format.
*/
m->m_off - MMAXOFF - sizeof (struct udpiphdr);
m->m len - sizeof (struct udpiphdr):
m->m-next = mO;
ui = - mtod (m, struct udpiphdr *):
ui->ui_next = ui->uiyrev = 0;
ui->ui xl = 0;
ui->ui-pr - IPPROTO UDP:
ui->ui-Ien - len + sizeof (struct udphdr);
ui->ui- src - inp->inp laddr;
ui->ui-dst = inp->inp-faddr:
ui->ui-sport = inp->inp lport;
ui->ui-dport - inp->inp-fport;
ui->ui-ulen = htons({u short)ui->ui len):
ui->u()en - ui->ui_ul;n;
/*

/* "bind" is not in the system (yet'?)
case PRU BIND:
;rror = inJlCbbind (inp, nam);
break;
/* neither is listen
case PRU_LISTEN:
error = EOPNOTSUPP;
break;

*/
case PRU CONNECT:
If (inp->inp_faddr.s_addr != INADDR_ANY)
error = EISCONN;
break;
error = inJlCbconnect(inp, (struct sockaddr_in *)nam);
if (error ~ 0)
soisconnected (so) ;
break;

dat~gram.

*/
ui->ui sum = 0;
if (udPcksum) {
ui->ui sum ~ in cksum(m, sheof (struct udpiphdr) + len);
if (ui=>ui sum ::.. 0)
ui=>ui_sum - Oxffff;
«struct ip *)ui)->ip len - sheof (struct udpiphdr) + len;
«struct ip *)ui)->ip-ttl - MAXTTL;
so - inp->inp socket;return (ip output(m, (struct mbuf *)0,
(so->so options & so DONTROUTE) ? &routetoif
(struct route *lO,
so->so_state , SS_PRIV));

/*ARGSUSED*/
"dp usrreq (so, req, m, nam)
struct socket "so;
-

case PRU DETACH:
If (inp = NULL)
error - ENOTCONN;
break;
inJlCbdetach (inp) ;
break;

/*

* Stuff checksum and output

/* billn. for now, attach the old 4.la way
error = in pcballoc{so, &udb):
if (error)break;
error - soreserve{so, 2048, 2048);
*/
error = inJlCbattach(so, &udb, 2048, 2048,
(struct sockaddr_in *)nam);
if (error)
break;
break;

case PRU_ACCEPT:
error - EOPNOTSUPP;
break;
case PRU_DISCONNECT:
if (inp->inp faddr. s addr
error - ENOTCONN;
break;
)

inJlCbdisconnect (inp) ;
soisdisconnected(so) :
break;
case PRU_SHUTDOWN:
socantsendmore (so) ;
break;

Fri Sep

5 19:09:49 1986

struct in_ addr laddr:
i f (nam) {
laddr - inp->inp laddr:
i f (inp->inp_faddr.s_addr != INADDR_ANY)
error - EISCONN;
break:

error - inycbconnect (inp, (struct sockaddr_in ") nam) ;
if (error)
break:
} else {
i f (inp->inp_faddr.s_addr error = ENOTCONN;
break;

error

m-

=

INADDR_ANY)

udp_output (inp, m);

NULL;

i f (nam) {
inycbdisconnect (inp);
inp->inp_laddr - laddr:

break;
case PRU ABORT:
InJ)Cbdetach (inp) ;
so free (so) ;
soisdisconnected (so);
break;
case PRU_CONTROL:
error - EOPNOTSUPP;
break;
case PRU_ SOCKADDR:
in setsockaddr ( (struct sockaddr_ in ") nam, (struct inpcb ") inp) ;
break:
default:
panic (lIudp_usrreqll) :
release:
if

(m

! - NULL)

m_freem(m) ;
return (error);

3

utssys.c

Fri Sep

5 19:08:14 1986

I" @(t)utssys.c 1.3 "I
tinclude "sys/param.h"
tinclude "sys/types .h lO
tinclude "sys/sysmacros.h lO
+include "sys/buf .h"
tinclude "sys/filsys.h"
tinclude "sys/mount.h lO
tinclude "sys/dir.h"
tinclude "sys/signal.h"
tinclude "sys/user .h"
tinclude "sys/errno.h"
tinclude "sys/var .h"
tinclude "sys/utsname.h"
utssys (I
(

reqister i;
reqister struct
char
int
int
I "uap;
struct {
daddr t
ino_tchar
char
lust;
reqister struct

a (
"cbuf;
mv;
type;

f tfree;
f-tinode;
f-fname [6];
(:fpaCk[6];
user "up;

up = &u;
uap - (struct a ")up->u ap;
switch (uap->type) {
case 0:

1* uname *1
if (copyout«caddr_t)&utsname, uap->cbuf, sizeof(struct utsnamel»
up->u_error - EFAULT;
return;

1* case 1 was umask *1
case 2:

I" ustat */
for(i=O; im flaqs-MINUSE && brdev (mp->m dev)-brdev (uap->mv) )
reqister struct filsys *fp;
fp - mp->m bufp->b un.b filsys;
ust. f tfree - FSLTOP (mp=>m dev, fp->s_ tfree) ;
ust. f - tinode - fp->s tinode;
bcopy(" fp->s fname, ust. f fname, sizeof (ust. f _ fname) ) ;
bcopy (fp->s-fpack, ust. f- fpack, sizeof (ust. f fpack»);
if (copyout(" (caddr_t) &ust, uap->cbuf, 18»)
up->u_error ~ EFAULT;
return;

up->u_error
return:
case 33:

=

EINVAL;

1* uvar "I
if (copyout«caddr_t)&v, uap->cbuf, sizeof(struct var)))
up->u_error - EFAULT;
return;

default:
up->u_ error - EFAULT;
J

1

Fri Sep

vt100.c

5 19:08:46 1986

1
extern int (*te putc) () ;
int vt_escO; int x;

1*

* copyright 1982 UniSoft Corporation
" Use of this material is subject to your disclosure agreement with
AT&T, Western Electric and UniSoft Corporation.

*

extern time_t Ibolt;
* VT100 emulator
* Called with each character destined for the console.
* Processes control sequences and keeps track of terminal state.
* Calls into bitmap.c actually do the Ilo

12 dtrap = Ibolt + 12 dtime:
if- (12_dimmed) 12undiliio:
if (c >= , ') {
bmputc (vt_ row+vtrow_ ofs, vt_col +vtcol_ ofs, c) ;
vt advance () ;
bmInvert (vt_row+vtrow_ofs, vt_col+vtcol_ofs):
return:

*1
1* SENSESCRN resets the contrast on screen output (via the console device
* driver} as if a key was hit.
*/

bminvert (vt row+vtrow ofs, vt col+vtcol_ofs):
switch (vt_keytype[c] )-(
case CBKSP:
i f (vt col> 0)
- vt_col--:
break:
case CCR:
vt_col - 0;
break:
case CLF:
if (++vt row >- vt maxrow) {
bIt (bmscrn+90*9, bmscrn+90*9*2, 9*90*38) ;
vt_row -- vt_winscrl:

tinclude Hsys/types .h"
tinclude "sys/12.hJdefine FAST
tdefine SENSESCRN
tdefine MAXVT N
tdefine MAXPARAMs

255

10

/* maximum value of any numeric parameter *1
/* maximum number of numeric parameters *1

short vt_n[MAXPARAMS]:
1* numeric parameters of \E [ commands * /
char vt mparam:
char vt:::tabset [88] = { 0 };
extern char bmbck, bmcolor, bmnormal;
extern char *bmscrn;
extern char kb altkp;
short vt_maxro; - 38;
short vt_maxcol - 88;
short vt row, vt col;
1* cursor location (O-vt_maxrow, O-vt_maxcol) */
short vtrow ofs :; 1;
short vtcOl:::ofs = 1:
1* row and column offsets * /
short vt_winscrl - 1:
1* lines to scroll each time *1

break;
case CHTAB:
for ( x

= vt col+l; x < vt maxcol-l
i f (-vt tabset[x] :;= 1 )
-break;
vt_col = x;
break;
case CESC:
teyutc = vt_esc;
break;
case CBELL:
beep 0 ;
break;
case CGARB:
break;

/* This routine interprets the characters destined for the console and
* performs like a VT100
It is implemented in terms of primitives
* defined in bitmap. c

*1
Jdefine
Jdefine
tdefine
Jdefine
tdefine
Jdefine
Jdefine
Jdefine

CBKSP
CCR
CLF
CHTAB
CESC
CSELL
CGARB
CCHAR

5

6

1*

* Process the escape sequences to the terminal

*1
char vt_keytype [] = (
CGARB, CGARB,
CBKSP, CHTAB,
CGARB, CGARB,
CGARB, CGARB,

CGARB, CGARB,
CLF,
CLF,
CGARB, CGARB,
CGARB, CESC,

CGARB,
CLF,
CGARB,
CGARB,

CGARB,
CCR,
CGARB,
CGARB,

CGARB,
CGARB,
CGARB,
CGARB,

CBELL,
CGARB,
CGARB,
CGARB,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CeSAR,
CCHAR,

CCHAR,
CCHAR,
ceHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCllAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CCHAR,

CCHAR,
CCHAR,
CCHAR,
CGARB,

);

vt putc Ie)
register char c:
{

x++)

1* after ESC key hit *1

vt_esc(c)
register char c;
(

extern int (*teyutc) ();
int vt_ brck () , vt_putc{) ;
switch (c) {
case ' [ ' :
teyutc - vt_brck;
1* check E[ sequence *1
return;
,>,
:
case
/* disable alternate keypad *1
kh_altkp - 0:
break;
1* enable alternate keypad *1
case ,_, :
kh_altkp - 1;
break;
1* reverse scroll */
case 'M':
bminvert (vt row+vtrow_ofs, vt_col+vtcol_ofs);
bmrscrl() :
bminvert (vt_row+vtrow_ofs, vt_col+vtcol_ofs);
break:
case 'H' :
vt_tabset [vt_colJ =1;

Fri Sep

vt100.c

2

5 19:08:46 1986

break:
teyutc - vtyutc:
return:

/ * \E [

vt brck(c)
register char c:

sequence checked here * /

{

extern int (*teyutc) ():
int vtyaram (), vt_ attrb () ;

0:

break:
case ' H' :
/* move cursor home "/
i f (vt_nl == 0)
vt row = 0:
else if «vt_row = vt_n1-1) >- vt maxrow)
vt row - vt maxrow - 1:
i f Ivt n2 ::.. 0)
- vt col - 0;
else if (6rt_col = vt_n2-1) >= vt maxcol)

vt mparam = 0:
vt-n[O] = vt n[l] = 0;
if- (c - , :'1 {
/" missing 1st number - look for 2nd ,,/
teyutc - vtyaram:
vt_ mparam++:
return:
if (c >= , 0' && c <- , 9' ) (
vt_n[O] = c - '0':
teyutc = vt_param;
return:
if

break:
case 'J':
/* clear screen */
i f Ivt n1 = 0)
- i f «vt row - 0) && (vt_col == 0»
- vt n1 = 2;
switch (vt n1) ( case 0: /*-clear from cursor to end * /
for (y = vt_col : y < vt_maxcol : y++ )
bmputc(vt row+vtrow ofs,y+vtcol ofs,' '):
for (x - vt rOW+l;- x < vt mixrow : X++ 1
bmblank(x+vtrow_ofs) :
break:
case 1: /* clear from beginning to cursor ,,/
for (x = 0: x < vt_row : x++ )
bmblank(x+vtrow ofs):
for (y - 0: y <= vt_cOl-: y++ )
bmputc(vt_row+vtrow_ofs,y+vtcol_ofs,' ');
break;
case 2: /" clear entire screen ,,/
bmclear() ;

(c ~

'2') (
teyutc - vt_attrb;
return;

vtyaram(c)
register char c;
{

register tmp:
int vtyutc () ;
if ( c >= , 0' && C <= , 9' ) (
tmp = (vt n[vt mparam] * 10) + (c - '0'):
vt n[vt mparaml = (tmp > MAXVT_N) '? MAXVT N
return:if

c

=

':'

tmp;

)

if (++vt_mparam >= MAXPARAMS) { /* too many parameters *1
teyutc = vtyutc;
return:
vt n[vt mparam]
return:-

vt cmd(c)
register char c;

=

break:
case ' C' :
/* move cursor right * /
i f (vt n1 0)
- vt_n1 - 1:
y = vt col + vt n1;
vt col-= ly < vt !!!axco1) '? y : vt_maxcol-l:
br;ak;
case 'D':
/* move cursor left */
i f (vt n1 ~ 0)
- vt_n1 - 1;

0:

/* now have last char of esc sequence */

break:
case 'K':
1* clear line */
switch (vt nIl {
case 0: / *-clear from cursor to end * /
for (y = vt_col : y < vt_maxcol : y++ )
bmputc (vt_row+vtrow_ofs,y+vtcol_ofs,' '):
break;
case 1: I" clear from beginning to cursor *1
for (y = 0 : y <= vt col : y++ )
bmputc (vt_row+vtrow_ofs, y+vtcol_ofs, , '):
break:
case 2: /* clear entire line */
bmblank(vt_row+vtrow_ofs) :

(

extern int (*te putc) () ;
register vt n1 :: vt n [0] :
register vt-n2 - vt-n[l];
register int x, y; int vtyutc () :
if (c--'f')
c='H':
i f «c >- , A') '" (c <= , Z'» {
bminvert (vt row+vtrow ofs, vt_col+vtcol_ofs);
switch (c) {case' A':
;* move cursor up *1
i f (vt_n1 - 0)
vt_n1 - 1:
vt_row - (vt_nl < vt_row) '? (vt_row - vt_nl)
break;
case 'B':
/* move cursor down *1
i f (vt_nl 0)
y - vt row + vt_nl;

break:
case 'L':
/* insert line(s) *;
i f (vt_n1 - 0)

0;

if (vt n1 > vt maxrow - vt_row)
- vt n1 :;; vt maxrow - vt row;
for (x-vt maxrow-1-;- y-vt maxrow-vt n1-1; y >- vt_row; X--, y--)
bii;cpl (x+vtrow ofs, y+vtrow- ofs) ;
for ( : x >- vt row : - x-- )
bmblank(x+vtrow_ofs) ;
break;
case 'M':
;* delete line(s) *;
i f (vt nl - 0)
- vt_nl - 1;
if (vt n1 > vt maxrow - vt_row)
vt n1 ~ vt maxrow - vt row:
for (x-vt row, y-vt row+vt nl;-y < vt maxrow; x++, y++)
bii;cpl(x+vtrow ofs,-y+vtrow ofs);
for ( ; x < vt maxrow-; x++ )
bmblank(x+vtrow_ofs) ;

Fri Sep

vt100.c

5 19:08:46 1986

3

break;
case 'P':
1* delete character(s) *1
i f (vt_n1 ~ 0)
vt n1 = 1;
i f (vt_n1 -; vt_maxcol - vt_col)
\,'t nl .. \.rt maxcol - vt col;
for (x-vt Col, y=vt col+vt n1;-y < vt maxcol; x++, y++)
bmmvc (vt row+vtrow- ofs, x+vtcol ofs,
Vt row+vtrow ofs, y+vtcol ofs);
for ( ; x < vt maxcol ; x++ l
bmputc(vt_row+vtrow_ofs,x+vtcOl_Ofs,' ');
break;
bminvert (vt row+vtrow ofs, vt_col+vtcol_ofs);
) else {
switch (c)
case'g':
i f (vt_n1 - 0)
vt tabset[vt_coll - 0;
for (x - 0 ; x < vt maxcol
vt_tabset[x) = 0;
break;
case 'm':
for (x

=

x++)

1* set normal display or reverse video *1
0; x <- vt mparam; x++)
switch (vt [xl) {
case 0: I"-turn underline off, set normal background "I
i f (bmbck !- bmnormal) {
bmswitch();
I" invert font table "I
bmbck = bmnormal;

n

bmcolor = bmbck;
I" underline off "I
break;
case 1: case 7: I" set reverse image "I
if (bmbck -- bmnormal) !
bmswitch();
1* invert font table "I
bmbck = bmnormal ? 0 : -1;
break;
case 4: 1* set underline" I
b!!!color = bmbck ? 0

-1;

break;
teyutc

=

vtyutc;

vt_ attrb (c)
1* \E[? *1
char c;
!
int vt_atrb(), vtyutc();
if(c >- '0' && c <= '9')
teyutc - vt_atrb;
else
teyutc

=

vtyutc;

int vt_putc () ;

vt_advance ( )
if (++vt col >- vt maxcol) J
' . ',?:ca:;s ar:l!.l:'_d .. ,
; t col = 07
.
if- (++vt row >- vt maxrow)
1* on last line *1
bIt (bmscrn+90*9, bmscrn+90*9*2, 9*90*38) ;
vt_row -- vt_winscrl;

Eri Sep

bm.e

5 19:08:34 1986

1

1*

* Copyright 1982 UniSoft Corporation

bmifont I)

* Use of this material is subject to your disclosure agreement with
* AT&T, Western Electric and Unisoft Corporation.

{

1* invert the font table (set or reset rev. video) *1

register short i;
register char *f, g;
extern long bblank [j ;

* Bitmap Display Driver
* The screen is 720 by 364 raster units. A comfortable pixel size is
* 9 by 10 giving 80 columns (9 wide) and 36 lines (10 deep). The
* extra 4 raster rows are unused. Unfortunately this arrangement is
* very expensive in processor time since pixels lie across byte boundaries.

i - sizeof(bmfont) - 1;
f = bmfont;
do {
g = -*f;
"f++ = g:

* For the time being the pixel size used will be 8 by 9 providing a
" screen area of 90 columns, and 40 lines.

while (--i !- -1);
for (i=O; i<16; i++)
bblank [i] =

* This is the low level display driver intended to simplify the task
* of writing higher level screen emulators by simUlating just the common
* aspects of all crts in the following functions:
bmsinvl)
bminit ()
bminvert (row, col)
bmputc (r, c, char)
bmwin (cmd, t, b, 1, r)

clears entire display
invert character at row, column
put the character at row, column
modifies window (top, bot, left, right) ;
cmd ~ 1 means scroll up a line
cmd ~ 0 means clear that area

1* amount of screen in longs *1

(

bblank [i]

-1) ;

1* invert the entire screen *1

{

register short i;
register char *p, q;

1* amount of screen in chars *1

i - MAXCOL " MAXROW " V_RESO;
P = bmscrn;

*1
ide fine FAST
idefine NODEBUG
iinclude 
Hnclude 
iinclude 
Hnclude 
char
char
char
char
char

*bmscrn;
bmcolor;
bmbck;
bmnormal;
bmfirst - 1:

bminit ()

do {
q - -*p:
*p++ - q:
} while (--i !- 0):

1*
1*
1*
1*
/*

pointer to screen -- initialized in bminit *1
underline color: same as bmbck for no underlining *1
current background color: 0 for white, -1 for black */
normal background color: 0 for white, -1 for black *1
is this the first boot? (not true for a restart) */

1* one time screen initialization (called from mch.s) *1

iifndef FAST
1* Modify a section of the display
* Cmd is 0 to clear the area, positive to scroll up that many lines
" or negative to scroll down that many.

*1
bmwin (cmd, tr, br, lc, rc)
short cmd, br, lc, rc:
register short tr:

{

/" amount of screen in longs * I

register short i:
register long *p;
extern long bblank [ ] :

register short wrap, j, i:
short cols, rows:
register char *pc, *ec:
register char color - bmcolor:

*MEMEND -= SCRNSIZE:
I" lop off mem for screen *1
bmscrn ~ "MEMEND:
/* logical screen address */
VIDADDR - «int) (bmscrn+*MEMBASE) »15) : /* init screen addr latch */

i
p

=
=

«SCRNSIZE - (MAXCOL " MAXROW * V RESO» » 2) - 1:
(long *) (bmscrn + (MlIXCOL * MAXROW " V_RESO»:

do {

/* so retrace lines won't show */
*p++ = -1:
} while (--i !- -1):
bmcolor - 0;
1* bmcolor switches in bminit if bmbck is -1 *1
bmbck = -1:
bmnormal = -1;
bmclear() ;
if (bmfirst) {
bmfirst - 0:
bmswitch () ;
bmclear ();
l else (
bmcolor = -1:
for (i-O; i<16; i++)
bblank[i] = -1;
bmclear ():

{

bmcolor -

iendif

1* Calculate number of logical lines to operate on */
rows

=

br - tr + 1;

/* Calculate number of columns (bytes) accross screen ,,/
co1s - rc - lc + 1;
/* Wrap is an offset to be added to scan line pointers at the end of
* each line to bring them around to the start of the next line.
* It is the number of columns not being scrolled (usually zero)
*1
wrap - BPL - cols;
1* wrap around offset ,,/

/* Pc points at the upper area of the screen (ie, that which will
* receive the scroll data).
*/
pc +- tr " (short) (BPL " V_RESO) + lc;

bmswitch ()
bmifont \);

pc - bmscrn;
Hfndef NODEBUG
if (tr-MAXROW 11br>-MAXCOL 1 1br=MAXCOL 11rc>=MAXCOL 1 1rc<=lc)
printf (Rbmwin (%s, %d, %d, %d, %d) is illegal \n R ,
cmd?"scroll": "clear", tr, br, lc, rc);
return:

(bmcolor ? 0

-1) ;

I" I is the number of scan lines to operate on.

ie. the number
" lines in the window. m.iz:lus the IlIlIIIher of linea to eoroll.

0:

Fri Sep

bm.e

5 19:08:34 1986

2

*/
i -

(short) (rows - cmd) * (short) (V_RESO) - 1; /* scan lines */

/* Here we do the scrolling if it is indicated */
if (cmd) (

telse FAST
bmcpl (dl, sl)
register dl, sl;
(

register char *dest, *src;

/* scroll command lines */

dest - bmscrn + (dl * (BPL * V RESO»;
src - bmscrn + (sl * (BPL * V_RESO»;

1* Bc is is set:. t:.o point at the first line to scroll up */
ec - pc + cmd * «short) (BPL) * (short) (V_RESO»);
/* scroll scan line at a time */
/* column counter */
j - cols - 1;
do *pc++ - *ec++;
/* optimizes to libra loop */
while (--j != -1);
pc +- wrap;
1* skip to next scan line */
ec +~ wrap;
while (--i != -1);

do (

i -

(short) (V_RESO)

do

* cmd -

1;

/* reset for clear */

/* clear */

j ~ cols - 1;
do *pc++ = color:
while (--j !- -1);
pc += wrap;
) while (--i !- -1);
return;

tendif
bminvert (r, c)
register short r, c;

/* reverse video char under cursor "/

register char *p = bmscrn;
register short i;

* V_RESO»
i - V RESO;
do ( *p = -*p;
p +- BPL;
) while (--i != 0);

P += (r * (BPL

bmmvc (dr, dc, sr, scI
register short dr, dc;
register short sr, sc;

+ c;

/* 1 scan line */

/* copy char at (sr,sc) to (dr,dc) */

(

register char *dest, *src;
register short i;
dest = bmscrn + (dr " (BPL " V_RESO» + dc;
src = bmscrn + (sr * (BPL " V_RESO» + sc;
i - V_RESO;
do (
"dest - * src;
dest +- BPL;
/"
scan line */
src +- BPL;
/"
scan line "/
) while (--i !- 0);

/* copy line sl to dl */

/* register as * /
/* register a4 */

/* Use the 13 registers a6, a3-aO and d7-dO to copy 52 bytes at a time. */
tOxFFFF, sp@- II);
asm(" moveml
/* save all the registers */
asm(" moveml
a4@,~Ox4FFF HI;
I" move 52 bytes */
asm(N moveml
tOx4FFF,a5@ ");
a4@
(52),
tOx4FFF
");
asm(" moveml
/* move 52 bytes */
asm(" moveml
tOx4FFF ,a5@ (52) ") ;
asm(" moveml
a4@(104),tOx4FFF ");
/* move 52 bytes */
tOx4FFF,a5@(104) "):
asm(" moveml
asm(1O moveml
a4@ (156), tOx4FFF ") ;
/* move 52 bytes */
tOx4FFF,a5@(156) ") :
asm(" moveml
a4@ (208), tOx4FFF ") :
asm(" moveml
/* move 52 bytes */
asm(" moveml
tOx4FFF,a5@(208) H):
asm(" moveml
a4@ (260) , tOx4FFF H) :
/* move 52 bytes */
asm(" moveml
tOx4FFF,a5@(260) ") :
asm(" moveml
a4@(312),tOx4FFF ");
/* move 52 bytes */
asm(" moveml
tOx4FFF, a5@ (312) ") ;
asm(" moveml
a4@ (364), tOx4FFF ") ;
/* move 52 bytes */
asm(U moveml
tOx4FFF, a5@ (364) ") ;
asm(" moveml
a4@(416) ,tOx4FFF ");
/* move 52 bytes */
asm(" moveml
tOx4FFF,a5@(416) ") :
asm (H moveml
a4@ (468), tOx4FFF ");
/* move 52 bytes */
asm(" moveml
tOx4FFF,a5@(468) ") ;
asm(" moveml
a4@ (520), tOx4FFF ");
/* move 52 bytes */
asm(" moveml
tOx4FFF ,a5@ (520) ");
asm(1O moveml
a4@(572),tOx4FFF 10);
/* move 52 bytes */
asm(" moveml
tOx4FFF,a5@(572) H) ;
asm(" moveml
a4@(624) ,tOx4FFF ");
/* move 52 bytes * /
asm(" moveml
tOx4FFF,a5@(624) H) ;
asm(H moveml
a4@(676),tOx4FFF ") ;
/* move 52 bytes */
asm (" moveml
tOx4FFF,a5@(676) ") ;
asm(" moveml
a4@ (728), tOx4FFF ") ;
/* move 52 bytes */
asm(" moveml
tOx4FFF,a5@(728) ");
asm (H moveml
a4@(780),tOx7F ");
/* move 28 more bytes */
tOx7F, a5@ (780) H) ;
asm(" moveml
a4@ (808), a5@ (808) ");
asm(" movw
/* move last 2 bytes */
sp@+,tOxFFFF II);
asm(" moveml
tifdef lint
if (dest)
return;
else if (src)
return;
tendif lint
)

tendif FAST
tifndef FAST
bmblank (dl)
register dl;

/" blank line dl */

(

register char "dest;
register short i;
tifndef FAST
bmcpl(dl, sl)
register dl, sl:

/* copy line sl to dl "/

dest - bmscrn + (dl " (BPL * V_RESO»:
i - BPL * V RESO;
do {
*dest - bmnormal;
dest++;
/* 1 scan line */
} while (--i != 0):

{

register char "dest, * src;
register short i;
dest - bmscrn + (dl * (BPL * V RESO»:
src - bmscrn + (sl • (BPL * V_RESO»;
l ~ BP~ " V_RESO;
do (
*dest - *src;
dest++:
scan line "I
1*
src++;
scan line */
/*
I while (--i != D) ;

telse FAST
bmblank (dl)
register dl;

I' blank line dl * /

{

register char *dest, *a4:
extern long bblank [ J ;
dest

=

'* NOTUSED * /

bmscrn + (dl " (BPL " V_RESO)):

/* register as *1

Fri Sep

bm.e

5 19:08:34 1986

1* save all the registers *1

asm(1I moveml
iOxFFFF,sp@- H);
a4 ~ (char *)bblank:
asm(" moveml
a4@,iOx4FFF to);
asm(H movl
a6,a4 ");
asm(" moveml
asm(" moveml
asm(H moveml
asm(" moveml
asm(" moveml
asm(" moveml
asm(H moveml
asm(" moveml
asm(" moveml
asm(" moveml
asm(" moveml
asm(" moveml
asm(" moveml
asm(" moveml
asm(" moveml
asm(" movw
asm(H moveml
tifdef lint
if (dest)
return;
else if (a4)
return;
tendif lint

3
asm(to moveml
asm(" moveml
asm(" moveml
asm(" moveml
asm(" moveml
asm P' moveml
asm(" moveml
asm(" cropl
asm(" bne
asm(" mavl
asm(" moveml
splx(x) :

1* set a6,a3-aO,d7-dO to blanks *1
1* set a4 to blanks *1

iOx5FFF,a5@ ");
tOx5FFF, a5@ (56) II);
tOx5FFF,a5@(112) II);
tOx5FFF,a5@(168) H) ;
iOx5FFF,a5@(224) to);
tOx5FFF, a5@ (280) H) ;
tOx5FFF,a5@(336) H);
tOx5FFF, a5@ (392) H) ;
iOx5FFF,a5@(448) a);
tOx5FFF,a5@(504) ") ;
tOx5FFF, a5@ (560) ");
iOx5FFF,a5@(616) ") ;
tOx5FFF,a5@(672) n) ;
tOx5FFF,a5@(728) ") ;
tOx3F,a5@(784) ");
_bblank,a5@(808) ");
sp@+, tOxFFFF ");

1* move 56 bytes *1

tOxFFFE, sp@- ")
tOxFFFE, sp@- ")
tOxFFFE, sp@- ")
tOxFFFE, sp@- ") ;
tOxFFFE, sp@- H) ;
tOxFFFE, sp@- ") ;
iOxFFFE, sp@- ") ;
_ bmscrn, sp ");
1$ II);
_ savesp, sp ");
sp@+,tOxFFFF ");

tifndef FAST
bmrscrl I)
{

register i - 29969;
register char *dest, *src;

1* move another 24 bytes *1
1* move last 2 bytes * 1

dest = bmscrn+30779;
src = bmscrn+29969;
do {
*dest-- - *src--;
} while (--i != -1);
telse FAST

1*
*
*
*
*

}

tendif FAST

1* draw a char at location r, c *1

bmputc (r, c, k)
register short r, c;
char k;

move 37 lines of 9 lines of pixels times 90 columns
which is 29970 bytes to bmscrn+29970 from
bmscrn+ 30780
use all of the registers except a6,a5,dO and a7

*1
bmrscrl ()
(

register char *p = bmscrn;
register char *f = &bmfont [0];
register short i;
Hfndef NODEBUG
i f (r < 0 II c < 0 I I r >= MAXROW I I c >- MAXCOL) (
printf (lIbmputc (%d, %d, '%c') is illegal \n",r, c, k) ;
return;
tendif
P += (r * (BPL
f += (k - , ')

*
«

V_RESO»

i - FONTVERT - 1;
do {
*p = *f++;
P

+-

+ c;

3;

BPL;

while (--i !- -1);
*p = bmcolor;

1* bytes in font table for one char *1
1* 1 scan line =- 90 bytes *1
1* blank row under cursor *1

long bblank[16];
int savesp;
bmclear()
(

int x;
tifdef lint
savesp++;
tendif
x - spl7 ();
asm(" moveml
asm(" movl
asm(H moveml
asm(" movl
asm(H addl
asm("1$: move!!'.l
asm(" movem1
asm(" movem1

asm (.. moveml
asm(1I movl
asm(" movl
asm(" addl
asm(" addl
asm(" movl
asm("l$: moveml
asm(" moveml
asm (" moveml
asm(tI moveml
asm (tl moveml
asm(" moveml
asm (. moveml
asm(" moveml
asm (" moveml
asm(" moveml
asm (" moveml
asm(" moveml
asm(" moveml
asm(" moveml
asm (" moveml
asm(" moveml
asm(H subw
asm(" subw

tOxFFFF,sp@- ");
_bmscrn,a6 ft);
bmscrn, as ");
i30732,a5 ");
t29922,a6 H);
t77,dO ");
a6@,tOxlFFE ");
tOx1FFE,a5@ II):
a6@(-48),tOxlFFE ");
tOxlFFE,a5@(-48) ");
a6@(-96),tOx1FFE ");
tOxlFFE,a5@(-96) ");
a6@(-144),tOx1FFE H)
tOxlFFE, a5@ (-144) H)
a6@(-192),tOx1FFE ")
tOxlFFE, a5@ (-192) H)
a6@(-240),tOxlFFE H)
tOx1FFE,a5@(-240) ");
a6@(-288),tOxlFFE ");
tOxlFFE,a5@(-288) "):
a6@(-336),tOxlFFE ");
tOxlFFE,a5@(-336) ");
t384,a6 ");
t384,a5 II);

asm(H
asm("
asm(1I
asm("
asm("

dO,1$ tI);
a6@ (32), tOxlE ");
tOxlE,a5@(32) ");
a6@(30),a5@(30) II);
sp@+,tOxFFFF ");

)

tendif FAST
tOxFFFF,sp@- ");
sp, savesp ");
_bblank, tOxFFFF "):
bmscrn, sp ");
i32400,sp ");
tOxFFFE,sp@- ")
tOxFFFE, sp@- ")
fOxFFFE, sp@- ")

dbra
moveml
moveml
movw
moveml

1* save all the registers *1
1* destination - 48 bytes *1
1* source - 48 bytes *1
1* 77 times -1 *1

1* move 16 more bytes) */



Source Exif Data:
File Type                       : PDF
File Type Extension             : pdf
MIME Type                       : application/pdf
PDF Version                     : 1.3
Linearized                      : No
XMP Toolkit                     : Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:56:37
Create Date                     : 2012:07:14 21:28:40-08:00
Modify Date                     : 2012:07:14 21:42:58-07:00
Metadata Date                   : 2012:07:14 21:42:58-07:00
Producer                        : Adobe Acrobat 9.51 Paper Capture Plug-in
Format                          : application/pdf
Document ID                     : uuid:0b386010-3fb2-416a-94d2-b494451f759b
Instance ID                     : uuid:93751062-f05c-47c3-92f2-82a114bc9027
Page Layout                     : SinglePage
Page Mode                       : UseOutlines
Page Count                      : 340
EXIF Metadata provided by EXIF.tools

Navigation menu