Annotation of tme/machine/sun3/sun3-mmu.c, revision 1.1

1.1     ! root        1: /* $Id: sun3-mmu.c,v 1.3 2005/04/30 15:09:44 fredette Exp $ */
        !             2: 
        !             3: /* machine/sun3/sun3-mmu.c - implementation of Sun 3 MMU emulation: */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2003, 2004 Matt Fredette
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. All advertising materials mentioning features or use of this software
        !            18:  *    must display the following acknowledgement:
        !            19:  *      This product includes software developed by Matt Fredette.
        !            20:  * 4. The name of the author may not be used to endorse or promote products
        !            21:  *    derived from this software without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            33:  * POSSIBILITY OF SUCH DAMAGE.
        !            34:  */
        !            35: 
        !            36: #include <tme/common.h>
        !            37: _TME_RCSID("$Id: sun3-mmu.c,v 1.3 2005/04/30 15:09:44 fredette Exp $");
        !            38: 
        !            39: /* includes: */
        !            40: #include "sun3-impl.h"
        !            41: 
        !            42: /* macros: */
        !            43: 
        !            44: /* real PTE entry bits: */
        !            45: #define TME_SUN3_PTE_VALID             (0x80000000)
        !            46: #define TME_SUN3_PTE_WRITE             (0x40000000)
        !            47: #define TME_SUN3_PTE_SYSTEM            (0x20000000)
        !            48: #define TME_SUN3_PTE_NC                        (0x10000000)
        !            49: #define TME_SUN3_PTE_PGTYPE            (0x0C000000)
        !            50: #define TME_SUN3_PTE_REF               (0x02000000)
        !            51: #define TME_SUN3_PTE_MOD               (0x01000000)
        !            52: #define TME_SUN3_PTE_PGFRAME           (0x0007FFFF)
        !            53: 
        !            54: /* real PTE page types: */
        !            55: #define TME_SUN3_PGTYPE_OBMEM          (0)
        !            56: #define TME_SUN3_PGTYPE_OBIO           (1)
        !            57: #define TME_SUN3_PGTYPE_VME_D16                (2)
        !            58: #define TME_SUN3_PGTYPE_VME_D32                (3)
        !            59: 
        !            60: /* real bus error register bits: */
        !            61: #define TME_SUN3_BUSERR_WATCHDOG       TME_BIT(0)      /* watchdog or user reset */
        !            62:                                        /* bit 1 unused */
        !            63: #define TME_SUN3_BUSERR_FPAENERR       TME_BIT(2)      /* FPA enable error */
        !            64: #define TME_SUN3_BUSERR_FPABERR                TME_BIT(3)      /* FPA bus error */
        !            65: #define TME_SUN3_BUSERR_VMEBUSERR      TME_BIT(4)      /* VME bus error */
        !            66: #define TME_SUN3_BUSERR_TIMEOUT                TME_BIT(5)      /* timeout error */
        !            67: #define TME_SUN3_BUSERR_PROTERR                TME_BIT(6)      /* MMU protection error */
        !            68: #define TME_SUN3_BUSERR_INVALID                TME_BIT(7)      /* MMU page invalid error */
        !            69: 
        !            70: /* this logs a bus error: */
        !            71: #ifndef TME_NO_LOG
        !            72: static void
        !            73: _tme_sun3_bus_fault_log(struct tme_sun3 *sun3, struct tme_bus_tlb *tlb, struct tme_bus_cycle *cycle)
        !            74: {
        !            75:   tme_bus_addr_t virtual_address;
        !            76:   struct tme_sun_mmu_pte pte;
        !            77:   tme_uint32_t pte_sun3;
        !            78:   const char *bus_name;
        !            79:   tme_bus_addr_t physical_address;
        !            80:   int rc;
        !            81: 
        !            82:   /* this silences gcc -Wuninitialized: */
        !            83:   bus_name = NULL;
        !            84: 
        !            85:   /* recover the virtual address used: */
        !            86:   virtual_address = cycle->tme_bus_cycle_address - tlb->tme_bus_tlb_addr_offset;
        !            87: 
        !            88:   /* look up the PTE involved: */
        !            89:   rc = tme_sun_mmu_pte_get(sun3->tme_sun3_mmu, 
        !            90:                           sun3->tme_sun3_context,
        !            91:                           virtual_address,
        !            92:                           &pte);
        !            93:   assert(rc == TME_OK);
        !            94:   pte_sun3 = pte.tme_sun_mmu_pte_raw;
        !            95:     
        !            96:   /* form the physical address and get the bus name: */
        !            97:   physical_address = (((pte_sun3 & TME_SUN3_PTE_PGFRAME) << TME_SUN3_PAGE_SIZE_LOG2)
        !            98:                      | (virtual_address & (TME_SUN3_PAGE_SIZE - 1)));
        !            99:   switch (TME_FIELD_MASK_EXTRACTU(pte_sun3, TME_SUN3_PTE_PGTYPE)) {
        !           100:   case TME_SUN3_PGTYPE_OBMEM: bus_name = "obmem"; break;
        !           101:   case TME_SUN3_PGTYPE_OBIO: bus_name = "obio"; break;
        !           102:   case TME_SUN3_PGTYPE_VME_D16:
        !           103:     bus_name = "VME_D16";
        !           104:     break;
        !           105:   case TME_SUN3_PGTYPE_VME_D32:
        !           106:     bus_name = "VME_D32";
        !           107:     break;
        !           108:   }
        !           109: 
        !           110:   /* log this bus error: */
        !           111:   tme_log(TME_SUN3_LOG_HANDLE(sun3), 1000, TME_OK,
        !           112:          (TME_SUN3_LOG_HANDLE(sun3), 
        !           113:           _("%s bus error, physical 0x%08x, virtual 0x%08x, buserr = 0x%02x"),
        !           114:           bus_name,
        !           115:           physical_address,
        !           116:           virtual_address,
        !           117:           sun3->tme_sun3_buserr));
        !           118: }
        !           119: #else  /* TME_NO_LOG */
        !           120: #define _tme_sun3_bus_fault_log(a, b, c) do { } while (/* CONSTCOND */ 0)
        !           121: #endif /* TME_NO_LOG */
        !           122: 
        !           123: /* our general bus fault handler: */
        !           124: static int
        !           125: _tme_sun3_bus_fault_handler(struct tme_sun3 *sun3, 
        !           126:                            struct tme_bus_tlb *tlb,
        !           127:                            struct tme_bus_cycle *cycle,
        !           128:                            int rc)
        !           129: {
        !           130:   tme_uint8_t buserr;
        !           131: 
        !           132:   /* dispatch on our fault code: */
        !           133:   switch (rc) {
        !           134: 
        !           135:     /* bus address nonexistent: */
        !           136:   case ENOENT:
        !           137:     buserr = TME_SUN3_BUSERR_TIMEOUT;
        !           138:     break;
        !           139: 
        !           140:     /* anything else is just a fault: */
        !           141:   default:
        !           142:     buserr = 0;
        !           143:     break;
        !           144:   }
        !           145: 
        !           146:   /* set the bus error register: */
        !           147:   sun3->tme_sun3_buserr = buserr;
        !           148: 
        !           149:   /* log the fault: */
        !           150:   _tme_sun3_bus_fault_log(sun3, tlb, cycle);
        !           151: 
        !           152:   return (rc);
        !           153: }
        !           154: 
        !           155: /* our obio bus fault handler: */
        !           156: static int
        !           157: _tme_sun3_obio_fault_handler(void *_sun3, struct tme_bus_tlb *tlb, struct tme_bus_cycle *cycle, int rc)
        !           158: {
        !           159: 
        !           160:   /* call the common bus fault handler: */
        !           161:   return (_tme_sun3_bus_fault_handler((struct tme_sun3 *) _sun3, tlb, cycle, rc));
        !           162: }
        !           163: 
        !           164: /* our obmem bus fault handler: */
        !           165: static int
        !           166: _tme_sun3_obmem_fault_handler(void *_sun3, struct tme_bus_tlb *tlb, struct tme_bus_cycle *cycle, int rc)
        !           167: {
        !           168: 
        !           169:   /* call the common bus fault handler: */
        !           170:   return (_tme_sun3_bus_fault_handler((struct tme_sun3 *) _sun3, tlb, cycle, rc));
        !           171: }
        !           172: 
        !           173: /* our VMEbus fault handler: */
        !           174: static int
        !           175: _tme_sun3_vmebus_fault_handler(void *_sun3, struct tme_bus_tlb *tlb, struct tme_bus_cycle *cycle, int rc)
        !           176: {
        !           177:   struct tme_sun3 *sun3;
        !           178: 
        !           179:   /* recover our sun3: */
        !           180:   sun3 = (struct tme_sun3 *) _sun3;
        !           181: 
        !           182:   /* call the common bus fault handler: */
        !           183:   rc = _tme_sun3_bus_fault_handler((struct tme_sun3 *) _sun3, tlb, cycle, rc);
        !           184: 
        !           185:   /* this bus fault happened on the VMEbus: */
        !           186:   sun3->tme_sun3_buserr |= TME_SUN3_BUSERR_VMEBUSERR;
        !           187: 
        !           188:   /* return the fault: */
        !           189:   return (rc);
        !           190: }
        !           191: 
        !           192: /* our dummy cycle handler: */
        !           193: static int
        !           194: _tme_sun3_cycle_dummy(void *_sun3, struct tme_bus_cycle *cycle)
        !           195: {
        !           196:   return (TME_OK);
        !           197: }
        !           198: 
        !           199: /* our page-invalid cycle handler: */
        !           200: static int
        !           201: _tme_sun3_mmu_invalid(void *_sun3, struct tme_bus_cycle *cycle)
        !           202: {
        !           203:   struct tme_sun3 *sun3;
        !           204: 
        !           205:   /* recover our sun3: */
        !           206:   sun3 = (struct tme_sun3 *) _sun3;
        !           207: 
        !           208:   /* log this bus error: */
        !           209:   tme_log(TME_SUN3_LOG_HANDLE(sun3), 1000, TME_OK,
        !           210:          (TME_SUN3_LOG_HANDLE(sun3), 
        !           211:           _("page invalid bus error")));
        !           212: 
        !           213:   /* set the bus error register: */
        !           214:   sun3->tme_sun3_buserr = TME_SUN3_BUSERR_INVALID;
        !           215: 
        !           216:   /* return the fault: */
        !           217:   return (EFAULT);
        !           218: }
        !           219: 
        !           220: /* our protection error cycle handler: */
        !           221: static int
        !           222: _tme_sun3_mmu_proterr(void *_sun3, struct tme_bus_cycle *cycle)
        !           223: {
        !           224:   struct tme_sun3 *sun3;
        !           225: 
        !           226:   /* recover our sun3: */
        !           227:   sun3 = (struct tme_sun3 *) _sun3;
        !           228: 
        !           229:   /* log this bus error: */
        !           230:   tme_log(TME_SUN3_LOG_HANDLE(sun3), 1000, TME_OK,
        !           231:          (TME_SUN3_LOG_HANDLE(sun3),
        !           232:           _("page protection bus error")));
        !           233: 
        !           234:   /* set the bus error register: */
        !           235:   sun3->tme_sun3_buserr = TME_SUN3_BUSERR_PROTERR;
        !           236: 
        !           237:   /* return the fault: */
        !           238:   return (EFAULT);
        !           239: }
        !           240: 
        !           241: /* our SDVMA disabled cycle handler: */
        !           242: static int
        !           243: _tme_sun3_sdvma_disabled(void *_sun3, struct tme_bus_cycle *cycle)
        !           244: {
        !           245:   return (ENOENT);
        !           246: }
        !           247: 
        !           248: /* our internal TLB filler: */
        !           249: static int
        !           250: _tme_sun3_tlb_fill(struct tme_sun3 *sun3, struct tme_bus_tlb *tlb, tme_uint8_t context,
        !           251:                   unsigned int *_function_code_or_codes, tme_uint32_t address, unsigned int cycles)
        !           252: {
        !           253:   unsigned int function_code;
        !           254:   unsigned int function_code_sp;
        !           255:   unsigned short access;
        !           256:   struct tme_bus_tlb tlb_bus;
        !           257:   unsigned int tlb_i;
        !           258:   unsigned short tlb_flags;
        !           259: 
        !           260:   /* recover the function code: */
        !           261:   function_code = *_function_code_or_codes;
        !           262: 
        !           263:   /* this must be a user or supervisor program or data function code: */
        !           264:   assert(function_code == TME_M68K_FC_UD
        !           265:         || function_code == TME_M68K_FC_UP
        !           266:         || function_code == TME_M68K_FC_SD
        !           267:         || function_code == TME_M68K_FC_SP);
        !           268: 
        !           269:   /* assume that if this TLB entry ends up good for the supervisor,
        !           270:      it's good for the supervisor program function code: */
        !           271:   function_code_sp = TME_BIT(TME_M68K_FC_SP);
        !           272: 
        !           273:   /* if we're in the boot state: */
        !           274:   if (__tme_predict_false((sun3->tme_sun3_enable & TME_SUN3_ENA_NOTBOOT) == 0)) {
        !           275: 
        !           276:     /* if this is the supervisor program function code: */
        !           277:     if (function_code == TME_M68K_FC_SP) {
        !           278: 
        !           279:       /* fill this TLB entry directly from the obmem bus: */
        !           280:       (*sun3->tme_sun3_obmem->tme_bus_tlb_fill)
        !           281:        (sun3->tme_sun3_obmem,
        !           282:         tlb,
        !           283:         TME_SUN3_PROM_BASE | (address & (TME_SUN3_PROM_SIZE - 1)),
        !           284:         cycles);
        !           285:        
        !           286:       /* create the mapping TLB entry: */
        !           287:       TME_ATOMIC_WRITE(tme_bus_addr_t,
        !           288:                       tlb_bus.tme_bus_tlb_addr_first,
        !           289:                       address & (((tme_bus_addr_t) 0) - TME_SUN3_PROM_SIZE));
        !           290:       TME_ATOMIC_WRITE(tme_bus_addr_t,
        !           291:                       tlb_bus.tme_bus_tlb_addr_last,
        !           292:                       address | (TME_SUN3_PROM_SIZE - 1));
        !           293:       tlb_bus.tme_bus_tlb_cycles_ok
        !           294:        = TME_BUS_CYCLE_READ;
        !           295:   
        !           296:       /* map the filled TLB entry: */
        !           297:       tme_bus_tlb_map(tlb, TME_SUN3_PROM_BASE | (address & (TME_SUN3_PROM_SIZE - 1)), &tlb_bus, address);
        !           298:        
        !           299:       /* this is good for the supervisor program function code only: */
        !           300:       *_function_code_or_codes = TME_BIT(TME_M68K_FC_SP);
        !           301: 
        !           302:       /* done: */
        !           303:       return(TME_OK);
        !           304:     }
        !           305: 
        !           306:     /* update the head pointer for the active boot state TLB entry
        !           307:        list: */
        !           308:     tlb_i = sun3->tme_sun3_boot_state_tlb_next
        !           309:       = ((sun3->tme_sun3_boot_state_tlb_next
        !           310:          + 1)
        !           311:         & (TME_SUN3_BOOT_STATE_TLBS - 1));
        !           312: 
        !           313:     /* if the new head pointer already has a TLB entry, and it doesn't
        !           314:        happen to be the same as this TLB entry, invalidate it: */
        !           315:     if (sun3->tme_sun3_boot_state_tlbs[tlb_i] != NULL
        !           316:        && (sun3->tme_sun3_boot_state_tlbs[tlb_i]
        !           317:            != TME_ATOMIC_READ(struct tme_bus_tlb *, 
        !           318:                               tlb->tme_bus_tlb_backing_reservation))) {
        !           319:       tme_bus_tlb_invalidate(sun3->tme_sun3_boot_state_tlbs[tlb_i]);
        !           320:     }
        !           321: 
        !           322:     /* add this TLB entry to the active list: */
        !           323:     sun3->tme_sun3_boot_state_tlbs[tlb_i] =
        !           324:       TME_ATOMIC_READ(struct tme_bus_tlb *, 
        !           325:                      tlb->tme_bus_tlb_backing_reservation);
        !           326: 
        !           327:     /* if this TLB entry ends up good for the supervisor, it's not
        !           328:        good for the supervisor program function code: */
        !           329:     function_code_sp = 0;
        !           330:   }
        !           331: 
        !           332:   /* fill this TLB entry from the MMU: */
        !           333:   access
        !           334:     = ((cycles & TME_BUS_CYCLE_WRITE)
        !           335:        ? TME_SUN_MMU_PTE_PROT_RW
        !           336:        : TME_SUN_MMU_PTE_PROT_RO);
        !           337:   access
        !           338:     = ((function_code == TME_M68K_FC_UD
        !           339:        || function_code == TME_M68K_FC_UP)
        !           340:        ? TME_SUN_MMU_PTE_PROT_USER(access)
        !           341:        : TME_SUN_MMU_PTE_PROT_SYSTEM(access));
        !           342:   tlb_flags = tme_sun_mmu_tlb_fill(sun3->tme_sun3_mmu,
        !           343:                                   tlb,
        !           344:                                   context,
        !           345:                                   address,
        !           346:                                   access);
        !           347: 
        !           348:   /* this TLB entry is good for the program and data function codes
        !           349:      for the user and/or the supervisor: */
        !           350:   *_function_code_or_codes 
        !           351:     = (((tlb_flags & TME_SUN_MMU_TLB_USER)
        !           352:        ? (TME_BIT(TME_M68K_FC_UD)
        !           353:           | TME_BIT(TME_M68K_FC_UP))
        !           354:        : 0)
        !           355:        | ((tlb_flags & TME_SUN_MMU_TLB_SYSTEM)
        !           356:          ? (TME_BIT(TME_M68K_FC_SD)
        !           357:             | function_code_sp)
        !           358:          : 0));
        !           359: 
        !           360:   /* if the memory error register is being tested: */
        !           361:   if (__tme_predict_false(sun3->tme_sun3_memerr_csr & TME_SUN3_MEMERR_PAR_TEST)) {
        !           362: 
        !           363:     /* this must be a supervisor data access: */
        !           364:     if (function_code != TME_M68K_FC_SD) {
        !           365:       abort();
        !           366:     }
        !           367:     
        !           368:     /* if this TLB's bus cycle handler isn't for the memory error
        !           369:        register itself: */
        !           370:     if (tlb->tme_bus_tlb_cycle != _tme_sun3_memerr_cycle_handler) {
        !           371: 
        !           372:       /* there must be no other TLB entry already involved in the test: */
        !           373:       if (sun3->tme_sun3_memerr_tlb != NULL) {
        !           374:        abort();
        !           375:       }
        !           376: 
        !           377:       /* remember this TLB entry pointer, and its original bus cycle
        !           378:         handler: */
        !           379:       sun3->tme_sun3_memerr_tlb = TME_ATOMIC_READ(struct tme_bus_tlb *, 
        !           380:                                                  tlb->tme_bus_tlb_backing_reservation);
        !           381:       assert (sun3->tme_sun3_memerr_tlb != NULL);
        !           382:       sun3->tme_sun3_memerr_cycle_private = tlb->tme_bus_tlb_cycle_private;
        !           383:       sun3->tme_sun3_memerr_cycle = tlb->tme_bus_tlb_cycle;
        !           384:       
        !           385:       /* this TLB entry does not allow fast reading and writing, and
        !           386:         it now uses the memory error test cycle handler: */
        !           387:       tlb->tme_bus_tlb_emulator_off_read = TME_EMULATOR_OFF_UNDEF;
        !           388:       tlb->tme_bus_tlb_emulator_off_write = TME_EMULATOR_OFF_UNDEF;
        !           389:       tlb->tme_bus_tlb_rwlock = NULL;
        !           390:       tlb->tme_bus_tlb_cycle_private = sun3;
        !           391:       tlb->tme_bus_tlb_cycle = _tme_sun3_memerr_test_cycle_handler;
        !           392: 
        !           393:       /* reset other memory error test values: */
        !           394:       sun3->tme_sun3_memerr_pending_csr = 0;
        !           395:     }
        !           396:   }
        !           397: 
        !           398:   return (TME_OK);
        !           399: }
        !           400: 
        !           401: /* our m68k TLB filler: */
        !           402: int
        !           403: _tme_sun3_m68k_tlb_fill(struct tme_m68k_bus_connection *conn_m68k, struct tme_m68k_tlb *tlb_m68k,
        !           404:                        unsigned int function_code, tme_uint32_t address, unsigned int cycles)
        !           405: {
        !           406:   struct tme_sun3 *sun3;
        !           407:   struct tme_bus_tlb *tlb;
        !           408:   struct tme_bus_tlb tlb_bus;
        !           409: 
        !           410:   /* recover our sun3: */
        !           411:   sun3 = (struct tme_sun3 *) conn_m68k->tme_m68k_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private;
        !           412: 
        !           413:   /* get the generic bus TLB: */
        !           414:   tlb = &tlb_m68k->tme_m68k_tlb_bus_tlb;
        !           415: 
        !           416:   /* if this is function code three: */
        !           417:   if (function_code == TME_M68K_FC_3) {
        !           418: 
        !           419:     /* if this address is within the UART bypass: */
        !           420:     if (address >= TME_SUN3_CONTROL_UART_BYPASS
        !           421:        && address < TME_SUN3_CONTROL_UART_BYPASS + TME_SUN_Z8530_SIZE) {
        !           422: 
        !           423:       /* fill this TLB entry directly from the obio bus: */
        !           424:       (*sun3->tme_sun3_obio->tme_bus_tlb_fill)
        !           425:        (sun3->tme_sun3_obio,
        !           426:         tlb,
        !           427:         (address - TME_SUN3_CONTROL_UART_BYPASS) + TME_SUN3_OBIO_ZS0,
        !           428:         cycles);
        !           429: 
        !           430:       /* create the mapping TLB entry: */
        !           431:       TME_ATOMIC_WRITE(tme_bus_addr_t,
        !           432:                       tlb_bus.tme_bus_tlb_addr_first,
        !           433:                       TME_SUN3_CONTROL_UART_BYPASS);
        !           434:       TME_ATOMIC_WRITE(tme_bus_addr_t,
        !           435:                       tlb_bus.tme_bus_tlb_addr_last,
        !           436:                       TME_SUN3_CONTROL_UART_BYPASS + TME_SUN_Z8530_SIZE - 1);
        !           437:       tlb_bus.tme_bus_tlb_cycles_ok
        !           438:        = (TME_BUS_CYCLE_READ
        !           439:           | TME_BUS_CYCLE_WRITE);
        !           440:   
        !           441:       /* map the filled TLB entry: */
        !           442:       tme_bus_tlb_map(tlb, (address - TME_SUN3_CONTROL_UART_BYPASS) + TME_SUN3_OBIO_ZS0, &tlb_bus, address);
        !           443:     }
        !           444: 
        !           445:     /* otherwise, this is something else in control space: */
        !           446:     else {
        !           447: 
        !           448:       /* initialize the TLB entry: */
        !           449:       tme_bus_tlb_initialize(tlb);
        !           450: 
        !           451:       /* we cover the entire address space up to the UART bypass: */
        !           452:       TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, 0);
        !           453:       TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, TME_SUN3_CONTROL_UART_BYPASS - 1);
        !           454: 
        !           455:       /* we allow reading and writing: */
        !           456:       tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
        !           457: 
        !           458:       /* our bus cycle handler: */
        !           459:       tlb->tme_bus_tlb_cycle_private = sun3;
        !           460:       tlb->tme_bus_tlb_cycle = _tme_sun3_control_cycle_handler;
        !           461:     }
        !           462: 
        !           463:     /* this is good for function code three only: */
        !           464:     tlb_m68k->tme_m68k_tlb_function_codes_mask = TME_BIT(TME_M68K_FC_3);
        !           465: 
        !           466:     /* done: */
        !           467:     return (TME_OK);
        !           468:   }
        !           469: 
        !           470:   /* this is a normal function code: */
        !           471:   tlb_m68k->tme_m68k_tlb_function_codes_mask = function_code;
        !           472:   return (_tme_sun3_tlb_fill(sun3, tlb, sun3->tme_sun3_context,
        !           473:                             &tlb_m68k->tme_m68k_tlb_function_codes_mask,
        !           474:                             address, cycles));
        !           475: }
        !           476: 
        !           477: /* our bus TLB filler: */
        !           478: int
        !           479: _tme_sun3_bus_tlb_fill(struct tme_bus_connection *conn_bus, struct tme_bus_tlb *tlb,
        !           480:                       tme_uint32_t address, unsigned int cycles)
        !           481: {
        !           482:   struct tme_sun3 *sun3;
        !           483:   struct tme_sun3_bus_connection *conn_sun3;
        !           484:   tme_uint32_t base, size;
        !           485:   struct tme_bus_tlb tlb_bus;
        !           486:   tme_uint8_t context;
        !           487:   unsigned int function_code_or_codes;
        !           488:   unsigned int tlb_i;
        !           489: 
        !           490:   /* recover our sun3: */
        !           491:   sun3 = (struct tme_sun3 *) conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
        !           492: 
        !           493:   /* recover the sun3 internal mainbus connection: */
        !           494:   conn_sun3 = (struct tme_sun3_bus_connection *) conn_bus;
        !           495: 
        !           496:   /* dispatch on the internal connection.  the bus address into a DVMA
        !           497:      address, context, and function code, except for the memory error
        !           498:      register and interrupt register connections, which are handled
        !           499:      specially: */
        !           500:   switch (conn_sun3->tme_sun3_bus_connection_which) {
        !           501: 
        !           502:   case TME_SUN3_CONN_OBIO_MASTER:
        !           503:     base = 0x0f000000;
        !           504:     size = TME_SUN3_DVMA_SIZE_OBIO;
        !           505:     context = sun3->tme_sun3_context;
        !           506:     function_code_or_codes = TME_M68K_FC_SD;
        !           507:     break;
        !           508: 
        !           509:   case TME_SUN3_CONN_BUS_VME:
        !           510:     base = 0x0ff00000;
        !           511:     size = TME_SUN3_DVMA_SIZE_VME;
        !           512:     context = sun3->tme_sun3_context;
        !           513:     function_code_or_codes = TME_M68K_FC_SD;
        !           514:     break;
        !           515: 
        !           516:   case TME_SUN3_CONN_REG_MEMERR:
        !           517:   case TME_SUN3_CONN_REG_INTREG:
        !           518:     
        !           519:     /* initialize the TLB entry: */
        !           520:     tme_bus_tlb_initialize(tlb);
        !           521: 
        !           522:     /* the address range: */
        !           523:     TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, 0);
        !           524:     TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, 
        !           525:                     ((conn_sun3->tme_sun3_bus_connection_which == TME_SUN3_CONN_REG_MEMERR
        !           526:                       ? TME_SUN3_MEMERR_SIZ_REG
        !           527:                       : sizeof(sun3->tme_sun3_ints))
        !           528:                      - 1));
        !           529: 
        !           530:     /* we allow reading and writing: */
        !           531:     tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
        !           532: 
        !           533:     /* our bus cycle handler: */
        !           534:     tlb->tme_bus_tlb_cycle_private = sun3;
        !           535:     tlb->tme_bus_tlb_cycle
        !           536:       = (conn_sun3->tme_sun3_bus_connection_which == TME_SUN3_CONN_REG_MEMERR
        !           537:         ? _tme_sun3_memerr_cycle_handler
        !           538:         : _tme_sun3_intreg_cycle_handler);
        !           539: 
        !           540:     /* done: */
        !           541:     return (TME_OK);
        !           542: 
        !           543:   default: abort();
        !           544:   }
        !           545: 
        !           546:   /* update the head pointer for the active SDVMA TLB entry list: */
        !           547:   tlb_i = sun3->tme_sun3_sdvma_tlb_next
        !           548:     = ((sun3->tme_sun3_sdvma_tlb_next
        !           549:        + 1)
        !           550:        & (TME_SUN3_SDVMA_TLBS - 1));
        !           551: 
        !           552:   /* if the new head pointer already has a TLB entry, and it doesn't
        !           553:      happen to be the same as this TLB entry, invalidate it: */
        !           554:   if (sun3->tme_sun3_sdvma_tlbs[tlb_i] != NULL
        !           555:       && (sun3->tme_sun3_sdvma_tlbs[tlb_i]
        !           556:          != TME_ATOMIC_READ(struct tme_bus_tlb *, 
        !           557:                             tlb->tme_bus_tlb_backing_reservation))) {
        !           558:     tme_bus_tlb_invalidate(sun3->tme_sun3_sdvma_tlbs[tlb_i]);
        !           559:   }
        !           560: 
        !           561:   /* add this TLB entry to the active list: */
        !           562:   sun3->tme_sun3_sdvma_tlbs[tlb_i] =
        !           563:     TME_ATOMIC_READ(struct tme_bus_tlb *, 
        !           564:                    tlb->tme_bus_tlb_backing_reservation);
        !           565: 
        !           566:   /* if system DVMA is disabled: */
        !           567:   if (__tme_predict_false(!(sun3->tme_sun3_enable & TME_SUN3_ENA_SDVMA))) {
        !           568: 
        !           569:     /* return a TLB entry that will generate a VME bus fault: */
        !           570:     tme_bus_tlb_initialize(tlb);
        !           571:     TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, 0);
        !           572:     TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, size - 1);
        !           573:     tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
        !           574:     tlb->tme_bus_tlb_cycle_private = sun3;
        !           575:     tlb->tme_bus_tlb_cycle = _tme_sun3_sdvma_disabled;
        !           576:     TME_BUS_TLB_FAULT_HANDLER(tlb, _tme_sun3_vmebus_fault_handler, sun3);
        !           577:     return (TME_OK);
        !           578:   }
        !           579: 
        !           580:   assert (!(address & base)
        !           581:          && (address < size));
        !           582: 
        !           583:   /* fill this TLB entry from the MMU: */
        !           584:   _tme_sun3_tlb_fill(sun3, tlb, context,
        !           585:                     &function_code_or_codes,
        !           586:                     address | base, cycles);
        !           587: 
        !           588:   /* create the mapping TLB entry.  we do this even if base == 0,
        !           589:      because the TLB entry as currently filled may cover more address
        !           590:      space than DVMA space on this machine is supposed to cover: */
        !           591:   TME_ATOMIC_WRITE(tme_bus_addr_t,
        !           592:                   tlb_bus.tme_bus_tlb_addr_first,
        !           593:                   0);
        !           594:   TME_ATOMIC_WRITE(tme_bus_addr_t,
        !           595:                   tlb_bus.tme_bus_tlb_addr_last,
        !           596:                   size - 1);
        !           597:   tlb_bus.tme_bus_tlb_cycles_ok
        !           598:     = (TME_BUS_CYCLE_READ
        !           599:        | TME_BUS_CYCLE_WRITE);
        !           600:   
        !           601:   /* map the filled TLB entry: */
        !           602:   tme_bus_tlb_map(tlb, address | base, &tlb_bus, address);
        !           603: 
        !           604:   /* XXX FIXME - what happens to a bus cycle to an unmapped DVMA
        !           605:      address?  is the answer different for obio masters and the VME
        !           606:      bus?  for now, these bus cycles get ignored in both cases: */
        !           607:   if (tlb->tme_bus_tlb_cycle == _tme_sun3_mmu_invalid) {
        !           608:     tlb->tme_bus_tlb_cycle = _tme_sun3_cycle_dummy;
        !           609:   }
        !           610: 
        !           611:   return (TME_OK);
        !           612: }
        !           613: 
        !           614: /* our post-MMU TLB filler: */
        !           615: static int
        !           616: _tme_sun3_tlb_fill_mmu(void *_sun3, struct tme_bus_tlb *tlb, 
        !           617:                       struct tme_sun_mmu_pte *pte,
        !           618:                       tme_uint32_t *_address,
        !           619:                       unsigned int cycles)
        !           620: {
        !           621:   struct tme_sun3 *sun3;
        !           622:   tme_uint32_t address;
        !           623:   unsigned int bus_type;
        !           624:   struct tme_bus_connection *conn_bus;
        !           625:   tme_bus_fault_handler bus_fault_handler;
        !           626:   int rc;
        !           627: 
        !           628:   /* recover our sun3: */
        !           629:   sun3 = (struct tme_sun3 *) _sun3;
        !           630: 
        !           631:   /* get the physical page frame and bus type: */
        !           632:   address = ((pte->tme_sun_mmu_pte_raw & TME_SUN3_PTE_PGFRAME) << TME_SUN3_PAGE_SIZE_LOG2);
        !           633:   bus_type = TME_FIELD_MASK_EXTRACTU(pte->tme_sun_mmu_pte_raw, TME_SUN3_PTE_PGTYPE);
        !           634: 
        !           635:   /* any mapping of any address in a PROM-sized region starting at
        !           636:      0x100000 in obio space means the PROM.  the virtual page frame is
        !           637:      actually used to form the physical address: */
        !           638:   if ((address & -TME_SUN3_PROM_SIZE) == TME_SUN3_OBIO_PROM
        !           639:       && bus_type == TME_SUN3_PGTYPE_OBIO) {
        !           640:     address = TME_SUN3_PROM_BASE | (*_address & ((TME_SUN3_PROM_SIZE - 1) & ~(TME_SUN3_PAGE_SIZE - 1)));
        !           641:     bus_type = TME_SUN3_PGTYPE_OBMEM;
        !           642:   }
        !           643: 
        !           644: #if 1 /* NetBSD/sun3 cgtwo bug */
        !           645:   /* XXX FIXME - this hack works around a bug in NetBSD/sun3, present
        !           646:      since revision 1.49 of src/sys/arch/sun3/conf/GENERIC (when the
        !           647:      sun3x port was merged into the sun3 port).  in this revision, the
        !           648:      declaration for cgtwo0 changed:
        !           649: 
        !           650: -cgtwo0 at vmes0 addr 0xff400000 level 4 vect 0xA8
        !           651: +cgtwo0 at vme2 addr 0x400000 ipl 4 vect 0xA8
        !           652: 
        !           653:      because the cg2mmap() function in src/sys/arch/sun3/dev/cg2.c
        !           654:      doesn't add the 0xff000000 mask to the configured physical
        !           655:      address (needed because the cgtwo is an A24 device), when Xsun
        !           656:      mmap()s the cgtwo it gets a mapping of physical address 0x400000
        !           657:      in VME space instead of the correct 0xff400000.  the sparc cgtwo
        !           658:      driver gets this right.
        !           659: 
        !           660:      so for now we force all accesses to VME D16 address 0x400000 to
        !           661:      0xff400000.  once the NetBSD bug has been fixed this code should
        !           662:      be removed: */
        !           663:   if (bus_type == TME_SUN3_PGTYPE_VME_D16
        !           664:       && ((address & 0xff400000) == 0x400000)) {
        !           665:     address |= 0xff000000;
        !           666:   }
        !           667: #endif /* NetBSD/sun3 cgtwo bug */
        !           668: 
        !           669:   /* add in the page offset to finish the address: */
        !           670:   address |= *_address & (TME_SUN3_PAGE_SIZE - 1);
        !           671:   *_address = address;
        !           672: 
        !           673:   /* if this is obio: */
        !           674:   if (bus_type == TME_SUN3_PGTYPE_OBIO) {
        !           675:     conn_bus = sun3->tme_sun3_obio;
        !           676:     bus_fault_handler = _tme_sun3_obio_fault_handler;
        !           677:   }
        !           678:   
        !           679:   /* if this is obmem: */
        !           680:   else if (bus_type == TME_SUN3_PGTYPE_OBMEM) {
        !           681:     conn_bus = sun3->tme_sun3_obmem;
        !           682:     bus_fault_handler = _tme_sun3_obmem_fault_handler;
        !           683:   }
        !           684: 
        !           685:   /* if this is the VME bus: */
        !           686:   else {
        !           687:     assert(bus_type == TME_SUN3_PGTYPE_VME_D16
        !           688:           || bus_type == TME_SUN3_PGTYPE_VME_D32);
        !           689:     conn_bus = sun3->tme_sun3_vmebus;
        !           690:     bus_fault_handler = _tme_sun3_vmebus_fault_handler;
        !           691:   }
        !           692: 
        !           693:   /* call the bus TLB filler: */
        !           694:   rc = ((*conn_bus->tme_bus_tlb_fill)
        !           695:        (conn_bus, tlb, address, cycles));
        !           696: 
        !           697:   /* if the bus TLB filler succeeded, add our bus fault handler: */
        !           698:   if (rc == TME_OK) {
        !           699:     TME_BUS_TLB_FAULT_HANDLER(tlb, bus_fault_handler, sun3);
        !           700:   }
        !           701: 
        !           702:   return (rc);
        !           703: }
        !           704: 
        !           705: /* this gets a PTE from the MMU: */
        !           706: int
        !           707: _tme_sun3_mmu_pte_get(struct tme_sun3 *sun3, tme_uint32_t address, tme_uint32_t *_pte_sun3)
        !           708: {
        !           709:   struct tme_sun_mmu_pte pte;
        !           710:   tme_uint32_t pte_sun3;
        !           711:   unsigned int pte_flags;
        !           712:   int rc;
        !           713: 
        !           714:   /* get the PTE from the MMU: */
        !           715:   rc = tme_sun_mmu_pte_get(sun3->tme_sun3_mmu, 
        !           716:                           sun3->tme_sun3_context,
        !           717:                           address,
        !           718:                           &pte);
        !           719:   assert(rc == TME_OK);
        !           720:     
        !           721:   /* form the Sun-3 PTE: */
        !           722:   pte_sun3 = pte.tme_sun_mmu_pte_raw;
        !           723:   pte_flags = pte.tme_sun_mmu_pte_flags;
        !           724:   if (pte_flags & TME_SUN_MMU_PTE_REF) {
        !           725:     pte_sun3 |= TME_SUN3_PTE_REF;
        !           726:   }
        !           727:   if (pte_flags & TME_SUN_MMU_PTE_MOD) {
        !           728:     pte_sun3 |= TME_SUN3_PTE_MOD;
        !           729:   }
        !           730: 
        !           731:   /* done: */
        !           732:   *_pte_sun3 = pte_sun3;
        !           733:   tme_log(TME_SUN3_LOG_HANDLE(sun3), 1000, TME_OK,
        !           734:          (TME_SUN3_LOG_HANDLE(sun3),
        !           735:           _("pte_get: PGMAP[%d:0x%08x] -> 0x%08x"), 
        !           736:           sun3->tme_sun3_context,
        !           737:           address,
        !           738:           pte_sun3));
        !           739:   return (TME_OK);
        !           740: }
        !           741: 
        !           742: /* this sets a PTE into the MMU: */
        !           743: int
        !           744: _tme_sun3_mmu_pte_set(struct tme_sun3 *sun3, tme_uint32_t address, tme_uint32_t pte_sun3)
        !           745: {
        !           746:   struct tme_sun_mmu_pte pte;
        !           747:   unsigned int pte_flags;
        !           748: #ifndef TME_NO_LOG
        !           749:   const char *bus_name;
        !           750:   tme_bus_addr_t physical_address;
        !           751:       
        !           752:   /* this silences gcc -Wuninitialized: */
        !           753:   bus_name = NULL;
        !           754: 
        !           755:   /* log this setting: */
        !           756:   physical_address = ((pte_sun3 & TME_SUN3_PTE_PGFRAME) << TME_SUN3_PAGE_SIZE_LOG2);
        !           757:   switch (TME_FIELD_MASK_EXTRACTU(pte_sun3, TME_SUN3_PTE_PGTYPE)) {
        !           758:   case TME_SUN3_PGTYPE_OBMEM: bus_name = "obmem"; break;
        !           759:   case TME_SUN3_PGTYPE_OBIO: bus_name = "obio"; break;
        !           760:   case TME_SUN3_PGTYPE_VME_D16: bus_name = "VME_D16"; break;
        !           761:   case TME_SUN3_PGTYPE_VME_D32: bus_name = "VME_D32"; break;
        !           762:   }
        !           763:   tme_log(TME_SUN3_LOG_HANDLE(sun3), 1000, TME_OK,
        !           764:          (TME_SUN3_LOG_HANDLE(sun3),
        !           765:           _("pte_set: PGMAP[%d:0x%08x] <- 0x%08x (%s 0x%08x)"), 
        !           766:           sun3->tme_sun3_context,
        !           767:           address,
        !           768:           pte_sun3,
        !           769:           bus_name,
        !           770:           physical_address));
        !           771: #endif /* !TME_NO_LOG */
        !           772: 
        !           773:   pte.tme_sun_mmu_pte_raw = pte_sun3;
        !           774:       
        !           775:   pte_flags = (pte_sun3 & TME_SUN3_PTE_WRITE
        !           776:               ? TME_SUN_MMU_PTE_PROT_RW
        !           777:               : TME_SUN_MMU_PTE_PROT_RO);
        !           778:   pte_flags = (TME_SUN_MMU_PTE_PROT_SYSTEM(pte_flags)
        !           779:               | TME_SUN_MMU_PTE_PROT_USER(pte_sun3 & TME_SUN3_PTE_SYSTEM
        !           780:                                           ? TME_SUN_MMU_PTE_PROT_ERROR
        !           781:                                           : pte_flags));
        !           782:   if (pte_sun3 & TME_SUN3_PTE_MOD) {
        !           783:     pte_flags |= TME_SUN_MMU_PTE_MOD;
        !           784:   }
        !           785:   if (pte_sun3 & TME_SUN3_PTE_REF) {
        !           786:     pte_flags |= TME_SUN_MMU_PTE_REF;
        !           787:   }
        !           788:   if (pte_sun3 & TME_SUN3_PTE_VALID) {
        !           789:     pte_flags |= TME_SUN_MMU_PTE_VALID;
        !           790:   }
        !           791:   pte.tme_sun_mmu_pte_flags = pte_flags;
        !           792:   
        !           793:   return (tme_sun_mmu_pte_set(sun3->tme_sun3_mmu, 
        !           794:                              sun3->tme_sun3_context,
        !           795:                              address,
        !           796:                              &pte));
        !           797: }
        !           798: 
        !           799: /* this is called when the SDVMA bit is changed in the enable register: */
        !           800: void
        !           801: _tme_sun3_mmu_sdvma_change(struct tme_sun3 *sun3)
        !           802: {
        !           803:   unsigned int tlb_i;
        !           804: 
        !           805:   /* whenever the SDVMA bit changes, we have to invalidate all SDVMA
        !           806:      TLB entries: */
        !           807:   for (tlb_i = 0; tlb_i < TME_SUN3_SDVMA_TLBS; tlb_i++) {
        !           808:     if (sun3->tme_sun3_sdvma_tlbs[tlb_i] != NULL) {
        !           809:       tme_bus_tlb_invalidate(sun3->tme_sun3_sdvma_tlbs[tlb_i]);
        !           810:       sun3->tme_sun3_sdvma_tlbs[tlb_i] = NULL;
        !           811:     }
        !           812:   }
        !           813: }
        !           814: 
        !           815: /* this is called when the context register is set: */
        !           816: void
        !           817: _tme_sun3_mmu_context_set(struct tme_sun3 *sun3)
        !           818: {
        !           819:   unsigned int tlb_i;
        !           820: 
        !           821:   /* every TLB set has nine contexts' worth of TLB entries.  context
        !           822:      zero is used for the "boot state", and the remaining contexts
        !           823:      correspond to the eight possible MMU contexts.  
        !           824: 
        !           825:      context zero is used for the boot state because at TLB set
        !           826:      allocation time, TLB sets are initialized pointing to the context
        !           827:      zero TLBs (by tme_sun_mmu_tlb_set_allocate), and TLBs must be
        !           828:      initialized to the boot state TLBs.
        !           829: 
        !           830:      in the boot state, TLB fills for supervisor program references
        !           831:      bypass the MMU and are filled to reference the PROM, and data
        !           832:      fills are filled as normal using the current context.  since context
        !           833:      register changes can happen while in the boot state, but we only
        !           834:      have one boot state context in the TLB sets, we have to track 
        !           835:      the data TLBs we fill in the boot state.
        !           836: 
        !           837:      we don't bother to track the supervisor program TLB fills, since
        !           838:      they never change.  */
        !           839: 
        !           840:   /* in the not-boot (i.e., normal, state): */
        !           841:   if (__tme_predict_true(sun3->tme_sun3_enable & TME_SUN3_ENA_NOTBOOT)) {
        !           842: 
        !           843:     tme_log(TME_SUN3_LOG_HANDLE(sun3), 1000, TME_OK,
        !           844:            (TME_SUN3_LOG_HANDLE(sun3),
        !           845:             _("context now #%d"),
        !           846:             sun3->tme_sun3_context));
        !           847: 
        !           848:     /* update all TLB sets to reflect the context change: */
        !           849:     tme_sun_mmu_tlbs_context_set(sun3->tme_sun3_mmu, sun3->tme_sun3_context + 1);
        !           850:   }
        !           851: 
        !           852:   /* in the boot state: */
        !           853:   else {
        !           854: 
        !           855:     tme_log(TME_SUN3_LOG_HANDLE(sun3), 1000, TME_OK,
        !           856:            (TME_SUN3_LOG_HANDLE(sun3),
        !           857:             _("context now #%d (boot state)"),
        !           858:             sun3->tme_sun3_context));
        !           859: 
        !           860:     /* update all TLB sets to reflect the pseudo-context change: */
        !           861:     tme_sun_mmu_tlbs_context_set(sun3->tme_sun3_mmu, 0);
        !           862: 
        !           863:     /* invalidate all of the boot-state data TLBs: */
        !           864:     for (tlb_i = 0; tlb_i < TME_SUN3_BOOT_STATE_TLBS; tlb_i++) {
        !           865:       if (sun3->tme_sun3_boot_state_tlbs[tlb_i] != NULL) {
        !           866:        tme_bus_tlb_invalidate(sun3->tme_sun3_boot_state_tlbs[tlb_i]);
        !           867:        sun3->tme_sun3_boot_state_tlbs[tlb_i] = NULL;
        !           868:       }
        !           869:     }
        !           870:   }
        !           871: }
        !           872: 
        !           873: /* this allocates a new TLB set: */
        !           874: int
        !           875: _tme_sun3_mmu_tlb_set_allocate(struct tme_bus_connection *conn_bus_asker,
        !           876:                               unsigned int count, unsigned int sizeof_one, 
        !           877:                               TME_ATOMIC_POINTER_TYPE(struct tme_bus_tlb *) _tlbs)
        !           878: {
        !           879:   struct tme_sun3 *sun3;
        !           880:   int rc;
        !           881: 
        !           882:   /* recover our sun3: */
        !           883:   sun3 = (struct tme_sun3 *) conn_bus_asker->tme_bus_connection.tme_connection_element->tme_element_private;
        !           884: 
        !           885:   /* get the MMU to allocate the TLB set: */
        !           886:   rc = tme_sun_mmu_tlb_set_allocate(sun3->tme_sun3_mmu, count, sizeof_one, _tlbs);
        !           887: 
        !           888:   return (rc);
        !           889: }
        !           890: 
        !           891: /* this creates a Sun-3 MMU: */
        !           892: void
        !           893: _tme_sun3_mmu_new(struct tme_sun3 *sun3)
        !           894: {
        !           895:   struct tme_sun_mmu_info mmu_info;
        !           896: 
        !           897:   mmu_info.tme_sun_mmu_info_element = sun3->tme_sun3_element;
        !           898:   mmu_info.tme_sun_mmu_info_address_bits = 28;
        !           899:   mmu_info.tme_sun_mmu_info_pgoffset_bits = TME_SUN3_PAGE_SIZE_LOG2;
        !           900:   mmu_info.tme_sun_mmu_info_pteindex_bits = 4;
        !           901:   mmu_info.tme_sun_mmu_info_contexts = 1 + 8; /* internal context zero is for the boot state */
        !           902:   mmu_info.tme_sun_mmu_info_pmegs = TME_SUN3_PMEGS;
        !           903:   mmu_info.tme_sun_mmu_info_seginv = 255;
        !           904:   mmu_info.tme_sun_mmu_info_tlb_fill_private = sun3;
        !           905:   mmu_info.tme_sun_mmu_info_tlb_fill = _tme_sun3_tlb_fill_mmu;
        !           906:   mmu_info.tme_sun_mmu_info_proterr_private = sun3;
        !           907:   mmu_info.tme_sun_mmu_info_proterr = _tme_sun3_mmu_proterr;
        !           908:   mmu_info.tme_sun_mmu_info_invalid_private = sun3;
        !           909:   mmu_info.tme_sun_mmu_info_invalid = _tme_sun3_mmu_invalid;
        !           910:   sun3->tme_sun3_mmu = tme_sun_mmu_new(&mmu_info);
        !           911: }

unix.superglobalmegacorp.com

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