|
|
1.1 ! root 1: /* $Id: sun-bwtwo.c,v 1.2 2005/04/30 15:12:56 fredette Exp $ */ ! 2: ! 3: /* machine/sun/sun-bwtwo.c - Sun bwtwo emulation: */ ! 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> ! 37: _TME_RCSID("$Id: sun-bwtwo.c,v 1.2 2005/04/30 15:12:56 fredette Exp $"); ! 38: ! 39: /* includes: */ ! 40: #include <tme/machine/sun.h> ! 41: #include <tme/generic/bus-device.h> ! 42: #include <tme/generic/fb.h> ! 43: #include "sun-fb.h" ! 44: ! 45: /* macros: */ ! 46: ! 47: /* bwtwo types: */ ! 48: #define TME_SUNBW2_TYPE_NULL (0) ! 49: #define TME_SUNBW2_TYPE_MULTIBUS (1) ! 50: #define TME_SUNBW2_TYPE_OLD_ONBOARD (2) ! 51: #define TME_SUNBW2_TYPE_ONBOARD (3) ! 52: #define TME_SUNBW2_TYPE_P4 (4) ! 53: ! 54: /* register offsets and sizes: */ ! 55: #define TME_SUNBW2_REG_CSR_MULTIBUS (0x81800) ! 56: #define TME_SUNBW2_REG_CSR_OLD_ONBOARD (0x20000) ! 57: #define TME_SUNBW2_SIZ_CSR (0x00002) ! 58: #define TME_SUNBW2_SIZ_CSR_PAGE (0x00800) ! 59: #define TME_SUNBW2_REG_P4 (0x00000) ! 60: #define TME_SUNBW2_SIZ_P4_PAGE (sizeof(tme_uint32_t)) ! 61: ! 62: /* the bits in the Multibus and old-onboard Control/Status register: */ ! 63: #define TME_SUNBW2_CSR_ENABLE_VIDEO (0x8000) /* enable video */ ! 64: #define TME_SUNBW2_CSR_ENABLE_COPY (0x4000) /* enable copy mode */ ! 65: #define TME_SUNBW2_CSR_ENABLE_INT (0x2000) /* interrupt enable */ ! 66: #define TME_SUNBW2_CSR_INT_ACTIVE (0x1000) /* interrupt is active */ ! 67: #define TME_SUNBW2_CSR_JUMPER_B (0x0800) /* jumper B */ ! 68: #define TME_SUNBW2_CSR_JUMPER_A (0x0400) /* jumper A */ ! 69: #define TME_SUNBW2_CSR_JUMPER_COLOR (0x0200) /* jumper color */ ! 70: #define TME_SUNBW2_CSR_JUMPER_HIRES (0x0100) /* jumper hires */ ! 71: #define TME_SUNBW2_CSR_COPYBASE_MASK (0x007E) /* copybase mask */ ! 72: ! 73: #if 0 ! 74: #define TME_SUNBW2_DEBUG ! 75: #endif ! 76: ! 77: /* structures: */ ! 78: ! 79: /* the card: */ ! 80: struct tme_sunbw2 { ! 81: ! 82: /* our simple bus device header: */ ! 83: struct tme_bus_device tme_sunbw2_device; ! 84: #define tme_sunbw2_element tme_sunbw2_device.tme_bus_device_element ! 85: ! 86: /* the mutex protecting the card: */ ! 87: tme_mutex_t tme_sunbw2_mutex; ! 88: ! 89: /* the rwlock protecting the card: */ ! 90: tme_rwlock_t tme_sunbw2_rwlock; ! 91: ! 92: /* the framebuffer connection: */ ! 93: struct tme_fb_connection *tme_sunbw2_fb_connection; ! 94: ! 95: /* the type of the bwtwo: */ ! 96: tme_uint32_t tme_sunbw2_type; ! 97: ! 98: /* the size of the bwtwo: */ ! 99: tme_uint32_t tme_sunbw2_size; ! 100: ! 101: /* the (relative) bus address of our csr register: */ ! 102: tme_bus_addr_t tme_sunbw2_csr_address; ! 103: ! 104: /* the (relative) bus addresses of the first byte of framebuffer ! 105: memory, the last byte of displayed framebuffer memory, and the ! 106: last byte of framebuffer memory: */ ! 107: tme_bus_addr_t tme_sunbw2_fb_address_first; ! 108: tme_bus_addr_t tme_sunbw2_fb_address_last_displayed; ! 109: tme_bus_addr_t tme_sunbw2_fb_address_last; ! 110: ! 111: /* the framebuffer memory: */ ! 112: tme_uint8_t *tme_sunbw2_fb_memory; ! 113: ! 114: /* any pad memory: */ ! 115: tme_uint8_t *tme_sunbw2_pad_memory; ! 116: ! 117: /* our csr: */ ! 118: tme_uint16_t tme_sunbw2_csr; ! 119: ! 120: /* our P4 register: */ ! 121: tme_uint32_t tme_sunbw2_p4; ! 122: ! 123: /* our second bus subregion: */ ! 124: struct tme_bus_subregion tme_sunbw2_subregion1; ! 125: }; ! 126: ! 127: #ifdef TME_SUNBW2_DEBUG ! 128: #define TME_SUNBW2_LO_WIDTH (1152) ! 129: #define TME_SUNBW2_LO_HEIGHT (900) ! 130: static int ! 131: _tme_sunbw2_update_debug(struct tme_fb_connection *conn_fb) ! 132: { ! 133: struct tme_sunbw2 *sunbw2; ! 134: static int y = -1; ! 135: static int x; ! 136: unsigned long pixel; ! 137: unsigned int pixel_byte; ! 138: tme_uint8_t pixel_bit; ! 139: int box, box_y, box_x; ! 140: ! 141: sunbw2 = conn_fb->tme_fb_connection.tme_connection_element->tme_element_private; ! 142: ! 143: for (box = 0; box < 2; box++) { ! 144: if (y < 0) { ! 145: y = 16; ! 146: x = 0; ! 147: continue; ! 148: } ! 149: for (box_y = 0; box_y < 2; box_y++) { ! 150: for (box_x = 0; box_x < 2; box_x++) { ! 151: pixel = (((y + box_y) ! 152: * TME_SUNBW2_LO_WIDTH) ! 153: + x ! 154: + box_x); ! 155: pixel_byte = (pixel / 8); ! 156: pixel_bit = (0x80 >> (pixel % 8)); ! 157: sunbw2->tme_sunbw2_fb_memory[pixel_byte] ^= pixel_bit; ! 158: } ! 159: } ! 160: if (box == 0) { ! 161: x += 2; ! 162: if (x == TME_SUNBW2_LO_WIDTH) { ! 163: x = 0; ! 164: y += 2; ! 165: if (y == TME_SUNBW2_LO_HEIGHT) { ! 166: y = 0; ! 167: } ! 168: } ! 169: } ! 170: } ! 171: ! 172: return (TME_OK); ! 173: } ! 174: #undef TME_SUNBW2_LO_WIDTH ! 175: #undef TME_SUNBW2_LO_HEIGHT ! 176: #endif /* TME_SUNBW2_DEBUG */ ! 177: ! 178: /* the sunbw2 framebuffer bus cycle handler: */ ! 179: static int ! 180: _tme_sunbw2_bus_cycle_fb(void *_sunbw2, struct tme_bus_cycle *cycle_init) ! 181: { ! 182: struct tme_sunbw2 *sunbw2; ! 183: ! 184: /* recover our data structure: */ ! 185: sunbw2 = (struct tme_sunbw2 *) _sunbw2; ! 186: ! 187: /* lock the mutex: */ ! 188: tme_mutex_lock(&sunbw2->tme_sunbw2_mutex); ! 189: ! 190: /* run the cycle: */ ! 191: assert (cycle_init->tme_bus_cycle_address ! 192: >= sunbw2->tme_sunbw2_fb_address_first); ! 193: tme_bus_cycle_xfer_memory(cycle_init, ! 194: (sunbw2->tme_sunbw2_fb_memory ! 195: - sunbw2->tme_sunbw2_fb_address_first), ! 196: sunbw2->tme_sunbw2_fb_address_last_displayed); ! 197: ! 198: /* unlock the mutex: */ ! 199: tme_mutex_unlock(&sunbw2->tme_sunbw2_mutex); ! 200: ! 201: /* no faults: */ ! 202: return (TME_OK); ! 203: } ! 204: ! 205: /* the sunbw2 pad bus cycle handler: */ ! 206: static int ! 207: _tme_sunbw2_bus_cycle_pad(void *_sunbw2, struct tme_bus_cycle *cycle_init) ! 208: { ! 209: struct tme_sunbw2 *sunbw2; ! 210: ! 211: /* recover our data structure: */ ! 212: sunbw2 = (struct tme_sunbw2 *) _sunbw2; ! 213: ! 214: /* lock the mutex: */ ! 215: tme_mutex_lock(&sunbw2->tme_sunbw2_mutex); ! 216: ! 217: /* run the cycle: */ ! 218: assert (cycle_init->tme_bus_cycle_address ! 219: > sunbw2->tme_sunbw2_fb_address_last_displayed); ! 220: tme_bus_cycle_xfer_memory(cycle_init, ! 221: (sunbw2->tme_sunbw2_pad_memory ! 222: - (sunbw2->tme_sunbw2_fb_address_last_displayed ! 223: + 1)), ! 224: sunbw2->tme_sunbw2_fb_address_last); ! 225: ! 226: /* unlock the mutex: */ ! 227: tme_mutex_unlock(&sunbw2->tme_sunbw2_mutex); ! 228: ! 229: /* no faults: */ ! 230: return (TME_OK); ! 231: } ! 232: ! 233: /* the sunbw2 CSR bus cycle handler: */ ! 234: static int ! 235: _tme_sunbw2_bus_cycle_csr(void *_sunbw2, struct tme_bus_cycle *cycle_init) ! 236: { ! 237: struct tme_sunbw2 *sunbw2; ! 238: tme_uint16_t csr_old, csr_new; ! 239: tme_bus_addr_t undecoded; ! 240: ! 241: /* recover our data structure: */ ! 242: sunbw2 = (struct tme_sunbw2 *) _sunbw2; ! 243: ! 244: /* lock the mutex: */ ! 245: tme_mutex_lock(&sunbw2->tme_sunbw2_mutex); ! 246: ! 247: /* get the old CSR value: */ ! 248: csr_old = tme_betoh_u16(sunbw2->tme_sunbw2_csr); ! 249: ! 250: /* the entire 2KB (one page's) worth of addresses at ! 251: tme_sunbw2_csr_address are all decoded (or, rather, not decoded) ! 252: as the CSR: */ ! 253: undecoded ! 254: = (cycle_init->tme_bus_cycle_address ! 255: & (TME_SUNBW2_SIZ_CSR_PAGE - sizeof(sunbw2->tme_sunbw2_csr))); ! 256: cycle_init->tme_bus_cycle_address ! 257: -= undecoded; ! 258: ! 259: /* run the cycle: */ ! 260: assert (cycle_init->tme_bus_cycle_address ! 261: >= sunbw2->tme_sunbw2_csr_address); ! 262: tme_bus_cycle_xfer_memory(cycle_init, ! 263: (((tme_uint8_t *) &sunbw2->tme_sunbw2_csr) ! 264: - sunbw2->tme_sunbw2_csr_address), ! 265: (sunbw2->tme_sunbw2_csr_address ! 266: + sizeof(sunbw2->tme_sunbw2_csr) ! 267: - 1)); ! 268: cycle_init->tme_bus_cycle_address ! 269: += undecoded; ! 270: ! 271: /* get the new CSR value: */ ! 272: csr_new = tme_betoh_u16(sunbw2->tme_sunbw2_csr); ! 273: ! 274: /* put back the unchanging bits: */ ! 275: csr_new ! 276: = ((csr_new ! 277: & ~(TME_SUNBW2_CSR_INT_ACTIVE ! 278: | TME_SUNBW2_CSR_JUMPER_B ! 279: | TME_SUNBW2_CSR_JUMPER_A ! 280: | TME_SUNBW2_CSR_JUMPER_COLOR ! 281: | TME_SUNBW2_CSR_JUMPER_HIRES)) ! 282: | (csr_old ! 283: & (TME_SUNBW2_CSR_INT_ACTIVE ! 284: | TME_SUNBW2_CSR_JUMPER_B ! 285: | TME_SUNBW2_CSR_JUMPER_A ! 286: | TME_SUNBW2_CSR_JUMPER_COLOR ! 287: | TME_SUNBW2_CSR_JUMPER_HIRES))); ! 288: ! 289: /* we do not support these bits: */ ! 290: if (csr_new ! 291: & (TME_SUNBW2_CSR_ENABLE_COPY ! 292: | TME_SUNBW2_CSR_ENABLE_INT)) { ! 293: abort(); ! 294: } ! 295: ! 296: /* set the new CSR value: */ ! 297: sunbw2->tme_sunbw2_csr = tme_htobe_u16(csr_new); ! 298: ! 299: /* unlock the mutex: */ ! 300: tme_mutex_unlock(&sunbw2->tme_sunbw2_mutex); ! 301: ! 302: /* no faults: */ ! 303: return (TME_OK); ! 304: } ! 305: ! 306: /* the sunbw2 P4 bus cycle handler: */ ! 307: static int ! 308: _tme_sunbw2_bus_cycle_p4(void *_sunbw2, struct tme_bus_cycle *cycle_init) ! 309: { ! 310: struct tme_sunbw2 *sunbw2; ! 311: tme_uint32_t p4_old, p4_new; ! 312: tme_bus_addr_t undecoded; ! 313: ! 314: /* recover our data structure: */ ! 315: sunbw2 = (struct tme_sunbw2 *) _sunbw2; ! 316: ! 317: /* lock the mutex: */ ! 318: tme_mutex_lock(&sunbw2->tme_sunbw2_mutex); ! 319: ! 320: /* get the old P4 value: */ ! 321: p4_old = tme_betoh_u32(sunbw2->tme_sunbw2_p4); ! 322: ! 323: /* the entire ?KB (one page's) worth of addresses at ! 324: TME_SUNBW2_REG_P4 are all decoded (or, rather, not decoded) ! 325: as the P4: */ ! 326: undecoded ! 327: = (cycle_init->tme_bus_cycle_address ! 328: & (TME_SUNBW2_SIZ_P4_PAGE - sizeof(sunbw2->tme_sunbw2_p4))); ! 329: cycle_init->tme_bus_cycle_address ! 330: -= undecoded; ! 331: ! 332: /* run the cycle: */ ! 333: assert (cycle_init->tme_bus_cycle_address ! 334: >= TME_SUNBW2_REG_P4); ! 335: tme_bus_cycle_xfer_memory(cycle_init, ! 336: (((tme_uint8_t *) &sunbw2->tme_sunbw2_p4) ! 337: - TME_SUNBW2_REG_P4), ! 338: (TME_SUNBW2_REG_P4 ! 339: + sizeof(sunbw2->tme_sunbw2_p4) ! 340: - 1)); ! 341: cycle_init->tme_bus_cycle_address ! 342: += undecoded; ! 343: ! 344: /* get the new P4 value: */ ! 345: p4_new = tme_betoh_u32(sunbw2->tme_sunbw2_p4); ! 346: ! 347: /* put back the unchanging bits: */ ! 348: p4_new ! 349: = ((p4_new ! 350: & ~TME_SUN_P4_RO_MASK) ! 351: | (p4_old ! 352: & TME_SUN_P4_RO_MASK)); ! 353: ! 354: /* we do not support these bits: */ ! 355: if (p4_new ! 356: & (TME_SUN_P4_REG_SYNC_RAMDAC ! 357: | TME_SUN_P4_REG_ENABLE_INT)) { ! 358: abort(); ! 359: } ! 360: ! 361: /* set the new P4 value: */ ! 362: sunbw2->tme_sunbw2_p4 = tme_htobe_u32(p4_new); ! 363: ! 364: /* unlock the mutex: */ ! 365: tme_mutex_unlock(&sunbw2->tme_sunbw2_mutex); ! 366: ! 367: /* no faults: */ ! 368: return (TME_OK); ! 369: } ! 370: ! 371: /* the sunbw2 TLB filler: */ ! 372: static int ! 373: _tme_sunbw2_tlb_fill(void *_sunbw2, struct tme_bus_tlb *tlb, ! 374: tme_bus_addr_t address, unsigned int cycles) ! 375: { ! 376: struct tme_sunbw2 *sunbw2; ! 377: ! 378: /* recover our data structure: */ ! 379: sunbw2 = (struct tme_sunbw2 *) _sunbw2; ! 380: ! 381: /* initialize the TLB entry: */ ! 382: tme_bus_tlb_initialize(tlb); ! 383: ! 384: /* if this is a Multibus or old-onboard bwtwo, and the address falls in the CSR: */ ! 385: if (((sunbw2->tme_sunbw2_type ! 386: == TME_SUNBW2_TYPE_MULTIBUS) ! 387: || (sunbw2->tme_sunbw2_type ! 388: == TME_SUNBW2_TYPE_OLD_ONBOARD)) ! 389: && (sunbw2->tme_sunbw2_csr_address ! 390: <= address) ! 391: && (address ! 392: < (sunbw2->tme_sunbw2_csr_address ! 393: + TME_SUNBW2_SIZ_CSR_PAGE))) { ! 394: ! 395: tlb->tme_bus_tlb_cycle = _tme_sunbw2_bus_cycle_csr; ! 396: ! 397: /* this TLB entry covers this range: */ ! 398: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 399: tlb->tme_bus_tlb_addr_first, ! 400: sunbw2->tme_sunbw2_csr_address); ! 401: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 402: tlb->tme_bus_tlb_addr_last, ! 403: (sunbw2->tme_sunbw2_csr_address ! 404: + TME_SUNBW2_SIZ_CSR ! 405: - 1)); ! 406: ! 407: /* this TLB entry cannot allow fast reading, since the page the ! 408: CSR is on isn't fully decoded - all words on the 2KB page are ! 409: the CSR: */ ! 410: } ! 411: ! 412: /* if this is a P4 bwtwo, and the address falls in the P4 register: */ ! 413: else if ((sunbw2->tme_sunbw2_type ! 414: == TME_SUNBW2_TYPE_P4) ! 415: && (address ! 416: < (TME_SUNBW2_REG_P4 ! 417: + TME_SUNBW2_SIZ_P4_PAGE))) { ! 418: ! 419: tlb->tme_bus_tlb_cycle = _tme_sunbw2_bus_cycle_p4; ! 420: ! 421: /* this TLB entry covers this range: */ ! 422: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 423: tlb->tme_bus_tlb_addr_first, ! 424: TME_SUNBW2_REG_P4); ! 425: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 426: tlb->tme_bus_tlb_addr_last, ! 427: (TME_SUNBW2_REG_P4 ! 428: + TME_SUNBW2_SIZ_P4_PAGE ! 429: - 1)); ! 430: ! 431: /* this TLB entry cannot allow fast reading, since the page the ! 432: P4 register is on isn't fully decoded - all words on the ?KB page are ! 433: the P4 register: */ ! 434: } ! 435: ! 436: /* if this address falls in the displayed framebuffer memory: */ ! 437: else if ((sunbw2->tme_sunbw2_fb_address_first ! 438: <= address) ! 439: && (address ! 440: <= sunbw2->tme_sunbw2_fb_address_last_displayed)) { ! 441: ! 442: assert (sunbw2->tme_sunbw2_fb_connection != NULL); ! 443: ! 444: tlb->tme_bus_tlb_cycle = _tme_sunbw2_bus_cycle_fb; ! 445: ! 446: /* this TLB entry covers this range: */ ! 447: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 448: tlb->tme_bus_tlb_addr_first, ! 449: sunbw2->tme_sunbw2_fb_address_first); ! 450: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 451: tlb->tme_bus_tlb_addr_last, ! 452: sunbw2->tme_sunbw2_fb_address_last_displayed); ! 453: ! 454: /* this TLB entry allows fast reading and writing: */ ! 455: tlb->tme_bus_tlb_emulator_off_read ! 456: = (sunbw2->tme_sunbw2_fb_memory ! 457: - sunbw2->tme_sunbw2_fb_address_first); ! 458: tlb->tme_bus_tlb_emulator_off_write ! 459: = (sunbw2->tme_sunbw2_fb_memory ! 460: - sunbw2->tme_sunbw2_fb_address_first); ! 461: } ! 462: ! 463: /* if this address falls in the pad memory: */ ! 464: else if ((sunbw2->tme_sunbw2_fb_address_last_displayed ! 465: < address) ! 466: && (address ! 467: <= sunbw2->tme_sunbw2_fb_address_last)) { ! 468: ! 469: tlb->tme_bus_tlb_cycle = _tme_sunbw2_bus_cycle_pad; ! 470: ! 471: /* this TLB entry covers this range: */ ! 472: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 473: tlb->tme_bus_tlb_addr_first, ! 474: (sunbw2->tme_sunbw2_fb_address_last_displayed ! 475: + 1)); ! 476: TME_ATOMIC_WRITE(tme_bus_addr_t, ! 477: tlb->tme_bus_tlb_addr_last, ! 478: sunbw2->tme_sunbw2_fb_address_last); ! 479: ! 480: /* this TLB entry allows fast reading and writing: */ ! 481: tlb->tme_bus_tlb_emulator_off_read ! 482: = (sunbw2->tme_sunbw2_pad_memory ! 483: - (sunbw2->tme_sunbw2_fb_address_last_displayed ! 484: + 1)); ! 485: tlb->tme_bus_tlb_emulator_off_write ! 486: = (sunbw2->tme_sunbw2_pad_memory ! 487: - (sunbw2->tme_sunbw2_fb_address_last_displayed ! 488: + 1)); ! 489: } ! 490: ! 491: /* the fast reading and writing rwlock: */ ! 492: tlb->tme_bus_tlb_rwlock = &sunbw2->tme_sunbw2_rwlock; ! 493: ! 494: /* allow reading and writing: */ ! 495: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE; ! 496: ! 497: /* our bus cycle handler private data: */ ! 498: tlb->tme_bus_tlb_cycle_private = _sunbw2; ! 499: ! 500: return (TME_OK); ! 501: } ! 502: ! 503: /* this makes a new framebuffer connection: */ ! 504: static int ! 505: _tme_sunbw2_connection_make(struct tme_connection *conn, unsigned int state) ! 506: { ! 507: struct tme_sunbw2 *sunbw2; ! 508: struct tme_fb_connection *conn_fb; ! 509: struct tme_fb_connection *conn_fb_other; ! 510: int rc; ! 511: ! 512: /* recover our data structures: */ ! 513: sunbw2 = conn->tme_connection_element->tme_element_private; ! 514: conn_fb = (struct tme_fb_connection *) conn; ! 515: conn_fb_other = (struct tme_fb_connection *) conn->tme_connection_other; ! 516: ! 517: /* both sides must be framebuffer connections: */ ! 518: assert(conn->tme_connection_type == TME_CONNECTION_FRAMEBUFFER); ! 519: assert(conn->tme_connection_other->tme_connection_type == TME_CONNECTION_FRAMEBUFFER); ! 520: ! 521: /* lock our mutex: */ ! 522: tme_mutex_lock(&sunbw2->tme_sunbw2_mutex); ! 523: ! 524: /* once the connection is made, we know whether or not the other ! 525: side of the connection is supplying specific memory that it wants ! 526: us to use, or if we should allocate memory ourselves: */ ! 527: if (conn_fb->tme_fb_connection_buffer == NULL) { ! 528: rc = tme_fb_xlat_alloc_src(conn_fb); ! 529: assert (rc == TME_OK); ! 530: } ! 531: sunbw2->tme_sunbw2_fb_memory = conn_fb->tme_fb_connection_buffer; ! 532: ! 533: /* we're always set up to answer calls across the connection, so we ! 534: only have to do work when the connection has gone full, namely ! 535: taking the other side of the connection: */ ! 536: if (state == TME_CONNECTION_FULL) { ! 537: ! 538: /* save our connection: */ ! 539: sunbw2->tme_sunbw2_fb_connection = conn_fb_other; ! 540: } ! 541: ! 542: /* unlock our mutex: */ ! 543: tme_mutex_unlock(&sunbw2->tme_sunbw2_mutex); ! 544: ! 545: return (TME_OK); ! 546: } ! 547: ! 548: /* this breaks a connection: */ ! 549: static int ! 550: _tme_sunbw2_connection_break(struct tme_connection *conn, unsigned int state) ! 551: { ! 552: abort(); ! 553: } ! 554: ! 555: /* this makes a new connection side for a sunbw2: */ ! 556: static int ! 557: _tme_sunbw2_connections_new(struct tme_element *element, ! 558: const char * const *args, ! 559: struct tme_connection **_conns, ! 560: char **_output) ! 561: { ! 562: struct tme_sunbw2 *sunbw2; ! 563: struct tme_fb_connection *conn_fb; ! 564: struct tme_connection *conn; ! 565: int rc; ! 566: ! 567: /* recover our data structure: */ ! 568: sunbw2 = (struct tme_sunbw2 *) element->tme_element_private; ! 569: ! 570: /* make the generic bus device connection side: */ ! 571: rc = tme_bus_device_connections_new(element, args, _conns, _output); ! 572: if (rc != TME_OK) { ! 573: return (rc); ! 574: } ! 575: ! 576: /* if we don't have a framebuffer connection, make one: */ ! 577: if (sunbw2->tme_sunbw2_fb_connection == NULL) { ! 578: ! 579: /* allocate the new framebuffer connection: */ ! 580: conn_fb = tme_new0(struct tme_fb_connection, 1); ! 581: conn = &conn_fb->tme_fb_connection; ! 582: ! 583: /* fill in the generic connection: */ ! 584: conn->tme_connection_next = *_conns; ! 585: conn->tme_connection_type = TME_CONNECTION_FRAMEBUFFER; ! 586: conn->tme_connection_score = tme_fb_connection_score; ! 587: conn->tme_connection_make = _tme_sunbw2_connection_make; ! 588: conn->tme_connection_break = _tme_sunbw2_connection_break; ! 589: ! 590: /* fill in the framebuffer connection: */ ! 591: conn_fb->tme_fb_connection_mode_change = NULL; ! 592: #ifdef TME_SUNBW2_DEBUG ! 593: conn_fb->tme_fb_connection_update = _tme_sunbw2_update_debug; ! 594: #else /* !TME_SUNBW2_DEBUG */ ! 595: conn_fb->tme_fb_connection_update = NULL; ! 596: #endif /* !TME_SUNBW2_DEBUG */ ! 597: ! 598: /* height and width: */ ! 599: conn_fb->tme_fb_connection_width = tme_sun_fb_p4_size_width(sunbw2->tme_sunbw2_size); ! 600: conn_fb->tme_fb_connection_height = tme_sun_fb_p4_size_height(sunbw2->tme_sunbw2_size); ! 601: ! 602: /* we are monochrome: */ ! 603: conn_fb->tme_fb_connection_class = TME_FB_XLAT_CLASS_MONOCHROME; ! 604: conn_fb->tme_fb_connection_depth = 1; ! 605: conn_fb->tme_fb_connection_bits_per_pixel = 1; ! 606: ! 607: /* we skip no pixels at the start of the scanline: */ ! 608: conn_fb->tme_fb_connection_skipx = 0; ! 609: ! 610: /* we pad to 32-bit boundaries: */ ! 611: conn_fb->tme_fb_connection_scanline_pad = 32; ! 612: ! 613: /* we are big-endian: */ ! 614: conn_fb->tme_fb_connection_order = TME_ENDIAN_BIG; ! 615: ! 616: /* we don't allocate memory until the connection is made, in case ! 617: the other side of the connection wants to provide us with a ! 618: specific memory region to use (maybe we're on a system with a ! 619: real bwtwo and we can write directly to its buffer): */ ! 620: conn_fb->tme_fb_connection_buffer = NULL; ! 621: ! 622: /* our pixels don't have subfields: */ ! 623: conn_fb->tme_fb_connection_mask_g = 0; ! 624: conn_fb->tme_fb_connection_mask_r = 0; ! 625: conn_fb->tme_fb_connection_mask_b = 0; ! 626: ! 627: /* intensities are a single bit, linearly mapped, but inverted: */ ! 628: conn_fb->tme_fb_connection_map_bits = 1; ! 629: conn_fb->tme_fb_connection_map_g = NULL; ! 630: conn_fb->tme_fb_connection_map_r = NULL; ! 631: conn_fb->tme_fb_connection_map_b = NULL; ! 632: conn_fb->tme_fb_connection_inverted = TRUE; ! 633: ! 634: /* return the connection side possibility: */ ! 635: *_conns = conn; ! 636: } ! 637: ! 638: /* done: */ ! 639: return (TME_OK); ! 640: } ! 641: ! 642: /* the new sun bwtwo function: */ ! 643: int ! 644: tme_sun_bwtwo(struct tme_element *element, const char * const *args, char **_output) ! 645: { ! 646: struct tme_sunbw2 *sunbw2; ! 647: struct tme_bus_subregion *fb_subregion; ! 648: struct tme_bus_subregion *reg_subregion; ! 649: tme_uint32_t bw2_type; ! 650: tme_uint32_t bw2_size; ! 651: tme_bus_addr_t fb_size; ! 652: int arg_i; ! 653: int usage; ! 654: ! 655: /* check our arguments: */ ! 656: usage = 0; ! 657: bw2_type = TME_SUNBW2_TYPE_NULL; ! 658: bw2_size = TME_SUN_P4_SIZE_1152_900; ! 659: arg_i = 1; ! 660: for (;;) { ! 661: ! 662: /* the framebuffer type: */ ! 663: if (TME_ARG_IS(args[arg_i + 0], "type")) { ! 664: if (TME_ARG_IS(args[arg_i + 1], "multibus")) { ! 665: bw2_type = TME_SUNBW2_TYPE_MULTIBUS; ! 666: } ! 667: else if (TME_ARG_IS(args[arg_i + 1], "old-onboard")) { ! 668: bw2_type = TME_SUNBW2_TYPE_OLD_ONBOARD; ! 669: } ! 670: else if (TME_ARG_IS(args[arg_i + 1], "onboard")) { ! 671: bw2_type = TME_SUNBW2_TYPE_ONBOARD; ! 672: } ! 673: else if (TME_ARG_IS(args[arg_i + 1], "P4")) { ! 674: bw2_type = TME_SUNBW2_TYPE_P4; ! 675: } ! 676: else { ! 677: usage = TRUE; ! 678: break; ! 679: } ! 680: arg_i += 2; ! 681: } ! 682: ! 683: /* the framebuffer size: */ ! 684: else if (TME_ARG_IS(args[arg_i + 0], "size")) { ! 685: bw2_size = tme_sun_fb_p4_size(args[arg_i + 1]); ! 686: if (bw2_size == TME_SUN_P4_SIZE_NULL) { ! 687: usage = TRUE; ! 688: break; ! 689: } ! 690: arg_i += 2; ! 691: } ! 692: ! 693: /* if we ran out of arguments: */ ! 694: else if (args[arg_i] == NULL) { ! 695: ! 696: break; ! 697: } ! 698: ! 699: /* otherwise this is a bad argument: */ ! 700: else { ! 701: tme_output_append_error(_output, ! 702: "%s %s, ", ! 703: args[arg_i], ! 704: _("unexpected")); ! 705: usage = TRUE; ! 706: break; ! 707: } ! 708: } ! 709: ! 710: /* dispatch on the bwtwo type to check that it and the size are ! 711: valid: */ ! 712: switch (bw2_type) { ! 713: ! 714: /* no bwtwo type was specified: */ ! 715: case TME_SUNBW2_TYPE_NULL: ! 716: /* XXX TBD */ ! 717: usage = TRUE; ! 718: break; ! 719: ! 720: /* the original Multibus bwtwo and onboard bwtwo only support ! 721: 1152x900 and 1024x1024: */ ! 722: case TME_SUNBW2_TYPE_MULTIBUS: ! 723: case TME_SUNBW2_TYPE_OLD_ONBOARD: ! 724: if (bw2_size != TME_SUN_P4_SIZE_1152_900 ! 725: && bw2_size != TME_SUN_P4_SIZE_1024_1024) { ! 726: /* XXX TBD */ ! 727: usage = TRUE; ! 728: } ! 729: break; ! 730: ! 731: /* the sizes supported by a CSR-less bwtwo appear to depend on the ! 732: actual model; we assume the user knows what he is doing: */ ! 733: case TME_SUNBW2_TYPE_ONBOARD: ! 734: break; ! 735: ! 736: /* we allow creating a P4 bwtwo with any of the P4 sizes, again ! 737: assuming that the user knows what he is doing: */ ! 738: case TME_SUNBW2_TYPE_P4: ! 739: break; ! 740: ! 741: default: ! 742: assert(FALSE); ! 743: break; ! 744: } ! 745: ! 746: if (usage) { ! 747: tme_output_append_error(_output, ! 748: "%s %s type { multibus | old-onboard | onboard | P4 } [ size { 1600x1280 | 1152x900 | 1024x1024 | 1280x1024 | 1440x1440 | 640x480 } ]", ! 749: _("usage:"), ! 750: args[0]); ! 751: return (EINVAL); ! 752: } ! 753: ! 754: /* start the sunbw2 structure: */ ! 755: sunbw2 = tme_new0(struct tme_sunbw2, 1); ! 756: sunbw2->tme_sunbw2_element = element; ! 757: tme_mutex_init(&sunbw2->tme_sunbw2_mutex); ! 758: tme_rwlock_init(&sunbw2->tme_sunbw2_rwlock); ! 759: ! 760: /* set the bwtwo type: */ ! 761: sunbw2->tme_sunbw2_type = bw2_type; ! 762: ! 763: /* set the bwtwo size: */ ! 764: sunbw2->tme_sunbw2_size = bw2_size; ! 765: ! 766: /* assume the (relative) bus address of the first byte of displayed ! 767: framebuffer memory: */ ! 768: sunbw2->tme_sunbw2_fb_address_first = 0; ! 769: ! 770: /* assume that the number of bytes of framebuffer memory is the ! 771: minimum number of bytes required, rounded up to the nearest power ! 772: of two: */ ! 773: fb_size = ((tme_sun_fb_p4_size_width(bw2_size) ! 774: * tme_sun_fb_p4_size_height(bw2_size)) ! 775: / 8); ! 776: if ((fb_size & (fb_size - 1)) != 0) { ! 777: for (; (fb_size & (fb_size - 1)) != 0; fb_size &= (fb_size - 1)); ! 778: fb_size <<= 1; ! 779: } ! 780: ! 781: /* assume that we will attach to two bus subregions, and that the ! 782: framebuffer memory will be first: */ ! 783: fb_subregion = &sunbw2->tme_sunbw2_device.tme_bus_device_subregions; ! 784: fb_subregion->tme_bus_subregion_next = &sunbw2->tme_sunbw2_subregion1; ! 785: sunbw2->tme_sunbw2_subregion1.tme_bus_subregion_next = NULL; ! 786: ! 787: /* dispatch on the bwtwo type: */ ! 788: switch (bw2_type) { ! 789: case TME_SUNBW2_TYPE_MULTIBUS: ! 790: case TME_SUNBW2_TYPE_OLD_ONBOARD: ! 791: ! 792: /* set our initial CSR: */ ! 793: sunbw2->tme_sunbw2_csr ! 794: = tme_htobe_u16(TME_SUNBW2_CSR_ENABLE_VIDEO ! 795: | (bw2_size == TME_SUN_P4_SIZE_1024_1024 ! 796: ? TME_SUNBW2_CSR_JUMPER_HIRES ! 797: : 0)); ! 798: ! 799: /* set our CSR address: */ ! 800: sunbw2->tme_sunbw2_csr_address ! 801: = (bw2_type == TME_SUNBW2_TYPE_MULTIBUS ! 802: ? TME_SUNBW2_REG_CSR_MULTIBUS ! 803: : TME_SUNBW2_REG_CSR_OLD_ONBOARD); ! 804: ! 805: /* our second bus subregion is for the CSR: */ ! 806: reg_subregion = &sunbw2->tme_sunbw2_subregion1; ! 807: reg_subregion->tme_bus_subregion_address_first ! 808: = sunbw2->tme_sunbw2_csr_address; ! 809: reg_subregion->tme_bus_subregion_address_last ! 810: = (reg_subregion->tme_bus_subregion_address_first ! 811: + TME_SUNBW2_SIZ_CSR_PAGE ! 812: - 1); ! 813: break; ! 814: ! 815: case TME_SUNBW2_TYPE_ONBOARD: ! 816: ! 817: /* we attach to only one bus subregion: */ ! 818: fb_subregion->tme_bus_subregion_next = NULL; ! 819: break; ! 820: ! 821: case TME_SUNBW2_TYPE_P4: ! 822: ! 823: /* set our initial P4 register: */ ! 824: sunbw2->tme_sunbw2_p4 ! 825: = tme_htobe_u16(TME_SUN_P4_ID_BWTWO ! 826: | bw2_size ! 827: | TME_SUN_P4_REG_ENABLE_VIDEO); ! 828: ! 829: /* the framebuffer memory begins at a fixed offset after the P4 register: */ ! 830: sunbw2->tme_sunbw2_fb_address_first = TME_SUN_P4_OFFSET_BWTWO; ! 831: ! 832: /* we attach the P4 register first, and the framebuffer memory second: */ ! 833: reg_subregion = &sunbw2->tme_sunbw2_device.tme_bus_device_subregions; ! 834: fb_subregion = &sunbw2->tme_sunbw2_subregion1; ! 835: reg_subregion->tme_bus_subregion_address_first = 0; ! 836: reg_subregion->tme_bus_subregion_address_last ! 837: = (reg_subregion->tme_bus_subregion_address_first ! 838: + sizeof(sunbw2->tme_sunbw2_p4) ! 839: - 1); ! 840: break; ! 841: } ! 842: ! 843: /* set the (relative) bus address of the last byte of displayed ! 844: framebuffer memory: */ ! 845: sunbw2->tme_sunbw2_fb_address_last_displayed ! 846: = (sunbw2->tme_sunbw2_fb_address_first ! 847: + ((tme_sun_fb_p4_size_width(bw2_size) ! 848: * tme_sun_fb_p4_size_height(bw2_size)) ! 849: / 8) ! 850: - 1); ! 851: ! 852: /* set the (relative) bus address of the last byte of framebuffer ! 853: memory: */ ! 854: sunbw2->tme_sunbw2_fb_address_last ! 855: = (sunbw2->tme_sunbw2_fb_address_first ! 856: + fb_size ! 857: - 1); ! 858: ! 859: /* finish the framebuffer memory subregion: */ ! 860: fb_subregion->tme_bus_subregion_address_first ! 861: = sunbw2->tme_sunbw2_fb_address_first; ! 862: fb_subregion->tme_bus_subregion_address_last ! 863: = sunbw2->tme_sunbw2_fb_address_last; ! 864: ! 865: /* assume that we don't need any pad (undisplayed) framebuffer memory: */ ! 866: sunbw2->tme_sunbw2_pad_memory = NULL; ! 867: assert (sunbw2->tme_sunbw2_fb_address_last ! 868: >= sunbw2->tme_sunbw2_fb_address_last_displayed); ! 869: ! 870: /* if we need to, allocate pad (undisplayed) framebuffer memory: */ ! 871: if (sunbw2->tme_sunbw2_fb_address_last ! 872: > sunbw2->tme_sunbw2_fb_address_last_displayed) { ! 873: ! 874: /* allocate the pad memory: */ ! 875: sunbw2->tme_sunbw2_pad_memory ! 876: = tme_new0(tme_uint8_t, ! 877: (sunbw2->tme_sunbw2_fb_address_last ! 878: - sunbw2->tme_sunbw2_fb_address_last_displayed)); ! 879: } ! 880: ! 881: /* initialize our simple bus device descriptor: */ ! 882: sunbw2->tme_sunbw2_device.tme_bus_device_element = element; ! 883: sunbw2->tme_sunbw2_device.tme_bus_device_tlb_fill = _tme_sunbw2_tlb_fill; ! 884: ! 885: /* fill the element: */ ! 886: element->tme_element_private = sunbw2; ! 887: element->tme_element_connections_new = _tme_sunbw2_connections_new; ! 888: ! 889: return (TME_OK); ! 890: } ! 891:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.