1: /* 2: * Copyright (c) 1987 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)mch_click.s 1.4 (2.11BSD GTE) 1995/11/22 7: */ 8: 9: #include "DEFS.h" 10: #include "../machine/mch_iopage.h" 11: 12: 13: /* 14: * copy(src, dst, count) 15: * memaddr src, dst; 16: * int count; 17: * 18: * Copy count clicks from src to dst. Uses KDSA5 and 6 to copy with mov 19: * instructions. Interrupt routines must restore segmentation registers 20: * if needed; see seg.h. 21: */ 22: ENTRY(copy) 23: jsr r5, csv 24: #ifdef INET 25: mov PS,-(sp) / have to lock out interrupts... 26: bit $0340,(sp) / Are we currently at spl0? 27: bne 1f 28: SPLNET / No, lock out network interrupts. 29: 1: 30: #endif 31: mov KDSA5,-(sp) / saveseg5(sp) 32: mov KDSD5,-(sp) 33: mov 10(r5),r3 / r3 = count 34: beq 3f / (exit early if zero) 35: mov 4(r5),KDSA5 / seg5 = (src, 1 click read only) 36: mov $RO,KDSD5 37: mov sp,r4 / save current sp 38: mov $eintstk,sp / and switch to intstk 39: mov KDSA6,_kdsa6 / save u area address, mark as mapped 40: mov 6(r5),KDSA6 / out and seg6 = (dst, 1 click read/ 41: mov $RW,KDSD6 / write) 42: 1: 43: mov $5*8192.,r0 / r0 = SEG5 { src } 44: mov $6*8192.,r1 / r1 = SEG6 { dst } 45: mov $8.,r2 / copy one click (8*8) 46: 2: 47: mov (r0)+,(r1)+ 48: mov (r0)+,(r1)+ 49: mov (r0)+,(r1)+ 50: mov (r0)+,(r1)+ 51: sob r2,2b 52: 53: inc KDSA5 / next click 54: inc KDSA6 55: sob r3,1b 56: 57: mov _kdsa6,KDSA6 / restore u area mapping 58: mov $USIZE-1\<8|RW, KDSD6 59: clr _kdsa6 60: mov r4,sp / back to normal stack 61: 3: 62: mov (sp)+,KDSD5 / restorseg5(sp) 63: mov (sp)+,KDSA5 64: #ifdef INET 65: mov (sp)+,PS / back to normal priority 66: #endif 67: jmp cret 68: 69: /* 70: * Clear count clicks at dst. Uses KDSA5. Interrupt routines must restore 71: * segmentation registers if needed; see seg.h. 72: * 73: * clear(dst, count) 74: * memaddr dst; 75: * u_int count; 76: */ 77: ENTRY(clear) 78: jsr r5, csv 79: mov KDSA5,-(sp) / saveseg5(sp) 80: mov KDSD5,-(sp) 81: mov 4(r5),KDSA5 / point KDSA5 at source 82: mov $RW,KDSD5 / 64 bytes, read-write 83: mov 6(r5),r3 / count 84: beq 3f 85: 1: 86: mov $5*8192.,r0 / point r0 at KDSA5 map 87: mov $8.,r2 / clear one click (8*8) 88: 2: 89: clr (r0)+ 90: clr (r0)+ 91: clr (r0)+ 92: clr (r0)+ 93: sob r2,2b 94: 95: inc KDSA5 / next click 96: sob r3,1b 97: 3: 98: mov (sp)+,KDSD5 / restore seg5 99: mov (sp)+,KDSA5 / restore seg5 100: jmp cret 101: 102: /* 103: * copyv(fromaddr, toaddr, count) 104: * virtual_addr fromaddr, 105: * toaddr; 106: * u_int count; 107: * 108: * typedef struct { 109: * memaddr click; 110: * u_int offset; 111: * } virtual_addr; 112: * 113: * Copy two arbitrary pieces of PDP11 virtual memory from one location 114: * to another. Up to 8K bytes can be copied at one time. 115: * 116: * A PDP11 virtual address is a two word value; a 16 bit "click" that 117: * defines the start in physical memory of an 8KB segment and an offset. 118: */ 119: ENTRY(copyv) 120: mov 10.(sp),r0 / exit early if count == 0 or >= 8K 121: beq 4f 122: cmp r0,$8192. 123: bhis 4f 124: mov r2,-(sp) / need a register for the stack switch 125: /* 126: * Note: the switched stack is only for use of a fatal kernel trap 127: * occurring during the copy; otherwise we might conflict with the 128: * other copy routines. 129: */ 130: mov sp,r2 / switch stacks 131: cmp sp,$eintstk / are we already in the intstk? 132: blo 1f 133: mov $eintstk,sp / No, point sp to intstk 134: 1: 135: mov PS,-(sp) / save current PS 136: bit $0340,(sp) / are we currently at SPL? 137: bne 2f 138: SPLNET / nope, lock out the network 139: 2: 140: mov KDSA5,-(sp) / save seg5 141: mov KDSD5,-(sp) 142: mov _kdsa6,-(sp) / save the current saved kdsa6 143: bne 3f / was it set to anything? 144: mov KDSA6,_kdsa6 / nope, set it to the current kdsa6 145: 3: 146: mov KDSA6,-(sp) / save user area 147: mov KDSD6,-(sp) 148: mov r2,r0 / set up bcopy arguments on new stack 149: add $14.,r0 / and grab click addresses ... 150: mov -(r0),-(sp) / copy count 151: mov -(r0),-(sp) / copy and translate toaddr.offset 152: add $6*8192.,(sp) 153: mov -(r0),r1 / pick up and save toaddr.click 154: mov -(r0),-(sp) / copy and translate fromaddr.offset 155: add $5*8192.,(sp) 156: 157: mov -(r0),KDSA5 / use fromaddr.click to remap seg5 158: mov $128.-1\<8.|RO,KDSD5 / for 8K read-only 159: mov r1,KDSA6 / use toaddr.click to remap seg6 160: mov $128.-1\<8.|RW,KDSD6 / for 8K read/write 161: jsr pc,_bcopy / finally, do the copy 162: add $6.,sp / toss the arguments to bcopy 163: mov (sp)+,KDSD6 / restore user area 164: mov (sp)+,KDSA6 165: mov (sp)+,_kdsa6 / restore old _kdsa6 value 166: mov (sp)+,KDSD5 / restore seg5 167: mov (sp)+,KDSA5 168: mov (sp)+,PS / unlock interrupts 169: mov r2,sp / restore stack pointer and retrieve 170: mov (sp)+,r2 / old register value 171: 4: 172: clr r0 / clear r0 and r1 (why?) 173: rts pc / and return 174: 175: /* 176: * fmove(par, pdr, from, to, length) 177: * u_short par, pdr; 178: * caddr_t from, to; 179: * u_short length; 180: * 181: * Map the par/pdr into segment 6 and perform a bcopy(from, to, length). 182: * Returns zero on success, EFAULT on failure. See uiofmove for more 183: * information. 184: * 185: * As written, fmove may only be called from the high kernel and is *not* 186: * re-entrant: it doesn't save the previous fault trap, uses the intstk and 187: * kdsa6 without checking to see if they're already in use (see the fault 188: * handler at 2f below) and assumes that a user structure is currently mapped 189: * in (see the restore of KDSD6 below). 190: */ 191: ENTRY(fmove) 192: mov r2,-(sp) / need a few registers for the 193: mov r3,-(sp) / copy and stack switch 194: mov r4,-(sp) 195: mov sp,r4 / switch stacks (SEG6 is out) 196: mov $eintstk,sp 197: mov r4,r0 / grab parameters 198: add $8.,r0 199: mov (r0)+,-(sp) / push par and pdr onto new stack 200: mov (r0)+,-(sp) 201: mov (r0)+,r1 / r1 = from 202: mov (r0)+,r2 / r2 = to 203: mov (r0),r0 / r0 = length 204: mov KDSA6,_kdsa6 / save current segment 6 mapping 205: mov (sp)+,KDSD6 / passed par/pdr 206: mov (sp)+,KDSA6 / and map segment 6 with the 207: mov $8f,nofault / catch any faults during the copy, 208: 209: /* 210: * The following code has been lifted almost intact from "bcopy". 211: * The biggest reason is for error recovery in the case of a user 212: * memory fault. 213: */ 214: tst r0 / if (length == 0) 215: beq 7f / return 216: cmp r0,$10. / if (length > 10) 217: bhi 2f / try words 218: 1: 219: movb (r1)+,(r2)+ / do *dst++ = *src++ 220: sob r0,1b / while (--length) 221: br 7f 222: 2: 223: bit $1,r1 / if (src&1 != dst&1) 224: beq 3f / do bytes 225: bit $1,r2 226: beq 1b / (src odd, dst even - do bytes) 227: movb (r1)+,(r2)+ / copy leading odd byte 228: dec r0 229: br 4f 230: 3: 231: bit $1,r2 232: bne 1b / (src even, dst odd - do bytes) 233: 4: 234: mov r0,r3 / save trailing byte indicator 235: clc 236: ror r0 / length >>= 1 (unsigned) 237: asr r0 / if (length >>= 1, wasodd(length)) 238: bcc 5f / handle leading non multiple of four 239: mov (r1)+,(r2)+ 240: 5: 241: asr r0 / if (length >>= 1, wasodd(length)) 242: bcc 6f / handle leading non multiple of eight 243: mov (r1)+,(r2)+ 244: mov (r1)+,(r2)+ 245: 6: 246: mov (r1)+,(r2)+ / do 247: mov (r1)+,(r2)+ / move eight bytes 248: mov (r1)+,(r2)+ 249: mov (r1)+,(r2)+ 250: sob r0,6b / while (--length) 251: asr r3 / if (odd trailing byte) 252: bcc 7f 253: movb (r1)+,(r2)+ / copy it 254: /* 255: * End of stolen bcopy code. 256: */ 257: 258: 7: 259: clr nofault / clear the fault trap and return 260: / status (zero from successful copy) 261: mov _kdsa6,KDSA6 / restore the previous segment 6 262: mov $USIZE-1\<8|RW, KDSD6 / mapping (user structure) 263: clr _kdsa6 / (segment 6 not mapped out any more) 264: mov r4,sp / restore previous stack pointer 265: mov (sp)+,r4 / and saved registers 266: mov (sp)+,r3 267: mov (sp)+,r2 268: rts pc / and return 269: 8: 270: mov $EFAULT,r0 / copy failed, return EFAULT 271: br 7b