|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.