2.11BSD/sys/pdp/mch_click.s
/*
* Copyright (c) 1987 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*
* @(#)mch_click.s 1.4 (2.11BSD GTE) 1995/11/22
*/
#include "DEFS.h"
#include "../machine/mch_iopage.h"
/*
* copy(src, dst, count)
* memaddr src, dst;
* int count;
*
* Copy count clicks from src to dst. Uses KDSA5 and 6 to copy with mov
* instructions. Interrupt routines must restore segmentation registers
* if needed; see seg.h.
*/
ENTRY(copy)
jsr r5, csv
#ifdef INET
mov PS,-(sp) / have to lock out interrupts...
bit $0340,(sp) / Are we currently at spl0?
bne 1f
SPLNET / No, lock out network interrupts.
1:
#endif
mov KDSA5,-(sp) / saveseg5(sp)
mov KDSD5,-(sp)
mov 10(r5),r3 / r3 = count
beq 3f / (exit early if zero)
mov 4(r5),KDSA5 / seg5 = (src, 1 click read only)
mov $RO,KDSD5
mov sp,r4 / save current sp
mov $eintstk,sp / and switch to intstk
mov KDSA6,_kdsa6 / save u area address, mark as mapped
mov 6(r5),KDSA6 / out and seg6 = (dst, 1 click read/
mov $RW,KDSD6 / write)
1:
mov $5*8192.,r0 / r0 = SEG5 { src }
mov $6*8192.,r1 / r1 = SEG6 { dst }
mov $8.,r2 / copy one click (8*8)
2:
mov (r0)+,(r1)+
mov (r0)+,(r1)+
mov (r0)+,(r1)+
mov (r0)+,(r1)+
sob r2,2b
inc KDSA5 / next click
inc KDSA6
sob r3,1b
mov _kdsa6,KDSA6 / restore u area mapping
mov $USIZE-1\<8|RW, KDSD6
clr _kdsa6
mov r4,sp / back to normal stack
3:
mov (sp)+,KDSD5 / restorseg5(sp)
mov (sp)+,KDSA5
#ifdef INET
mov (sp)+,PS / back to normal priority
#endif
jmp cret
/*
* Clear count clicks at dst. Uses KDSA5. Interrupt routines must restore
* segmentation registers if needed; see seg.h.
*
* clear(dst, count)
* memaddr dst;
* u_int count;
*/
ENTRY(clear)
jsr r5, csv
mov KDSA5,-(sp) / saveseg5(sp)
mov KDSD5,-(sp)
mov 4(r5),KDSA5 / point KDSA5 at source
mov $RW,KDSD5 / 64 bytes, read-write
mov 6(r5),r3 / count
beq 3f
1:
mov $5*8192.,r0 / point r0 at KDSA5 map
mov $8.,r2 / clear one click (8*8)
2:
clr (r0)+
clr (r0)+
clr (r0)+
clr (r0)+
sob r2,2b
inc KDSA5 / next click
sob r3,1b
3:
mov (sp)+,KDSD5 / restore seg5
mov (sp)+,KDSA5 / restore seg5
jmp cret
/*
* copyv(fromaddr, toaddr, count)
* virtual_addr fromaddr,
* toaddr;
* u_int count;
*
* typedef struct {
* memaddr click;
* u_int offset;
* } virtual_addr;
*
* Copy two arbitrary pieces of PDP11 virtual memory from one location
* to another. Up to 8K bytes can be copied at one time.
*
* A PDP11 virtual address is a two word value; a 16 bit "click" that
* defines the start in physical memory of an 8KB segment and an offset.
*/
ENTRY(copyv)
mov 10.(sp),r0 / exit early if count == 0 or >= 8K
beq 4f
cmp r0,$8192.
bhis 4f
mov r2,-(sp) / need a register for the stack switch
/*
* Note: the switched stack is only for use of a fatal kernel trap
* occurring during the copy; otherwise we might conflict with the
* other copy routines.
*/
mov sp,r2 / switch stacks
cmp sp,$eintstk / are we already in the intstk?
blo 1f
mov $eintstk,sp / No, point sp to intstk
1:
mov PS,-(sp) / save current PS
bit $0340,(sp) / are we currently at SPL?
bne 2f
SPLNET / nope, lock out the network
2:
mov KDSA5,-(sp) / save seg5
mov KDSD5,-(sp)
mov _kdsa6,-(sp) / save the current saved kdsa6
bne 3f / was it set to anything?
mov KDSA6,_kdsa6 / nope, set it to the current kdsa6
3:
mov KDSA6,-(sp) / save user area
mov KDSD6,-(sp)
mov r2,r0 / set up bcopy arguments on new stack
add $14.,r0 / and grab click addresses ...
mov -(r0),-(sp) / copy count
mov -(r0),-(sp) / copy and translate toaddr.offset
add $6*8192.,(sp)
mov -(r0),r1 / pick up and save toaddr.click
mov -(r0),-(sp) / copy and translate fromaddr.offset
add $5*8192.,(sp)
mov -(r0),KDSA5 / use fromaddr.click to remap seg5
mov $128.-1\<8.|RO,KDSD5 / for 8K read-only
mov r1,KDSA6 / use toaddr.click to remap seg6
mov $128.-1\<8.|RW,KDSD6 / for 8K read/write
jsr pc,_bcopy / finally, do the copy
add $6.,sp / toss the arguments to bcopy
mov (sp)+,KDSD6 / restore user area
mov (sp)+,KDSA6
mov (sp)+,_kdsa6 / restore old _kdsa6 value
mov (sp)+,KDSD5 / restore seg5
mov (sp)+,KDSA5
mov (sp)+,PS / unlock interrupts
mov r2,sp / restore stack pointer and retrieve
mov (sp)+,r2 / old register value
4:
clr r0 / clear r0 and r1 (why?)
rts pc / and return
/*
* fmove(par, pdr, from, to, length)
* u_short par, pdr;
* caddr_t from, to;
* u_short length;
*
* Map the par/pdr into segment 6 and perform a bcopy(from, to, length).
* Returns zero on success, EFAULT on failure. See uiofmove for more
* information.
*
* As written, fmove may only be called from the high kernel and is *not*
* re-entrant: it doesn't save the previous fault trap, uses the intstk and
* kdsa6 without checking to see if they're already in use (see the fault
* handler at 2f below) and assumes that a user structure is currently mapped
* in (see the restore of KDSD6 below).
*/
ENTRY(fmove)
mov r2,-(sp) / need a few registers for the
mov r3,-(sp) / copy and stack switch
mov r4,-(sp)
mov sp,r4 / switch stacks (SEG6 is out)
mov $eintstk,sp
mov r4,r0 / grab parameters
add $8.,r0
mov (r0)+,-(sp) / push par and pdr onto new stack
mov (r0)+,-(sp)
mov (r0)+,r1 / r1 = from
mov (r0)+,r2 / r2 = to
mov (r0),r0 / r0 = length
mov KDSA6,_kdsa6 / save current segment 6 mapping
mov (sp)+,KDSD6 / passed par/pdr
mov (sp)+,KDSA6 / and map segment 6 with the
mov $8f,nofault / catch any faults during the copy,
/*
* The following code has been lifted almost intact from "bcopy".
* The biggest reason is for error recovery in the case of a user
* memory fault.
*/
tst r0 / if (length == 0)
beq 7f / return
cmp r0,$10. / if (length > 10)
bhi 2f / try words
1:
movb (r1)+,(r2)+ / do *dst++ = *src++
sob r0,1b / while (--length)
br 7f
2:
bit $1,r1 / if (src&1 != dst&1)
beq 3f / do bytes
bit $1,r2
beq 1b / (src odd, dst even - do bytes)
movb (r1)+,(r2)+ / copy leading odd byte
dec r0
br 4f
3:
bit $1,r2
bne 1b / (src even, dst odd - do bytes)
4:
mov r0,r3 / save trailing byte indicator
clc
ror r0 / length >>= 1 (unsigned)
asr r0 / if (length >>= 1, wasodd(length))
bcc 5f / handle leading non multiple of four
mov (r1)+,(r2)+
5:
asr r0 / if (length >>= 1, wasodd(length))
bcc 6f / handle leading non multiple of eight
mov (r1)+,(r2)+
mov (r1)+,(r2)+
6:
mov (r1)+,(r2)+ / do
mov (r1)+,(r2)+ / move eight bytes
mov (r1)+,(r2)+
mov (r1)+,(r2)+
sob r0,6b / while (--length)
asr r3 / if (odd trailing byte)
bcc 7f
movb (r1)+,(r2)+ / copy it
/*
* End of stolen bcopy code.
*/
7:
clr nofault / clear the fault trap and return
/ status (zero from successful copy)
mov _kdsa6,KDSA6 / restore the previous segment 6
mov $USIZE-1\<8|RW, KDSD6 / mapping (user structure)
clr _kdsa6 / (segment 6 not mapped out any more)
mov r4,sp / restore previous stack pointer
mov (sp)+,r4 / and saved registers
mov (sp)+,r3
mov (sp)+,r2
rts pc / and return
8:
mov $EFAULT,r0 / copy failed, return EFAULT
br 7b