Annotation of XNU/osfmk/ppc/bat_init.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: #include <mach/std_types.h>
                     23: #include <ppc/proc_reg.h>
                     24: #include <ppc/boot.h>
                     25: #include <ppc/mem.h>
                     26: 
                     27: #ifdef XXX_LOADER
                     28: unsigned int kernel_seg_regs[] = {
                     29:   KERNEL_SEG_REG0_VALUE,
                     30:   KERNEL_SEG_REG1_VALUE,
                     31:   SEG_REG_INVALID, /* 2 */
                     32:   SEG_REG_INVALID, /* 3 */
                     33:   SEG_REG_INVALID, /* 4 */
                     34:   KERNEL_SEG_REG5_VALUE, /* 5 - I/O segment */
                     35:   SEG_REG_INVALID, /* 6 */
                     36:   SEG_REG_INVALID, /* 7 */
                     37:   KERNEL_SEG_REG8_VALUE, /* 8-F are possible IO space */
                     38:   KERNEL_SEG_REG9_VALUE,
                     39:   KERNEL_SEG_REG10_VALUE,
                     40:   KERNEL_SEG_REG11_VALUE,
                     41:   KERNEL_SEG_REG12_VALUE,
                     42:   KERNEL_SEG_REG13_VALUE,
                     43:   KERNEL_SEG_REG14_VALUE, /* 14 - A/V video */
                     44:   KERNEL_SEG_REG15_VALUE /* 15 - NuBus etc */
                     45: };
                     46: #else
                     47: extern unsigned int kernel_seg_regs[];
                     48: #endif
                     49: 
                     50: // The sophisticated BAT manager
                     51: 
                     52: unsigned int mappedSegments = 0;
                     53: unsigned int availableBATs = 0xE;              // BAT0 used, 1-3 available
                     54: 
                     55: vm_offset_t
                     56: PEResidentAddress( vm_offset_t address, vm_size_t length )
                     57: {
                     58:     if( mappedSegments & (1 << (15 & (address >> 28))))
                     59:        return( address);
                     60:     else
                     61:        return( 0);
                     62: }
                     63: 
                     64: vm_offset_t
                     65: PEMapSegment( vm_offset_t address, vm_size_t length )
                     66: {
                     67:     vm_offset_t                retAddress;
                     68:     bat_t              bat;
                     69:     int                        batNum;
                     70: 
                     71:     retAddress = PEResidentAddress( address, length );
                     72:     if( retAddress)
                     73:        return( retAddress);
                     74: 
                     75:     if( length < (256 * 1024))
                     76:        return( 0);
                     77:     if( availableBATs == 0)
                     78:        return( 0);
                     79: 
                     80:     for( batNum = 0;
                     81:         (0 == (availableBATs & (1 << batNum)));
                     82:         batNum++);
                     83: 
                     84:     bat.upper.word          = address & 0xf0000000;
                     85:     bat.lower.word          = bat.upper.word;
                     86: 
                     87:     bat.upper.bits.bl    = 0x7ff;      /* size = 256M */
                     88:     bat.upper.bits.vs    = 1;
                     89:     bat.upper.bits.vp    = 0;          /* user disabled */
                     90: 
                     91:     bat.lower.bits.wimg  = PTE_WIMG_IO;
                     92:     bat.lower.bits.pp    = 2;          /* read/write access */
                     93:     
                     94:     // Update the shadow bats.
                     95:     shadow_BAT.DBATs[batNum].upper = bat.upper.word;
                     96:     shadow_BAT.DBATs[batNum].lower = bat.lower.word;
                     97:     
                     98:     sync();isync();
                     99:     switch( batNum) {                  // !%$@!! mtdbat needs literal
                    100:        case 0:
                    101:            mtdbatu( 0, BAT_INVALID);   /* invalidate old mapping */
                    102:            mtdbatl( 0, bat.lower.word);
                    103:            mtdbatu( 0, bat.upper.word);
                    104:            break;
                    105:        case 1:
                    106:            mtdbatu( 1, BAT_INVALID);
                    107:            mtdbatl( 1, bat.lower.word);
                    108:            mtdbatu( 1, bat.upper.word);
                    109:            break;
                    110:        case 2:
                    111:            mtdbatu( 2, BAT_INVALID);
                    112:            mtdbatl( 2, bat.lower.word);
                    113:            mtdbatu( 2, bat.upper.word);
                    114:            break;
                    115:        case 3:
                    116:            mtdbatu( 3, BAT_INVALID);
                    117:            mtdbatl( 3, bat.lower.word);
                    118:            mtdbatu( 3, bat.upper.word);
                    119:            break;
                    120:     }
                    121:     sync();isync();
                    122: 
                    123:     availableBATs &= ~(1 << batNum);
                    124:     mappedSegments |= (1 << (15 & (address >> 28)));
                    125: 
                    126:     return( address);
                    127: }
                    128: 
                    129: void initialize_bats(boot_args *args)
                    130: {
                    131:        int i;
                    132: 
                    133:        /* Give ourselves the virtual map that we would like */
                    134:        bat_t                 bat;
                    135: 
                    136:        /* Make sure that the BATs map what we expect. Note
                    137:         * that we assume BAT0 maps kernel text & data.
                    138:         *
                    139:         * Except, oops, none of the BATs have ever been set.
                    140:         * Developer worked only by fluke.
                    141:         */
                    142: 
                    143:        bat.upper.word       = 0;
                    144:        bat.upper.bits.bepi  = 0x0;     /* start at logical addr 0M */
                    145:        /*
                    146:         * We should be smarter here about picking an
                    147:         * amount to map
                    148:         */
                    149:        bat.upper.bits.bl    = 0x7ff;   /* size = 256M */
                    150:        bat.upper.bits.vs    = 1;
                    151:        bat.upper.bits.vp    = 0;
                    152: 
                    153:        bat.lower.word       = 0;
                    154:        bat.lower.bits.brpn  = 0x0;     /* start at physical addr 0 */
                    155:        bat.lower.bits.wimg  = PTE_WIMG_DEFAULT;
                    156:        bat.lower.bits.pp    = 2;       /* read/write access */
                    157: 
                    158:        /* Mustn't cause any data traffic here,
                    159:         * we're modifying our data BAT register!
                    160:         */
                    161: 
                    162:        sync();
                    163:        mtdbatu(0, BAT_INVALID);        /* invalidate old mapping */
                    164:        isync();
                    165:        mtdbatl(0, bat.lower.word);
                    166:        isync();
                    167:        mtdbatu(0, bat.upper.word);     /* update with new mapping */
                    168:        isync();
                    169:        mtibatl(0, bat.lower.word);
                    170:        isync();
                    171:        mtibatu(0, bat.upper.word);     /* update with new mapping */
                    172:        isync();
                    173: 
                    174:        sync();isync();
                    175:        mtdbatu(1,BAT_INVALID); mtdbatl(1,BAT_INVALID);
                    176:        mtibatu(1,BAT_INVALID); mtibatl(1,BAT_INVALID);
                    177:        mtdbatu(2,BAT_INVALID); mtdbatl(2,BAT_INVALID);
                    178:        mtibatu(2,BAT_INVALID); mtibatl(2,BAT_INVALID);
                    179:        mtdbatu(3,BAT_INVALID); mtdbatl(3,BAT_INVALID);
                    180:        mtibatu(3,BAT_INVALID); mtibatl(3,BAT_INVALID);
                    181:        sync();isync();
                    182: 
                    183:        PEMapSegment( 0xf0000000, 0x10000000);
                    184:        if( args->Video.v_baseAddr)
                    185:          PEMapSegment( args->Video.v_baseAddr, 0x10000000);
                    186: 
                    187:        /* Set up segment registers as VM through space 0 */
                    188:        isync();
                    189:        for (i=0; i<=15; i++) {
                    190:          mtsrin(KERNEL_SEG_REG0_VALUE | i, i * 0x10000000);
                    191:        }
                    192:        isync();
                    193: }
                    194: 
                    195: /*
                    196:  * Adjust the size of the region mapped by a BAT
                    197:  * to to be just large enough to include the specified
                    198:  * offset, and return the offset of the new end of the region.
                    199:  * Note that both 'offsets' are really *lengths*, i.e. the
                    200:  * offset of the end of the mapped region from the beginning.
                    201:  * Either the instruction or data BATs (or both) can be specified.
                    202:  * If the new length is greater than the size mappable by a BAT,
                    203:  * then that value is just returned and no changes are made.
                    204:  */
                    205: vm_offset_t
                    206: adjust_bat_limit(
                    207:     vm_offset_t                new_minimum,
                    208:     int                        batn,
                    209:     boolean_t          ibat,
                    210:     boolean_t          dbat
                    211: )
                    212: {
                    213:     vm_offset_t                new_limit;
                    214: 
                    215:     if (new_minimum <= 256*1024*1024) {
                    216:        unsigned int    bl = 0;
                    217: 
                    218:        new_limit = 128*1024;
                    219:        while (new_limit < new_minimum) {
                    220:            new_limit *= 2;
                    221:            bl = (bl << 1) | 1;
                    222:        }
                    223: 
                    224:        {
                    225:            batu_t      batu;
                    226: 
                    227:            if (dbat) switch (batn) {
                    228: 
                    229:            case 0:
                    230:                mfdbatu(batu, 0 );
                    231:                batu.bits.bl = bl;
                    232: 
                    233:                sync(); isync();
                    234:                mtdbatu( 0, batu);
                    235:                sync(); isync();
                    236: 
                    237:                break;
                    238: 
                    239:            case 1:
                    240:                mfdbatu(batu, 1 );
                    241:                batu.bits.bl = bl;
                    242: 
                    243:                sync(); isync();
                    244:                mtdbatu( 1, batu);
                    245:                sync(); isync();
                    246: 
                    247:                break;
                    248: 
                    249:            case 2:
                    250:                mfdbatu(batu, 2 );
                    251:                batu.bits.bl = bl;
                    252: 
                    253:                sync(); isync();
                    254:                mtdbatu( 2, batu);
                    255:                sync(); isync();
                    256: 
                    257:                break;
                    258: 
                    259:            case 3:
                    260:                mfdbatu(batu, 3 );
                    261:                batu.bits.bl = bl;
                    262: 
                    263:                sync(); isync();
                    264:                mtdbatu( 3, batu);
                    265:                sync(); isync();
                    266: 
                    267:                break;
                    268:            }
                    269: 
                    270:            if (ibat) switch (batn) {
                    271: 
                    272:            case 0:
                    273:                mfibatu(batu, 0 );
                    274:                batu.bits.bl = bl;
                    275: 
                    276:                sync(); isync();
                    277:                mtibatu( 0, batu);
                    278:                sync(); isync();
                    279: 
                    280:                break;
                    281: 
                    282:            case 1:
                    283:                mfibatu(batu, 1 );
                    284:                batu.bits.bl = bl;
                    285: 
                    286:                sync(); isync();
                    287:                mtibatu( 1, batu);
                    288:                sync(); isync();
                    289: 
                    290:                break;
                    291: 
                    292:            case 2:
                    293:                mfibatu(batu, 2 );
                    294:                batu.bits.bl = bl;
                    295: 
                    296:                sync(); isync();
                    297:                mtibatu( 2, batu);
                    298:                sync(); isync();
                    299: 
                    300:                break;
                    301: 
                    302:            case 3:
                    303:                mfibatu(batu, 3 );
                    304:                batu.bits.bl = bl;
                    305: 
                    306:                sync(); isync();
                    307:                mtibatu( 3, batu);
                    308:                sync(); isync();
                    309: 
                    310:                break;
                    311:            }
                    312:        }
                    313:     }
                    314:     else
                    315:        new_limit = new_minimum;
                    316: 
                    317:     return (new_limit);
                    318: }

unix.superglobalmegacorp.com

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