|
|
1.1 ! root 1: #include "../h/param.h" ! 2: #include "../h/buf.h" ! 3: #include "../h/cmap.h" ! 4: #include "../h/conf.h" ! 5: #include "../h/dir.h" ! 6: #include "../h/dk.h" ! 7: #include "../h/map.h" ! 8: #include "../machine/mtpr.h" ! 9: #include "../machine/pte.h" ! 10: #include "../h/systm.h" ! 11: #include "../vba/vbavar.h" ! 12: #include "../h/user.h" ! 13: #include "../h/vmmac.h" ! 14: #include "../h/proc.h" ! 15: ! 16: ! 17: /* ! 18: * Next piece of logic takes care of unusual cases when less (or more) than ! 19: * a full block (or sector) are required. This is done by the swaping ! 20: * logic, when it brings page table pages from the swap device. ! 21: * Since some controllers can't read less than a sector, the ! 22: * only alternative is to read the disk to a temporary buffer and ! 23: * then to move the amount needed back to the process (usually proc[0] ! 24: * or proc[2]). ! 25: * On Tahoe, the virtual addresses versus physical I/O problem creates ! 26: * the need to move I/O data through an intermediate buffer whenever one ! 27: * of the following is true: ! 28: * 1) The data length is not a multiple of sector size ! 29: * 2) The base address + length cross a physical page boundary ! 30: * 3) The virtual address for I/O is not in the system space. ! 31: */ ! 32: ! 33: buf_setup(bp, sectsize) ! 34: register struct buf *bp; ! 35: long sectsize; /* This disk's physical sector size */ ! 36: { ! 37: /* ! 38: * IO buffer preparation for possible buffered transfer. ! 39: * The relevant page table entries are kept in the 'buf' structure, ! 40: * for later use by the driver's 'start' routine or 'interrupt' ! 41: * routine, when user's data has to be moved to the intermediate ! 42: * buffer. ! 43: */ ! 44: register struct pte *source_pte_adr; ! 45: register struct proc *rp; ! 46: register v; ! 47: ! 48: if ((((int)bp->b_un.b_addr & PGOFSET) + bp->b_bcount) > NBPG || ! 49: (bp->b_bcount % sectsize) != 0 || ! 50: ((int)bp->b_un.b_addr & 0xc0000000) != 0xc0000000) { ! 51: bp->b_flags |= B_NOT1K; ! 52: v = btop(bp->b_un.b_addr); ! 53: if (bp->b_flags & B_DIRTY) ! 54: rp = &proc[2]; ! 55: if (bp->b_flags & B_UAREA) ! 56: source_pte_adr = &rp->p_addr[v]; ! 57: else ! 58: source_pte_adr = vtopte(rp, v); ! 59: bp->b_ptecnt = (bp->b_bcount + NBPG -1 + ! 60: ((int)bp->b_un.b_addr & PGOFSET)) / NBPG; ! 61: bcopy (source_pte_adr, bp->b_upte, bp->b_ptecnt*4); ! 62: } ! 63: } ! 64: ! 65: int mapbusy; /* semaphore on the system IOmap buffer */ ! 66: ! 67: get_ioadr(bp, buffer, map, utl) ! 68: struct buf *bp; ! 69: char *buffer; /* Driver's own intermediate buffer. */ ! 70: long *map; /* A bunch of system pte's */ ! 71: struct user *utl; /* The system address mapped through 'map' */ ! 72: /* ! 73: * This routine is usually called by the 'start' routine. It ! 74: * returns the physical address of the first byte for IO, to ! 75: * be presented to the controller. If intermediate buffering is ! 76: * needed and a write out is done, now is the time to get the ! 77: * original user's data in the buffer. ! 78: */ ! 79: { ! 80: register phadr, i; ! 81: ! 82: if (bp->b_flags & B_NOT1K) { ! 83: phadr = vtoph (bp->b_proc, buffer); ! 84: if ( (bp->b_flags & B_READ) == 0) { ! 85: for (i=0; i<bp->b_ptecnt; i++) { ! 86: map[i] = bp->b_upte[i] ! 87: & ~PG_PROT | PG_V | PG_KR; ! 88: mtpr ((caddr_t)utl + i*NBPG, TBIS); ! 89: mtpr ((caddr_t)utl + i*NBPG, P1DC); ! 90: } ! 91: bcopy (((int)bp->b_un.b_addr & PGOFSET) + ! 92: (caddr_t)utl, buffer,bp->b_bcount); ! 93: } ! 94: } ! 95: else ! 96: phadr = vtoph (bp->b_proc, bp->b_un.b_addr); ! 97: return (phadr); ! 98: } ! 99: ! 100: end_transfer(bp, buffer, map, utl) ! 101: register struct buf *bp; ! 102: char *buffer; /* Driver's own intermediate buffer. */ ! 103: long *map; /* A bunch of system pte's */ ! 104: struct user *utl; /* The system address mapped through 'map' */ ! 105: { ! 106: /* ! 107: * Called by the driver's interrupt routine, after the data is ! 108: * realy in or out. If that was a read, and the NOT1K flag was on, ! 109: * now is the time to move the data back into user's space. ! 110: * Mostly analogous to the get_ioadr routine, but in the reverse direction. ! 111: */ ! 112: register i, cnt; ! 113: ! 114: if (bp->b_flags & B_READ) ! 115: if (bp->b_flags & B_NOT1K) { ! 116: for (cnt = bp->b_bcount ; cnt >= 0; cnt -= NBPG) { ! 117: mtpr ((int)buffer + cnt-1, P1DC); ! 118: mtpr ((caddr_t)bp->b_un.b_addr + cnt-1, P1DC); ! 119: } ! 120: if ( ((int)buffer & PGOFSET) != 0) ! 121: mtpr (buffer, P1DC); ! 122: if ( ((int)bp->b_un.b_addr & PGOFSET) != 0) ! 123: mtpr ((caddr_t)bp->b_un.b_addr, P1DC); ! 124: for (i=0; i<bp->b_ptecnt; i++) { ! 125: map[i] = bp->b_upte[i] ! 126: & ~PG_PROT | PG_V | PG_KW; ! 127: mtpr ((caddr_t)utl + i*NBPG, TBIS); ! 128: } ! 129: bcopy (buffer, ! 130: ((int)bp->b_un.b_addr & PGOFSET) + ! 131: (caddr_t)utl, bp->b_bcount); ! 132: } ! 133: else ! 134: mtpr (bp->b_un.b_addr, P1DC); ! 135: bp->b_flags &= ~B_NOT1K; ! 136: } ! 137: ! 138: movob (byte, address) ! 139: { ! 140: asm(" movob 7(fp),*8(fp);"); ! 141: } ! 142: ! 143: movow (word, address) ! 144: { ! 145: asm(" movow 6(fp),*8(fp);"); ! 146: } ! 147:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.