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