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

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

unix.superglobalmegacorp.com

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