Annotation of tme/machine/sun/sun-bwtwo.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

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