Annotation of tme/machine/sun/sun-bwtwo.c, revision 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.