|
|
1.1.1.2 ! root 1: /* $Id: sun3-control.c,v 1.3 2009/08/30 14:20:59 fredette Exp $ */ 1.1 root 2: 3: /* machine/sun3/sun3-control.c - implementation of Sun 3 emulation control space: */ 4: 5: /* 6: * Copyright (c) 2003, 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: sun3-control.c,v 1.3 2009/08/30 14:20:59 fredette Exp $"); 1.1 root 38: 39: /* includes: */ 40: #include "sun3-impl.h" 41: 42: /* the bus cycle handler for function code three space: */ 43: int 44: _tme_sun3_control_cycle_handler(void *_sun3, struct tme_bus_cycle *cycle_init) 45: { 46: struct tme_sun3 *sun3; 47: struct tme_bus_cycle cycle_resp; 48: tme_uint32_t address, reg; 49: tme_uint8_t port_data[sizeof(tme_uint32_t)]; 50: tme_uint8_t *port_data8; 51: tme_uint32_t *port_data32; 52: tme_uint32_t value32; 53: tme_uint8_t enable_old, enable_new; 54: int rc; 55: 56: /* recover our sun3: */ 57: sun3 = (struct tme_sun3 *) _sun3; 58: 59: /* get the address, convert it into a register number, then mask 60: the address: */ 61: address = cycle_init->tme_bus_cycle_address; 62: reg = TME_SUN3_CONTROL_REG(address); 63: if (reg != TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_IDPROM)) { 64: address &= TME_SUN3_CONTROL_MASK_ADDRESS; 65: } 66: 67: /* dispatch on the register, to get bytes for our port: */ 68: port_data8 = &port_data[0]; 69: port_data32 = (tme_uint32_t *) &port_data[0]; 70: switch (reg) { 71: 72: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_IDPROM): 73: memcpy(port_data, 74: &sun3->tme_sun3_idprom_contents[(address & (TME_SUN_IDPROM_SIZE - 1))], 75: TME_MIN(sizeof(port_data), 76: TME_SUN_IDPROM_SIZE - (address & (TME_SUN_IDPROM_SIZE - 1)))); 77: break; 78: 79: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_PGMAP): 80: rc = _tme_sun3_mmu_pte_get(sun3, address, &value32); 81: assert(rc == TME_OK); 82: *port_data32 = tme_htobe_u32(value32); 83: break; 84: 85: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_SEGMAP): 86: *port_data8 = tme_sun_mmu_segmap_get(sun3->tme_sun3_mmu, sun3->tme_sun3_context, address); 87: break; 88: 89: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_CONTEXT): 90: *port_data8 = sun3->tme_sun3_context; 91: break; 92: 93: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_ENABLE): 94: *port_data8 = sun3->tme_sun3_enable; 95: break; 96: 97: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_UDVMA): 98: *port_data8 = sun3->tme_sun3_udvma; 99: break; 100: 101: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_BUSERR): 102: *port_data8 = sun3->tme_sun3_buserr; 103: break; 104: 105: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_DIAG): 106: *port_data8 = sun3->tme_sun3_diag; 107: break; 108: 109: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_VAC_TAGS): 110: abort(); 111: break; 112: 113: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_VAC_DATA): 114: abort(); 115: break; 116: 117: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_VAC_FLUSH): 118: abort(); 119: break; 120: 121: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_COPY): 122: abort(); 123: break; 124: 125: default: 126: abort(); 127: } 128: 129: /* run the bus cycle: */ 130: cycle_resp.tme_bus_cycle_buffer = &port_data[0]; 131: cycle_resp.tme_bus_cycle_buffer_increment = 1; 132: cycle_resp.tme_bus_cycle_lane_routing = cycle_init->tme_bus_cycle_lane_routing; 133: cycle_resp.tme_bus_cycle_address = 0; 134: cycle_resp.tme_bus_cycle_type = (cycle_init->tme_bus_cycle_type 135: ^ (TME_BUS_CYCLE_WRITE 136: | TME_BUS_CYCLE_READ)); 137: cycle_resp.tme_bus_cycle_port = TME_BUS_CYCLE_PORT(0, TME_BUS32_LOG2); 138: tme_bus_cycle_xfer(cycle_init, &cycle_resp); 139: 140: /* whenever the bus error register is read or written, it is 141: cleared: */ 142: if (reg == TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_BUSERR)) { 143: sun3->tme_sun3_buserr = 0; 144: } 145: 146: /* these registers only need action taken when they're written: */ 147: if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) { 148: 149: /* dispatch on the register: */ 150: switch (reg) { 151: 152: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_PGMAP): 153: value32 = tme_betoh_u32(*port_data32); 154: rc = _tme_sun3_mmu_pte_set(sun3, address, value32); 155: assert (rc == TME_OK); 156: break; 157: 158: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_SEGMAP): 159: tme_sun_mmu_segmap_set(sun3->tme_sun3_mmu, sun3->tme_sun3_context, address, *port_data8 % TME_SUN3_PMEGS); 160: break; 161: 162: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_CONTEXT): 163: sun3->tme_sun3_context = *port_data8; 164: _tme_sun3_mmu_context_set(sun3); 165: break; 166: 167: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_ENABLE): 168: enable_old = sun3->tme_sun3_enable; 169: enable_new = (enable_old & TME_SUN3_ENA_DIAG) | (*port_data8 & ~TME_SUN3_ENA_DIAG); 170: sun3->tme_sun3_enable = enable_new; 171: 172: /* if we're changing to or from boot state, make a pseudo-context change: */ 173: if ((enable_old ^ enable_new) & TME_SUN3_ENA_NOTBOOT) { 174: _tme_sun3_mmu_context_set(sun3); 175: } 176: 177: /* if we're changing the m6888x enable bit, call out the change: */ 178: if ((enable_old ^ enable_new) & TME_SUN3_ENA_FPP) { 179: rc = ((*sun3->tme_sun3_m68k->tme_m68k_bus_m6888x_enable) 180: (sun3->tme_sun3_m68k, (enable_new & TME_SUN3_ENA_FPP))); 181: assert (rc == TME_OK); 182: } 183: 184: /* if we're enabling or disabling system DVMA, call out the change: */ 185: if ((enable_old ^ enable_new) & TME_SUN3_ENA_SDVMA) { 186: _tme_sun3_mmu_sdvma_change(sun3); 187: } 188: 189: /* certain things can't be enabled: */ 190: if (enable_new 191: & (TME_SUN3_ENA_COPY 192: | TME_SUN3_ENA_CACHE)) { 193: abort(); 194: } 195: break; 196: 197: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_UDVMA): 198: if (sun3->tme_sun3_enable & TME_SUN3_ENA_NOTBOOT) { 199: abort(); 200: } 201: sun3->tme_sun3_udvma = *port_data8; 202: break; 203: 204: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_DIAG): 205: sun3->tme_sun3_diag = *port_data8; 206: /* TBD */ 207: break; 208: 209: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_VAC_TAGS): 210: abort(); 211: break; 212: 213: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_VAC_DATA): 214: abort(); 215: break; 216: 217: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_VAC_FLUSH): 218: abort(); 219: break; 220: 221: case TME_SUN3_CONTROL_REG(TME_SUN3_CONTROL_COPY): 222: abort(); 223: break; 224: } 225: } 226: 227: return (TME_OK); 228: } 229: 230: /* the bus cycle handler for the interrupt register: */ 231: int 232: _tme_sun3_intreg_cycle_handler(void *_sun3, struct tme_bus_cycle *cycle_init) 233: { 234: struct tme_sun3 *sun3; 235: int rc; 236: 237: /* recover our sun3: */ 238: sun3 = (struct tme_sun3 *) _sun3; 239: 240: /* do the transfer: */ 241: tme_bus_cycle_xfer_memory(cycle_init, 242: &sun3->tme_sun3_ints, 243: sizeof(sun3->tme_sun3_ints) - 1); 244: 245: /* if the interrupt register has been written: */ 246: if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) { 247: rc = _tme_sun3_ipl_check(sun3); 248: assert(rc == TME_OK); 249: } 250: 251: return (TME_OK); 252: } 253: 254: /* this calls out a memory error interrupt change: */ 255: static void 256: _tme_sun3_memerr_callout(struct tme_sun3 *sun3) 257: { 258: unsigned int int_asserted; 259: struct tme_bus_connection *conn_bus; 260: int rc; 261: 262: /* see if the memory error interrupt should be asserted: */ 263: int_asserted 264: = ((sun3->tme_sun3_memerr_csr 265: & (TME_SUN3_MEMERR_X_INT_ACTIVE 266: | TME_SUN3_MEMERR_X_ENABLE_INT)) 267: == (TME_SUN3_MEMERR_X_INT_ACTIVE 268: | TME_SUN3_MEMERR_X_ENABLE_INT)); 269: 270: /* if we need to call out an interrupt change: */ 271: if (!int_asserted != !sun3->tme_sun3_memerr_int_asserted) { 272: 273: /* get our bus connection: */ 274: conn_bus = sun3->tme_sun3_memerr_bus; 275: 276: /* call out the bus interrupt signal edge: */ 277: rc = (*conn_bus->tme_bus_signal) 278: (conn_bus, 279: TME_BUS_SIGNAL_INT_UNSPEC 280: | (int_asserted 281: ? TME_BUS_SIGNAL_LEVEL_ASSERTED 282: : TME_BUS_SIGNAL_LEVEL_NEGATED)); 283: 284: /* if this callout was successful, note the new state of the 285: interrupt signal: */ 286: if (rc == TME_OK) { 287: sun3->tme_sun3_memerr_int_asserted = int_asserted; 288: } 289: 290: /* otherwise, abort: */ 291: else { 292: abort(); 293: } 294: } 295: } 296: 297: /* the bus cycle handler for the memory error register: */ 298: int 299: _tme_sun3_memerr_cycle_handler(void *_sun3, struct tme_bus_cycle *cycle_init) 300: { 301: struct tme_sun3 *sun3; 302: tme_uint8_t memerr_reg[TME_SUN3_MEMERR_SIZ_REG]; 303: int write_csr, unlatch; 304: tme_uint8_t csr_old, csr_new; 305: 306: /* the read-only bits: */ 307: #define TME_SUN3_MEMERR_RO (TME_SUN3_MEMERR_X_INT_ACTIVE \ 308: | TME_SUN3_MEMERR_PAR_ERR_BL3 \ 309: | TME_SUN3_MEMERR_PAR_ERR_BL2 \ 310: | TME_SUN3_MEMERR_PAR_ERR_BL1 \ 311: | TME_SUN3_MEMERR_PAR_ERR_BL0) 312: 313: /* recover our sun3: */ 314: sun3 = (struct tme_sun3 *) _sun3; 315: 316: /* fill the memory error register: */ 317: memerr_reg[TME_SUN3_MEMERR_REG_CSR] = sun3->tme_sun3_memerr_csr; 318: *((tme_uint32_t *) &memerr_reg[TME_SUN3_MEMERR_SIZ_VADDR]) = tme_htobe_u32(sun3->tme_sun3_memerr_vaddr); 319: 320: /* assume this cycle won't write the CSR or unlatch the register: */ 321: write_csr = FALSE; 322: unlatch = FALSE; 323: 324: /* if this is a write: */ 325: if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) { 326: 327: /* see if this writes the CSR: */ 328: write_csr = TME_RANGES_OVERLAP(cycle_init->tme_bus_cycle_address, 329: (cycle_init->tme_bus_cycle_address 330: + cycle_init->tme_bus_cycle_size 331: - 1), 332: TME_SUN3_MEMERR_REG_CSR, 333: (TME_SUN3_MEMERR_REG_CSR 334: + TME_SUN3_MEMERR_SIZ_CSR 335: - 1)); 336: 337: /* see if this write unlatches the register: */ 338: unlatch = TME_RANGES_OVERLAP(cycle_init->tme_bus_cycle_address, 339: (cycle_init->tme_bus_cycle_address 340: + cycle_init->tme_bus_cycle_size 341: - 1), 342: TME_SUN3_MEMERR_REG_VADDR, 343: TME_SUN3_MEMERR_REG_VADDR); 344: } 345: 346: /* do the transfer: */ 347: tme_bus_cycle_xfer_memory(cycle_init, 348: memerr_reg, 349: sizeof(memerr_reg) - 1); 350: 351: /* if this is a write: */ 352: if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) { 353: 354: /* get the old CSR value, and assume that the new CSR value is the 355: same: */ 356: csr_old = sun3->tme_sun3_memerr_csr; 357: csr_new = csr_old; 358: 359: /* if the CSR register has been written: */ 360: if (write_csr) { 361: 362: /* get the new CSR value, but preserve the read-only bits: */ 363: csr_new = ((csr_new & TME_SUN3_MEMERR_RO) 364: | (memerr_reg[TME_SUN3_MEMERR_REG_CSR] & ~TME_SUN3_MEMERR_RO)); 365: } 366: 367: /* if the memory error register has been unlatched: */ 368: if (unlatch) { 369: 370: /* clear the memory error: */ 371: csr_new &= ~TME_SUN3_MEMERR_RO; 372: sun3->tme_sun3_memerr_vaddr = 0; 373: } 374: 375: /* if the CSR register has changed: */ 376: if (csr_new != csr_old) { 377: 378: /* set the new CSR value and call out an interrupt change: */ 379: sun3->tme_sun3_memerr_csr = csr_new; 380: _tme_sun3_memerr_callout(sun3); 381: 382: /* if the memory error register is being tested: */ 383: if (csr_new & TME_SUN3_MEMERR_PAR_TEST) { 384: 385: /* if the test is just beginning, invalidate all TLB entries: */ 386: if (!(csr_old & TME_SUN3_MEMERR_PAR_TEST)) { 387: tme_sun_mmu_tlbs_invalidate(sun3->tme_sun3_mmu); 388: } 389: } 390: } 391: } 392: 393: return (TME_OK); 394: } 395: 396: /* the bus cycle handler for the memory error register test: */ 397: int 398: _tme_sun3_memerr_test_cycle_handler(void *_sun3, struct tme_bus_cycle *cycle_init) 399: { 400: struct tme_sun3 *sun3; 401: struct tme_bus_tlb *tlb; 402: tme_uint32_t vaddr, cycle_align; 403: tme_uint8_t csr; 404: int rc; 405: 406: /* recover our sun3: */ 407: sun3 = (struct tme_sun3 *) _sun3; 408: 409: /* get the memory error test TLB entry: */ 410: tlb = sun3->tme_sun3_memerr_tlb; 411: if (tlb == NULL) { 412: abort(); 413: } 414: 415: /* recover the virtual address from the TLB entry. this TLB entry 416: should be for normal memory, which means it should have no shift: */ 417: if (tlb->tme_bus_tlb_addr_shift != 0) { 418: abort(); 419: } 420: vaddr = (cycle_init->tme_bus_cycle_address 421: - tlb->tme_bus_tlb_addr_offset); 422: 423: /* calculate the number of bytes after the last byte of the cycle 424: until the next 32-bit boundary. this bus cycle must not cross a 425: 32-bit boundary: */ 426: cycle_align = ((vaddr & (sizeof(tme_uint32_t) - 1)) 427: + cycle_init->tme_bus_cycle_size); 428: if (cycle_align > sizeof(tme_uint32_t)) { 429: abort(); 430: } 431: cycle_align = sizeof(tme_uint32_t) - cycle_align; 432: 433: /* make the pending csr value. this calculates a mask of 434: TME_SUN3_MEMERR_PAR_ERR_BLx bits corresponding to the byte lanes 435: being read or written in this cycle: */ 436: csr = (1 << cycle_init->tme_bus_cycle_size) - 1; 437: csr <<= cycle_align; 438: 439: /* if this cycle is a read: */ 440: if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ) { 441: 442: /* parity checking must be enabled and there must be no memory 443: error pending: */ 444: if ((sun3->tme_sun3_memerr_csr 445: & (TME_SUN3_MEMERR_X_INT_ACTIVE 446: | TME_SUN3_MEMERR_PAR_ENABLE)) 447: != TME_SUN3_MEMERR_PAR_ENABLE) { 448: abort(); 449: } 450: 451: /* this must be a read of the written address: */ 452: if ((sun3->tme_sun3_memerr_pending_csr & csr) == 0 453: || ((sun3->tme_sun3_memerr_pending_vaddr ^ vaddr) & -sizeof(tme_uint32_t)) != 0) { 454: abort(); 455: } 456: 457: /* do the read: */ 458: rc = ((*sun3->tme_sun3_memerr_cycle) 459: (sun3->tme_sun3_memerr_cycle_private, 460: cycle_init)); 461: 462: /* set the memory error control register: */ 463: sun3->tme_sun3_memerr_csr 464: = ((sun3->tme_sun3_memerr_csr 465: & ~TME_SUN3_MEMERR_RO) 466: | TME_SUN3_MEMERR_X_INT_ACTIVE 467: | (sun3->tme_sun3_memerr_pending_csr & csr)); 468: 469: /* set the memory error address register: */ 470: sun3->tme_sun3_memerr_vaddr 471: = ((sun3->tme_sun3_context << 28) 472: | vaddr); 473: 474: /* call out an interrupt: */ 475: _tme_sun3_memerr_callout(sun3); 476: 477: /* invalidate the memory test TLB entry: */ 1.1.1.2 ! root 478: tme_token_invalidate(tlb->tme_bus_tlb_token); 1.1 root 479: sun3->tme_sun3_memerr_tlb = NULL; 480: 481: /* tell the CPU that a synchronous event of some kind has happened 482: on the bus: */ 483: return (rc == TME_OK 484: ? TME_BUS_CYCLE_SYNCHRONOUS_EVENT 485: : rc); 486: } 487: 488: /* otherwise, this must be a write: */ 489: if (cycle_init->tme_bus_cycle_type != TME_BUS_CYCLE_WRITE) { 490: abort(); 491: } 492: 493: /* this must be the first write: */ 494: if (sun3->tme_sun3_memerr_pending_csr != 0) { 495: abort(); 496: } 497: 498: /* remember the pending memory error address and CSR value: */ 499: sun3->tme_sun3_memerr_pending_csr = csr; 500: sun3->tme_sun3_memerr_pending_vaddr = vaddr; 501: 502: /* run the cycle normally: */ 503: return ((*sun3->tme_sun3_memerr_cycle) 504: (sun3->tme_sun3_memerr_cycle_private, 505: cycle_init)); 506: 507: #undef TME_SUN3_MEMERR_RO 508: } 509: 510: #if 1 511: #include <stdio.h> 512: 513: /* this dumps out the sun3 state: */ 514: void 515: tme_sun3_dump(struct tme_sun3 *sun3) 516: { 517: 518: /* dump out the page map register: */ 519: fprintf(stderr, "CONTEXT = 0x%02x\n", sun3->tme_sun3_context); 520: fprintf(stderr, "\n"); 521: fprintf(stderr, "DIAG = 0x%02x\n", sun3->tme_sun3_diag); 522: fprintf(stderr, "UDVMA = 0x%02x\n", sun3->tme_sun3_udvma); 523: fprintf(stderr, "BUSERR = 0x%04x\n", sun3->tme_sun3_buserr); 524: fprintf(stderr, "ENABLE = 0x%02x\n", sun3->tme_sun3_enable); 525: fprintf(stderr, "INTS = 0x%02x\n", sun3->tme_sun3_ints); 526: fprintf(stderr, "MEMERR = 0x%02x 0x%04x\n", sun3->tme_sun3_memerr_csr, sun3->tme_sun3_memerr_vaddr); 527: } 528: #endif /* 1 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.