|
|
1.1 ! root 1: /* ! 2: * these routines are written in C until the 386 compiler/assembler ! 3: * are available ! 4: * ! 5: * Copyright (c) Ciaran O'Donnell, Bievres (FRANCE), 1991 ! 6: */ ! 7: ! 8: #include <sys/coherent.h> ! 9: #include <sys/reg.h> ! 10: #include <sys/clist.h> ! 11: #include <errno.h> ! 12: #include <sys/inode.h> ! 13: #include <sys/proc.h> ! 14: #include <sys/seg.h> ! 15: #include <signal.h> ! 16: #include <sys/uproc.h> ! 17: #include <sys/buf.h> ! 18: ! 19: #define min(a, b) ((a) < (b) ? (a) : (b)) ! 20: ! 21: /* ! 22: * dmacopy() ! 23: * ! 24: * Copy "npage" 4 kbyte pages from phys addr "from" to phys addr "to". ! 25: */ ! 26: dmacopy(npage, from, to) ! 27: long npage; ! 28: cseg_t *from, *to; ! 29: { ! 30: int save = setspace(SEG_386_KD); ! 31: ! 32: while (npage--) { ! 33: int work = workAlloc(); /* Get a virtual click pair. */ ! 34: ptable1_v[work] = *from++ | SEG_SRW; ! 35: ptable1_v[work + 1] = *to++ | SEG_SRW; ! 36: mmuupd(); ! 37: copyseg_d(NBPC, ctob(work), ctob(work + 1)); ! 38: workFree(work); ! 39: } ! 40: setspace(save); ! 41: } ! 42: ! 43: /* ! 44: * dmaclear() ! 45: * ! 46: * Given a byte count, a system global address, and a fill value, ! 47: * write the fill value through the given range of memory. ! 48: */ ! 49: dmaclear(nbytes, to, fill) ! 50: long nbytes, fill; ! 51: paddr_t to; ! 52: { ! 53: unsigned off; ! 54: int n; ! 55: cseg_t *base; ! 56: int save = setspace(SEG_386_KD); ! 57: int work = workAlloc(); /* Get a virtual click pair. */ ! 58: ! 59: off = to & (NBPC-1); ! 60: base = &sysmem.u.pbase[btocrd(to)]; ! 61: n = min(nbytes, NBPC-off); ! 62: ptable1_v[work] = *base++ | SEG_SRW; ! 63: mmuupd(); ! 64: ! 65: clearseg_d(n, ctob(work)+off, fill); ! 66: nbytes -= n; ! 67: ! 68: while (nbytes >= NBPC) { ! 69: ptable1_v[work] = *base++ | SEG_SRW; ! 70: mmuupd(); ! 71: clearseg_d(NBPC, ctob(work), fill); ! 72: nbytes -= NBPC; ! 73: } ! 74: ! 75: if (nbytes) { ! 76: ptable1_v[work] = *base++ | SEG_SRW; ! 77: mmuupd(); ! 78: clearseg_d(nbytes, ctob(work), fill); ! 79: } ! 80: setspace(save); ! 81: workFree(work); ! 82: } ! 83: ! 84: /* ! 85: * dmain() ! 86: * ! 87: * Copy in "nbytes" from system global address "to" to kernel address ! 88: * "vaddr". ! 89: */ ! 90: dmain(nbytes, to, vaddr) ! 91: long nbytes; ! 92: paddr_t to; ! 93: caddr_t vaddr; ! 94: { ! 95: unsigned off; ! 96: unsigned n, n1; ! 97: cseg_t* base; ! 98: int work = workAlloc(); /* Get a virtual click pair. */ ! 99: int save = setspace(SEG_386_KD); ! 100: ! 101: off = to & (NBPC-1); ! 102: base = &sysmem.u.pbase[btocrd(to)]; ! 103: ! 104: n = min(nbytes, NBPC-off); ! 105: ptable1_v[work] = *base++ | SEG_SRW; ! 106: mmuupd(); ! 107: ! 108: if (nbytes==n) { ! 109: /* ! 110: * only one page ! 111: * n = min(n & (sizeof(long)-1), n) ! 112: * copy n bytes; nbytes -= n; ! 113: * copy (nbytes >> 2) long words; nbytes &= sizeof(long)-1 ! 114: * copy nbytes bytes ! 115: */ ! 116: if (n >= sizeof(long)) ! 117: n &= sizeof(long)-1; ! 118: if (n) ! 119: copyseg_b(n, ctob(work)+off, vaddr); ! 120: off += n; ! 121: vaddr += n; ! 122: nbytes -= n; ! 123: if (n = nbytes & ~(sizeof(long)-1)) { ! 124: copyseg_d(n, ctob(work)+off, vaddr); ! 125: off += n; ! 126: vaddr += n; ! 127: nbytes -= n; ! 128: } ! 129: } else { ! 130: /* ! 131: * more than one page ! 132: * copy n&3 bytes ! 133: * copy n >> 2 long words ! 134: * in the first page ! 135: */ ! 136: if (n1 = n & 3) ! 137: copyseg_b(n1, ctob(work)+off, vaddr); ! 138: off += n1; ! 139: vaddr += n1; ! 140: nbytes -= n1; ! 141: if (n = n & ~(sizeof(long)-1)) { ! 142: copyseg_d(n, ctob(work)+off, vaddr); ! 143: off += n; ! 144: vaddr += n; ! 145: nbytes -= n; ! 146: } ! 147: ! 148: /* ! 149: * copy nbytes>>BPCSHIFT full pages ! 150: */ ! 151: while (nbytes >= NBPC) { ! 152: ptable1_v[work] = *base++ | SEG_SRW; ! 153: mmuupd(); ! 154: ! 155: copyseg_d(NBPC, ctob(work), vaddr); ! 156: vaddr += NBPC; ! 157: nbytes -= NBPC; ! 158: } ! 159: /* ! 160: * page n-1 (last one) ! 161: * ! 162: * copy nbytes>>2 long words ! 163: * copy nbytes & 3 bytes ! 164: */ ! 165: ptable1_v[work] = *base++ | SEG_SRW; ! 166: mmuupd(); ! 167: ! 168: if (n = nbytes & ~(sizeof(long)-1)) { ! 169: copyseg_d(n, ctob(work), vaddr); ! 170: vaddr += n; ! 171: nbytes -= n; ! 172: } ! 173: if (nbytes) ! 174: copyseg_b(nbytes, ctob(work)+n, vaddr); ! 175: } ! 176: ! 177: setspace(save); ! 178: workFree(work); ! 179: } ! 180: ! 181: /* ! 182: * dmaout() ! 183: * ! 184: * Copy out "nbytes" from kernel address "vaddr" to system global address ! 185: * "to". ! 186: */ ! 187: dmaout(nbytes, to, vaddr) ! 188: long nbytes; ! 189: paddr_t to; ! 190: caddr_t vaddr; ! 191: { ! 192: unsigned off; ! 193: unsigned n, n1; ! 194: cseg_t *base; ! 195: int work = workAlloc(); /* Get a virtual click pair. */ ! 196: int save = setspace(SEG_386_KD); ! 197: ! 198: off = to & (NBPC-1); ! 199: base = &sysmem.u.pbase[btocrd(to)]; ! 200: ! 201: n = min(nbytes, NBPC-off); ! 202: ptable1_v[work] = *base++ | SEG_SRW; ! 203: mmuupd(); ! 204: ! 205: if (nbytes==n) { ! 206: /* ! 207: * only one page ! 208: * n = min(n & (sizeof(long)-1), n) ! 209: * copy n bytes; nbytes -= n; ! 210: * copy (nbytes >> 2) long words; nbytes &= sizeof(long)-1 ! 211: * copy nbytes bytes ! 212: */ ! 213: if (n1 = n & (sizeof(long)-1)) ! 214: copyseg_b(n1, vaddr, ctob(work)+off); ! 215: off += n1; ! 216: vaddr += n1; ! 217: nbytes -= n1; ! 218: if (n = nbytes & ~(sizeof(long)-1)) { ! 219: copyseg_d(n, vaddr, ctob(work)+off); ! 220: off += n; ! 221: vaddr += n; ! 222: nbytes -= n; ! 223: } ! 224: } else { ! 225: /* ! 226: * more than one page ! 227: * copy n&3 bytes ! 228: * copy n >> 2 long words ! 229: * in the first page ! 230: */ ! 231: if (n1 = n & (sizeof(long)-1)) ! 232: copyseg_b(n1, vaddr, ctob(work)+off); ! 233: off += n1; ! 234: vaddr += n1; ! 235: nbytes -= n1; ! 236: if (n = n & ~(sizeof(long)-1)) { ! 237: copyseg_d(n, vaddr, ctob(work)+off); ! 238: off += n; ! 239: vaddr += n; ! 240: nbytes -= n; ! 241: } ! 242: ! 243: /* ! 244: * copy nbytes>>BPCSHIFT full pages ! 245: */ ! 246: while (nbytes >= NBPC) { ! 247: ptable1_v[work] = *base++ | SEG_SRW; ! 248: mmuupd(); ! 249: copyseg_d(NBPC, vaddr, ctob(work)); ! 250: vaddr += NBPC; ! 251: nbytes -= NBPC; ! 252: } ! 253: ! 254: /* now the transfer to memory is click-aligned */ ! 255: off = 0; ! 256: ! 257: /* ! 258: * page n-1 (last one) ! 259: * ! 260: * copy nbytes>>2 long words ! 261: * copy nbytes & 3 bytes ! 262: */ ! 263: ptable1_v[work] = *base++ | SEG_SRW; ! 264: mmuupd(); ! 265: ! 266: if (n = nbytes & ~(sizeof(long)-1)) { ! 267: copyseg_d(n, vaddr, ctob(work)); ! 268: vaddr += n; ! 269: off += n; ! 270: nbytes -= n; ! 271: } ! 272: if (nbytes) ! 273: copyseg_b(nbytes, vaddr, ctob(work)+off); ! 274: } ! 275: ! 276: setspace(save); ! 277: workFree(work); ! 278: } ! 279: ! 280: /* ! 281: * dmaio2() ! 282: * ! 283: * Copy in "nbytes" from an I/O port "port" to the system global address ! 284: * "to". ! 285: */ ! 286: dmaio2(nbytes, to, port) ! 287: long nbytes, port; ! 288: paddr_t to; ! 289: { ! 290: unsigned off; ! 291: int n; ! 292: cseg_t *base; ! 293: int save = setspace(SEG_386_KD); ! 294: int work = workAlloc(); /* Get a virtual click pair. */ ! 295: ! 296: off = to & (NBPC-1); ! 297: base = &sysmem.u.pbase[btocrd(to)]; ! 298: ! 299: n = min(nbytes, NBPC-off); ! 300: ptable1_v[work] = *base++ | SEG_SRW; ! 301: mmuupd(); ! 302: ! 303: io2seg(n, ctob(work)+off, port); ! 304: nbytes -= n; ! 305: ! 306: while (nbytes >= NBPC) { ! 307: ptable1_v[work] = *base++ | SEG_SRW; ! 308: mmuupd(); ! 309: io2seg(NBPC, ctob(work), port); ! 310: nbytes -= NBPC; ! 311: } ! 312: ! 313: if (nbytes) { ! 314: ptable1_v[work] = *base++ | SEG_SRW; ! 315: mmuupd(); ! 316: io2seg(nbytes, ctob(work), port); ! 317: } ! 318: setspace(save); ! 319: workFree(work); ! 320: } ! 321: ! 322: /* ! 323: * dma2io() ! 324: * ! 325: * Copy out "nbytes" from the system global address "from" to an I/O port ! 326: * "port". ! 327: */ ! 328: dma2io(nbytes, to, port) ! 329: long nbytes, port; ! 330: paddr_t to; ! 331: { ! 332: unsigned off; ! 333: int n; ! 334: cseg_t *base; ! 335: int save = setspace(SEG_386_KD); ! 336: int work = workAlloc(); /* Get a virtual click pair. */ ! 337: ! 338: off = to & (NBPC-1); ! 339: base = &sysmem.u.pbase[btocrd(to)]; ! 340: ! 341: n = min(nbytes, NBPC-off); ! 342: ptable1_v[work] = *base++ | SEG_SRW; ! 343: mmuupd(); ! 344: ! 345: seg2io(n, ctob(work)+off, port); ! 346: nbytes -= n; ! 347: ! 348: while (nbytes >= NBPC) { ! 349: ptable1_v[work] = *base++ | SEG_SRW; ! 350: mmuupd(); ! 351: seg2io(NBPC, ctob(work), port); ! 352: nbytes -= NBPC; ! 353: } ! 354: ! 355: if (nbytes) { ! 356: ptable1_v[work] = *base++ | SEG_SRW; ! 357: mmuupd(); ! 358: seg2io(nbytes, ctob(work), port); ! 359: } ! 360: setspace(save); ! 361: workFree(work); ! 362: } ! 363: ! 364: /* ! 365: * pxcopy() ! 366: * ! 367: * copy "n" bytes of data at kernel address "v" from address "uo" in: ! 368: * system global address space (space&SEG_VIRT) ! 369: * physical memory !(space&SEG_VIRT) ! 370: * Rights are determined by (space&~SEG_VIRT): ! 371: * "v" can be anywhere in kernel address space SEG_386_KD ! 372: * "v" must be an address accessible to the user SEG_386_UD ! 373: * Up to one click of data can be copied. No alignment restrictions ! 374: * on "uo" apply. ! 375: */ ! 376: pxcopy(uo, v, n, space) ! 377: unsigned uo; ! 378: char *v; ! 379: register int n; ! 380: { ! 381: cseg_t *base; ! 382: register int save, err; ! 383: int work; ! 384: ! 385: if (n > NBPC) ! 386: return 0; ! 387: ! 388: work = workAlloc(); ! 389: if (space & SEG_VIRT) { ! 390: space &= ~SEG_VIRT; ! 391: base = &sysmem.u.pbase[btocrd(uo)]; ! 392: ptable1_v[work] = *base++ | SEG_SRW; ! 393: ptable1_v[work + 1] = *base++ | SEG_SRW; ! 394: } else { ! 395: ptable1_v[work] = (uo&~(NBPC-1)) + SEG_SRW; ! 396: ptable1_v[work + 1] = (uo&~(NBPC-1)) + NBPC + SEG_SRW; ! 397: } ! 398: mmuupd(); ! 399: save = setspace(space); ! 400: ! 401: err = ukcopy(ctob(work) + (uo&(NBPC-1)), v, n); ! 402: setspace(save); ! 403: workFree(work); ! 404: return err; ! 405: } ! 406: ! 407: /* ! 408: * xpcopy() ! 409: * ! 410: * copy "n" bytes of data from kernel address "v" to address "uo" in: ! 411: * system global address space (space&SEG_VIRT) ! 412: * physical memory !(space&SEG_VIRT) ! 413: * Rights are determined by (space&~SEG_VIRT): ! 414: * "v" can be anywhere in kernel address space SEG_386_KD ! 415: * "v" must be an address accessible to the user SEG_386_UD ! 416: * Up to one click of data can be copied. No alignment restrictions on "uo" ! 417: * apply. ! 418: */ ! 419: xpcopy(v, uo, n, space) ! 420: char *v; ! 421: unsigned uo; ! 422: register int n; ! 423: { ! 424: register cseg_t *base; ! 425: register int save, err; ! 426: int work; ! 427: ! 428: if (n > NBPC) ! 429: return 0; ! 430: ! 431: work = workAlloc(); ! 432: if (space & SEG_VIRT) { ! 433: space &= ~SEG_VIRT; ! 434: base = &sysmem.u.pbase[btocrd(uo)]; ! 435: ptable1_v[work] = *base++ | SEG_SRW; ! 436: ptable1_v[work + 1] = *base++ | SEG_SRW; ! 437: } else { ! 438: ptable1_v[work] = (uo&~(NBPC-1)) + SEG_SRW; ! 439: ptable1_v[work + 1] = (uo&~(NBPC-1)) + NBPC + SEG_SRW; ! 440: } ! 441: mmuupd(); ! 442: save = setspace(space); ! 443: ! 444: err = kucopy(v, ctob(work) + (uo&(NBPC-1)), n); ! 445: setspace(save); ! 446: workFree(work); ! 447: return err; ! 448: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.