Annotation of tme/machine/sun/sun-si.c, revision 1.1.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.