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

unix.superglobalmegacorp.com

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