Annotation of coherent/b/kernel/i386/mmu.c, revision 1.1.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.