Annotation of coherent/b/STREAMS/i386/mmu.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * MMU dependent code for Coherent 386
        !             3:  *
        !             4:  * Copyright (c) Ciaran O'Donnell, Bievres (FRANCE), 1991
        !             5:  */
        !             6: 
        !             7: #include <kernel/alloc.h>
        !             8: 
        !             9: #include <sys/coherent.h>
        !            10: #include <sys/clist.h>
        !            11: #include <sys/errno.h>
        !            12: #include <sys/inode.h>
        !            13: #include <sys/seg.h>
        !            14: #include <signal.h>
        !            15: #include <sys/buf.h>
        !            16: #include <l.out.h>
        !            17: #include <ieeefp.h>
        !            18: 
        !            19: /* These defines belong somewhere else:  */
        !            20: #define LOMEM  0x15    /* CMOS address of size in K of memory below 1MB.  */
        !            21: #define EXTMEM 0x17    /* CMOS address of size in K of memory above 1MB.  */
        !            22: #define ONE_K  1024
        !            23: #define ONE_MEG        1048576
        !            24: #define USE_NDATA      1
        !            25: 
        !            26: /*
        !            27:  * DMA will not work to memory above 16M, so limit the amount of memory
        !            28:  * above 1M to 15M.  A much cleverer scheme should be implemented.
        !            29:  */
        !            30: int HACK_LIMIT = (15*ONE_MEG);
        !            31: 
        !            32: /*
        !            33:  * For 0 < i < 64, buddysize[i] is log(base 2) of nearest power of two
        !            34:  * which is greater than or equal to i.
        !            35:  */
        !            36: char   buddysize[64] = {
        !            37:        -1, 0, 1, 2, 2, 3, 3, 3,
        !            38:        3, 4, 4, 4, 4, 4, 4, 4,
        !            39:        4, 5, 5, 5, 5, 5, 5, 5,
        !            40:        5, 5, 5, 5, 5, 5, 5, 5,
        !            41:        5, 6, 6, 6, 6, 6, 6, 6,
        !            42:        6, 6, 6, 6, 6, 6, 6, 6,
        !            43:        6, 6, 6, 6, 6, 6, 6, 6,
        !            44:        6, 6, 6, 6, 6, 6, 6, 6 };
        !            45: 
        !            46: #define        min(a, b)       ((a) < (b) ? (a) : (b))
        !            47: 
        !            48: /*
        !            49:  * Functions.
        !            50:  *     Import.
        !            51:  *     Export.
        !            52:  *     Local.
        !            53:  */
        !            54: void           areacheck();
        !            55: void           areafree();
        !            56: void           areainit();
        !            57: BLOCKLIST *    arealloc();
        !            58: int            areasize();
        !            59: cseg_t *       c_alloc();
        !            60: cseg_t *       c_extend(); 
        !            61: void           c_free();
        !            62: int            c_grow();
        !            63: int            countsize();
        !            64: void           doload();
        !            65: char *         getPhysMem();
        !            66: void           i8086();
        !            67: void           idtinit();
        !            68: void           init_phy_seg();
        !            69: void           mchinit();
        !            70: void           msigend();
        !            71: void           physMemInit();
        !            72: SR             *loaded();
        !            73: unsigned int   read16_cmos();
        !            74: void           segload();
        !            75: void           sunload();
        !            76: void           unload();
        !            77: void           valloc();
        !            78: 
        !            79: 
        !            80: /*
        !            81:  * "load" a handle "hp"  to a segment into the space tree for a process
        !            82:  */
        !            83: void
        !            84: doload(srp)
        !            85: register SR    *srp;
        !            86: {
        !            87:        register int    n;
        !            88:        register        cseg_t *pp;
        !            89:        register int    base1, flags;
        !            90:        register int    akey;
        !            91: 
        !            92:        pp = srp->sr_segp->s_vmem;
        !            93:        flags = srp->sr_segp->s_flags;
        !            94:        base1 = btocrd(srp->sr_base);
        !            95:        n = btoc(srp->sr_size);
        !            96: 
        !            97:        /*
        !            98:         * we load all pages
        !            99:         */
        !           100:         /* a shm segment ref may be Read-Write or Read-Only */
        !           101:        if (srp->sr_flag & SRFRODT)
        !           102:                akey = SEG_RO;
        !           103:        else {
        !           104:                switch (flags&(SFSYST|SFTEXT)) {
        !           105:                case SFTEXT:    akey = SEG_RO;  break;
        !           106:                case SFSYST:    akey = SEG_SRW; break;
        !           107:                default:        akey = SEG_RW;  break;
        !           108:                }
        !           109:        }
        !           110: 
        !           111:        do
        !           112:                ptable1_v[base1++] = (*pp++ & ~SEG_NPL) | akey;
        !           113:        while (--n);
        !           114:        mmuupd();
        !           115: }
        !           116: 
        !           117: /*
        !           118:  * unload a handle key "key" to a segment from the MMU hardware
        !           119:  */
        !           120: void
        !           121: unload(srp)
        !           122: register SR *srp;
        !           123: {
        !           124:        register int    n, base1;
        !           125: 
        !           126:        base1 = btocrd(srp->sr_base);
        !           127:        
        !           128:        n = btoc(srp->sr_size);
        !           129:        do {
        !           130:                ptable1_v[base1++] = SEG_ILL;
        !           131:        } while (--n);
        !           132:        mmuupd();
        !           133: }
        !           134: 
        !           135: /*
        !           136:  * Allocate 'clicks_wanted' clicks of core space.
        !           137:  * Returns physical segment descriptor if success, else NULL.
        !           138:  * The physical segment descriptor is a table of page table entries
        !           139:  * suitable for insertion into a page table.
        !           140:  */
        !           141: cseg_t *
        !           142: c_alloc(clicks_wanted)
        !           143: unsigned       clicks_wanted;
        !           144: {
        !           145:        unsigned        pno;
        !           146:        cseg_t *pp;
        !           147:        register cseg_t *qp;
        !           148: 
        !           149:        /* Do we have enough free physical clicks for this request?  */
        !           150:        if (clicks_wanted > allocno())
        !           151:                goto no_c_alloc;
        !           152: 
        !           153:        /* Allocate some space for the table to return.  */
        !           154:        if ((pp = (cseg_t *)arealloc(clicks_wanted)) == 0)
        !           155:                goto no_c_alloc;
        !           156:        qp = pp;
        !           157: 
        !           158:        /* fill in entries in the requested table */
        !           159:        do {
        !           160:                pno = *--sysmem.pfree;
        !           161:                if (!pvalid(pno))
        !           162:                        panic("c_alloc");
        !           163:                *qp++ = (clickseg(pno) & ~SEG_BITS) | SEG_PRE;
        !           164:        } while (--clicks_wanted);
        !           165:        return pp;
        !           166: 
        !           167: no_c_alloc:
        !           168:        return 0;
        !           169: }
        !           170: 
        !           171: /*
        !           172:  * Given an array "pp" containing "numClicks" click descriptors,
        !           173:  *   if "pp" is the click list for a user segment currently loaded
        !           174:  *     invalidate click entries for "pp" in the current page table
        !           175:  *   return each click in "pp" to the sysmem pool, if it came from there.
        !           176:  *   return the array "pp" to the buddy pool.
        !           177:  */
        !           178: void
        !           179: c_free(pp, numClicks)
        !           180: cseg_t *pp;
        !           181: unsigned       numClicks;
        !           182: {
        !           183:        unsigned        pno;
        !           184:        register cseg_t *qp;
        !           185:        register int    sz;
        !           186:        SR              *srp;
        !           187: 
        !           188:        if (srp = loaded(pp)) {
        !           189:                unload(srp);
        !           190:                srp->sr_segp = 0;
        !           191:        }
        !           192:        sz = numClicks;
        !           193:        if (&sysmem.pfree[sz] > sysmem.efree)
        !           194:                panic("c_free - nalloc");
        !           195:        qp = pp;
        !           196:        do {
        !           197:                if ((*qp & SEG_NPL) == 0) {
        !           198:                        pno = segclick(*qp);
        !           199:                        if (!pvalid(pno))
        !           200:                                panic("c_free");
        !           201:                        *sysmem.pfree++ = pno;
        !           202:                } else {
        !           203:                        T_HAL(0x40000, printf("c_free NPL %x ", *qp));
        !           204:                }
        !           205:                qp++;
        !           206:        } while (--sz);
        !           207:        areafree((BLOCKLIST *)pp, numClicks);
        !           208: }
        !           209: 
        !           210: /*
        !           211:  * Given a user virtual address, a physical address, and a byte
        !           212:  * count, map the specified virtual address into the user data
        !           213:  * page table for the current process.
        !           214:  *
        !           215:  * This is meant to be called from the console ioctl, KDMAPDISP.
        !           216:  * The user virtual address must be click aligned.
        !           217:  * The range of physical addresses must lie outside installed RAM
        !           218:  * or within the "PHYS_MEM" pool.
        !           219:  *
        !           220:  * Return 1 on success, else 0.
        !           221:  */
        !           222: int
        !           223: mapPhysUser(virtAddr, physAddr, numBytes)
        !           224: {
        !           225:        int ret = 0;
        !           226:        SR * srp = u.u_segl + SIPDATA;
        !           227:        SEG * sp = srp->sr_segp;
        !           228:        cseg_t * pp = sp->s_vmem, * qp;
        !           229:        int pno, clickOffset, numClicks, i;
        !           230: 
        !           231:        /* Check alignment. */
        !           232:        if ((virtAddr & (NBPC-1)) || (physAddr & (NBPC-1))) {
        !           233:                T_HAL(0x40000, printf("mPU: failed alignment "));
        !           234:                goto mPUdone;
        !           235:        }
        !           236: 
        !           237:        /* Check validity of range of virtual addresses. */
        !           238:        if (virtAddr < srp->sr_base ||
        !           239:          (virtAddr + numBytes) >= (srp->sr_base + srp->sr_size)) {
        !           240:                T_HAL(0x40000, printf("mPU: bad vaddr "));
        !           241:                goto mPUdone;
        !           242:        }
        !           243: 
        !           244:        /* Check validity of range of physical addresses. */
        !           245:        /* if not in PHYS_MEM pool... */
        !           246:        if (!physValid(physAddr, numBytes)) {
        !           247: 
        !           248:                /* get installed RAM physical addresses */
        !           249:                unsigned int physLow = ctob((read16_cmos(LOMEM) + 3) >> 2);
        !           250:                unsigned int physHigh = ctob((read16_cmos(EXTMEM) + 3) >> 2)
        !           251:                  + ONE_MEG;
        !           252: 
        !           253:                T_HAL(0x40000, printf("physLow=%x physHigh=%x ",
        !           254:                  physLow, physHigh));
        !           255: 
        !           256:                /* Fail if physical range overlaps installed base RAM. */
        !           257:                if (physAddr < physLow) {
        !           258:                        T_HAL(0x40000, printf("mPU: overlap base RAM "));
        !           259:                        goto mPUdone;
        !           260:                }
        !           261: 
        !           262:                /* Fail if physical range overlaps installed extended RAM. */
        !           263:                if (physAddr < physHigh && (physAddr + numBytes) >= ONE_MEG) {
        !           264:                        T_HAL(0x40000, printf("mPU: overlap extended RAM "));
        !           265:                        goto mPUdone;
        !           266:                }
        !           267:        }
        !           268: 
        !           269:        /*
        !           270:         * For each click in user data segment which is to be remapped
        !           271:         *   if current click was taken from sysmem pool
        !           272:         *     return current click to sysmem pool
        !           273:         *   write new physical address into current click entry
        !           274:         *   mark current click as not coming from sysmem pool
        !           275:         *   map current click into page table
        !           276:         */
        !           277:        clickOffset = btocrd(virtAddr - srp->sr_base);
        !           278:        numClicks = numBytes >> BPCSHIFT;
        !           279:        for (qp = pp + clickOffset, i = 0; i < numClicks; i++, qp++) {
        !           280:                if ((*qp & SEG_NPL) == 0) {
        !           281:                        pno = segclick(*qp);
        !           282:                        if (!pvalid(pno)) {
        !           283:                                T_HAL(0x40000, printf("mPU: bad release "));
        !           284:                        } else {
        !           285:                                *sysmem.pfree++ = pno;
        !           286:                                T_HAL(0x40000,
        !           287:                                  printf("mPU: freeing virtual click %x ",
        !           288:                                  virtAddr + ctob(i)));
        !           289:                        }
        !           290:                } else {
        !           291:                        T_HAL(0x40000,
        !           292:                          printf("mPU: rewriting virtual NPL click %x ",
        !           293:                          virtAddr + ctob(i)));
        !           294:                }
        !           295:                *qp = (physAddr + ctob(i)) | (SEG_RW | SEG_NPL);
        !           296:                ptable1_v[btocrd(virtAddr) + i] = *qp;
        !           297:        }
        !           298:        mmuupd();
        !           299:        ret = 1;
        !           300: 
        !           301: mPUdone:
        !           302:        return ret;
        !           303: }
        !           304: 
        !           305: /*
        !           306:  * Add a click to a segment.
        !           307:  * Enlarge buddy table for segment, if needed.
        !           308:  *
        !           309:  * Arguments:
        !           310:  *     pp points to segment reference table (segp->s_vmem, e.g.)
        !           311:  *     osz is old segment size, in clicks
        !           312:  *
        !           313:  * Return pointer to enlarged segment reference table, or NULL if failed.
        !           314:  */
        !           315: cseg_t *
        !           316: c_extend(pp, osz) 
        !           317: register cseg_t *pp;
        !           318: int osz;
        !           319: {
        !           320:        register        cseg_t *pp1;
        !           321:        register unsigned       pno;
        !           322:        register int    i;
        !           323:        SR              *srp;
        !           324: 
        !           325:        /* Fail if no more free clicks available. */
        !           326:        if (sysmem.pfree < &sysmem.tfree[1])
        !           327:                goto no_c_extend;
        !           328: 
        !           329:        /* Don't grow segment beyond hardware segment size (4 megabytes). */
        !           330:        if (osz >= (NBPS/NBPC))
        !           331:                goto no_c_extend;
        !           332: 
        !           333:        if (srp = loaded(pp)) {
        !           334:                unload(srp);
        !           335:                srp->sr_segp = 0;
        !           336:        }
        !           337: 
        !           338:        /*
        !           339:         * If the old size was a power of 2, it has used up an entire
        !           340:         * buddy area, so we will need to allocate more space.
        !           341:         */
        !           342:        if (IS_POW2(osz)) {
        !           343:                if ((pp1 = (cseg_t*) arealloc(osz+1))==0)
        !           344:                        goto no_c_extend;
        !           345:                for (i=0; i < osz; i++)
        !           346:                        pp1[i] = pp[i];
        !           347:                areafree(pp, osz);
        !           348:                pp = pp1;
        !           349:        }
        !           350: 
        !           351:        for (i=osz; --i >= 0;)
        !           352:                pp[i+1] = pp[i];
        !           353: 
        !           354:        pno = *--sysmem.pfree;
        !           355:        if (!pvalid(pno))
        !           356:                panic("c_extend");
        !           357:        pp[0] = clickseg(pno) | SEG_RW;
        !           358:        return pp;
        !           359: 
        !           360: no_c_extend:
        !           361:        return 0;
        !           362: }
        !           363: 
        !           364: /*
        !           365:  * Given segment size in bytes, estimate total space needed
        !           366:  * to keep track of the segment (I think - hws).
        !           367:  *
        !           368:  * return value is num_bytes plus some overhead...
        !           369:  */
        !           370: int
        !           371: countsize(num_bytes)
        !           372: int num_bytes;
        !           373: {
        !           374:        int ret;
        !           375: 
        !           376:        if (num_bytes <= NBPC/sizeof(long))
        !           377:                ret = num_bytes+1;
        !           378:        else
        !           379:                ret = num_bytes
        !           380:                  + ((num_bytes + NBPC/sizeof(long) - 1) >> BPC1SHIFT) + 1;
        !           381:        return ret;
        !           382: }
        !           383: 
        !           384: /*
        !           385:  * buddy allocation 
        !           386:  */
        !           387: 
        !           388: /*
        !           389:  * Deallocate a segment descriptor area.
        !           390:  * "sp" is not really a BLOCKLIST*, rather a cseg_t *.
        !           391:  * "numClicks" is the number of clicks referenced in the area.
        !           392:  */
        !           393: void
        !           394: areafree(sp, numClicks)
        !           395: BLOCKLIST *sp;
        !           396: int numClicks;
        !           397: {
        !           398:        register int    n;      /* adresse du buddy, taille du reste */
        !           399:        register int    ix, nx;
        !           400:        register        BLOCKLIST *buddy;
        !           401: 
        !           402:        areacheck(2, sp);
        !           403: 
        !           404:        /*
        !           405:         * Pointer "sp" points to an element in the sysmem table of
        !           406:         * free clicks.
        !           407:         * Integer "ix" is the index of "sp" into that table.
        !           408:         * Will use "ix" to index into one or more buddy tables.
        !           409:         */
        !           410:        ix = sp - sysmem.u.budtab;
        !           411:        n = areasize(numClicks);
        !           412:        do {
        !           413:                /* "nx" is index of buddy element to the one at "ix". */
        !           414:                nx = BUDDY(ix, n);
        !           415:                if (sysmem.budfree[nx>>WSHIFT] & 1<<(nx&(WCOUNT-1))) {
        !           416:                        /* coalesce two buddies */
        !           417:                        buddy = sysmem.u.budtab + nx; 
        !           418:                        if (buddy->kval != n)
        !           419:                                break;
        !           420:                        sysmem.budfree[nx>>WSHIFT] &= ~ (1<<(nx & (WCOUNT-1)));
        !           421:                        DELETE2(buddy);
        !           422:                        if (nx < ix) 
        !           423:                                ix = nx;
        !           424:                } else
        !           425:                        break;
        !           426:        } while (++n < NBUDDY);
        !           427:        sysmem.budfree[ix>>WSHIFT] |= 1 << (ix & (WCOUNT-1));
        !           428:        buddy = sysmem.u.budtab + ix;
        !           429:        INSERT2(BLOCKLIST, buddy, &sysmem.bfree[n]);
        !           430:        buddy->kval = n;
        !           431:        areacheck(3, buddy);
        !           432: }
        !           433: 
        !           434: /*
        !           435:  * arealloc()
        !           436:  *
        !           437:  * Given size in "clicks" of a segment to manage,
        !           438:  * return pointer to an array of enough descriptors.
        !           439:  * If not enough free descriptors available, return 0.
        !           440:  */
        !           441: BLOCKLIST *
        !           442: arealloc(clicks)
        !           443: register int clicks;
        !           444: {
        !           445:        register        BLOCKLIST *sp;
        !           446:        register        BLOCKLIST *p, *q;
        !           447:        register int    size;
        !           448:        BLOCKLIST       *rsp;
        !           449:        register int    nx;
        !           450: 
        !           451:        areacheck(0, 0);
        !           452:        size = areasize(clicks);
        !           453:        /*
        !           454:         * 1. Find little end, bloc p, free >= size
        !           455:         */
        !           456:        for (q = p = sysmem.bfree + size;p->forw == p; size++, p++)
        !           457:                if (p >= sysmem.bfree + NBUDDY - 1) {
        !           458:                        return(0);      /* y en a pas */
        !           459:                }
        !           460: 
        !           461:        rsp = p->forw;
        !           462:        DELETE2(rsp);
        !           463:        nx = rsp - sysmem.u.budtab;
        !           464:        sysmem.budfree[nx>>WSHIFT] &= ~(1 << (nx & (WCOUNT-1)));
        !           465:        size = 1<<size;
        !           466:        sp = rsp + size; /* buddy address */
        !           467:        while (p-- != q) {
        !           468:                /*
        !           469:                 * 2.1 The block is too big, uncouple & free buddy
        !           470:                 */
        !           471:                sp -= (size >>= 1);
        !           472:                nx = sp - sysmem.u.budtab;
        !           473:                sysmem.budfree[nx>>WSHIFT] |= 1 << (nx & (WCOUNT-1));
        !           474:                INSERT2(BLOCKLIST, sp, p);
        !           475:                sp->kval = p - sysmem.bfree;
        !           476:        }
        !           477:        areacheck(1, rsp);
        !           478:        return rsp;
        !           479: }
        !           480: 
        !           481: void
        !           482: areainit(n)
        !           483: {
        !           484:        extern char __end[];
        !           485:        register int i;
        !           486: 
        !           487:        for (i=0; i < (1<<(NBUDDY-WSHIFT)); i++)
        !           488:                sysmem.budfree[i] = 0;
        !           489:        for (i=0; i<NBUDDY; i++)
        !           490:                INIT2(&sysmem.bfree[i]);
        !           491:        sysmem.u.budtab = (BLOCKLIST *)__end;
        !           492:        n /= sizeof(BLOCKLIST);
        !           493:        if (n > (1 << NBUDDY))
        !           494:                panic("areainit");
        !           495:        for (i=0; i<n; i++)
        !           496:                areafree(&sysmem.u.budtab[i], sizeof(BLOCKLIST)/sizeof(long));
        !           497: }
        !           498: 
        !           499: /*
        !           500:  * areasize()
        !           501:  *
        !           502:  * Do a log(base 2) calculation on n.
        !           503:  * If n is zero, return -1.
        !           504:  *
        !           505:  * Else, consider the nearest power of two which is greater than or
        !           506:  * equal to n
        !           507:  *     p/2 < n <= p
        !           508:  * Then set p = 4 * (2**x).  Note BLKSZ is 2.
        !           509:  * Return max(x,0).
        !           510:  *
        !           511:  * If n is too large (more than 3F00), we will go beyond the limits of
        !           512:  * table buddysize[].
        !           513:  *
        !           514:  * In practice, n is the total number of clicks needed in a segment,
        !           515:  * and the return value will be used to access a buddy system list.
        !           516:  */
        !           517: int
        !           518: areasize(n)
        !           519: register unsigned int  n;
        !           520: {
        !           521:        register int m;
        !           522: #ifdef FROTZ
        !           523:        int ret, oldn = n;
        !           524: #endif
        !           525: 
        !           526:        if (n > 0x3F00)
        !           527:                panic("areasize");
        !           528: 
        !           529:        n = (n + (1 << BLKSZ) - 1) >> BLKSZ;
        !           530:        m = n & 0x3F;
        !           531: #ifdef FROTZ
        !           532:        if ((n >>= 6) == 0)
        !           533:                ret = buddysize[m];
        !           534:        else {
        !           535:                int index;
        !           536: 
        !           537:                index = n;
        !           538:                if (m)
        !           539:                        index++;
        !           540:                ret = buddysize[index] + 6;
        !           541:        }
        !           542:        return ret;
        !           543: #else
        !           544:        if ((n >>= 6) == 0)
        !           545:                return buddysize[m];
        !           546:        return buddysize[n + ((m!=0)?1:0)] + 6;
        !           547: #endif
        !           548: }
        !           549: 
        !           550: #define        MAXBUDDY        2048
        !           551: #define        CHECK(p) ((p>=&sysmem.bfree[0] && p<&sysmem.bfree[NBUDDY]) || \
        !           552:                (p>=sysmem.u.budtab && p<&sysmem.u.budtab[1<<NBUDDY]))
        !           553: void
        !           554: areacheck(flag, sp)
        !           555: register       BLOCKLIST *sp;
        !           556: {
        !           557:        register        BLOCKLIST *next, *start;
        !           558:        register int i, nx;
        !           559: 
        !           560:        if (sp) {
        !           561:                if (&sysmem.u.budtab[sp-sysmem.u.budtab] != sp)
        !           562:                  printf("*check* %d %x %x\n", flag, sp, sysmem.u.budtab);
        !           563:        }
        !           564:                
        !           565:        for (i=0; i<NBUDDY; i++) {
        !           566:                start = next = &sysmem.bfree[i];
        !           567:                do {
        !           568:                        next = next->forw;
        !           569:                        if (!CHECK(next))
        !           570:                                printf("next = %x (%d)\n", next, flag);
        !           571:                        if (next->back != start)
        !           572:                                printf("%x->forw->back != %x\n", next, start);
        !           573:                        if (next != &sysmem.bfree[i]) {
        !           574:                                if (next->kval != i)
        !           575:                                        printf("bad kval %x, %d (%d)\n",
        !           576:                                                next, next->kval, flag);
        !           577:                                nx = next - sysmem.u.budtab;
        !           578:                                if ((sysmem.budfree[nx>>WSHIFT] & (1 << (nx & (WCOUNT-1)))) == 0)
        !           579:                                        printf("in bfree but not budfree %x (%d)\n", next, flag);
        !           580:                        }
        !           581:                        start = next;
        !           582:                } while (next != &sysmem.bfree[i]);
        !           583:        }
        !           584: }
        !           585: 
        !           586: MAKESR(physMem, _physMem);
        !           587: extern int     PHYS_MEM;       /* Number of bytes of contiguous RAM needed */
        !           588: 
        !           589: /*
        !           590:  * A block of contiguous physical memory has been allocated for special
        !           591:  * i/o devices.
        !           592:  * Problem: clicks of physical memory are in reverse order in the
        !           593:  * page table.
        !           594:  * This routine reverses the page table entries for the pages
        !           595:  * involved.  It relies *heavily* on all pages having virtual addresses
        !           596:  * in the FFCx xxxx segment.
        !           597:  *
        !           598:  * If all goes well, assign physAvailStart to the virtual address of
        !           599:  * the beginning of the region, and physAvailBytes to the number of bytes
        !           600:  * in the region.  Otherwise, leave physAvailStart and physAvailBytes at 0.
        !           601:  *
        !           602:  * As memory is allocated, physAvailStart advances to point to the next
        !           603:  * available byte of contiguous memory, physAvailBytes is decremented,
        !           604:  * and physPoolStart remains set to the virtual address of the start of
        !           605:  * the contiguous pool.
        !           606:  */
        !           607: static int     physPoolStart;  /* start of contiguous memory area */
        !           608: static int     physAvailStart; /* next free byte in contiguous memory area */
        !           609: static int     physAvailBytes; /* number of bytes in contiguous memory area */
        !           610: 
        !           611: /*
        !           612:  * Check whether a range of physical addresses lies within the
        !           613:  * pool of contiguous physical memory.
        !           614:  */
        !           615: int
        !           616: physValid(base, numBytes)
        !           617: unsigned int base, numBytes;
        !           618: {
        !           619:        int vpool;
        !           620:        int ret = 0;
        !           621: 
        !           622:        if (PHYS_MEM) {
        !           623:                vpool = vtop(physPoolStart);
        !           624:                T_HAL(0x40000, printf("PHYS_MEM phys addrs %x to %x  ",
        !           625:                  vpool, vpool + PHYS_MEM));
        !           626:                if (base >= vpool && (base + numBytes) <= (vpool + PHYS_MEM))
        !           627:                        ret = 1;
        !           628:        } else {
        !           629:                T_HAL(0x40000, printf("No PHYS_MEM "));
        !           630:        }
        !           631: 
        !           632:        T_HAL(0x40000, printf("physValid(%x, %x) = %d ", base, numBytes, ret));
        !           633:        return ret;
        !           634: }
        !           635: 
        !           636: void
        !           637: physMemInit()
        !           638: {
        !           639:        int m, vaddr;
        !           640:        int err = 0, num_clicks = btoc(PHYS_MEM);
        !           641:        int prevPaddr, paddr;
        !           642: 
        !           643:        /*
        !           644:         * Going half way into page table for physMem
        !           645:         *   If entry and its complementary entry aren't both in top segment
        !           646:         *     Error exit (no phys mem will be available).
        !           647:         *   Get page table entries and swap them.
        !           648:         */
        !           649:        for (m = 0; m < num_clicks/2; m++) {
        !           650:                int m2 = num_clicks - 1 - m;    /* complementary index */
        !           651: 
        !           652:                /* compute virtual addresses */
        !           653:                int lo_addr = physMem.sr_base + ctob(m);
        !           654:                int hi_addr = physMem.sr_base + ctob(m2);
        !           655: 
        !           656:                /* compute indices into page table (ptable1_v) */
        !           657:                int lo_p1ix = btocrd(lo_addr);
        !           658:                int hi_p1ix = btocrd(hi_addr);
        !           659: 
        !           660:                /* fetch physical addresses from page table */
        !           661:                int lo_paddr = ptable1_v[lo_p1ix];
        !           662:                int hi_paddr = ptable1_v[hi_p1ix];
        !           663: 
        !           664:                /* abort if either address is not in top segment */
        !           665:                if (btosrd(lo_addr) != 0x3FF) {
        !           666:                        err = 1;
        !           667:                        break;
        !           668:                }
        !           669:                if (btosrd(hi_addr) != 0x3FF) {
        !           670:                        err = 1;
        !           671:                        break;
        !           672:                }
        !           673: 
        !           674:                /* exchange page table entries */
        !           675:                ptable1_v[lo_p1ix] = hi_paddr;
        !           676:                ptable1_v[hi_p1ix] = lo_paddr;
        !           677:        }
        !           678: 
        !           679:        /*
        !           680:         * Final sanity check.
        !           681:         * In case someone gets creative with startup code, check
        !           682:         * again here that the memory is actually contiguous.
        !           683:         */
        !           684:        prevPaddr = vtop(physMem.sr_base);
        !           685:        for (m = 0; m < num_clicks - 1; m++) {
        !           686:                paddr = vtop(physMem.sr_base + ctob(m + 1));
        !           687:                if (paddr - prevPaddr != NBPC) {
        !           688:                        err = 1;
        !           689:                        break;
        !           690:                }
        !           691:                prevPaddr = paddr;
        !           692:        }
        !           693: 
        !           694:        if (!err) {
        !           695:                physPoolStart = physAvailStart = physMem.sr_base;
        !           696:                physAvailBytes = PHYS_MEM;
        !           697:        }
        !           698: }
        !           699: 
        !           700: /*
        !           701:  * Return virtual address of block of contiguous physical memory.
        !           702:  * If request cannot be granted, return 0.
        !           703:  *
        !           704:  * Expect physMem resource to be granted during load routine of device
        !           705:  * drivers.  Once allocated, memory is not returned to the physMem pool.
        !           706:  */
        !           707: char *
        !           708: getPhysMem(numBytes)
        !           709: unsigned int numBytes;
        !           710: {
        !           711:        char * ret = NULL;
        !           712: 
        !           713:        if (numBytes <= physAvailBytes) {
        !           714:                ret = (char *)physAvailStart;
        !           715:                physAvailStart += numBytes;
        !           716:                physAvailBytes -= numBytes;
        !           717:        } else
        !           718:                printf("getPhysMem failed - %d additional bytes "
        !           719:                  "PHYS_MEM needed\n", physAvailBytes - numBytes);
        !           720:        return ret;
        !           721: }
        !           722: 
        !           723: /*
        !           724:  * Return virtual address of aligned block of contiguous physical memory.
        !           725:  * Mainly for devices using the stupid Intel DMA hardware without
        !           726:  *   scatter/gather.
        !           727:  * If request cannot be granted, return 0.
        !           728:  *
        !           729:  * Argument "align" says what physical boundary we need alignment on.
        !           730:  * It must be a power of 2.
        !           731:  * For 4k alignment, align = 4k, etc.
        !           732:  * Sorry, but will throw away memory to get to the next acceptable address.
        !           733:  *
        !           734:  * Once allocated, memory is not returned to the physMem pool.
        !           735:  */
        !           736: char *
        !           737: getDmaMem(numBytes, align)
        !           738: unsigned int numBytes;
        !           739: unsigned int align;
        !           740: {
        !           741:        char * ret = NULL;
        !           742:        int wastedBytes, neededBytes;
        !           743: 
        !           744:        if (align == 0) {
        !           745:                printf("getDmaMem(0) (?)\n");
        !           746:                goto getDmaMemDone;
        !           747:        }
        !           748: 
        !           749:        if (!IS_POW2(align)) {
        !           750:                printf("getDmaMem(%x) (?)\n", align);
        !           751:                goto getDmaMemDone;
        !           752:        }
        !           753: 
        !           754:        /*
        !           755:         * Waste RAM from bottom of pool up to physical
        !           756:         * address with desired alignment.
        !           757:         */
        !           758:        wastedBytes = align - (vtop(physAvailStart) % align);
        !           759:        neededBytes = numBytes + wastedBytes;
        !           760: 
        !           761:        if (neededBytes <= physAvailBytes) {
        !           762:                ret = (char *)physAvailStart + wastedBytes;
        !           763:                physAvailStart += neededBytes;
        !           764:                physAvailBytes -= neededBytes;
        !           765:        } else
        !           766:                printf("getDmaMem failed - %d additional bytes "
        !           767:                  "PHYS_MEM needed\n", physAvailBytes - neededBytes);
        !           768: 
        !           769: getDmaMemDone:
        !           770:        return ret;
        !           771: }
        !           772: /***************/
        !           773: 
        !           774: #undef ptable1_v
        !           775: 
        !           776: /*
        !           777:  * pageDir is the physical address of the click in use for the page
        !           778:  * directory, offset by ctob(SBASE - PBASE)
        !           779:  */
        !           780: #define        pageDir         ((long *)(&stext[ctob(-1)]))
        !           781: 
        !           782: int total_clicks;      /* How many clicks did we start with?  */
        !           783: 
        !           784: void
        !           785: mchinit()
        !           786: {
        !           787:        extern char __end[], __end_data[], stext[], __end_text[], sdata[];
        !           788:        extern int RAM0, RAMSIZE;
        !           789: 
        !           790:        int lo;         /* Number of bytes of physical memory below 640K.  */
        !           791:        int hi;         /* Number of bytes of physical memory above 1M.  */
        !           792:        register char *pe; 
        !           793:        register int zero = 0;
        !           794:        register int    i;
        !           795:        register        long *ptable1_v;
        !           796:        register unsigned short base;
        !           797:        int     sysseg, codeseg, stackseg, ramseg, ptable1;
        !           798:        int     ptoff;  /* An offset into pageDir[]  */
        !           799: #if USE_NDATA
        !           800:        int     dataseg[NDATA];
        !           801: #else
        !           802:        int     dataseg;
        !           803: #endif
        !           804:        int     nalloc;
        !           805:        extern char     digtab[];
        !           806:        static  SEG     uinit;
        !           807:        int     budArenaBytes;  /* number of bytes in buddy pool */
        !           808:        int     kerBytes;       /* number of bytes in kernel text and data */
        !           809: 
        !           810:        /*
        !           811:         * 1.
        !           812:         *   a. Relocate the data on a page boundary (4K bytes) the
        !           813:         *      bootstrap relocates it on a paragraph boundary (16 bytes)
        !           814:         *
        !           815:         *   b. Verify that the data has been relocated correctly 
        !           816:         */
        !           817:        pe = __end_data;                                        /* 1.a */
        !           818:        i = (((unsigned)__end_text+15) & ~15) - (unsigned)sdata;
        !           819:        do {
        !           820:                pe--;
        !           821:                pe[0] = pe[i];
        !           822:        } while (pe != sdata);                                  /* 1.b */
        !           823: 
        !           824:        /*
        !           825:         * Can now access the .data segment from C.
        !           826:         * If not, next loop will hang the kernel.
        !           827:         */
        !           828:        CHIRP('A');
        !           829:        while (digtab[0]!='0');
        !           830:        CHIRP('*');
        !           831: 
        !           832:        /* Zero the bss. */
        !           833:        pe = __end_data;
        !           834:        do
        !           835:                *pe++ = zero;
        !           836:        while (pe != __end);
        !           837: 
        !           838:        /*
        !           839:         * Zero the level 0 page directory, which occupies the click
        !           840:         * of virtual space immediately below kernel text.
        !           841:         */
        !           842:        pe = (char *) pageDir;
        !           843:        do
        !           844:                *pe++ = zero;
        !           845:        while (pe != stext);
        !           846: 
        !           847:        CHIRP('2');
        !           848: 
        !           849:        /*
        !           850:         * 3. Calculate total system memory.
        !           851:         *    Count the space used by the system and the page
        !           852:         *    descriptors, the interrupt stack, and the refresh work area
        !           853:         *
        !           854:         * a. initialize allocation area and adjust system size
        !           855:         *    to take allocation area and free page area into account
        !           856:         */
        !           857: 
        !           858:        /*
        !           859:         * btoc(__end) - SBASE is the number of clicks in kernel text
        !           860:         * plus data, rounded up.
        !           861:         * PBASE is the starting physical click number of the kernel.
        !           862:         *
        !           863:         * Set sysmem.lo to the physical click address just past the kernel.
        !           864:         */
        !           865:        DV(__end);
        !           866: 
        !           867:        kerBytes = __end - ((SBASE - PBASE)<<BPCSHIFT);
        !           868:        DV(kerBytes);
        !           869: 
        !           870:        sysmem.lo = btoc(kerBytes);
        !           871:        DV(sysmem.lo);
        !           872: 
        !           873:        /*
        !           874:         * lo is the size in bytes of memory between the end of the kernel
        !           875:         *      and the end of memory below 640K.
        !           876:         * hi is the size in bytes of memory over 1 Megabyte (Extended memory).
        !           877:         *
        !           878:         * Round the sizes from the CMOS down to the next click.  This
        !           879:         * compensates for systems where the CMOS reports sizes that are
        !           880:         * not multiples of 4K.
        !           881:         */
        !           882:        DV(read16_cmos(LOMEM));
        !           883:        lo = ctob(read16_cmos(LOMEM) >> 2) - ctob(sysmem.lo);
        !           884:        DV(lo);
        !           885: 
        !           886:        DV(read16_cmos(EXTMEM));
        !           887:        hi = ctob(read16_cmos(EXTMEM) >> 2);
        !           888:        DV(hi);
        !           889: 
        !           890:        /*
        !           891:         * Sometimes, we die horribly if there is too much memory.
        !           892:         * Artificially limit hi to HACK_LIMIT.
        !           893:         */
        !           894:        if (hi > HACK_LIMIT)
        !           895:                hi = HACK_LIMIT;
        !           896: 
        !           897:        /* clear base memory above the kernel */
        !           898: #if    0
        !           899:        CHIRP('z');
        !           900:        memset (ctob (sysmem.lo + SBASE - PBASE), 0, lo);
        !           901:        CHIRP('Z');
        !           902: 
        !           903:        /* clear extended memory */
        !           904:        memset (ONE_MEG + ctob (SBASE - PBASE), 0, hi);
        !           905:        CHIRP('Y');
        !           906: #endif
        !           907:        
        !           908:        /* Record total memory for later use.  */
        !           909:        total_mem = ctob(sysmem.lo) + lo + hi;
        !           910:        DV(total_mem);
        !           911: 
        !           912:        /*
        !           913:         * sysmem.pfree and relatives will keep track of a pool of 4k pages
        !           914:         * assigned to processes, hereinafter known as the sysmem pool.
        !           915:         * How many clicks can go into this pool?  nalloc.
        !           916:         * Allow NBPC for the click itself, a short for the sysmem pointer,
        !           917:         * and SPLASH*sizeof(long) for buddy system overhead.
        !           918:         */
        !           919:        nalloc = (lo+hi) / (sizeof(short) + SPLASH*sizeof(long) + NBPC);
        !           920:        DV(nalloc);
        !           921: 
        !           922:        /*
        !           923:         * ASSERT:
        !           924:         * For the moment we want only to assure that the
        !           925:         * BUDDY arena and the stack of free pages will fit below
        !           926:         * 640K.
        !           927:         */
        !           928:        budArenaBytes = SPLASH*nalloc*sizeof(long);
        !           929:        DV(budArenaBytes);
        !           930: 
        !           931: #define SIZEOF_FREE_PAGES ((btoc(hi) + btoc(lo))* sizeof(short))
        !           932:        T_PIGGY(0x800, budArenaBytes + SIZEOF_FREE_PAGES >= lo ?
        !           933:                        panic("Too much memory") : 0);
        !           934: 
        !           935:        /*
        !           936:         * Initialize the buddy system arena.  This memory is used
        !           937:         * for the compressed page tables.
        !           938:         */
        !           939:        areainit(budArenaBytes);
        !           940: 
        !           941:        /*
        !           942:         * Initialize the stack of free pages.
        !           943:         * __end is the virtual address just past kernel data
        !           944:         * Point sysmem.tfree to the lowest virtual address just above
        !           945:         * the buddy pool, and initialize sysmem.pfree there.
        !           946:         */
        !           947:        sysmem.tfree = sysmem.pfree = 
        !           948:          (unsigned short *)(__end + budArenaBytes);
        !           949:        DV(sysmem.tfree);
        !           950: 
        !           951:        /* sysmem.hi is the physical click number just past high RAM */
        !           952:        sysmem.hi = btoc(hi+ONE_MEG);
        !           953:        DV(sysmem.hi);
        !           954: 
        !           955:        /* base is the physical click number just past base RAM */
        !           956:        base = sysmem.lo + (lo>>BPCSHIFT);
        !           957:        DV(base);
        !           958: 
        !           959:        /*
        !           960:         * Adjust sysmem.lo to be the physical click number just above
        !           961:         * not just the kernel, but above sysmem overhead as well.
        !           962:         */
        !           963:        sysmem.lo = btoc(kerBytes + budArenaBytes + nalloc*sizeof(short));
        !           964:        DV(sysmem.lo);
        !           965: 
        !           966:        /*
        !           967:         * sysmem.vaddre is the virtual address of the next click after the
        !           968:         * kernel.
        !           969:         */
        !           970:        sysmem.vaddre = ctob(sysmem.lo+SBASE-PBASE);
        !           971:        DV(sysmem.vaddre);
        !           972: 
        !           973:        /* include in system area pages for arena, free area */
        !           974: 
        !           975:        CHIRP('3');
        !           976: 
        !           977:        /*
        !           978:         * 4.
        !           979:         *  Free the memory from [end, 640) kilobytes
        !           980:         *  Free the memory from [1024, 16*1024) kilobytes
        !           981:         *
        !           982:         *  We are building a stack of free pages bounded below
        !           983:         *  by sysmem.tfree and above by sysmem.efree.  sysmem.pfree
        !           984:         *  is the top of the stack.  The stack grows upwards.
        !           985:         */
        !           986:        total_clicks = 0;
        !           987: 
        !           988:        /*
        !           989:         * Initialize the sysmem table (phase 1 - base RAM).
        !           990:         * Put base RAM above the kernel and sysmem overhead area into
        !           991:         * sysmem pool.
        !           992:         */
        !           993:        while (base > sysmem.lo) {
        !           994:                *sysmem.pfree++ = --base;
        !           995:                ++total_clicks;
        !           996:        }
        !           997: 
        !           998:        /*
        !           999:         * Initialize the sysmem table (phase 2 - extended RAM).
        !          1000:         * Put all extended RAM into the sysmem pool.
        !          1001:         */
        !          1002:        base = btoc(ONE_MEG);
        !          1003:        while (base < sysmem.hi && total_clicks < nalloc) {
        !          1004:                *sysmem.pfree++ = base++;
        !          1005:                ++total_clicks;
        !          1006:        }
        !          1007:        DV(total_clicks);
        !          1008: 
        !          1009:        /*
        !          1010:         * Roundoff error may have made nalloc smaller than necessary.
        !          1011:         */
        !          1012:        while(base < sysmem.hi) {
        !          1013:                if (sysmem.pfree + 1 >= sysmem.vaddre)
        !          1014:                        break;
        !          1015:                *sysmem.pfree++ = base++;
        !          1016:                ++total_clicks;
        !          1017:                nalloc++;
        !          1018:        }
        !          1019:        DV(total_clicks);
        !          1020:        DV(nalloc);
        !          1021: 
        !          1022:        /*
        !          1023:         * sysmem.efree points just past the last pointer in the sysmem
        !          1024:         * table.
        !          1025:         */
        !          1026:        sysmem.efree = sysmem.pfree;
        !          1027:        DV(sysmem.efree);
        !          1028:        DV(allocno());
        !          1029: 
        !          1030: #if    0
        !          1031:        /*
        !          1032:         * NIGEL: Trace macros must now be given expressions. This one isn't
        !          1033:         * worth cleaning up.
        !          1034:         */
        !          1035: 
        !          1036:        T_PIGGY(0x800, {
        !          1037:                /*
        !          1038:                 * ASSERT:  The stack of free pages should end within a click
        !          1039:                 * of the lowest available memory.
        !          1040:                 */
        !          1041:                if ((cseg_t *)ctob(sysmem.lo+SBASE-PBASE) < sysmem.efree) {
        !          1042:                        panic("sysmem.lo is too low");
        !          1043:                }
        !          1044: 
        !          1045:                if (sysmem.efree < (cseg_t *)ctob(sysmem.lo+SBASE-PBASE - 1)){
        !          1046:                        panic("sysmem.efree is too low");
        !          1047:                }
        !          1048: 
        !          1049:                /*
        !          1050:                 * ASSERT:  There should be nalloc total_clicks.
        !          1051:                 */
        !          1052:                if (nalloc != total_clicks) {
        !          1053:                        panic("nalloc != total_clicks ");
        !          1054:                }
        !          1055:        });
        !          1056: #endif
        !          1057: 
        !          1058:        CHIRP('4');
        !          1059: 
        !          1060:        /*
        !          1061:         * 5. allocate page entries and initialize level 0 ^'s
        !          1062:         * a. [ 00000000 .. 003FFFFF)           user code segment
        !          1063:         * b. [ 00400000 .. 007FFFFF)           user data & bss
        !          1064:         * c. [ 7FC00000 .. 7FFFFFFF)           user stack
        !          1065:         *c.i.[ 80000000 .. 80FFFFFF)           ram disk
        !          1066:         * d. [ FF800000 .. FFBFFFFF)           pointers to level 1 page table
        !          1067:         * e. [ FFC00000 .. FFFFFFFF)           system process addresses
        !          1068:         */
        !          1069:        codeseg = clickseg(*--sysmem.pfree);            /* 5.a */
        !          1070:        pageDir[0x000] = codeseg  | DIR_RW; 
        !          1071: 
        !          1072: #if USE_NDATA
        !          1073:        for (i = 0; i < NDATA; i++) {
        !          1074:                dataseg[i] = clickseg(*--sysmem.pfree); /* 5.b */
        !          1075:                pageDir[0x001+i] = dataseg[i] | DIR_RW;
        !          1076:        }
        !          1077: #else
        !          1078:        dataseg = clickseg(*--sysmem.pfree);            /* 5.b */
        !          1079:        pageDir[0x001] = dataseg | DIR_RW;
        !          1080: #endif
        !          1081: 
        !          1082:        stackseg = clickseg(*--sysmem.pfree);           /* 5.c */
        !          1083:        pageDir[0x1FF] = stackseg  | DIR_RW; 
        !          1084: 
        !          1085:        /*
        !          1086:         * ptable1 is a handle for the click containing page table
        !          1087:         * entries for the page table.
        !          1088:         *
        !          1089:         * allocate a click for ptable1
        !          1090:         * Then point at it from the page directory.
        !          1091:         */
        !          1092:        ptable1 = clickseg(*--sysmem.pfree);            /* 5.d */
        !          1093:        pageDir[0x3FE] = ptable1 | DIR_RW; 
        !          1094: 
        !          1095:        sysseg = clickseg(*--sysmem.pfree);             /* 5.e */
        !          1096:        pageDir[0x3FF] = sysseg  | DIR_RW;
        !          1097: 
        !          1098:        CHIRP('5');
        !          1099: 
        !          1100:        /*
        !          1101:         * 6. initialize  level 2 ^'s to [5.d]
        !          1102:         */
        !          1103: 
        !          1104:        ptable1_v  = (long *)(ptable1 + ctob(SBASE-PBASE));
        !          1105:        DV(pageDir);
        !          1106:        DV(ptable1_v);
        !          1107:        ptable1_v[0x000] = codeseg | SEG_SRW;
        !          1108: #if USE_NDATA
        !          1109:        for (i = 0; i < NDATA; i++)
        !          1110:                ptable1_v[0x001+i] = dataseg[i] | SEG_SRW;
        !          1111: #else
        !          1112:        ptable1_v[0x001] = dataseg | SEG_SRW;
        !          1113: #endif
        !          1114:        ptable1_v[0x1FF] = stackseg| SEG_SRW;
        !          1115: 
        !          1116:        /*
        !          1117:         * This ram disk stuff should go away once the scheme
        !          1118:         * for allocating pieces of virtual memory space is in place.
        !          1119:         */
        !          1120:        for (ptoff = btosrd(RAM0) & 0x3ff;
        !          1121:          ptoff < (btosrd(RAM0 + 2 * RAMSIZE) & 0x3ff); ++ptoff) {
        !          1122:                ramseg =  clickseg(*--sysmem.pfree);            /* 5.c.i */
        !          1123:                pageDir[ptoff] = ramseg  | DIR_RW; 
        !          1124:                ptable1_v[ptoff] = ramseg | SEG_SRW;
        !          1125:        }
        !          1126: 
        !          1127:        ptable1_v[0x3FF] = sysseg  | SEG_SRW;
        !          1128: 
        !          1129:        CHIRP('6');
        !          1130: 
        !          1131:        /*
        !          1132:         * 7.
        !          1133:         * b. map kernel code and data
        !          1134:         *      map ^ to:
        !          1135:         * c.   level 0 page table
        !          1136:         * d.   level 1 page table
        !          1137:         * e.   I/O segments (video RAM, ...) 
        !          1138:         */ 
        !          1139: 
        !          1140:        ptable1_v  = (long *)(sysseg + ctob(SBASE-PBASE));      /* 7.b */
        !          1141:        DV(ptable1_v);
        !          1142:        for (i = PBASE; i <sysmem.lo; i++)
        !          1143:                ptable1_v[i-PBASE] = clickseg(i) | SEG_SRW;
        !          1144: 
        !          1145:        ptable1_v[0x3FE] = clickseg(PTABLE0_P) | SEG_SRW;       /* 7.c */
        !          1146:        ptable1_v[0x3FD] = ptable1 | SEG_SRW;                   /* 7.d */
        !          1147: 
        !          1148:        init_phy_seg(ptable1_v, ROM-SBASE,   0x0000F0000);      /* 7.e. */
        !          1149:        init_phy_seg(ptable1_v, VIDEOa-SBASE,0x0000B0000);
        !          1150:        init_phy_seg(ptable1_v, VIDEOb-SBASE,0x0000B8000);
        !          1151: 
        !          1152:        CHIRP('7');
        !          1153: 
        !          1154:        /*
        !          1155:         * 8. allocate and map U area
        !          1156:         */
        !          1157: 
        !          1158:        uinit.s_flags = SFSYST|SFCORE;
        !          1159:        uinit.s_size = UPASIZE;
        !          1160:        uinit.s_vmem = c_alloc(btoc(UPASIZE));
        !          1161:        ptable1_v[0x3FF] = *uinit.s_vmem | SEG_SRW;
        !          1162:        procq.p_segp[SIUSERP] = &uinit;
        !          1163: 
        !          1164:        CHIRP('8');
        !          1165: 
        !          1166:        /*
        !          1167:         * 9. make FFC00000 and 00002000 map to the same address
        !          1168:         * to prevent the prefetch after the instruction turning on
        !          1169:         * paging from causing a page fault
        !          1170:         */
        !          1171:        ptable1_v  = (long *)(codeseg + ctob(SBASE-PBASE));
        !          1172:        DV(ptable1_v);
        !          1173:        ptable1_v[PBASE] = clickseg(PBASE) | SEG_SRW;
        !          1174: 
        !          1175:        CHIRP('9');
        !          1176: 
        !          1177:        /*
        !          1178:         * 10. load page table base address into MMU
        !          1179:         *      fix up the interrupt vectors
        !          1180:         */
        !          1181:        mmuupdnR0();
        !          1182:        CHIRP('U');
        !          1183:        idtinit();
        !          1184:        CHIRP('I');
        !          1185: }
        !          1186: 
        !          1187: typedef struct
        !          1188: {
        !          1189:        unsigned short  off_lo;
        !          1190:        unsigned short  seg;
        !          1191:        unsigned short  flags;
        !          1192:        unsigned short  off_hi;
        !          1193: } IDT;
        !          1194: 
        !          1195: /*
        !          1196:  * ldtinit()
        !          1197:  *
        !          1198:  * Fix up descriptors which are hard to create properly at compile/link time.
        !          1199:  * Apply to idt and ldt.
        !          1200:  *
        !          1201:  * Swap 16-bit words at descriptor+2, descriptor+6.
        !          1202:  */
        !          1203: void
        !          1204: idtinit()
        !          1205: {
        !          1206:        extern IDT      idt[], idtend[];
        !          1207:        extern IDT      ldt[], ldtend[];
        !          1208:        extern IDT      gdtFixBegin[], gdtFixEnd[];
        !          1209: 
        !          1210:        register IDT *ip;
        !          1211:        register unsigned short tmp;
        !          1212: 
        !          1213:        for (ip = idt; ip < idtend; ip++) {
        !          1214:                tmp = ip->off_hi;
        !          1215:                ip->off_hi = ip->seg;
        !          1216:                ip->seg = tmp;
        !          1217:        }
        !          1218: 
        !          1219:        for (ip = ldt; ip < ldtend; ip++) {
        !          1220:                tmp = ip->off_hi;
        !          1221:                ip->off_hi = ip->seg;
        !          1222:                ip->seg = tmp;
        !          1223:        }
        !          1224: 
        !          1225:        for (ip = gdtFixBegin; ip < gdtFixEnd; ip++) {
        !          1226:                tmp = ip->off_hi;
        !          1227:                ip->off_hi = ip->seg;
        !          1228:                ip->seg = tmp;
        !          1229:        }
        !          1230: }
        !          1231: 
        !          1232: void
        !          1233: init_phy_seg(ptable1_v, addr, base)
        !          1234: long   *ptable1_v;
        !          1235: {
        !          1236:        register int i;
        !          1237: 
        !          1238:        for (i=0; i<btoc(0x10000); i++) {
        !          1239:                ptable1_v[addr+i] = base | SEG_SRW; 
        !          1240:                base += NBPC;
        !          1241:        }
        !          1242: }
        !          1243: 
        !          1244: /*
        !          1245:  * Load up segmentation registers.
        !          1246:  */
        !          1247: SR     ugmtab[NUSEG];
        !          1248: 
        !          1249: void
        !          1250: segload()
        !          1251: {
        !          1252:        register int i;
        !          1253:        register        SR *start;
        !          1254: 
        !          1255:        /*
        !          1256:         * 1. unprogram the currently active UGM user segments
        !          1257:         *    reset ugmtab
        !          1258:         */
        !          1259:        for (start = &ugmtab[1]; start < &ugmtab[NUSEG]; start++) {
        !          1260:                if (start->sr_segp)
        !          1261:                        unload(start);
        !          1262:                start->sr_segp = 0;
        !          1263:        }
        !          1264: 
        !          1265:        /*
        !          1266:         * 2. Load each segment in the p->p_region list into the MMU
        !          1267:         *    Remember values in ugmtab.
        !          1268:         */
        !          1269:        start = &ugmtab[1];
        !          1270:        for (i = 1; i < NUSEG; i++) {
        !          1271:                if (u.u_segl[i].sr_segp) {
        !          1272:                        *start = u.u_segl[i];
        !          1273:                        switch (i) {
        !          1274:                        case SIPDATA:
        !          1275:                                if (u.u_segl[SISTACK].sr_base)
        !          1276:                                        start->sr_size = min(start->sr_size,
        !          1277:                                          (long)u.u_segl[SISTACK].sr_base-
        !          1278:                                          u.u_segl[SISTACK].sr_size);
        !          1279:                                break;
        !          1280:                        case SISTACK:
        !          1281:                                start->sr_base -= start->sr_size;
        !          1282:                                break;
        !          1283:                        }
        !          1284: 
        !          1285:                        start->sr_segp = 0;
        !          1286:                        if (SELF->p_segp[i]) {
        !          1287:                                start->sr_segp = SELF->p_segp[i];
        !          1288:                                doload(start);
        !          1289:                        }
        !          1290:                        start++;
        !          1291:                }
        !          1292:        }
        !          1293: 
        !          1294:        /* 3.  Update shm segment information. */
        !          1295:        shmLoad();
        !          1296: }
        !          1297: 
        !          1298: SR *
        !          1299: loaded(pp)
        !          1300: register cseg_t *pp;
        !          1301: {
        !          1302:        register SR     *start;
        !          1303: 
        !          1304:        for (start = ugmtab; start < ugmtab + NUSEG; start++) {
        !          1305:                if (start->sr_segp && start->sr_segp->s_vmem == pp) {
        !          1306:                        return start;
        !          1307:                }
        !          1308:        }
        !          1309:        return 0;
        !          1310: }
        !          1311: 
        !          1312: MAKESR(r0stk, _r0stk);
        !          1313: extern int tss_sp0;
        !          1314: 
        !          1315: /*
        !          1316:  * General initialization
        !          1317:  */
        !          1318: void
        !          1319: i8086()
        !          1320: {
        !          1321:        unsigned        csize, isize, ssize, allsize;
        !          1322:        caddr_t base;
        !          1323:        unsigned int    calc_mem, boost;
        !          1324: 
        !          1325:        /* This is the first C code executed after paging is turned on. */
        !          1326: 
        !          1327:        workPoolInit();
        !          1328: 
        !          1329:        /*
        !          1330:         * Allocate contiguous physical memory if PHYS_MEM is patched
        !          1331:         * to a nonzero value.
        !          1332:         */
        !          1333:        if (PHYS_MEM) {
        !          1334:                physMem.sr_size = (PHYS_MEM+NBPC-1)&~(NBPC-1);
        !          1335:                valloc(&physMem);
        !          1336:                physMemInit();
        !          1337:        }
        !          1338: 
        !          1339:        /*
        !          1340:         * Allocate a click for ring 0 stack.
        !          1341:         */
        !          1342:        r0stk.sr_size = NBPC;
        !          1343:        valloc(&r0stk);
        !          1344:        tss_sp0 = r0stk.sr_base + NBPC;
        !          1345: 
        !          1346:        /*
        !          1347:         * calc_mem is used for autosizing buffer cache and kalloc pool.
        !          1348:         * It is total_mem, limited below by 1 meg and above by 12 meg.
        !          1349:         * The upper limit is a temporary move to allow booting on 16 Meg
        !          1350:         * systems.
        !          1351:         *
        !          1352:         * "boost" is used in autosizing buffer cache and kalloc pool.
        !          1353:         * It is the number of megabytes of calc_mem above 1 meg, i.e.,
        !          1354:         * a number between 0 and 11.
        !          1355:         */
        !          1356:        if (total_mem < ONE_MEG)
        !          1357:                calc_mem = ONE_MEG;
        !          1358:        else if (total_mem > 12 * ONE_MEG)
        !          1359:                calc_mem = 12 * ONE_MEG;
        !          1360:        else
        !          1361:                calc_mem = total_mem;
        !          1362: 
        !          1363:        boost = (calc_mem - ONE_MEG) / ONE_MEG;
        !          1364: 
        !          1365:        /*
        !          1366:         * If the number of cache buffers was not explicitly set (i.e., !0)
        !          1367:         * then calculate the number of buffers using the simple heuristic:
        !          1368:         *     128 minimum + 400 per MB of available RAM (i.e., after 1MB)
        !          1369:         */
        !          1370:        if (NBUF == 0)
        !          1371:                NBUF = 128 + (400 * boost);
        !          1372: 
        !          1373:        /*
        !          1374:         * Calculate NHASH as the next lower prime number from NBUF.
        !          1375:         */
        !          1376:        NHASH = nlp(NBUF);
        !          1377: 
        !          1378:        /*
        !          1379:         * If the amount of kalloc() space was not explicitly set (i.e., !0)
        !          1380:         * then calculate using the simple heuristic:
        !          1381:         *     64k minimum + 32k per MB of available RAM (i.e., after 1MB)
        !          1382:         */
        !          1383:        if (ALLSIZE == 0)
        !          1384:                ALLSIZE = 65536 + (32768 * boost);
        !          1385: 
        !          1386:        blockp.sr_size = NBUF*BSIZE;
        !          1387:        valloc(&blockp);
        !          1388: 
        !          1389:        allocp.sr_size= allsize = NBUF*sizeof(BUF) + ALLSIZE;
        !          1390: #if USE_SLOT
        !          1391:        allocp.sr_size += ssize = NSLOT * (sizeof(int) + slotsz);
        !          1392: #else
        !          1393:        ssize = 0;
        !          1394: #endif
        !          1395:        allocp.sr_size += isize = NINODE* sizeof(INODE);
        !          1396:        allocp.sr_size += csize = NCLIST* sizeof(CLIST);
        !          1397:        valloc(&allocp);
        !          1398:        base = allocp.sr_base;
        !          1399:        allkp = setarena(base, allsize);
        !          1400:        base += allsize;
        !          1401: #if USE_SLOT
        !          1402:        slotp = (int *)base;
        !          1403:        base += ssize;
        !          1404: #endif
        !          1405:        inodep = (INODE*) base;
        !          1406:        base += isize;
        !          1407:        clistp = (paddr_t)base;
        !          1408: }
        !          1409: 
        !          1410: /*
        !          1411:  * Allocate srp->sr_size bytes of physical memory, and map it into
        !          1412:  * virtual memory space.  At the end, the struct at srp will describe
        !          1413:  * the new segment.
        !          1414:  */
        !          1415: void
        !          1416: valloc(srp)
        !          1417: SR     *srp;
        !          1418: {
        !          1419:        register int npage;
        !          1420: 
        !          1421:        /*
        !          1422:         * If we've run out of virtual memory space, panic().
        !          1423:         *
        !          1424:         * A more graceful solution is needed, but valloc() does
        !          1425:         * not provide a return value.
        !          1426:         */
        !          1427:        if (sysmem.vaddre + srp->sr_size > MAX_VADDR) {
        !          1428:                panic("valloc: out of virtual memory space");
        !          1429:        }
        !          1430: 
        !          1431:        npage = btoc(srp->sr_size);
        !          1432: 
        !          1433:        srp->sr_base = sysmem.vaddre;
        !          1434:        srp->sr_segp->s_size = srp->sr_size;
        !          1435:        srp->sr_segp->s_vmem = c_alloc(npage);
        !          1436:        srp->sr_segp->s_flags = SFSYST|SFCORE;
        !          1437:        doload(srp);
        !          1438: 
        !          1439:        sysmem.vaddre += ctob(npage);
        !          1440: }
        !          1441: 
        !          1442: /*
        !          1443:  * See if the given process may fit in core.
        !          1444:  */
        !          1445: int
        !          1446: testcore(pp)
        !          1447: register PROC *pp;
        !          1448: {
        !          1449:        return 1;
        !          1450: }
        !          1451: 
        !          1452: /*
        !          1453:  * Calculate segmentation for a
        !          1454:  * new program. If there is a stack segment
        !          1455:  * present merge it into the data segment and
        !          1456:  * relocate the argument list.
        !          1457:  * Make sure that the changes are reflected in the u.u_segl array
        !          1458:  * which sproto sets up.
        !          1459:  */
        !          1460: int
        !          1461: mproto()
        !          1462: {
        !          1463:        return 1;
        !          1464: }
        !          1465: 
        !          1466: int
        !          1467: accdata(base, count)
        !          1468: unsigned       base, count;
        !          1469: {
        !          1470:        SR *srp;
        !          1471: 
        !          1472:        srp = &u.u_segl[SIPDATA];
        !          1473:        return base>=srp->sr_base && base+count <= srp->sr_base+srp->sr_size;
        !          1474: }
        !          1475: 
        !          1476: int
        !          1477: accstack(base, count)
        !          1478: unsigned       base;
        !          1479: {
        !          1480:        SR *srp;
        !          1481: 
        !          1482:        srp = &u.u_segl[SISTACK];
        !          1483:        return base>=srp->sr_base-srp->sr_size && base+count<=srp->sr_base;
        !          1484: }
        !          1485: 
        !          1486: int
        !          1487: acctext(base, count)
        !          1488: unsigned       base;
        !          1489: {
        !          1490:        SR *srp;
        !          1491: 
        !          1492:        srp = &u.u_segl[SISTEXT];
        !          1493:        return base>=srp->sr_base && base+count <= srp->sr_base+srp->sr_size;
        !          1494: }
        !          1495: 
        !          1496: printhex(v, max)
        !          1497: unsigned long v;
        !          1498: {
        !          1499:        register int i;
        !          1500: 
        !          1501:        for (i = max-1; i>=0; --i) 
        !          1502:                putchar(digtab[(v >> (i*4)) & 0xF]);
        !          1503: }
        !          1504: 
        !          1505: /* Read a 16 byte number from the CMOS.  */
        !          1506: unsigned int
        !          1507: read16_cmos(addr)
        !          1508: unsigned int addr;
        !          1509: {
        !          1510:         unsigned char read_cmos();
        !          1511:        
        !          1512:        return((read_cmos(addr+1)<<8) + read_cmos(addr));
        !          1513: } /* read16_cmos() */
        !          1514: 
        !          1515: int
        !          1516: c_grow(sp, new_bytes)
        !          1517: SEG *sp;
        !          1518: int new_bytes;
        !          1519: {
        !          1520:        register int    i;
        !          1521:        register cseg_t *pp;
        !          1522:        int             new_clicks, pno, nsize, old_clicks;
        !          1523:        SR              *srp;
        !          1524: 
        !          1525:        T_PIGGY(0x8000000, printf("c_grow(sp: %x, new: %x)", sp, new_bytes));
        !          1526: 
        !          1527:        new_clicks = btoc(new_bytes);
        !          1528:        old_clicks = btoc(sp->s_size);
        !          1529: 
        !          1530:        if (new_clicks == old_clicks) {
        !          1531:                goto ok_c_grow;
        !          1532:        }
        !          1533: 
        !          1534:        if (new_clicks < old_clicks) {
        !          1535:                printf("%s:can't contract segment\n",u.u_comm);
        !          1536:                goto no_c_grow;
        !          1537:        }
        !          1538: 
        !          1539:        if (new_clicks - old_clicks > allocno()) {
        !          1540:                goto no_c_grow;
        !          1541:        }
        !          1542: 
        !          1543:        T_PIGGY(0x8000000, printf("nc: %x, oc: %x,",new_clicks,old_clicks));
        !          1544: 
        !          1545:        /*
        !          1546:         * Allocate a new descriptor vector if necessary.
        !          1547:         * pp is the element corresponding to the virtual address
        !          1548:         * "0"(sr_base)
        !          1549:         */
        !          1550:        pp = sp->s_vmem;
        !          1551:        nsize = areasize(new_clicks);
        !          1552:        if (nsize != areasize(old_clicks)
        !          1553:          && !(pp = (cseg_t*)arealloc(new_clicks))) {
        !          1554:                T_PIGGY(0x8000000,
        !          1555:                         printf("Can not allocate new descriptor."));
        !          1556:                goto no_c_grow;
        !          1557:        }
        !          1558: 
        !          1559:        T_PIGGY(0x8000000, printf("new pp: %x", pp));
        !          1560: 
        !          1561:        if (0 != (srp = loaded(sp->s_vmem))) {
        !          1562:                T_PIGGY(0x8000000, printf("unloading srp: %x, ", srp));
        !          1563:                unload(srp);
        !          1564:                srp->sr_segp = 0;
        !          1565:        }
        !          1566: 
        !          1567:        /*
        !          1568:         * Allocate new descriptors.
        !          1569:         */
        !          1570:        T_PIGGY(0x8000000, printf("new desc: ["));
        !          1571:        for (i = old_clicks; i < new_clicks; i++) {
        !          1572:                pno = *--sysmem.pfree;
        !          1573:                pp[i] = clickseg(pno) | SEG_RW;
        !          1574:                T_PIGGY(0x8000000, printf("%x, ", pp[i]));
        !          1575:        }
        !          1576:        T_PIGGY(0x8000000, printf("]"));
        !          1577: 
        !          1578:        /*
        !          1579:         * Copy unchanged descriptors and free old vector if necessary.
        !          1580:         */
        !          1581:        if (pp != sp->s_vmem) {
        !          1582:                T_PIGGY(0x8000000, printf("old desc: ["));
        !          1583:                for (i = 0; i < old_clicks; i++) {
        !          1584:                        pp[i] = sp->s_vmem[i];
        !          1585:                        T_PIGGY(0x8000000, printf("%x, ", pp[i]));
        !          1586:                }
        !          1587:                T_PIGGY(0x8000000, printf("]"));
        !          1588:                areafree((BLOCKLIST*)sp->s_vmem, old_clicks);
        !          1589:        }
        !          1590: 
        !          1591:        sp->s_vmem = pp;
        !          1592: 
        !          1593:        /*
        !          1594:         * clear the added clicks
        !          1595:         *
        !          1596:         * MAPIO macro - convert array of page descriptors, offset
        !          1597:         *   into system global address.
        !          1598:         */
        !          1599:        T_PIGGY(0x8000000, printf("dmaclear(%x, %x, 0)", 
        !          1600:                                ctob(new_clicks - old_clicks),
        !          1601:                                MAPIO(sp->s_vmem, ctob(old_clicks))
        !          1602:                           )); /* T_PIGGY() */
        !          1603: 
        !          1604:        dmaclear (ctob (new_clicks - old_clicks),
        !          1605:                  MAPIO(sp->s_vmem, ctob(old_clicks)));
        !          1606: 
        !          1607: ok_c_grow:
        !          1608:        return 0;
        !          1609: 
        !          1610: no_c_grow:
        !          1611:        return -1;
        !          1612: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.