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

1.1.1.3 ! root        1: /* $Id: sun-si.c,v 1.7 2010/06/05 19:25:16 fredette Exp $ */
1.1       root        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>
1.1.1.3 ! root       37: _TME_RCSID("$Id: sun-si.c,v 1.7 2010/06/05 19:25:16 fredette Exp $");
1.1       root       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: */
1.1.1.3 ! root      192:   struct tme_token *tme_sun_si_ncr5380_tlb_token;
1.1       root      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;
1.1.1.3 ! root      476:   tme_bus_addr32_t address;
1.1       root      477:   tme_uint8_t cycle_size;
                    478:   tme_uint32_t dma_count;
                    479:   int new_callouts;
                    480: 
                    481:   /* get the address and cycle size: */
                    482:   address = cycle_init->tme_bus_cycle_address;
                    483:   cycle_size = cycle_init->tme_bus_cycle_size;
                    484: 
                    485:   /* it appears that si hardware doesn't respond to a byte access
                    486:      to its DMA count register.  at least, SunOS' sc probe routine
                    487:      seems to rely on this to distinguish an si from an sc: */
                    488:   if (address == TME_SUN_SI_REG_DMA_COUNT
                    489:       && cycle_size == sizeof(tme_uint8_t)) {
                    490:     return (EINVAL);
                    491:   }
                    492: 
                    493:   /* recover our data structure: */
                    494:   sun_si = (struct tme_sun_si *) _sun_si;
                    495: 
                    496:   /* assume we won't need any new callouts: */
                    497:   new_callouts = 0;
                    498: 
                    499:   /* lock the mutex: */
                    500:   tme_mutex_lock(&sun_si->tme_sun_si_mutex);
                    501: 
                    502:   /* get the previous CSR value: */
                    503:   csr_old = TME_SUN_SI_CSR_GET(sun_si);
                    504: 
                    505:   /* run the cycle: */
                    506:   tme_bus_cycle_xfer_memory(cycle_init, 
                    507:                            sun_si->tme_sun_si_regs,
                    508:                            TME_SUN_SI_SIZ_REGS - 1);
                    509: 
                    510: #define _TME_SUN_SI_REG_IS(reg, type) TME_RANGES_OVERLAP(address, address + cycle_size - 1, (reg), (reg) + sizeof(type) - 1)
                    511: 
                    512:   /* if this was a write: */
                    513:   if (cycle_init->tme_bus_cycle_type
                    514:       == TME_BUS_CYCLE_WRITE) {
                    515: 
                    516:     /* if this is a VME controller: */
                    517:     if (sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_VME) {
                    518: 
                    519:       /* if this was a write to the DMA count register: */
                    520:       if (_TME_SUN_SI_REG_IS(TME_SUN_SI_REG_DMA_COUNT, tme_uint32_t)) {
                    521: 
                    522:        /* get the DMA count register: */
                    523:        dma_count = TME_SUN_SI_REG32_GET(sun_si, TME_SUN_SI_REG_DMA_COUNT);
                    524: 
                    525:        /* copy the DMA count register to the FIFO count register: */
                    526:        TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_VME_FIFO_COUNT_H, (dma_count >> 16));
                    527:        TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_FIFO_COUNT_L, (dma_count & 0xffff));
                    528:       }
                    529:     }
                    530: 
                    531:     /* get the current CSR value, and put back any bits that
                    532:        software can't change: */
                    533:     csr_mask = (sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_3E
                    534:                ? TME_SUN_SI_CSR_3E_READONLY
                    535:                : TME_SUN_SI_CSR_READONLY);
                    536:     csr_new = ((TME_SUN_SI_CSR_GET(sun_si)
                    537:                & ~csr_mask)
                    538:               | (csr_old
                    539:                  & csr_mask));
                    540: 
                    541:     /* get the sets of CSR bits that have changed: */
                    542:     csr_diff = (csr_old ^ csr_new);
                    543: 
                    544:     /* if the FIFO is being reset: */
                    545:     if (sun_si->tme_sun_si_type != TME_SUN_SI_TYPE_3E
                    546:        && (csr_diff & TME_SUN_SI_CSR_RESET_FIFO)
                    547:        && !(csr_new & TME_SUN_SI_CSR_RESET_FIFO)) {
                    548: 
                    549:       /* reset the FIFOs: */
                    550:       TME_SUN_SI_REG32_PUT(sun_si, TME_SUN_SI_REG_DMA_ADDRESS, 0);
                    551:       TME_SUN_SI_REG32_PUT(sun_si, TME_SUN_SI_REG_DMA_COUNT, 0);
                    552:       switch (sun_si->tme_sun_si_type) {
                    553:       default: 
                    554:        assert(FALSE);
                    555:        /* FALLTHROUGH */
                    556:       case TME_SUN_SI_TYPE_ONBOARD:
                    557:        TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_ONBOARD_FIFO_DATA, 0);
                    558:        TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_FIFO_COUNT_L, 0);
                    559:        break;
                    560:       case TME_SUN_SI_TYPE_VME:
                    561:        TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_FIFO_COUNT_L, 0);
                    562:        TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_VME_FIFO_COUNT_H, 0);
1.1.1.2   root      563:        csr_new &= ~TME_SUN_SI_CSR_VME_LOB_MASK;
1.1       root      564:        break;
                    565:       case TME_SUN_SI_TYPE_COBRA:
                    566:        abort();
                    567:        break;
                    568:       }
                    569:     }
                    570: 
                    571:     /* if the CSR has changed at all: */
                    572:     if (csr_new != csr_old) {
                    573: 
                    574:       /* put back the new CSR: */
                    575:       tme_log(&sun_si->tme_sun_si_element->tme_element_log_handle,
                    576:              100, TME_OK,
                    577:              (&sun_si->tme_sun_si_element->tme_element_log_handle,
                    578:               "CSR now 0x%04x",
                    579:               csr_new));
                    580:       TME_SUN_SI_CSR_PUT(sun_si, csr_new);
                    581: 
                    582:       /* assume that we need to call out changes to bus signals and
                    583:        our interrupt: */
                    584:       new_callouts |= TME_SUN_SI_CALLOUT_INT | TME_SUN_SI_CALLOUT_SIGNALS;
                    585:     }
                    586:   }
                    587: 
                    588:   /* make any new callouts: */
                    589:   _tme_sun_si_callout(sun_si, new_callouts);
                    590: 
                    591:   /* unlock the mutex: */
                    592:   tme_mutex_unlock(&sun_si->tme_sun_si_mutex);
                    593: 
                    594:   /* no faults: */
                    595:   return (TME_OK);
                    596: }
                    597: 
                    598: /* the sun_si TLB filler for the board registers (and, on the 3/E, for
                    599:    the board memory on the VME bus): */
                    600: static int
                    601: _tme_sun_si_tlb_fill_regs(struct tme_bus_connection *conn_bus,
                    602:                          struct tme_bus_tlb *tlb, 
1.1.1.3 ! root      603:                          tme_bus_addr_t address_bus,
        !           604:                          unsigned int cycles)
1.1       root      605: {
                    606:   struct tme_sun_si *sun_si;
1.1.1.3 ! root      607:   tme_bus_addr32_t address;
1.1       root      608:   struct tme_bus_connection *conn_ncr5380;
1.1.1.3 ! root      609:   tme_bus_addr32_t address_regs;
1.1       root      610:   struct tme_bus_tlb tlb_mapping;
                    611:   int rc;
                    612: 
                    613:   /* recover our data structures: */
                    614:   sun_si = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
                    615: 
1.1.1.3 ! root      616:   /* get the internal address: */
        !           617:   address = address_bus;
        !           618:   assert (address == address_bus);
        !           619: 
1.1       root      620:   /* assume that the registers start at address zero: */
                    621:   address_regs = 0;
                    622: 
                    623:   /* dispatch on the controller type: */
                    624:   switch (sun_si->tme_sun_si_type) {
                    625: 
                    626:   case TME_SUN_SI_TYPE_3E:
                    627: 
                    628:     /* the board registers follow the DMA buffer: */
                    629:     address_regs = TME_SUN_SI_3E_SIZ_DMA;
                    630: 
                    631:     /* if this address is in the DMA buffer: */
                    632:     if (address < TME_SUN_SI_3E_SIZ_DMA) {
                    633: 
                    634:       /* initialize the TLB entry: */
                    635:       tme_bus_tlb_initialize(tlb);
                    636: 
                    637:       /* this TLB entry covers this range: */
1.1.1.2   root      638:       tlb->tme_bus_tlb_addr_first = 0;
                    639:       tlb->tme_bus_tlb_addr_last = TME_SUN_SI_3E_SIZ_DMA - 1;
1.1       root      640: 
                    641:       /* this TLB entry allows fast reading and writing: */
                    642:       tlb->tme_bus_tlb_emulator_off_read = sun_si->tme_sun_si_3e_dma;
                    643:       tlb->tme_bus_tlb_emulator_off_write = sun_si->tme_sun_si_3e_dma;
                    644:       
                    645:       /* allow reading and writing: */
                    646:       tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
                    647: 
                    648:       /* our bus cycle handler: */
                    649:       tlb->tme_bus_tlb_cycle_private = sun_si;
                    650:       tlb->tme_bus_tlb_cycle = _tme_sun_si_bus_cycle_3e_dma;
                    651: 
                    652:       return (TME_OK);
                    653:     }
                    654:     break;
                    655: 
                    656:   default:
                    657:     break;
                    658:   }
                    659: 
                    660:   /* offset the address: */
                    661:   address -= address_regs;
                    662: 
                    663:   /* the address must be within range: */
                    664:   assert(address < TME_SUN_SI_SIZ_REGS);
                    665: 
                    666:   /* if this address is in the NCR 5380 registers: */
                    667:   if (address < TME_SUN_SI_SIZ_NCR5380) {
                    668: 
                    669:     /* get the NCR 5380 connection: */
                    670:     conn_ncr5380 = sun_si->tme_sun_si_conn_ncr5380;
                    671: 
                    672:     /* call the NCR 5380 TLB fill function: */
                    673:     rc = (conn_ncr5380 != NULL
                    674:          ? (*conn_ncr5380->tme_bus_tlb_fill)(conn_ncr5380, tlb,
                    675:                                              address, cycles)
                    676:          : EINVAL);
                    677: 
                    678:     /* if that succeeded: */
                    679:     if (rc == TME_OK) {
                    680:       
                    681:       /* create the mapping TLB entry: */
1.1.1.2   root      682:       tlb_mapping.tme_bus_tlb_addr_first = (address_regs + TME_SUN_SI_REG_NCR5380);
                    683:       tlb_mapping.tme_bus_tlb_addr_last
                    684:        = (address_regs
                    685:           + TME_SUN_SI_REG_NCR5380
                    686:           + TME_SUN_SI_SIZ_NCR5380
                    687:           - 1);
1.1       root      688:       tlb_mapping.tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
                    689:       
                    690:       /* map the filled TLB entry: */
                    691:       tme_bus_tlb_map(tlb, 0, &tlb_mapping, address_regs + TME_SUN_SI_REG_NCR5380);
                    692:     }
                    693: 
                    694:     return (rc);
                    695:   }
                    696: 
                    697:   /* initialize the TLB entry: */
                    698:   tme_bus_tlb_initialize(tlb);
                    699: 
                    700:   /* this TLB entry covers this range: */
1.1.1.2   root      701:   tlb->tme_bus_tlb_addr_first = (address_regs + TME_SUN_SI_SIZ_NCR5380);
                    702:   tlb->tme_bus_tlb_addr_last = (address_regs + TME_SUN_SI_SIZ_REGS - 1);
                    703: 
                    704:   /* NB: even though our controller registers don't have read
                    705:      side-effects, we can't support fast reading, because we have to
                    706:      be able to fault a byte access to the DMA count register.  at
                    707:      least, SunOS' sc probe routine seems to rely on this to
                    708:      distinguish an si from an sc: */
1.1       root      709: 
                    710:   /* allow reading and writing: */
                    711:   tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
                    712: 
                    713:   /* our bus cycle handler: */
                    714:   tlb->tme_bus_tlb_cycle_private = sun_si;
                    715:   tlb->tme_bus_tlb_cycle = _tme_sun_si_bus_cycle_regs;
                    716: 
                    717:   return (TME_OK);
                    718: }
                    719: 
                    720: /* the interrupt acknowledge function for the VME and 3/E types: */
                    721: static int
                    722: _tme_sun_si_intack(struct tme_bus_connection *conn_bus, unsigned int signal, int *_vector)
                    723: {
                    724:   struct tme_sun_si *sun_si;
                    725:   int vector;
                    726: 
                    727:   /* recover our data structure: */
                    728:   sun_si = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
                    729: 
                    730:   /* dispatch on the controller type: */
                    731:   switch (sun_si->tme_sun_si_type) {
                    732:   default:
                    733:     assert (FALSE);
                    734:     /* FALLTHROUGH */
                    735: 
                    736:   case TME_SUN_SI_TYPE_3E:
                    737:     vector = sun_si->tme_sun_si_regs[TME_SUN_SI_REG_3E_IVEC];
                    738:     break;
                    739: 
                    740:   case TME_SUN_SI_TYPE_VME:
                    741:     vector = TME_SUN_SI_REG16_GET(sun_si, TME_SUN_SI_REG_VME_IV_AM) & 0xff;
                    742:     break;
                    743:   }
                    744: 
                    745:   /* return the interrupt vector: */
                    746:   *_vector = vector;
                    747:   return (TME_OK);
                    748: }
                    749: 
                    750: /* the sun_si bus signal handler for the NCR 5380: */
                    751: static int
                    752: _tme_sun_si_bus_signal(struct tme_bus_connection *conn_bus, 
                    753:                       unsigned int signal)
                    754: {
                    755:   struct tme_sun_si *sun_si;
                    756:   tme_uint32_t csr;
                    757: 
                    758:   /* this must be the unspecified interrupt signal: */
                    759:   assert (TME_BUS_SIGNAL_WHICH(signal) == TME_BUS_SIGNAL_INT_UNSPEC);
                    760: 
                    761:   /* recover our data structures: */
                    762:   sun_si = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
                    763: 
                    764:   /* lock our mutex: */
                    765:   tme_mutex_lock(&sun_si->tme_sun_si_mutex);
                    766: 
                    767:   /* update the CSR value: */
                    768:   csr = TME_SUN_SI_CSR_GET(sun_si);
                    769:   csr = ((csr
                    770:          & ~TME_SUN_SI_CSR_INT_NCR5380)
                    771:         | (((signal & TME_BUS_SIGNAL_LEVEL_MASK)
                    772:             == TME_BUS_SIGNAL_LEVEL_ASSERTED)
                    773:            ? TME_SUN_SI_CSR_INT_NCR5380
                    774:            : 0));
                    775:   TME_SUN_SI_CSR_PUT(sun_si, csr);
                    776: 
                    777:   /* call out an interrupt change: */
                    778:   _tme_sun_si_callout(sun_si, TME_SUN_SI_CALLOUT_INT);
                    779: 
                    780:   /* unlock our mutex: */
                    781:   tme_mutex_unlock(&sun_si->tme_sun_si_mutex);
                    782: 
                    783:   return (TME_OK);
                    784: }
                    785: 
                    786: /* the sun_si bus fault handler for the NCR 5380 DMA: */
                    787: static int
                    788: _tme_sun_si_bus_fault_handler(void *_sun_si, 
                    789:                              struct tme_bus_tlb *tlb,
                    790:                              struct tme_bus_cycle *cycle,
                    791:                              int rc)
                    792: {
                    793:   struct tme_sun_si *sun_si;
                    794: 
                    795:   /* recover our data structure: */
                    796:   sun_si = (struct tme_sun_si *) _sun_si;
                    797: 
                    798:   /* lock our mutex: */
                    799:   tme_mutex_lock(&sun_si->tme_sun_si_mutex);
                    800: 
                    801:   /* set a DMA bus error and call out an interrupt change: */
                    802:   TME_SUN_SI_CSR_PUT(sun_si, TME_SUN_SI_CSR_GET(sun_si) | TME_SUN_SI_CSR_DMA_BUS_ERROR);
                    803:   _tme_sun_si_callout(sun_si, TME_SUN_SI_CALLOUT_INT);    
                    804: 
                    805:   /* unlock our mutex: */
                    806:   tme_mutex_unlock(&sun_si->tme_sun_si_mutex);
                    807:   
                    808:   return (rc);
                    809: }
                    810: 
                    811: /* the sun_si TLB filler for the NCR 5380 DMA: */
                    812: static int
                    813: _tme_sun_si_tlb_fill(struct tme_bus_connection *conn_bus,
                    814:                     struct tme_bus_tlb *tlb, 
1.1.1.3 ! root      815:                     tme_bus_addr_t ncr5380_address_wider,
1.1       root      816:                     unsigned int cycles)
                    817: {
                    818:   struct tme_sun_si *sun_si;
1.1.1.3 ! root      819:   tme_bus_addr32_t ncr5380_address;
1.1       root      820:   tme_uint32_t csr;
1.1.1.3 ! root      821:   tme_bus_addr32_t dma_address;
1.1       root      822:   tme_uint32_t dma_count;
                    823:   tme_uint32_t bpr;
                    824:   unsigned int bpr_count;
                    825: #if defined(TME_SUN_SI_STRICT_VME)
                    826:   unsigned int bpr_i;
                    827: #endif /* defined(TME_SUN_SI_STRICT_VME) */
                    828:   struct tme_bus_tlb tlb_mapping;
                    829:   int rc;
                    830: 
                    831:   /* recover our data structures: */
                    832:   sun_si = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
                    833: 
1.1.1.3 ! root      834:   /* get the normal-width NCR 5380 DMA address: */
        !           835:   ncr5380_address = ncr5380_address_wider;
        !           836:   assert (ncr5380_address == ncr5380_address_wider);
        !           837: 
1.1       root      838:   /* assume that this call will succeed: */
                    839:   rc = TME_OK;
                    840: 
                    841:   /* lock our mutex: */
                    842:   tme_mutex_lock(&sun_si->tme_sun_si_mutex);
                    843: 
                    844:   /* if the NCR 5380 already has an outstanding TLB entry, and it
                    845:      doesn't happen to be this TLB entry, invalidate it: */
1.1.1.3 ! root      846:   if (sun_si->tme_sun_si_ncr5380_tlb_token != NULL
1.1       root      847:       && (tlb == NULL
1.1.1.3 ! root      848:          || (sun_si->tme_sun_si_ncr5380_tlb_token
        !           849:              != tlb->tme_bus_tlb_token))) {
        !           850:     tme_token_invalidate(sun_si->tme_sun_si_ncr5380_tlb_token);
1.1       root      851: 
                    852:     /* the NCR 5380 doesn't have any outstanding TLB entry: */
1.1.1.3 ! root      853:     sun_si->tme_sun_si_ncr5380_tlb_token = NULL;
1.1       root      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: */
1.1.1.2   root      921:     tlb->tme_bus_tlb_addr_first = 0;
                    922:     tlb->tme_bus_tlb_addr_last = dma_count - 1;
1.1       root      923: 
                    924:     /* this TLB entry supports fast reading and writing: */
                    925:     tlb->tme_bus_tlb_emulator_off_read = sun_si->tme_sun_si_3e_dma + dma_address;
                    926:     tlb->tme_bus_tlb_emulator_off_write = sun_si->tme_sun_si_3e_dma + dma_address;
                    927: 
                    928:     /* allow reading and writing: */
                    929:     tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
                    930: 
                    931:     /* our bus cycle handler: */
                    932:     tlb->tme_bus_tlb_cycle_private = sun_si;
                    933:     tlb->tme_bus_tlb_cycle = _tme_sun_si_bus_cycle_3e_dma;
                    934: 
                    935:     /* unlock our mutex: */
                    936:     tme_mutex_unlock(&sun_si->tme_sun_si_mutex);
                    937: 
                    938:     return (TME_OK);
                    939: 
                    940:   case TME_SUN_SI_TYPE_VME:
                    941: 
                    942:     /* if the NCR 5380 has stopped doing DMA, or if it has exhausted
                    943:        DMA, or if DMA is not enabled: */
                    944:     if (cycles == TME_BUS_CYCLE_UNDEF
                    945:        || ncr5380_address >= dma_count
                    946:        || ((csr
                    947:             & (TME_SUN_SI_CSR_DMA_CONFLICT
                    948:                | TME_SUN_SI_CSR_DMA_BUS_ERROR
                    949:                | TME_SUN_SI_CSR_DMA_ENABLE))
                    950:            != TME_SUN_SI_CSR_DMA_ENABLE)) {
                    951: 
                    952:       /* if the NCR 5380 has stopped doing DMA, cap the DMA count and
                    953:         address to the amount of DMA that was available, thus
                    954:         cancelling the effect of the NCR 5380 prefetch.  this
                    955:         prevents the DMA count from going negative, confusing the Sun
                    956:         PROM and probably SunOS.  I'm guessing that all of the SCSI
                    957:         devices ever used with Suns change information transfer phase
                    958:         faster than the NCR 5380 prefetches a byte from DMA, which is
                    959:         why this DMA-count-going-negative problem is never seen.  since
                    960:         our NCR 5380 is infinitely fast at prefetch, we have to deal: */
                    961:       if (cycles == TME_BUS_CYCLE_UNDEF
                    962:          && ncr5380_address > dma_count) {
                    963:        assert (ncr5380_address == (dma_count + 1));
                    964:        dma_address -= (ncr5380_address - dma_count);
                    965:        ncr5380_address = dma_count;
                    966:       }
                    967: 
                    968:       /* update the DMA address and count registers: */
                    969:       TME_SUN_SI_REG32_PUT(sun_si, TME_SUN_SI_REG_DMA_ADDRESS, dma_address);
                    970:       TME_SUN_SI_REG32_PUT(sun_si, TME_SUN_SI_REG_DMA_COUNT, dma_count - ncr5380_address);
                    971:       TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_VME_FIFO_COUNT_H, ((dma_count - ncr5380_address) >> 16));
                    972:       TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_FIFO_COUNT_L, ((dma_count - ncr5380_address) & 0xffff));
                    973: 
                    974:       /* assume that our emulated byte pack is empty: */
                    975:       bpr = 0;
                    976:       bpr_count = 0;
                    977: 
                    978: #ifdef TME_SUN_SI_STRICT_VME
                    979: 
                    980:       /* if the NCR 5380 was doing DMA writes to memory (i.e., it was
                    981:          receiving): */
                    982:       if (!(csr & TME_SUN_SI_CSR_DMA_SEND)) {
                    983: 
                    984:        /* calculate how many bytes must be left in the byte pack: */
                    985:        bpr_count = ncr5380_address;
                    986:        bpr_count &= ((csr & TME_SUN_SI_CSR_VME_BPCON)
                    987:                      ? (sizeof(tme_uint16_t) - 1)
                    988:                      : (sizeof(tme_uint32_t) - 1));
                    989: 
                    990:        /* get the byte pack contents from the memory that the NCR
                    991:           5380 DMA'ed into.  this is why all DMA writes have to be to
                    992:           fast memory under TME_SUN_SI_STRICT_VME - if you DMA to
                    993:           memory with side-effects, we can't read the data back out
                    994:           again without incurring more side-effects, and we don't
                    995:           want to do a *full* emulation of the DMA engine: */
                    996:        for (bpr_i = bpr_count; bpr_i > 0; bpr_i--) {
                    997:          bpr = (bpr << 8) | sun_si->tme_sun_si_dma_buffer_write[ncr5380_address - bpr_i];
                    998:        }
                    999: 
                   1000:        /* left-justify the byte pack: */
                   1001:        bpr <<= ((((csr & TME_SUN_SI_CSR_VME_BPCON)
                   1002:                    ? sizeof(tme_uint16_t)
                   1003:                    : sizeof(tme_uint32_t))
                   1004:                   - bpr_count)
                   1005:                  * 8);
                   1006: 
                   1007:       }
                   1008: 
                   1009:       /* otherwise, the NCR 5380 was doing DMA reads to memory (i.e.,
                   1010:         it was sending): */
                   1011:       else {
                   1012: 
                   1013:        /* nothing to do.  we don't emulate the byte pack for sending: */
                   1014:       }
                   1015: 
                   1016: #endif  /* TME_SUN_SI_STRICT_VME */
                   1017: 
                   1018:       /* update the byte pack and the CSR: */
                   1019:       TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_VME_BPR_H, (bpr >> 16));
                   1020:       TME_SUN_SI_REG16_PUT(sun_si, TME_SUN_SI_REG_VME_BPR_L, (bpr & 0xffff));
                   1021:       TME_FIELD_MASK_DEPOSITU(csr, TME_SUN_SI_CSR_VME_LOB_MASK, bpr_count);
                   1022:       TME_SUN_SI_CSR_PUT(sun_si, csr);
                   1023: 
                   1024:       /* return EAGAIN to the NCR 5380, unless it was the NCR 5380
                   1025:         that stopped doing DMA: */
                   1026:       if (cycles != TME_BUS_CYCLE_UNDEF) {
                   1027:        rc = EAGAIN;
                   1028:       }
                   1029:       break;
                   1030:     }
                   1031:     break;
                   1032: 
                   1033:   case TME_SUN_SI_TYPE_ONBOARD:
                   1034:     /* TBD */
                   1035:     abort();
                   1036: 
                   1037:   case TME_SUN_SI_TYPE_COBRA:
                   1038:     /* TBD */
                   1039:     abort();
                   1040:   }
                   1041: 
                   1042:   /* if DMA is not ready for some reason: */
                   1043:   if (rc == EAGAIN) {
                   1044: 
1.1.1.2   root     1045:     /* initialize any local TLB entry passed by the caller.  this
                   1046:        will make it unusable: */
1.1       root     1047:     if (tlb != NULL) {
1.1.1.2   root     1048:       tme_bus_tlb_initialize(tlb);
1.1       root     1049:     }
                   1050: 
                   1051:     /* if DMA is enabled: */
                   1052:     if (csr & TME_SUN_SI_CSR_DMA_ENABLE) {
                   1053: 
                   1054:       /* set a DMA interrupt and call out an interrupt change: */
                   1055:       TME_SUN_SI_CSR_PUT(sun_si, TME_SUN_SI_CSR_GET(sun_si) | TME_SUN_SI_CSR_INT_DMA);
                   1056:       _tme_sun_si_callout(sun_si, TME_SUN_SI_CALLOUT_INT);    
                   1057:     }
                   1058: 
                   1059:     /* cancel the remainder of the TLB fill: */
                   1060:     cycles = TME_BUS_CYCLE_UNDEF;
                   1061:   }
                   1062: 
                   1063:   /* get the bus connection for memory: */
                   1064:   conn_bus = sun_si->tme_sun_si_conn_memory;
                   1065: 
                   1066:   /* if we need to fill a TLB entry on the bus: */
                   1067:   if (cycles != TME_BUS_CYCLE_UNDEF) {
                   1068: 
                   1069:     /* the NCR 5380 now has this outstanding TLB entry: */
1.1.1.3 ! root     1070:     sun_si->tme_sun_si_ncr5380_tlb_token
        !          1071:       = tlb->tme_bus_tlb_token;
1.1       root     1072:   }
                   1073: 
                   1074:   /* unlock our mutex: */
                   1075:   tme_mutex_unlock(&sun_si->tme_sun_si_mutex);
                   1076: 
                   1077:   /* if we need to fill a TLB entry on the bus: */
                   1078:   if (cycles != TME_BUS_CYCLE_UNDEF) {
                   1079: 
                   1080:     /* DMA must be OK so far: */
                   1081:     assert (rc == TME_OK);
                   1082:     assert (dma_count > ncr5380_address);
                   1083: 
                   1084:     /* call out to fill this TLB entry on the bus: */
                   1085:     rc = (conn_bus != NULL
                   1086:          ? (*conn_bus->tme_bus_tlb_fill)(conn_bus, 
                   1087:                                          tlb,
                   1088:                                          dma_address,
                   1089:                                          cycles)
                   1090:          : ENXIO);
                   1091: 
                   1092:     /* if this callout succeeded: */
                   1093:     if (rc == TME_OK) {
                   1094: 
                   1095: #if defined(TME_SUN_SI_STRICT_VME) || defined(TME_SUN_SI_STRICT_ONBOARD) || defined(TME_SUN_SI_STRICT_COBRA)
                   1096: 
                   1097:       /* when the NCR 5380 wants to do DMA writes, in order to
                   1098:         correctly emulate the byte pack registers on these
                   1099:         controllers without having to emulate their full DMA behavior
                   1100:         (copying 16- or 32-bit words into a controller register for
                   1101:         the NCR 5380), we just insist that all DMA be done to memory
                   1102:         that supports fast access: */
                   1103:       if ((cycles & TME_BUS_CYCLE_WRITE)
                   1104:          && tlb->tme_bus_tlb_emulator_off_write == TME_EMULATOR_OFF_UNDEF) {
                   1105:        abort();
                   1106:       }
                   1107:       
                   1108: #endif /* defined(TME_SUN_SI_STRICT_VME) || defined(TME_SUN_SI_STRICT_ONBOARD) || defined(TME_SUN_SI_STRICT_COBRA) */
                   1109: 
                   1110:       /* create the mapping TLB entry: */
1.1.1.2   root     1111:       tlb_mapping.tme_bus_tlb_addr_first = ncr5380_address;
                   1112:       tlb_mapping.tme_bus_tlb_addr_last = dma_count - 1;
1.1       root     1113:       tlb_mapping.tme_bus_tlb_cycles_ok = cycles;
                   1114:       
                   1115:       /* map the filled TLB entry: */
                   1116:       tme_bus_tlb_map(tlb, dma_address, &tlb_mapping, ncr5380_address);
                   1117: 
                   1118:       /* add our bus fault handler: */
                   1119:       TME_BUS_TLB_FAULT_HANDLER(tlb, _tme_sun_si_bus_fault_handler, sun_si);
                   1120:     }
                   1121:   }
                   1122: 
                   1123:   return (rc);
                   1124: }
                   1125: 
1.1.1.3 ! root     1126: /* the sun_si TLB adder for the NCR 5380: */
1.1       root     1127: static int
1.1.1.3 ! root     1128: _tme_sun_si_tlb_set_add(struct tme_bus_connection *conn_bus,
        !          1129:                        struct tme_bus_tlb_set_info *tlb_set_info)
1.1       root     1130: {
                   1131:   struct tme_sun_si *sun_si;
                   1132: 
                   1133:   /* recover our data structures: */
                   1134:   sun_si = conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
                   1135: 
                   1136:   /* pass the sun_si's request through to the memory bus: */
                   1137:   conn_bus = sun_si->tme_sun_si_conn_memory;
                   1138:   return (conn_bus != NULL
1.1.1.3 ! root     1139:          ? (*conn_bus->tme_bus_tlb_set_add)(conn_bus, 
        !          1140:                                             tlb_set_info)
1.1       root     1141:          : ENXIO);
                   1142: }
                   1143: 
                   1144: /* this scores a new connection: */
                   1145: static int
                   1146: _tme_sun_si_connection_score(struct tme_connection *conn, unsigned int *_score)
                   1147: {
                   1148:   struct tme_sun_si *sun_si;
                   1149:   struct tme_sun_si_connection *conn_sun_si;
                   1150: 
                   1151:   /* both sides must be generic bus connections: */
                   1152:   assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC);
                   1153:   assert(conn->tme_connection_other->tme_connection_type
                   1154:         == conn->tme_connection_type);
                   1155: 
                   1156:   /* recover our data structures: */
                   1157:   sun_si = conn->tme_connection_element->tme_element_private;
                   1158:   conn_sun_si = (struct tme_sun_si_connection *)conn;
                   1159: 
                   1160:   /* this is a generic bus connection, so just score it nonzero and
                   1161:      return.  note that there's no good way to differentiate a
                   1162:      connection to a bus from a connection to just another chip, so we
                   1163:      always return a nonzero score here: */
                   1164:   *_score = 1;
                   1165:   return (TME_OK);
                   1166: }
                   1167: 
                   1168: /* this makes a new connection: */
                   1169: static int
                   1170: _tme_sun_si_connection_make(struct tme_connection *conn, unsigned int state)
                   1171: {
                   1172:   struct tme_sun_si *sun_si;
                   1173:   struct tme_sun_si_connection *conn_sun_si;
                   1174:   struct tme_bus_connection *conn_bus;
                   1175: 
                   1176:   /* both sides must be generic bus connections: */
                   1177:   assert(conn->tme_connection_type == TME_CONNECTION_BUS_GENERIC);
                   1178:   assert(conn->tme_connection_other->tme_connection_type
                   1179:         == conn->tme_connection_type);
                   1180: 
                   1181:   /* recover our data structures: */
                   1182:   sun_si = conn->tme_connection_element->tme_element_private;
                   1183:   conn_sun_si = (struct tme_sun_si_connection *) conn;
                   1184:   conn_bus = &conn_sun_si->tme_sun_si_connection;
                   1185: 
                   1186:   /* we're always set up to answer calls across the connection, so we
                   1187:      only have to do work when the connection has gone full, namely
                   1188:      taking the other side of the connection: */
                   1189:   if (state == TME_CONNECTION_FULL) {
                   1190: 
                   1191:     /* lock our mutex: */
                   1192:     tme_mutex_lock(&sun_si->tme_sun_si_mutex);
                   1193: 
                   1194:     /* save our connection: */
                   1195:     if (conn_bus->tme_bus_tlb_fill == _tme_sun_si_tlb_fill) {
                   1196:       sun_si->tme_sun_si_conn_ncr5380 = (struct tme_bus_connection *) conn->tme_connection_other;
                   1197:     }
                   1198:     else {
                   1199:       if (conn_sun_si->tme_sun_si_connection_regs) {
                   1200:        sun_si->tme_sun_si_conn_regs = (struct tme_bus_connection *) conn->tme_connection_other;
                   1201:       }
                   1202:       if (!(sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_ONBOARD
                   1203:            || sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_COBRA)
                   1204:          || !conn_sun_si->tme_sun_si_connection_regs) {
                   1205:        sun_si->tme_sun_si_conn_memory = (struct tme_bus_connection *) conn->tme_connection_other;
                   1206:       }
                   1207:     }
                   1208: 
                   1209:     /* unlock our mutex: */
                   1210:     tme_mutex_unlock(&sun_si->tme_sun_si_mutex);
                   1211:   }
                   1212: 
                   1213:   return (TME_OK);
                   1214: }
                   1215: 
                   1216: /* this breaks a connection: */
                   1217: static int
                   1218: _tme_sun_si_connection_break(struct tme_connection *conn, unsigned int state)
                   1219: {
                   1220:   abort();
                   1221: }
                   1222: 
                   1223: /* this makes a new connection side for a sun_si: */
                   1224: static int
                   1225: _tme_sun_si_connections_new(struct tme_element *element,
                   1226:                            const char * const *args,
                   1227:                            struct tme_connection **_conns,
                   1228:                            char **_output)
                   1229: {
                   1230:   struct tme_sun_si *sun_si;
                   1231:   struct tme_sun_si_connection *conn_sun_si;
                   1232:   struct tme_bus_connection *conn_bus;
                   1233:   struct tme_connection *conn;
                   1234:   unsigned int ncr5380;
                   1235:   unsigned int regs;
                   1236:   int usage;
                   1237:   int rc;
                   1238: 
                   1239:   /* recover our data structure: */
                   1240:   sun_si = (struct tme_sun_si *) element->tme_element_private;
                   1241:   
                   1242:   /* we don't bother locking the mutex simply to check if connections
                   1243:      already exist: */
                   1244: 
                   1245:   /* check our arguments: */
                   1246:   usage = FALSE;
                   1247:   rc = 0;
                   1248:   regs = FALSE;
                   1249:   ncr5380 = FALSE;
                   1250: 
                   1251:   /* if this connection is for the registers: */
                   1252:   if (TME_ARG_IS(args[1], "csr")) {
                   1253: 
                   1254:     /* if we already have a register connection, complain: */
                   1255:     if (sun_si->tme_sun_si_conn_regs != NULL) {
                   1256:       rc = EEXIST;
                   1257:     }
                   1258: 
                   1259:     /* otherwise, make the new connection: */
                   1260:     else {
                   1261:       regs = TRUE;
                   1262:     }
                   1263:   }
                   1264: 
                   1265:   /* else, if this connection is for the memory: */
                   1266:   else if ((sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_ONBOARD
                   1267:            || sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_COBRA)
                   1268:           && TME_ARG_IS(args[1], "memory")) {
                   1269: 
                   1270:     /* if we already have a memory connection, complain: */
                   1271:     if (sun_si->tme_sun_si_conn_memory != NULL) {
                   1272:       rc = EEXIST;
                   1273:     }
                   1274:   }
                   1275: 
                   1276:   /* else, the connection must be for the ncr5380: */
                   1277:   else if (args[1] == NULL) {
                   1278:     
                   1279:     /* if we already have an ncr5380 connection, complain: */
                   1280:     if (sun_si->tme_sun_si_conn_ncr5380 != NULL) {
                   1281:       rc = EEXIST;
                   1282:     }
                   1283: 
                   1284:     /* otherwise, make the new connection: */
                   1285:     else {
                   1286:       ncr5380 = TRUE;
                   1287:     }
                   1288:   }
                   1289: 
                   1290:   /* otherwise, this is a bad argument: */
                   1291:   else {
                   1292:     tme_output_append_error(_output,
                   1293:                            "%s %s, ",
                   1294:                            args[1],
                   1295:                            _("unexpected"));
                   1296:     usage = TRUE;
                   1297:   }
                   1298: 
                   1299:   if (usage) {
                   1300:     tme_output_append_error(_output, 
                   1301:                            ((sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_ONBOARD
                   1302:                              || sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_COBRA)
                   1303:                             ? "%s %s [ csr | memory ]"
                   1304:                             : "%s %s [ csr ]"),
                   1305:                            _("usage:"),
                   1306:                            args[0]);
                   1307:     rc = EINVAL;
                   1308:   }
                   1309:   
                   1310:   if (rc) {
                   1311:     return (rc);
                   1312:   }
                   1313: 
                   1314:   /* make a new connection: */
                   1315:   conn_sun_si = tme_new0(struct tme_sun_si_connection, 1);
                   1316:   conn_bus = &conn_sun_si->tme_sun_si_connection;
                   1317:   conn = &conn_bus->tme_bus_connection;
                   1318: 
                   1319:   /* fill in the generic connection: */
                   1320:   conn->tme_connection_next = *_conns;
                   1321:   conn->tme_connection_type = TME_CONNECTION_BUS_GENERIC;
                   1322:   conn->tme_connection_score = _tme_sun_si_connection_score;
                   1323:   conn->tme_connection_make = _tme_sun_si_connection_make;
                   1324:   conn->tme_connection_break = _tme_sun_si_connection_break;
                   1325: 
                   1326:   /* fill in the generic bus connection: */
                   1327:   conn_bus->tme_bus_subregions.tme_bus_subregion_address_first = 0;
                   1328:   conn_bus->tme_bus_subregions.tme_bus_subregion_next = NULL;
                   1329:   if (ncr5380) {
                   1330:     conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = ((tme_bus_addr_t) 0) - 1;
                   1331:     conn_bus->tme_bus_signals_add = NULL;
                   1332:     conn_bus->tme_bus_signal = _tme_sun_si_bus_signal;
1.1.1.3 ! root     1333:     conn_bus->tme_bus_tlb_set_add = _tme_sun_si_tlb_set_add;
1.1       root     1334:     conn_bus->tme_bus_tlb_fill = _tme_sun_si_tlb_fill;
                   1335:   }
                   1336:   else if (regs) {
                   1337:     conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = TME_SUN_SI_SIZ_REGS - 1;
                   1338:     conn_bus->tme_bus_tlb_fill = _tme_sun_si_tlb_fill_regs;
                   1339:     if (sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_VME
                   1340:        || sun_si->tme_sun_si_type == TME_SUN_SI_TYPE_3E) {
                   1341:       conn_bus->tme_bus_intack = _tme_sun_si_intack;
                   1342:     }
                   1343:   }
                   1344:   else {
                   1345:     conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = 0;
                   1346:   }
                   1347: 
                   1348:   /* fill in the internal information: */
                   1349:   conn_sun_si->tme_sun_si_connection_regs = regs;
                   1350: 
                   1351:   /* return the connection side possibility: */
                   1352:   *_conns = conn;
                   1353:   return (TME_OK);
                   1354: }
                   1355: 
                   1356: /* the new sun_si function: */
                   1357: int
                   1358: tme_sun_si(struct tme_element *element, const char * const *args, char **_output)
                   1359: {
                   1360:   struct tme_sun_si *sun_si;
                   1361:   int arg_i;
                   1362:   int usage;
                   1363:   tme_uint32_t si_type;
                   1364: 
                   1365:   /* check our arguments: */
                   1366:   usage = 0;
                   1367:   si_type = TME_SUN_SI_TYPE_NULL;
                   1368:   arg_i = 1;
                   1369:   for (;;) {
                   1370: 
                   1371:     /* the si type: */
                   1372:     if (TME_ARG_IS(args[arg_i + 0], "type")) {
                   1373:       if (TME_ARG_IS(args[arg_i + 1], "vme")) {
                   1374:        si_type = TME_SUN_SI_TYPE_VME;
                   1375:       }
                   1376:       else if (TME_ARG_IS(args[arg_i + 1], "onboard")) {
                   1377:        si_type = TME_SUN_SI_TYPE_ONBOARD;
                   1378:       }
                   1379:       else if (TME_ARG_IS(args[arg_i + 1], "3/E")) {
                   1380:        si_type = TME_SUN_SI_TYPE_3E;
                   1381:       }
                   1382:       else if (TME_ARG_IS(args[arg_i + 1], "cobra")) {
                   1383:        si_type = TME_SUN_SI_TYPE_COBRA;
                   1384:       }
                   1385:       else {
                   1386:        usage = TRUE;
                   1387:        break;
                   1388:       }
                   1389:       arg_i += 2;
                   1390:     }
                   1391: 
                   1392:     /* if we ran out of arguments: */
                   1393:     else if (args[arg_i] == NULL) {
                   1394: 
                   1395:       break;
                   1396:     }
                   1397: 
                   1398:     /* otherwise this is a bad argument: */
                   1399:     else {
                   1400:       tme_output_append_error(_output,
                   1401:                              "%s %s, ",
                   1402:                              args[arg_i],
                   1403:                              _("unexpected"));
                   1404:       usage = TRUE;
                   1405:       break;
                   1406:     }
                   1407:   }
                   1408: 
1.1.1.2   root     1409:   if (si_type == TME_SUN_SI_TYPE_NULL) {
                   1410:     usage = TRUE;
                   1411:   }
                   1412: 
1.1       root     1413:   if (usage) {
                   1414:     tme_output_append_error(_output, 
1.1.1.2   root     1415:                            "%s %s type { vme | onboard | 3/E | cobra }",
1.1       root     1416:                            _("usage:"),
                   1417:                            args[0]);
                   1418:     return (EINVAL);
                   1419:   }
                   1420: 
                   1421:   /* start the sun_si structure: */
                   1422:   sun_si = tme_new0(struct tme_sun_si, 1);
                   1423:   sun_si->tme_sun_si_type = si_type;
                   1424:   sun_si->tme_sun_si_3e_dma = (si_type == TME_SUN_SI_TYPE_3E
1.1.1.2   root     1425:                               ? tme_new(tme_uint8_t, TME_SUN_SI_3E_SIZ_DMA)
1.1       root     1426:                               : NULL);
                   1427:   sun_si->tme_sun_si_element = element;
                   1428:   TME_SUN_SI_CSR_PUT(sun_si,
                   1429:                     ((si_type == TME_SUN_SI_TYPE_VME
                   1430:                       ? TME_SUN_SI_CSR_VME_MODIFIED
                   1431:                       : 0)
                   1432:                      | (si_type == TME_SUN_SI_TYPE_3E
                   1433:                         ? TME_SUN_SI_CSR_3E_VCC
                   1434:                         : TME_SUN_SI_CSR_RESET_FIFO)
                   1435:                      | TME_SUN_SI_CSR_RESET_CONTROLLER));
                   1436:   sun_si->tme_sun_si_csr_ncr5380 = TME_SUN_SI_CSR_GET(sun_si);
                   1437:   tme_mutex_init(&sun_si->tme_sun_si_mutex);
                   1438:   tme_rwlock_init(&sun_si->tme_sun_si_rwlock);
                   1439: 
                   1440:   /* fill the element: */
                   1441:   element->tme_element_private = sun_si;
                   1442:   element->tme_element_connections_new = _tme_sun_si_connections_new;
                   1443: 
                   1444:   return (TME_OK);
                   1445: }

unix.superglobalmegacorp.com

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