Annotation of tme/machine/sun/sun-si.c, revision 1.1

1.1     ! root        1: /* $Id: sun-si.c,v 1.1 2005/02/17 12:19:17 fredette Exp $ */
        !             2: 
        !             3: /* machine/sun/sun-si.c - Sun ncr5380-based SCSI implementation: */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 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: sun-si.c,v 1.1 2005/02/17 12:19:17 fredette Exp $");
        !            38: 
        !            39: /* includes: */
        !            40: #include <tme/element.h>
        !            41: #undef TME_BUS_VERSION
        !            42: #define TME_BUS_VERSION TME_X_VERSION(0, 0)
        !            43: #include <tme/generic/bus.h>
        !            44: 
        !            45: /* macros: */
        !            46: 
        !            47: /* controller types: */
        !            48: #define TME_SUN_SI_TYPE_NULL                   (0)
        !            49: #define TME_SUN_SI_TYPE_VME                    (1)
        !            50: #define TME_SUN_SI_TYPE_ONBOARD                        (2)
        !            51: #define TME_SUN_SI_TYPE_3E                     (3)
        !            52: #define TME_SUN_SI_TYPE_COBRA                  (4)
        !            53: 
        !            54: /* register offsets and sizes: */
        !            55: 
        !            56: /* all controllers: */
        !            57: #define TME_SUN_SI_REG_NCR5380                 (0)
        !            58: #define TME_SUN_SI_SIZ_NCR5380                 (8)
        !            59: 
        !            60: /* all controllers except onboard, and the Sun 3/E limits these to 16 bits: */
        !            61: #define TME_SUN_SI_REG_DMA_ADDRESS             (8)
        !            62: #define TME_SUN_SI_REG_DMA_COUNT               (12)
        !            63: 
        !            64: /* Cobra controller only: */
        !            65: #define TME_SUN_SI_REG_COBRA_FIFO_COUNT                (16)
        !            66: #define TME_SUN_SI_REG_COBRA_CSR               (20)
        !            67: #define TME_SIN_SI_REG_COBRA_BPR               (24)
        !            68: 
        !            69: /* onboard controller only: */
        !            70: #define TME_SUN_SI_REG_ONBOARD_UDC_DATA                (16)
        !            71: #define TME_SUN_SI_REG_ONBOARD_UDC_ADDRESS     (18)
        !            72: #define TME_SUN_SI_REG_ONBOARD_FIFO_DATA       (20)
        !            73: 
        !            74: /* onboard and VME controllers only: */
        !            75: #define TME_SUN_SI_REG_FIFO_COUNT_L            (22)
        !            76: 
        !            77: /* all controllers except for the Cobra: */
        !            78: #define TME_SUN_SI_REG_CSR                     (24)
        !            79: 
        !            80: /* 3/E controller only: */
        !            81: #define TME_SUN_SI_REG_3E_IVEC                 (27)
        !            82: 
        !            83: /* VME controller only: */
        !            84: #define TME_SUN_SI_REG_VME_BPR_H               (26)
        !            85: #define TME_SUN_SI_REG_VME_BPR_L               (28)
        !            86: #define TME_SUN_SI_REG_VME_IV_AM               (30)
        !            87: #define TME_SUN_SI_REG_VME_FIFO_COUNT_H                (32)
        !            88: 
        !            89: #define TME_SUN_SI_SIZ_REGS                    (34)
        !            90: 
        !            91: /* the 3/E includes a 64KB DMA buffer: */
        !            92: #define TME_SUN_SI_3E_SIZ_DMA                  (0x10000)
        !            93: 
        !            94: /* the bits in the Control/Status Register: */
        !            95: #define TME_SUN_SI_CSR_ONBOARD_DMA_ACTIVE      TME_BIT(15)     /* onboard controller only */
        !            96: #define TME_SUN_SI_CSR_DMA_CONFLICT            TME_BIT(14)     /* all controllers except for the 3/E */
        !            97: #define TME_SUN_SI_CSR_DMA_BUS_ERROR           TME_BIT(13)     /* all controllers except for the 3/E */
        !            98: #define TME_SUN_SI_CSR_VME_MODIFIED            TME_BIT(12)     /* VME controller only */
        !            99: #define TME_SUN_SI_CSR_FIFO_FULL               TME_BIT(11)     /* all controllers except for the 3/E (and Cobra?) */
        !           100: #define TME_SUN_SI_CSR_FIFO_EMPTY              TME_BIT(10)     /* all controllers except for the 3/E (and Cobra?) */
        !           101: #define TME_SUN_SI_CSR_INT_NCR5380             TME_BIT(9)      /* all controllers */
        !           102: #define TME_SUN_SI_CSR_INT_DMA                 TME_BIT(8)      /* all controllers except for the 3/E (and Cobra?) */
        !           103: #define TME_SUN_SI_CSR_VME_LOB_MASK            (0x00c0)        /* VME controller only */
        !           104: #define TME_SUN_SI_CSR_VME_BPCON               TME_BIT(5)      /* VME controller only */
        !           105: #define TME_SUN_SI_CSR_DMA_ENABLE              TME_BIT(4)      /* all controllers except for onboard */
        !           106: #define TME_SUN_SI_CSR_DMA_SEND                        TME_BIT(3)      /* all controllers */
        !           107: #define TME_SUN_SI_CSR_INT_ENABLE              TME_BIT(2)      /* all controllers */
        !           108: #define TME_SUN_SI_CSR_RESET_FIFO              TME_BIT(1)      /* all controllers except for the 3/E */
        !           109: #define TME_SUN_SI_CSR_3E_VCC                  TME_BIT(1)      /* 3/E controller only */
        !           110: #define TME_SUN_SI_CSR_RESET_CONTROLLER                TME_BIT(0)      /* all controllers */
        !           111: 
        !           112: /* the read-only bits in the Control/Status Register: */
        !           113: /* all controllers except for the 3/E: */
        !           114: #define TME_SUN_SI_CSR_READONLY                (~(TME_SUN_SI_CSR_VME_BPCON             \
        !           115:                                           | TME_SUN_SI_CSR_DMA_ENABLE          \
        !           116:                                           | TME_SUN_SI_CSR_DMA_SEND            \
        !           117:                                           | TME_SUN_SI_CSR_INT_ENABLE          \
        !           118:                                           | TME_SUN_SI_CSR_RESET_FIFO          \
        !           119:                                           | TME_SUN_SI_CSR_RESET_CONTROLLER))
        !           120: /* 3/E controller only: */
        !           121: #define TME_SUN_SI_CSR_3E_READONLY     (TME_SUN_SI_CSR_READONLY | TME_SUN_SI_CSR_3E_VCC)
        !           122: 
        !           123: /* these get and put a 32-bit register: */
        !           124: #define TME_SUN_SI_REG32_GET(sun_si, reg)      \
        !           125:   tme_betoh_u32(*((tme_uint32_t *) &(sun_si)->tme_sun_si_regs[(reg)]))
        !           126: #define TME_SUN_SI_REG32_PUT(sun_si, reg, val) \
        !           127:   (*((tme_uint32_t *) &(sun_si)->tme_sun_si_regs[(reg)]) = tme_htobe_u32(val))
        !           128: 
        !           129: /* these get and put a 16-bit register: */
        !           130: #define TME_SUN_SI_REG16_GET(sun_si, reg)      \
        !           131:   tme_betoh_u16(*((tme_uint16_t *) &(sun_si)->tme_sun_si_regs[(reg)]))
        !           132: #define TME_SUN_SI_REG16_PUT(sun_si, reg, val) \
        !           133:   (*((tme_uint16_t *) &(sun_si)->tme_sun_si_regs[(reg)]) = tme_htobe_u16(val))
        !           134: 
        !           135: /* these get and put the CSR register: */
        !           136: #define TME_SUN_SI_CSR_GET(sun_si)                             \
        !           137:   ((sun_si)->tme_sun_si_type == TME_SUN_SI_TYPE_COBRA          \
        !           138:    ? TME_SUN_SI_REG32_GET(sun_si, TME_SUN_SI_REG_COBRA_CSR)    \
        !           139:    : TME_SUN_SI_REG16_GET(sun_si, TME_SUN_SI_REG_CSR))
        !           140: #define TME_SUN_SI_CSR_PUT(sun_si, csr)                                \
        !           141:   ((sun_si)->tme_sun_si_type == TME_SUN_SI_TYPE_COBRA          \
        !           142:    ? TME_SUN_SI_REG32_PUT(sun_si, TME_SUN_SI_REG_COBRA_CSR, csr)\
        !           143:    : TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_CSR, csr))
        !           144: 
        !           145: /* the callout flags: */
        !           146: #define TME_SUN_SI_CALLOUT_CHECK       (0)
        !           147: #define TME_SUN_SI_CALLOUT_RUNNING     TME_BIT(0)
        !           148: #define TME_SUN_SI_CALLOUTS_MASK       (-2)
        !           149: #define  TME_SUN_SI_CALLOUT_SIGNALS    TME_BIT(1)
        !           150: #define         TME_SUN_SI_CALLOUT_INT TME_BIT(2)
        !           151: 
        !           152: #if 1
        !           153: #define TME_SUN_SI_DEBUG
        !           154: #endif
        !           155: 
        !           156: /* structures: */
        !           157: 
        !           158: /* the controller: */
        !           159: struct tme_sun_si {
        !           160: 
        !           161:   /* backpointer to our element: */
        !           162:   struct tme_element *tme_sun_si_element;
        !           163: 
        !           164:   /* the mutex protecting the card: */
        !           165:   tme_mutex_t tme_sun_si_mutex;
        !           166: 
        !           167:   /* the rwlock protecting the card: */
        !           168:   tme_rwlock_t tme_sun_si_rwlock;
        !           169: 
        !           170:   /* the bus connection for the card's registers: */
        !           171:   struct tme_bus_connection *tme_sun_si_conn_regs;
        !           172: 
        !           173:   /* the bus connection for the card's memory: */
        !           174:   struct tme_bus_connection *tme_sun_si_conn_memory;
        !           175: 
        !           176:   /* the bus connection for the card's ncr5380: */
        !           177:   struct tme_bus_connection *tme_sun_si_conn_ncr5380;
        !           178: 
        !           179:   /* the type of the si: */
        !           180:   tme_uint32_t tme_sun_si_type;
        !           181: 
        !           182:   /* the callout flags: */
        !           183:   int tme_sun_si_callout_flags;
        !           184: 
        !           185:   /* if our interrupt line is currently asserted: */
        !           186:   int tme_sun_si_last_int_asserted;
        !           187: 
        !           188:   /* it's easiest to just model the board registers as a chunk of memory: */
        !           189:   tme_uint8_t tme_sun_si_regs[TME_SUN_SI_SIZ_REGS];
        !           190: 
        !           191:   /* any outstanding NCR 5380 TLB entry: */
        !           192:   struct tme_bus_tlb *tme_sun_si_ncr5380_tlb;
        !           193: 
        !           194:   /* the 3/E DMA buffer: */
        !           195:   tme_uint8_t *tme_sun_si_3e_dma;
        !           196: 
        !           197:   /* the CSR last called out to the NCR 5380: */
        !           198:   tme_uint32_t tme_sun_si_csr_ncr5380;
        !           199: };
        !           200: 
        !           201: /* a sun_si internal bus connection: */
        !           202: struct tme_sun_si_connection {
        !           203: 
        !           204:   /* the external bus connection: */
        !           205:   struct tme_bus_connection tme_sun_si_connection;
        !           206: 
        !           207:   /* this is nonzero if a TME_CONNECTION_BUS_GENERIC chip connection
        !           208:      is for the registers: */
        !           209:   unsigned int tme_sun_si_connection_regs;
        !           210: };
        !           211: 
        !           212: #ifdef TME_SUN_SI_DEBUG
        !           213: void
        !           214: _tme_sun_si_reg_put(struct tme_sun_si *sun_si,
        !           215:                    int reg,
        !           216:                    tme_uint32_t val_new,
        !           217:                    unsigned int val_size)
        !           218: {
        !           219:   const char *reg_name;
        !           220:   tme_uint32_t val_old;
        !           221: 
        !           222:   if (val_size == sizeof(tme_uint32_t)) {
        !           223:     val_old = TME_SUN_SI_REG32_GET(sun_si, reg);
        !           224:     TME_SUN_SI_REG32_PUT(sun_si, reg, val_new);
        !           225:   }
        !           226:   else {
        !           227:     assert (val_size == sizeof(tme_uint16_t));
        !           228:     val_old = TME_SUN_SI_REG16_GET(sun_si, reg);
        !           229:     TME_SUN_SI_REG16_PUT(sun_si, reg, val_new);
        !           230:     val_new &= 0xffff;
        !           231:   }
        !           232: 
        !           233:   if (val_new == val_old) {
        !           234:     return;
        !           235:   }
        !           236: 
        !           237:   /* try to get the name of this register: */
        !           238:   reg_name = NULL;
        !           239: #define _TME_SUN_SI_REG_IS(_reg, type) (reg_name == NULL && reg == (_reg) && val_size == sizeof(type))
        !           240:   if (sun_si->tme_sun_si_type != TME_SUN_SI_TYPE_ONBOARD
        !           241:       && _TME_SUN_SI_REG_IS(TME_SUN_SI_REG_DMA_ADDRESS, tme_uint32_t)) {
        !           242:     reg_name = "dma_address";
        !           243:   }
        !           244:   if (sun_si->tme_sun_si_type != TME_SUN_SI_TYPE_ONBOARD
        !           245:       && _TME_SUN_SI_REG_IS(TME_SUN_SI_REG_DMA_COUNT, tme_uint32_t)) {
        !           246:     reg_name = "dma_count";
        !           247:   }
        !           248:   if ((sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_ONBOARD
        !           249:        || sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_VME)
        !           250:       && _TME_SUN_SI_REG_IS(TME_SUN_SI_REG_FIFO_COUNT_L, tme_uint16_t)) {
        !           251:     reg_name = "fifo_count_l";
        !           252:   }
        !           253:   if (sun_si->tme_sun_si_type != TME_SUN_SI_TYPE_COBRA
        !           254:       && _TME_SUN_SI_REG_IS(TME_SUN_SI_REG_CSR, tme_uint16_t)) {
        !           255:     reg_name = "CSR";
        !           256:   }
        !           257:   if (sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_VME) {
        !           258:     if (_TME_SUN_SI_REG_IS(TME_SUN_SI_REG_VME_BPR_H, tme_uint16_t)) {
        !           259:       reg_name = "bpr_h";
        !           260:     }
        !           261:     if (_TME_SUN_SI_REG_IS(TME_SUN_SI_REG_VME_BPR_L, tme_uint16_t)) {
        !           262:       reg_name = "bpr_l";
        !           263:     }
        !           264:     if (_TME_SUN_SI_REG_IS(TME_SUN_SI_REG_VME_FIFO_COUNT_H, tme_uint16_t)) {
        !           265:       reg_name = "fifo_count_h";
        !           266:     }
        !           267:   }
        !           268: #undef _TME_SUN_SI_REG_IS
        !           269:   if (reg_name == NULL) {
        !           270:     reg_name = "???";
        !           271:   }
        !           272:   tme_log(&sun_si->tme_sun_si_element->tme_element_log_handle,
        !           273:            100, TME_OK,
        !           274:            (&sun_si->tme_sun_si_element->tme_element_log_handle,
        !           275:             "%s old 0x%04x new 0x%04x",
        !           276:             reg_name,
        !           277:             val_old,
        !           278:             val_new));
        !           279: }
        !           280: #undef TME_SUN_SI_REG16_PUT
        !           281: #define TME_SUN_SI_REG16_PUT(sun_si, reg, val) _tme_sun_si_reg_put((sun_si), (reg), (val), sizeof(tme_uint16_t))
        !           282: #undef TME_SUN_SI_REG32_PUT
        !           283: #define TME_SUN_SI_REG32_PUT(sun_si, reg, val) _tme_sun_si_reg_put((sun_si), (reg), (val), sizeof(tme_uint32_t))
        !           284: #endif /* TME_SUN_SI_DEBUG */
        !           285: 
        !           286: /* the sun_si callout function.  it must be called with the mutex locked: */
        !           287: static void
        !           288: _tme_sun_si_callout(struct tme_sun_si *sun_si, int new_callouts)
        !           289: {
        !           290:   struct tme_bus_connection *conn_ncr5380;
        !           291:   struct tme_bus_connection *conn_bus;
        !           292:   tme_uint32_t csr, csr_diff;
        !           293:   unsigned int signal, level;
        !           294:   int callouts, later_callouts;
        !           295:   int rc;
        !           296:   int int_asserted;
        !           297:   
        !           298:   /* add in any new callouts: */
        !           299:   sun_si->tme_sun_si_callout_flags |= new_callouts;
        !           300: 
        !           301:   /* if this function is already running in another thread, simply
        !           302:      return now.  the other thread will do our work: */
        !           303:   if (sun_si->tme_sun_si_callout_flags & TME_SUN_SI_CALLOUT_RUNNING) {
        !           304:     return;
        !           305:   }
        !           306: 
        !           307:   /* callouts are now running: */
        !           308:   sun_si->tme_sun_si_callout_flags |= TME_SUN_SI_CALLOUT_RUNNING;
        !           309: 
        !           310:   /* assume that we won't need any later callouts: */
        !           311:   later_callouts = 0;
        !           312: 
        !           313:   /* loop while callouts are needed: */
        !           314:   for (; (callouts = sun_si->tme_sun_si_callout_flags) & TME_SUN_SI_CALLOUTS_MASK; ) {
        !           315: 
        !           316:     /* clear the needed callouts: */
        !           317:     sun_si->tme_sun_si_callout_flags = callouts & ~TME_SUN_SI_CALLOUTS_MASK;
        !           318:     callouts &= TME_SUN_SI_CALLOUTS_MASK;
        !           319: 
        !           320:     /* get the current CSR value: */
        !           321:     csr = TME_SUN_SI_CSR_GET(sun_si);
        !           322: 
        !           323:     /* get the next changed CSR bit to convert to a bus signal to the
        !           324:        NCR 5380: */
        !           325:     csr_diff = ((csr
        !           326:                 ^ sun_si->tme_sun_si_csr_ncr5380)
        !           327:                & (TME_SUN_SI_CSR_RESET_CONTROLLER
        !           328:                   | ((sun_si->tme_sun_si_type != TME_SUN_SI_TYPE_ONBOARD)
        !           329:                      ? TME_SUN_SI_CSR_DMA_ENABLE
        !           330:                      : 0)));
        !           331:     csr_diff = (csr_diff ^ (csr_diff - 1)) & csr_diff;
        !           332:       
        !           333:     /* if there is a changed CSR bit to call out: */
        !           334:     if (csr_diff != 0) {
        !           335: 
        !           336:       /* assume that if the signal's bit is set in the CSR, it will
        !           337:         be asserted: */
        !           338:       level = (csr & csr_diff) != 0;
        !           339: 
        !           340:       /* dispatch on the CSR bit: */
        !           341:       switch (csr_diff) {
        !           342:       default:
        !           343:        assert (FALSE);
        !           344:        /* FALLTHROUGH */
        !           345: 
        !           346:       case TME_SUN_SI_CSR_RESET_CONTROLLER:
        !           347:        signal = TME_BUS_SIGNAL_RESET;
        !           348:        level = !level;
        !           349:        break;
        !           350: 
        !           351:       case TME_SUN_SI_CSR_DMA_ENABLE:
        !           352:        signal = TME_BUS_SIGNAL_DACK;
        !           353:        break;
        !           354:       }
        !           355: 
        !           356:       /* create a real signal level value: */
        !           357:       level = (level
        !           358:               ? TME_BUS_SIGNAL_LEVEL_ASSERTED
        !           359:               : TME_BUS_SIGNAL_LEVEL_NEGATED);
        !           360: 
        !           361:       /* get this card's ncr5380 connection: */
        !           362:       conn_ncr5380 = sun_si->tme_sun_si_conn_ncr5380;
        !           363: 
        !           364:       /* unlock the mutex: */
        !           365:       tme_mutex_unlock(&sun_si->tme_sun_si_mutex);
        !           366:       
        !           367:       /* do the callout: */
        !           368:       rc = (conn_ncr5380 != NULL
        !           369:            ? ((*conn_ncr5380->tme_bus_signal)
        !           370:               (conn_ncr5380,
        !           371:                signal | level))
        !           372:            : TME_OK);
        !           373:        
        !           374:       /* lock the mutex: */
        !           375:       tme_mutex_lock(&sun_si->tme_sun_si_mutex);
        !           376:       
        !           377:       /* if the callout was unsuccessful, remember that at some later
        !           378:         time this callout should be attempted again: */
        !           379:       if (rc != TME_OK) {
        !           380:        later_callouts |= TME_SUN_SI_CALLOUT_SIGNALS;
        !           381:       }
        !           382: 
        !           383:       /* otherwise, the callout was successful: */
        !           384:       else {
        !           385: 
        !           386:        /* update the ncr5380 image of the CSR: */
        !           387:        sun_si->tme_sun_si_csr_ncr5380 = 
        !           388:          ((sun_si->tme_sun_si_csr_ncr5380 & ~csr_diff)
        !           389:           | (csr & csr_diff));
        !           390: 
        !           391:        /* there may be more signals to call out, so attempt this
        !           392:           callout again now: */
        !           393:        sun_si->tme_sun_si_callout_flags |= TME_SUN_SI_CALLOUT_SIGNALS;
        !           394:       }
        !           395:     }
        !           396: 
        !           397:     /* get the current CSR value: */
        !           398:     csr = TME_SUN_SI_CSR_GET(sun_si);
        !           399: 
        !           400:     /* see if the interrupt signal should be asserted or negated.  on
        !           401:        all controllers except for onboard, DMA must be enabled for the
        !           402:        interrupt signal to reach the CPU: */
        !           403:     int_asserted = ((csr & TME_SUN_SI_CSR_INT_ENABLE)
        !           404:                    && (sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_ONBOARD
        !           405:                        || (csr & TME_SUN_SI_CSR_DMA_ENABLE))
        !           406:                      && (csr & (TME_SUN_SI_CSR_DMA_CONFLICT
        !           407:                                 | TME_SUN_SI_CSR_DMA_BUS_ERROR
        !           408:                                 | TME_SUN_SI_CSR_INT_NCR5380
        !           409:                                 | TME_SUN_SI_CSR_INT_DMA)));
        !           410: 
        !           411:     /* if the interrupt signal doesn't already have the right state: */
        !           412:     if (!int_asserted != !sun_si->tme_sun_si_last_int_asserted) {
        !           413: 
        !           414:       /* get our bus connection: */
        !           415:       conn_bus = sun_si->tme_sun_si_conn_regs;
        !           416:        
        !           417:       /* unlock our mutex: */
        !           418:       tme_mutex_unlock(&sun_si->tme_sun_si_mutex);
        !           419:        
        !           420:       /* call out the bus interrupt signal edge: */
        !           421:       rc = (conn_bus != NULL
        !           422:            ? ((*conn_bus->tme_bus_signal)
        !           423:               (conn_bus,
        !           424:                TME_BUS_SIGNAL_INT_UNSPEC
        !           425:                | (int_asserted
        !           426:                   ? TME_BUS_SIGNAL_LEVEL_ASSERTED
        !           427:                   : TME_BUS_SIGNAL_LEVEL_NEGATED)))
        !           428:            : TME_OK);
        !           429: 
        !           430:       /* lock our mutex: */
        !           431:       tme_mutex_lock(&sun_si->tme_sun_si_mutex);
        !           432:        
        !           433:       /* if this callout was successful, note the new state of the
        !           434:         interrupt signal: */
        !           435:       if (rc == TME_OK) {
        !           436:        sun_si->tme_sun_si_last_int_asserted = int_asserted;
        !           437:       }
        !           438: 
        !           439:       /* otherwise, remember that at some later time this callout
        !           440:         should be attempted again: */
        !           441:       else {
        !           442:        later_callouts |= TME_SUN_SI_CALLOUT_INT;
        !           443:       }
        !           444:     }
        !           445:   }
        !           446:   
        !           447:   /* put in any later callouts, and clear that callouts are running: */
        !           448:   sun_si->tme_sun_si_callout_flags = later_callouts;
        !           449: }
        !           450: 
        !           451: /* the 3/E DMA bus cycle handler: */
        !           452: static int
        !           453: _tme_sun_si_bus_cycle_3e_dma(void *_sun_si, struct tme_bus_cycle *cycle)
        !           454: {
        !           455:   struct tme_sun_si *sun_si;
        !           456: 
        !           457:   /* recover our data structure: */
        !           458:   sun_si = (struct tme_sun_si *) _sun_si;
        !           459: 
        !           460:   /* run the cycle: */
        !           461:   tme_bus_cycle_xfer_memory(cycle, 
        !           462:                            sun_si->tme_sun_si_3e_dma,
        !           463:                            TME_SUN_SI_3E_SIZ_DMA - 1);
        !           464: 
        !           465:   /* no faults: */
        !           466:   return (TME_OK);
        !           467: }
        !           468: 
        !           469: /* the sun_si bus cycle handler for the board registers: */
        !           470: static int
        !           471: _tme_sun_si_bus_cycle_regs(void *_sun_si, 
        !           472:                           struct tme_bus_cycle *cycle_init)
        !           473: {
        !           474:   struct tme_sun_si *sun_si;
        !           475:   tme_uint32_t csr_old, csr_new, csr_diff, csr_mask;
        !           476:   tme_bus_addr_t address;
        !           477:   tme_uint8_t cycle_size;
        !           478:   tme_uint32_t csr;
        !           479:   tme_uint32_t dma_count;
        !           480:   int new_callouts;
        !           481: 
        !           482:   /* get the address and cycle size: */
        !           483:   address = cycle_init->tme_bus_cycle_address;
        !           484:   cycle_size = cycle_init->tme_bus_cycle_size;
        !           485: 
        !           486:   /* it appears that si hardware doesn't respond to a byte access
        !           487:      to its DMA count register.  at least, SunOS' sc probe routine
        !           488:      seems to rely on this to distinguish an si from an sc: */
        !           489:   if (address == TME_SUN_SI_REG_DMA_COUNT
        !           490:       && cycle_size == sizeof(tme_uint8_t)) {
        !           491:     return (EINVAL);
        !           492:   }
        !           493: 
        !           494:   /* recover our data structure: */
        !           495:   sun_si = (struct tme_sun_si *) _sun_si;
        !           496: 
        !           497:   /* assume we won't need any new callouts: */
        !           498:   new_callouts = 0;
        !           499: 
        !           500:   /* lock the mutex: */
        !           501:   tme_mutex_lock(&sun_si->tme_sun_si_mutex);
        !           502: 
        !           503:   /* get the previous CSR value: */
        !           504:   csr_old = TME_SUN_SI_CSR_GET(sun_si);
        !           505: 
        !           506:   /* run the cycle: */
        !           507:   tme_bus_cycle_xfer_memory(cycle_init, 
        !           508:                            sun_si->tme_sun_si_regs,
        !           509:                            TME_SUN_SI_SIZ_REGS - 1);
        !           510: 
        !           511: #define _TME_SUN_SI_REG_IS(reg, type) TME_RANGES_OVERLAP(address, address + cycle_size - 1, (reg), (reg) + sizeof(type) - 1)
        !           512: 
        !           513:   /* if this was a write: */
        !           514:   if (cycle_init->tme_bus_cycle_type
        !           515:       == TME_BUS_CYCLE_WRITE) {
        !           516: 
        !           517:     /* if this is a VME controller: */
        !           518:     if (sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_VME) {
        !           519: 
        !           520:       /* if this was a write to the DMA count register: */
        !           521:       if (_TME_SUN_SI_REG_IS(TME_SUN_SI_REG_DMA_COUNT, tme_uint32_t)) {
        !           522: 
        !           523:        /* get the DMA count register: */
        !           524:        dma_count = TME_SUN_SI_REG32_GET(sun_si, TME_SUN_SI_REG_DMA_COUNT);
        !           525: 
        !           526:        /* copy the DMA count register to the FIFO count register: */
        !           527:        TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_VME_FIFO_COUNT_H, (dma_count >> 16));
        !           528:        TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_FIFO_COUNT_L, (dma_count & 0xffff));
        !           529:       }
        !           530:     }
        !           531: 
        !           532:     /* get the current CSR value, and put back any bits that
        !           533:        software can't change: */
        !           534:     csr_mask = (sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_3E
        !           535:                ? TME_SUN_SI_CSR_3E_READONLY
        !           536:                : TME_SUN_SI_CSR_READONLY);
        !           537:     csr_new = ((TME_SUN_SI_CSR_GET(sun_si)
        !           538:                & ~csr_mask)
        !           539:               | (csr_old
        !           540:                  & csr_mask));
        !           541: 
        !           542:     /* get the sets of CSR bits that have changed: */
        !           543:     csr_diff = (csr_old ^ csr_new);
        !           544: 
        !           545:     /* if the FIFO is being reset: */
        !           546:     if (sun_si->tme_sun_si_type != TME_SUN_SI_TYPE_3E
        !           547:        && (csr_diff & TME_SUN_SI_CSR_RESET_FIFO)
        !           548:        && !(csr_new & TME_SUN_SI_CSR_RESET_FIFO)) {
        !           549: 
        !           550:       /* reset the FIFOs: */
        !           551:       TME_SUN_SI_REG32_PUT(sun_si, TME_SUN_SI_REG_DMA_ADDRESS, 0);
        !           552:       TME_SUN_SI_REG32_PUT(sun_si, TME_SUN_SI_REG_DMA_COUNT, 0);
        !           553:       switch (sun_si->tme_sun_si_type) {
        !           554:       default: 
        !           555:        assert(FALSE);
        !           556:        /* FALLTHROUGH */
        !           557:       case TME_SUN_SI_TYPE_ONBOARD:
        !           558:        TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_ONBOARD_FIFO_DATA, 0);
        !           559:        TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_FIFO_COUNT_L, 0);
        !           560:        break;
        !           561:       case TME_SUN_SI_TYPE_VME:
        !           562:        TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_FIFO_COUNT_L, 0);
        !           563:        TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_VME_FIFO_COUNT_H, 0);
        !           564:        csr &= ~TME_SUN_SI_CSR_VME_LOB_MASK;
        !           565:        break;
        !           566:       case TME_SUN_SI_TYPE_COBRA:
        !           567:        abort();
        !           568:        break;
        !           569:       }
        !           570:     }
        !           571: 
        !           572:     /* if the CSR has changed at all: */
        !           573:     if (csr_new != csr_old) {
        !           574: 
        !           575:       /* put back the new CSR: */
        !           576:       tme_log(&sun_si->tme_sun_si_element->tme_element_log_handle,
        !           577:              100, TME_OK,
        !           578:              (&sun_si->tme_sun_si_element->tme_element_log_handle,
        !           579:               "CSR now 0x%04x",
        !           580:               csr_new));
        !           581:       TME_SUN_SI_CSR_PUT(sun_si, csr_new);
        !           582: 
        !           583:       /* assume that we need to call out changes to bus signals and
        !           584:        our interrupt: */
        !           585:       new_callouts |= TME_SUN_SI_CALLOUT_INT | TME_SUN_SI_CALLOUT_SIGNALS;
        !           586:     }
        !           587:   }
        !           588: 
        !           589:   /* make any new callouts: */
        !           590:   _tme_sun_si_callout(sun_si, new_callouts);
        !           591: 
        !           592:   /* unlock the mutex: */
        !           593:   tme_mutex_unlock(&sun_si->tme_sun_si_mutex);
        !           594: 
        !           595:   /* no faults: */
        !           596:   return (TME_OK);
        !           597: }
        !           598: 
        !           599: /* the sun_si TLB filler for the board registers (and, on the 3/E, for
        !           600:    the board memory on the VME bus): */
        !           601: static int
        !           602: _tme_sun_si_tlb_fill_regs(struct tme_bus_connection *conn_bus,
        !           603:                          struct tme_bus_tlb *tlb, 
        !           604:                          tme_bus_addr_t address, unsigned int cycles)
        !           605: {
        !           606:   struct tme_sun_si *sun_si;
        !           607:   struct tme_bus_connection *conn_ncr5380;
        !           608:   tme_bus_addr_t address_regs;
        !           609:   struct tme_bus_tlb tlb_mapping;
        !           610:   int rc;
        !           611: 
        !           612:   /* recover our data structures: */
        !           613:   sun_si = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
        !           614: 
        !           615:   /* assume that the registers start at address zero: */
        !           616:   address_regs = 0;
        !           617: 
        !           618:   /* dispatch on the controller type: */
        !           619:   switch (sun_si->tme_sun_si_type) {
        !           620: 
        !           621:   case TME_SUN_SI_TYPE_3E:
        !           622: 
        !           623:     /* the board registers follow the DMA buffer: */
        !           624:     address_regs = TME_SUN_SI_3E_SIZ_DMA;
        !           625: 
        !           626:     /* if this address is in the DMA buffer: */
        !           627:     if (address < TME_SUN_SI_3E_SIZ_DMA) {
        !           628: 
        !           629:       /* initialize the TLB entry: */
        !           630:       tme_bus_tlb_initialize(tlb);
        !           631: 
        !           632:       /* this TLB entry covers this range: */
        !           633:       TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, 0);
        !           634:       TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, TME_SUN_SI_3E_SIZ_DMA - 1);
        !           635: 
        !           636:       /* this TLB entry allows fast reading and writing: */
        !           637:       tlb->tme_bus_tlb_emulator_off_read = sun_si->tme_sun_si_3e_dma;
        !           638:       tlb->tme_bus_tlb_emulator_off_write = sun_si->tme_sun_si_3e_dma;
        !           639:       
        !           640:       /* allow reading and writing: */
        !           641:       tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
        !           642: 
        !           643:       /* our bus cycle handler: */
        !           644:       tlb->tme_bus_tlb_cycle_private = sun_si;
        !           645:       tlb->tme_bus_tlb_cycle = _tme_sun_si_bus_cycle_3e_dma;
        !           646: 
        !           647:       return (TME_OK);
        !           648:     }
        !           649:     break;
        !           650: 
        !           651:   default:
        !           652:     break;
        !           653:   }
        !           654: 
        !           655:   /* offset the address: */
        !           656:   address -= address_regs;
        !           657: 
        !           658:   /* the address must be within range: */
        !           659:   assert(address < TME_SUN_SI_SIZ_REGS);
        !           660: 
        !           661:   /* if this address is in the NCR 5380 registers: */
        !           662:   if (address < TME_SUN_SI_SIZ_NCR5380) {
        !           663: 
        !           664:     /* get the NCR 5380 connection: */
        !           665:     conn_ncr5380 = sun_si->tme_sun_si_conn_ncr5380;
        !           666: 
        !           667:     /* call the NCR 5380 TLB fill function: */
        !           668:     rc = (conn_ncr5380 != NULL
        !           669:          ? (*conn_ncr5380->tme_bus_tlb_fill)(conn_ncr5380, tlb,
        !           670:                                              address, cycles)
        !           671:          : EINVAL);
        !           672: 
        !           673:     /* if that succeeded: */
        !           674:     if (rc == TME_OK) {
        !           675:       
        !           676:       /* create the mapping TLB entry: */
        !           677:       TME_ATOMIC_WRITE(tme_bus_addr_t,
        !           678:                       tlb_mapping.tme_bus_tlb_addr_first,
        !           679:                       (address_regs
        !           680:                        + TME_SUN_SI_REG_NCR5380));
        !           681:       TME_ATOMIC_WRITE(tme_bus_addr_t,
        !           682:                       tlb_mapping.tme_bus_tlb_addr_last,
        !           683:                       (address_regs
        !           684:                        + TME_SUN_SI_REG_NCR5380
        !           685:                        + TME_SUN_SI_SIZ_NCR5380
        !           686:                        - 1));
        !           687:       tlb_mapping.tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
        !           688:       
        !           689:       /* map the filled TLB entry: */
        !           690:       tme_bus_tlb_map(tlb, 0, &tlb_mapping, address_regs + TME_SUN_SI_REG_NCR5380);
        !           691:     }
        !           692: 
        !           693:     return (rc);
        !           694:   }
        !           695: 
        !           696:   /* initialize the TLB entry: */
        !           697:   tme_bus_tlb_initialize(tlb);
        !           698: 
        !           699:   /* this TLB entry covers this range: */
        !           700:   TME_ATOMIC_WRITE(tme_bus_addr_t,
        !           701:                   tlb->tme_bus_tlb_addr_first, 
        !           702:                   (address_regs
        !           703:                    + TME_SUN_SI_SIZ_NCR5380));
        !           704:   TME_ATOMIC_WRITE(tme_bus_addr_t,
        !           705:                   tlb->tme_bus_tlb_addr_last,
        !           706:                   (address_regs
        !           707:                    + TME_SUN_SI_SIZ_REGS
        !           708:                    - 1));
        !           709: 
        !           710:   /* our controller registers don't have read side-effects, so they
        !           711:      support fast reading: */
        !           712:   tlb->tme_bus_tlb_emulator_off_read = sun_si->tme_sun_si_regs - address_regs;
        !           713: 
        !           714:   /* allow reading and writing: */
        !           715:   tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
        !           716: 
        !           717:   /* our bus cycle handler: */
        !           718:   tlb->tme_bus_tlb_cycle_private = sun_si;
        !           719:   tlb->tme_bus_tlb_cycle = _tme_sun_si_bus_cycle_regs;
        !           720: 
        !           721:   return (TME_OK);
        !           722: }
        !           723: 
        !           724: /* the interrupt acknowledge function for the VME and 3/E types: */
        !           725: static int
        !           726: _tme_sun_si_intack(struct tme_bus_connection *conn_bus, unsigned int signal, int *_vector)
        !           727: {
        !           728:   struct tme_sun_si *sun_si;
        !           729:   int vector;
        !           730: 
        !           731:   /* recover our data structure: */
        !           732:   sun_si = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
        !           733: 
        !           734:   /* dispatch on the controller type: */
        !           735:   switch (sun_si->tme_sun_si_type) {
        !           736:   default:
        !           737:     assert (FALSE);
        !           738:     /* FALLTHROUGH */
        !           739: 
        !           740:   case TME_SUN_SI_TYPE_3E:
        !           741:     vector = sun_si->tme_sun_si_regs[TME_SUN_SI_REG_3E_IVEC];
        !           742:     break;
        !           743: 
        !           744:   case TME_SUN_SI_TYPE_VME:
        !           745:     vector = TME_SUN_SI_REG16_GET(sun_si, TME_SUN_SI_REG_VME_IV_AM) & 0xff;
        !           746:     break;
        !           747:   }
        !           748: 
        !           749:   /* return the interrupt vector: */
        !           750:   *_vector = vector;
        !           751:   return (TME_OK);
        !           752: }
        !           753: 
        !           754: /* the sun_si bus signal handler for the NCR 5380: */
        !           755: static int
        !           756: _tme_sun_si_bus_signal(struct tme_bus_connection *conn_bus, 
        !           757:                       unsigned int signal)
        !           758: {
        !           759:   struct tme_sun_si *sun_si;
        !           760:   tme_uint32_t csr;
        !           761: 
        !           762:   /* this must be the unspecified interrupt signal: */
        !           763:   assert (TME_BUS_SIGNAL_WHICH(signal) == TME_BUS_SIGNAL_INT_UNSPEC);
        !           764: 
        !           765:   /* recover our data structures: */
        !           766:   sun_si = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
        !           767: 
        !           768:   /* lock our mutex: */
        !           769:   tme_mutex_lock(&sun_si->tme_sun_si_mutex);
        !           770: 
        !           771:   /* update the CSR value: */
        !           772:   csr = TME_SUN_SI_CSR_GET(sun_si);
        !           773:   csr = ((csr
        !           774:          & ~TME_SUN_SI_CSR_INT_NCR5380)
        !           775:         | (((signal & TME_BUS_SIGNAL_LEVEL_MASK)
        !           776:             == TME_BUS_SIGNAL_LEVEL_ASSERTED)
        !           777:            ? TME_SUN_SI_CSR_INT_NCR5380
        !           778:            : 0));
        !           779:   TME_SUN_SI_CSR_PUT(sun_si, csr);
        !           780: 
        !           781:   /* call out an interrupt change: */
        !           782:   _tme_sun_si_callout(sun_si, TME_SUN_SI_CALLOUT_INT);
        !           783: 
        !           784:   /* unlock our mutex: */
        !           785:   tme_mutex_unlock(&sun_si->tme_sun_si_mutex);
        !           786: 
        !           787:   return (TME_OK);
        !           788: }
        !           789: 
        !           790: /* the sun_si bus fault handler for the NCR 5380 DMA: */
        !           791: static int
        !           792: _tme_sun_si_bus_fault_handler(void *_sun_si, 
        !           793:                              struct tme_bus_tlb *tlb,
        !           794:                              struct tme_bus_cycle *cycle,
        !           795:                              int rc)
        !           796: {
        !           797:   struct tme_sun_si *sun_si;
        !           798: 
        !           799:   /* recover our data structure: */
        !           800:   sun_si = (struct tme_sun_si *) _sun_si;
        !           801: 
        !           802:   /* lock our mutex: */
        !           803:   tme_mutex_lock(&sun_si->tme_sun_si_mutex);
        !           804: 
        !           805:   /* set a DMA bus error and call out an interrupt change: */
        !           806:   TME_SUN_SI_CSR_PUT(sun_si, TME_SUN_SI_CSR_GET(sun_si) | TME_SUN_SI_CSR_DMA_BUS_ERROR);
        !           807:   _tme_sun_si_callout(sun_si, TME_SUN_SI_CALLOUT_INT);    
        !           808: 
        !           809:   /* unlock our mutex: */
        !           810:   tme_mutex_unlock(&sun_si->tme_sun_si_mutex);
        !           811:   
        !           812:   return (rc);
        !           813: }
        !           814: 
        !           815: /* the sun_si TLB filler for the NCR 5380 DMA: */
        !           816: static int
        !           817: _tme_sun_si_tlb_fill(struct tme_bus_connection *conn_bus,
        !           818:                     struct tme_bus_tlb *tlb, 
        !           819:                     tme_bus_addr_t ncr5380_address, 
        !           820:                     unsigned int cycles)
        !           821: {
        !           822:   struct tme_sun_si *sun_si;
        !           823:   tme_uint32_t csr;
        !           824:   tme_bus_addr_t dma_address;
        !           825:   tme_uint32_t dma_count;
        !           826:   tme_uint32_t bpr;
        !           827:   unsigned int bpr_count;
        !           828: #if defined(TME_SUN_SI_STRICT_VME)
        !           829:   unsigned int bpr_i;
        !           830: #endif /* defined(TME_SUN_SI_STRICT_VME) */
        !           831:   struct tme_bus_tlb tlb_mapping;
        !           832:   int rc;
        !           833: 
        !           834:   /* recover our data structures: */
        !           835:   sun_si = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
        !           836: 
        !           837:   /* assume that this call will succeed: */
        !           838:   rc = TME_OK;
        !           839: 
        !           840:   /* lock our mutex: */
        !           841:   tme_mutex_lock(&sun_si->tme_sun_si_mutex);
        !           842: 
        !           843:   /* if the NCR 5380 already has an outstanding TLB entry, and it
        !           844:      doesn't happen to be this TLB entry, invalidate it: */
        !           845:   if (sun_si->tme_sun_si_ncr5380_tlb != NULL
        !           846:       && (tlb == NULL
        !           847:          || (sun_si->tme_sun_si_ncr5380_tlb 
        !           848:              != TME_ATOMIC_READ(struct tme_bus_tlb *, 
        !           849:                                 tlb->tme_bus_tlb_backing_reservation)))) {
        !           850:     tme_bus_tlb_invalidate(sun_si->tme_sun_si_ncr5380_tlb);
        !           851: 
        !           852:     /* the NCR 5380 doesn't have any outstanding TLB entry: */
        !           853:     sun_si->tme_sun_si_ncr5380_tlb = NULL;
        !           854:   }
        !           855: 
        !           856:   /* get the CSR value: */
        !           857:   csr = TME_SUN_SI_CSR_GET(sun_si);
        !           858: 
        !           859:   /* assume that this is not an onboard controller, and get the DMA
        !           860:      address register, plus the NCR 5380 address, and the DMA count
        !           861:      register: */
        !           862:   dma_address = TME_SUN_SI_REG32_GET(sun_si, TME_SUN_SI_REG_DMA_ADDRESS) + ncr5380_address;
        !           863:   dma_count = TME_SUN_SI_REG32_GET(sun_si, TME_SUN_SI_REG_DMA_COUNT);
        !           864:     
        !           865:   /* dispatch on the controller type: */
        !           866:   switch (sun_si->tme_sun_si_type) {
        !           867: 
        !           868:   default:
        !           869:     assert(FALSE);
        !           870:     /* FALLTHROUGH */
        !           871: 
        !           872:   case TME_SUN_SI_TYPE_3E:
        !           873: 
        !           874:     /* mask the DMA address and count registers to 16 bits: */
        !           875:     dma_address &= 0xffff;
        !           876:     dma_count &= 0xffff;
        !           877: 
        !           878:     /* if the NCR 5380 has stopped doing DMA, or if it has exhausted
        !           879:        DMA, or if DMA is not enabled: */
        !           880:     if (cycles == TME_BUS_CYCLE_UNDEF
        !           881:        || ncr5380_address >= dma_count
        !           882:        || !(csr & TME_SUN_SI_CSR_DMA_ENABLE)) {
        !           883: 
        !           884:       /* if the NCR 5380 has stopped doing DMA, cap the DMA count and
        !           885:         address to the amount of DMA that was available, thus
        !           886:         cancelling the effect of the NCR 5380 prefetch.  this
        !           887:         prevents the DMA count from going negative, confusing the Sun
        !           888:         PROM and probably SunOS.  I'm guessing that all of the SCSI
        !           889:         devices ever used with Suns change information transfer phase
        !           890:         faster than the NCR 5380 prefetches a byte from DMA, which is
        !           891:         why this DMA-count-going-negative problem is never seen.  since
        !           892:         our NCR 5380 is infinitely fast at prefetch, we have to deal: */
        !           893:       if (cycles == TME_BUS_CYCLE_UNDEF
        !           894:          && ncr5380_address > dma_count) {
        !           895:        assert (ncr5380_address == (dma_count + 1));
        !           896:        dma_address -= (ncr5380_address - dma_count);
        !           897:        ncr5380_address = dma_count;
        !           898:       }
        !           899: 
        !           900:       /* update the DMA address and count registers: */
        !           901:       TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_DMA_ADDRESS + sizeof(tme_uint16_t), 
        !           902:                           dma_address);
        !           903:       TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_DMA_COUNT + sizeof(tme_uint16_t), 
        !           904:                           dma_count - ncr5380_address);
        !           905: 
        !           906:       /* return EAGAIN to the NCR 5380, unless it was the NCR 5380
        !           907:          that stopped doing DMA: */
        !           908:       if (cycles != TME_BUS_CYCLE_UNDEF) {
        !           909:        rc = EAGAIN;
        !           910:       }
        !           911:       break;
        !           912:     }
        !           913: 
        !           914:     /* XXX does DMA wrap around in the 3/E DMA memory? */
        !           915:     dma_count = TME_MIN((TME_SUN_SI_3E_SIZ_DMA - dma_address), dma_count);
        !           916: 
        !           917:     /* initialize the TLB entry: */
        !           918:     tme_bus_tlb_initialize(tlb);
        !           919: 
        !           920:     /* this TLB entry covers this range: */
        !           921:     TME_ATOMIC_WRITE(tme_bus_addr_t,
        !           922:                     tlb->tme_bus_tlb_addr_first, 
        !           923:                     0);
        !           924:     TME_ATOMIC_WRITE(tme_bus_addr_t,
        !           925:                     tlb->tme_bus_tlb_addr_last,
        !           926:                     dma_count - 1);
        !           927: 
        !           928:     /* this TLB entry supports fast reading and writing: */
        !           929:     tlb->tme_bus_tlb_emulator_off_read = sun_si->tme_sun_si_3e_dma + dma_address;
        !           930:     tlb->tme_bus_tlb_emulator_off_write = sun_si->tme_sun_si_3e_dma + dma_address;
        !           931: 
        !           932:     /* allow reading and writing: */
        !           933:     tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
        !           934: 
        !           935:     /* our bus cycle handler: */
        !           936:     tlb->tme_bus_tlb_cycle_private = sun_si;
        !           937:     tlb->tme_bus_tlb_cycle = _tme_sun_si_bus_cycle_3e_dma;
        !           938: 
        !           939:     /* unlock our mutex: */
        !           940:     tme_mutex_unlock(&sun_si->tme_sun_si_mutex);
        !           941: 
        !           942:     return (TME_OK);
        !           943: 
        !           944:   case TME_SUN_SI_TYPE_VME:
        !           945: 
        !           946:     /* if the NCR 5380 has stopped doing DMA, or if it has exhausted
        !           947:        DMA, or if DMA is not enabled: */
        !           948:     if (cycles == TME_BUS_CYCLE_UNDEF
        !           949:        || ncr5380_address >= dma_count
        !           950:        || ((csr
        !           951:             & (TME_SUN_SI_CSR_DMA_CONFLICT
        !           952:                | TME_SUN_SI_CSR_DMA_BUS_ERROR
        !           953:                | TME_SUN_SI_CSR_DMA_ENABLE))
        !           954:            != TME_SUN_SI_CSR_DMA_ENABLE)) {
        !           955: 
        !           956:       /* if the NCR 5380 has stopped doing DMA, cap the DMA count and
        !           957:         address to the amount of DMA that was available, thus
        !           958:         cancelling the effect of the NCR 5380 prefetch.  this
        !           959:         prevents the DMA count from going negative, confusing the Sun
        !           960:         PROM and probably SunOS.  I'm guessing that all of the SCSI
        !           961:         devices ever used with Suns change information transfer phase
        !           962:         faster than the NCR 5380 prefetches a byte from DMA, which is
        !           963:         why this DMA-count-going-negative problem is never seen.  since
        !           964:         our NCR 5380 is infinitely fast at prefetch, we have to deal: */
        !           965:       if (cycles == TME_BUS_CYCLE_UNDEF
        !           966:          && ncr5380_address > dma_count) {
        !           967:        assert (ncr5380_address == (dma_count + 1));
        !           968:        dma_address -= (ncr5380_address - dma_count);
        !           969:        ncr5380_address = dma_count;
        !           970:       }
        !           971: 
        !           972:       /* update the DMA address and count registers: */
        !           973:       TME_SUN_SI_REG32_PUT(sun_si, TME_SUN_SI_REG_DMA_ADDRESS, dma_address);
        !           974:       TME_SUN_SI_REG32_PUT(sun_si, TME_SUN_SI_REG_DMA_COUNT, dma_count - ncr5380_address);
        !           975:       TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_VME_FIFO_COUNT_H, ((dma_count - ncr5380_address) >> 16));
        !           976:       TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_FIFO_COUNT_L, ((dma_count - ncr5380_address) & 0xffff));
        !           977: 
        !           978:       /* assume that our emulated byte pack is empty: */
        !           979:       bpr = 0;
        !           980:       bpr_count = 0;
        !           981: 
        !           982: #ifdef TME_SUN_SI_STRICT_VME
        !           983: 
        !           984:       /* if the NCR 5380 was doing DMA writes to memory (i.e., it was
        !           985:          receiving): */
        !           986:       if (!(csr & TME_SUN_SI_CSR_DMA_SEND)) {
        !           987: 
        !           988:        /* calculate how many bytes must be left in the byte pack: */
        !           989:        bpr_count = ncr5380_address;
        !           990:        bpr_count &= ((csr & TME_SUN_SI_CSR_VME_BPCON)
        !           991:                      ? (sizeof(tme_uint16_t) - 1)
        !           992:                      : (sizeof(tme_uint32_t) - 1));
        !           993: 
        !           994:        /* get the byte pack contents from the memory that the NCR
        !           995:           5380 DMA'ed into.  this is why all DMA writes have to be to
        !           996:           fast memory under TME_SUN_SI_STRICT_VME - if you DMA to
        !           997:           memory with side-effects, we can't read the data back out
        !           998:           again without incurring more side-effects, and we don't
        !           999:           want to do a *full* emulation of the DMA engine: */
        !          1000:        for (bpr_i = bpr_count; bpr_i > 0; bpr_i--) {
        !          1001:          bpr = (bpr << 8) | sun_si->tme_sun_si_dma_buffer_write[ncr5380_address - bpr_i];
        !          1002:        }
        !          1003: 
        !          1004:        /* left-justify the byte pack: */
        !          1005:        bpr <<= ((((csr & TME_SUN_SI_CSR_VME_BPCON)
        !          1006:                    ? sizeof(tme_uint16_t)
        !          1007:                    : sizeof(tme_uint32_t))
        !          1008:                   - bpr_count)
        !          1009:                  * 8);
        !          1010: 
        !          1011:       }
        !          1012: 
        !          1013:       /* otherwise, the NCR 5380 was doing DMA reads to memory (i.e.,
        !          1014:         it was sending): */
        !          1015:       else {
        !          1016: 
        !          1017:        /* nothing to do.  we don't emulate the byte pack for sending: */
        !          1018:       }
        !          1019: 
        !          1020: #endif  /* TME_SUN_SI_STRICT_VME */
        !          1021: 
        !          1022:       /* update the byte pack and the CSR: */
        !          1023:       TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_VME_BPR_H, (bpr >> 16));
        !          1024:       TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_VME_BPR_L, (bpr & 0xffff));
        !          1025:       TME_FIELD_MASK_DEPOSITU(csr, TME_SUN_SI_CSR_VME_LOB_MASK, bpr_count);
        !          1026:       TME_SUN_SI_CSR_PUT(sun_si, csr);
        !          1027: 
        !          1028:       /* return EAGAIN to the NCR 5380, unless it was the NCR 5380
        !          1029:         that stopped doing DMA: */
        !          1030:       if (cycles != TME_BUS_CYCLE_UNDEF) {
        !          1031:        rc = EAGAIN;
        !          1032:       }
        !          1033:       break;
        !          1034:     }
        !          1035:     break;
        !          1036: 
        !          1037:   case TME_SUN_SI_TYPE_ONBOARD:
        !          1038:     /* TBD */
        !          1039:     abort();
        !          1040: 
        !          1041:   case TME_SUN_SI_TYPE_COBRA:
        !          1042:     /* TBD */
        !          1043:     abort();
        !          1044:   }
        !          1045: 
        !          1046:   /* if DMA is not ready for some reason: */
        !          1047:   if (rc == EAGAIN) {
        !          1048: 
        !          1049:     /* invalidate any local TLB entry passed by the caller: */
        !          1050:     if (tlb != NULL) {
        !          1051:       tme_bus_tlb_invalidate(tlb);
        !          1052:     }
        !          1053: 
        !          1054:     /* if DMA is enabled: */
        !          1055:     if (csr & TME_SUN_SI_CSR_DMA_ENABLE) {
        !          1056: 
        !          1057:       /* set a DMA interrupt and call out an interrupt change: */
        !          1058:       TME_SUN_SI_CSR_PUT(sun_si, TME_SUN_SI_CSR_GET(sun_si) | TME_SUN_SI_CSR_INT_DMA);
        !          1059:       _tme_sun_si_callout(sun_si, TME_SUN_SI_CALLOUT_INT);    
        !          1060:     }
        !          1061: 
        !          1062:     /* cancel the remainder of the TLB fill: */
        !          1063:     cycles = TME_BUS_CYCLE_UNDEF;
        !          1064:   }
        !          1065: 
        !          1066:   /* get the bus connection for memory: */
        !          1067:   conn_bus = sun_si->tme_sun_si_conn_memory;
        !          1068: 
        !          1069:   /* if we need to fill a TLB entry on the bus: */
        !          1070:   if (cycles != TME_BUS_CYCLE_UNDEF) {
        !          1071: 
        !          1072:     /* the NCR 5380 now has this outstanding TLB entry: */
        !          1073:     sun_si->tme_sun_si_ncr5380_tlb
        !          1074:       = TME_ATOMIC_READ(struct tme_bus_tlb *, tlb->tme_bus_tlb_backing_reservation);
        !          1075:   }
        !          1076: 
        !          1077:   /* unlock our mutex: */
        !          1078:   tme_mutex_unlock(&sun_si->tme_sun_si_mutex);
        !          1079: 
        !          1080:   /* if we need to fill a TLB entry on the bus: */
        !          1081:   if (cycles != TME_BUS_CYCLE_UNDEF) {
        !          1082: 
        !          1083:     /* DMA must be OK so far: */
        !          1084:     assert (rc == TME_OK);
        !          1085:     assert (dma_count > ncr5380_address);
        !          1086: 
        !          1087:     /* call out to fill this TLB entry on the bus: */
        !          1088:     rc = (conn_bus != NULL
        !          1089:          ? (*conn_bus->tme_bus_tlb_fill)(conn_bus, 
        !          1090:                                          tlb,
        !          1091:                                          dma_address,
        !          1092:                                          cycles)
        !          1093:          : ENXIO);
        !          1094: 
        !          1095:     /* if this callout succeeded: */
        !          1096:     if (rc == TME_OK) {
        !          1097: 
        !          1098: #if defined(TME_SUN_SI_STRICT_VME) || defined(TME_SUN_SI_STRICT_ONBOARD) || defined(TME_SUN_SI_STRICT_COBRA)
        !          1099: 
        !          1100:       /* when the NCR 5380 wants to do DMA writes, in order to
        !          1101:         correctly emulate the byte pack registers on these
        !          1102:         controllers without having to emulate their full DMA behavior
        !          1103:         (copying 16- or 32-bit words into a controller register for
        !          1104:         the NCR 5380), we just insist that all DMA be done to memory
        !          1105:         that supports fast access: */
        !          1106:       if ((cycles & TME_BUS_CYCLE_WRITE)
        !          1107:          && tlb->tme_bus_tlb_emulator_off_write == TME_EMULATOR_OFF_UNDEF) {
        !          1108:        abort();
        !          1109:       }
        !          1110:       
        !          1111: #endif /* defined(TME_SUN_SI_STRICT_VME) || defined(TME_SUN_SI_STRICT_ONBOARD) || defined(TME_SUN_SI_STRICT_COBRA) */
        !          1112: 
        !          1113:       /* create the mapping TLB entry: */
        !          1114:       TME_ATOMIC_WRITE(tme_bus_addr_t,
        !          1115:                       tlb_mapping.tme_bus_tlb_addr_first,
        !          1116:                       ncr5380_address);
        !          1117:       TME_ATOMIC_WRITE(tme_bus_addr_t,
        !          1118:                       tlb_mapping.tme_bus_tlb_addr_last,
        !          1119:                       (dma_count
        !          1120:                        - 1));
        !          1121:       tlb_mapping.tme_bus_tlb_cycles_ok = cycles;
        !          1122:       
        !          1123:       /* map the filled TLB entry: */
        !          1124:       tme_bus_tlb_map(tlb, dma_address, &tlb_mapping, ncr5380_address);
        !          1125: 
        !          1126:       /* add our bus fault handler: */
        !          1127:       TME_BUS_TLB_FAULT_HANDLER(tlb, _tme_sun_si_bus_fault_handler, sun_si);
        !          1128:     }
        !          1129:   }
        !          1130: 
        !          1131:   return (rc);
        !          1132: }
        !          1133: 
        !          1134: /* the sun_si TLB allocator for the NCR 5380: */
        !          1135: static int
        !          1136: _tme_sun_si_tlb_set_allocate(struct tme_bus_connection *conn_bus,
        !          1137:                             unsigned int count, unsigned int sizeof_one, 
        !          1138:                             TME_ATOMIC_POINTER_TYPE(struct tme_bus_tlb *) _tlbs)
        !          1139: {
        !          1140:   struct tme_sun_si *sun_si;
        !          1141: 
        !          1142:   /* recover our data structures: */
        !          1143:   sun_si = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
        !          1144: 
        !          1145:   /* pass the sun_si's request through to the memory bus: */
        !          1146:   conn_bus = sun_si->tme_sun_si_conn_memory;
        !          1147:   return (conn_bus != NULL
        !          1148:          ? (*conn_bus->tme_bus_tlb_set_allocate)(conn_bus, 
        !          1149:                                                  count, sizeof_one,
        !          1150:                                                  _tlbs)
        !          1151:          : ENXIO);
        !          1152: }
        !          1153: 
        !          1154: /* this scores a new connection: */
        !          1155: static int
        !          1156: _tme_sun_si_connection_score(struct tme_connection *conn, unsigned int *_score)
        !          1157: {
        !          1158:   struct tme_sun_si *sun_si;
        !          1159:   struct tme_sun_si_connection *conn_sun_si;
        !          1160: 
        !          1161:   /* both sides must be generic bus connections: */
        !          1162:   assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC);
        !          1163:   assert(conn->tme_connection_other->tme_connection_type
        !          1164:         == conn->tme_connection_type);
        !          1165: 
        !          1166:   /* recover our data structures: */
        !          1167:   sun_si = conn->tme_connection_element->tme_element_private;
        !          1168:   conn_sun_si = (struct tme_sun_si_connection *)conn;
        !          1169: 
        !          1170:   /* this is a generic bus connection, so just score it nonzero and
        !          1171:      return.  note that there's no good way to differentiate a
        !          1172:      connection to a bus from a connection to just another chip, so we
        !          1173:      always return a nonzero score here: */
        !          1174:   *_score = 1;
        !          1175:   return (TME_OK);
        !          1176: }
        !          1177: 
        !          1178: /* this makes a new connection: */
        !          1179: static int
        !          1180: _tme_sun_si_connection_make(struct tme_connection *conn, unsigned int state)
        !          1181: {
        !          1182:   struct tme_sun_si *sun_si;
        !          1183:   struct tme_sun_si_connection *conn_sun_si;
        !          1184:   struct tme_bus_connection *conn_bus;
        !          1185: 
        !          1186:   /* both sides must be generic bus connections: */
        !          1187:   assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC);
        !          1188:   assert(conn->tme_connection_other->tme_connection_type
        !          1189:         == conn->tme_connection_type);
        !          1190: 
        !          1191:   /* recover our data structures: */
        !          1192:   sun_si = conn->tme_connection_element->tme_element_private;
        !          1193:   conn_sun_si = (struct tme_sun_si_connection *) conn;
        !          1194:   conn_bus = &conn_sun_si->tme_sun_si_connection;
        !          1195: 
        !          1196:   /* we're always set up to answer calls across the connection, so we
        !          1197:      only have to do work when the connection has gone full, namely
        !          1198:      taking the other side of the connection: */
        !          1199:   if (state == TME_CONNECTION_FULL) {
        !          1200: 
        !          1201:     /* lock our mutex: */
        !          1202:     tme_mutex_lock(&sun_si->tme_sun_si_mutex);
        !          1203: 
        !          1204:     /* save our connection: */
        !          1205:     if (conn_bus->tme_bus_tlb_fill == _tme_sun_si_tlb_fill) {
        !          1206:       sun_si->tme_sun_si_conn_ncr5380 = (struct tme_bus_connection *) conn->tme_connection_other;
        !          1207:     }
        !          1208:     else {
        !          1209:       if (conn_sun_si->tme_sun_si_connection_regs) {
        !          1210:        sun_si->tme_sun_si_conn_regs = (struct tme_bus_connection *) conn->tme_connection_other;
        !          1211:       }
        !          1212:       if (!(sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_ONBOARD
        !          1213:            || sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_COBRA)
        !          1214:          || !conn_sun_si->tme_sun_si_connection_regs) {
        !          1215:        sun_si->tme_sun_si_conn_memory = (struct tme_bus_connection *) conn->tme_connection_other;
        !          1216:       }
        !          1217:     }
        !          1218: 
        !          1219:     /* unlock our mutex: */
        !          1220:     tme_mutex_unlock(&sun_si->tme_sun_si_mutex);
        !          1221:   }
        !          1222: 
        !          1223:   return (TME_OK);
        !          1224: }
        !          1225: 
        !          1226: /* this breaks a connection: */
        !          1227: static int
        !          1228: _tme_sun_si_connection_break(struct tme_connection *conn, unsigned int state)
        !          1229: {
        !          1230:   abort();
        !          1231: }
        !          1232: 
        !          1233: /* this makes a new connection side for a sun_si: */
        !          1234: static int
        !          1235: _tme_sun_si_connections_new(struct tme_element *element,
        !          1236:                            const char * const *args,
        !          1237:                            struct tme_connection **_conns,
        !          1238:                            char **_output)
        !          1239: {
        !          1240:   struct tme_sun_si *sun_si;
        !          1241:   struct tme_sun_si_connection *conn_sun_si;
        !          1242:   struct tme_bus_connection *conn_bus;
        !          1243:   struct tme_connection *conn;
        !          1244:   unsigned int ncr5380;
        !          1245:   unsigned int regs;
        !          1246:   int usage;
        !          1247:   int rc;
        !          1248: 
        !          1249:   /* recover our data structure: */
        !          1250:   sun_si = (struct tme_sun_si *) element->tme_element_private;
        !          1251:   
        !          1252:   /* we don't bother locking the mutex simply to check if connections
        !          1253:      already exist: */
        !          1254: 
        !          1255:   /* check our arguments: */
        !          1256:   usage = FALSE;
        !          1257:   rc = 0;
        !          1258:   regs = FALSE;
        !          1259:   ncr5380 = FALSE;
        !          1260: 
        !          1261:   /* if this connection is for the registers: */
        !          1262:   if (TME_ARG_IS(args[1], "csr")) {
        !          1263: 
        !          1264:     /* if we already have a register connection, complain: */
        !          1265:     if (sun_si->tme_sun_si_conn_regs != NULL) {
        !          1266:       rc = EEXIST;
        !          1267:     }
        !          1268: 
        !          1269:     /* otherwise, make the new connection: */
        !          1270:     else {
        !          1271:       regs = TRUE;
        !          1272:     }
        !          1273:   }
        !          1274: 
        !          1275:   /* else, if this connection is for the memory: */
        !          1276:   else if ((sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_ONBOARD
        !          1277:            || sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_COBRA)
        !          1278:           && TME_ARG_IS(args[1], "memory")) {
        !          1279: 
        !          1280:     /* if we already have a memory connection, complain: */
        !          1281:     if (sun_si->tme_sun_si_conn_memory != NULL) {
        !          1282:       rc = EEXIST;
        !          1283:     }
        !          1284:   }
        !          1285: 
        !          1286:   /* else, the connection must be for the ncr5380: */
        !          1287:   else if (args[1] == NULL) {
        !          1288:     
        !          1289:     /* if we already have an ncr5380 connection, complain: */
        !          1290:     if (sun_si->tme_sun_si_conn_ncr5380 != NULL) {
        !          1291:       rc = EEXIST;
        !          1292:     }
        !          1293: 
        !          1294:     /* otherwise, make the new connection: */
        !          1295:     else {
        !          1296:       ncr5380 = TRUE;
        !          1297:     }
        !          1298:   }
        !          1299: 
        !          1300:   /* otherwise, this is a bad argument: */
        !          1301:   else {
        !          1302:     tme_output_append_error(_output,
        !          1303:                            "%s %s, ",
        !          1304:                            args[1],
        !          1305:                            _("unexpected"));
        !          1306:     usage = TRUE;
        !          1307:   }
        !          1308: 
        !          1309:   if (usage) {
        !          1310:     tme_output_append_error(_output, 
        !          1311:                            ((sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_ONBOARD
        !          1312:                              || sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_COBRA)
        !          1313:                             ? "%s %s [ csr | memory ]"
        !          1314:                             : "%s %s [ csr ]"),
        !          1315:                            _("usage:"),
        !          1316:                            args[0]);
        !          1317:     rc = EINVAL;
        !          1318:   }
        !          1319:   
        !          1320:   if (rc) {
        !          1321:     return (rc);
        !          1322:   }
        !          1323: 
        !          1324:   /* make a new connection: */
        !          1325:   conn_sun_si = tme_new0(struct tme_sun_si_connection, 1);
        !          1326:   conn_bus = &conn_sun_si->tme_sun_si_connection;
        !          1327:   conn = &conn_bus->tme_bus_connection;
        !          1328: 
        !          1329:   /* fill in the generic connection: */
        !          1330:   conn->tme_connection_next = *_conns;
        !          1331:   conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC;
        !          1332:   conn->tme_connection_score = _tme_sun_si_connection_score;
        !          1333:   conn->tme_connection_make = _tme_sun_si_connection_make;
        !          1334:   conn->tme_connection_break = _tme_sun_si_connection_break;
        !          1335: 
        !          1336:   /* fill in the generic bus connection: */
        !          1337:   conn_bus->tme_bus_subregions.tme_bus_subregion_address_first = 0;
        !          1338:   conn_bus->tme_bus_subregions.tme_bus_subregion_next = NULL;
        !          1339:   if (ncr5380) {
        !          1340:     conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = ((tme_bus_addr_t) 0) - 1;
        !          1341:     conn_bus->tme_bus_signals_add = NULL;
        !          1342:     conn_bus->tme_bus_signal = _tme_sun_si_bus_signal;
        !          1343:     conn_bus->tme_bus_tlb_set_allocate = _tme_sun_si_tlb_set_allocate;
        !          1344:     conn_bus->tme_bus_tlb_fill = _tme_sun_si_tlb_fill;
        !          1345:   }
        !          1346:   else if (regs) {
        !          1347:     conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = TME_SUN_SI_SIZ_REGS - 1;
        !          1348:     conn_bus->tme_bus_tlb_fill = _tme_sun_si_tlb_fill_regs;
        !          1349:     if (sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_VME
        !          1350:        || sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_3E) {
        !          1351:       conn_bus->tme_bus_intack = _tme_sun_si_intack;
        !          1352:     }
        !          1353:   }
        !          1354:   else {
        !          1355:     conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = 0;
        !          1356:   }
        !          1357: 
        !          1358:   /* fill in the internal information: */
        !          1359:   conn_sun_si->tme_sun_si_connection_regs = regs;
        !          1360: 
        !          1361:   /* return the connection side possibility: */
        !          1362:   *_conns = conn;
        !          1363:   return (TME_OK);
        !          1364: }
        !          1365: 
        !          1366: /* the new sun_si function: */
        !          1367: int
        !          1368: tme_sun_si(struct tme_element *element, const char * const *args, char **_output)
        !          1369: {
        !          1370:   struct tme_sun_si *sun_si;
        !          1371:   int arg_i;
        !          1372:   int usage;
        !          1373:   tme_uint32_t si_type;
        !          1374: 
        !          1375:   /* check our arguments: */
        !          1376:   usage = 0;
        !          1377:   si_type = TME_SUN_SI_TYPE_NULL;
        !          1378:   arg_i = 1;
        !          1379:   for (;;) {
        !          1380: 
        !          1381:     /* the si type: */
        !          1382:     if (TME_ARG_IS(args[arg_i + 0], "type")) {
        !          1383:       if (TME_ARG_IS(args[arg_i + 1], "vme")) {
        !          1384:        si_type = TME_SUN_SI_TYPE_VME;
        !          1385:       }
        !          1386:       else if (TME_ARG_IS(args[arg_i + 1], "onboard")) {
        !          1387:        si_type = TME_SUN_SI_TYPE_ONBOARD;
        !          1388:       }
        !          1389:       else if (TME_ARG_IS(args[arg_i + 1], "3/E")) {
        !          1390:        si_type = TME_SUN_SI_TYPE_3E;
        !          1391:       }
        !          1392:       else if (TME_ARG_IS(args[arg_i + 1], "cobra")) {
        !          1393:        si_type = TME_SUN_SI_TYPE_COBRA;
        !          1394:       }
        !          1395:       else {
        !          1396:        usage = TRUE;
        !          1397:        break;
        !          1398:       }
        !          1399:       arg_i += 2;
        !          1400:     }
        !          1401: 
        !          1402:     /* if we ran out of arguments: */
        !          1403:     else if (args[arg_i] == NULL) {
        !          1404: 
        !          1405:       break;
        !          1406:     }
        !          1407: 
        !          1408:     /* otherwise this is a bad argument: */
        !          1409:     else {
        !          1410:       tme_output_append_error(_output,
        !          1411:                              "%s %s, ",
        !          1412:                              args[arg_i],
        !          1413:                              _("unexpected"));
        !          1414:       usage = TRUE;
        !          1415:       break;
        !          1416:     }
        !          1417:   }
        !          1418: 
        !          1419:   if (usage) {
        !          1420:     tme_output_append_error(_output, 
        !          1421:                            "%s %s type { vme | onboard | 3/E | cobra } [ size { 1600x1280 | 1152x900 | 1024x1024 | 1280x1024 | 1440x1440 | 640x480 } ]",
        !          1422:                            _("usage:"),
        !          1423:                            args[0]);
        !          1424:     return (EINVAL);
        !          1425:   }
        !          1426: 
        !          1427:   /* start the sun_si structure: */
        !          1428:   sun_si = tme_new0(struct tme_sun_si, 1);
        !          1429:   sun_si->tme_sun_si_type = si_type;
        !          1430:   sun_si->tme_sun_si_3e_dma = (si_type == TME_SUN_SI_TYPE_3E
        !          1431:                               ? tme_new(char, TME_SUN_SI_3E_SIZ_DMA)
        !          1432:                               : NULL);
        !          1433:   sun_si->tme_sun_si_element = element;
        !          1434:   TME_SUN_SI_CSR_PUT(sun_si,
        !          1435:                     ((si_type == TME_SUN_SI_TYPE_VME
        !          1436:                       ? TME_SUN_SI_CSR_VME_MODIFIED
        !          1437:                       : 0)
        !          1438:                      | (si_type == TME_SUN_SI_TYPE_3E
        !          1439:                         ? TME_SUN_SI_CSR_3E_VCC
        !          1440:                         : TME_SUN_SI_CSR_RESET_FIFO)
        !          1441:                      | TME_SUN_SI_CSR_RESET_CONTROLLER));
        !          1442:   sun_si->tme_sun_si_csr_ncr5380 = TME_SUN_SI_CSR_GET(sun_si);
        !          1443:   tme_mutex_init(&sun_si->tme_sun_si_mutex);
        !          1444:   tme_rwlock_init(&sun_si->tme_sun_si_rwlock);
        !          1445: 
        !          1446:   /* fill the element: */
        !          1447:   element->tme_element_private = sun_si;
        !          1448:   element->tme_element_connections_new = _tme_sun_si_connections_new;
        !          1449: 
        !          1450:   return (TME_OK);
        !          1451: }

unix.superglobalmegacorp.com

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