Annotation of tme/ic/mk48txx.c, revision 1.1.1.2

1.1.1.2 ! root        1: /* $Id: mk48txx.c,v 1.4 2010/06/05 14:54:10 fredette Exp $ */
1.1       root        2: 
                      3: /* ic/mk48txx.c - implementation of Mostek 48Txx emulation: */
                      4: 
                      5: /*
                      6:  * Copyright (c) 2006 Matt Fredette
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *      This product includes software developed by Matt Fredette.
                     20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     33:  * POSSIBILITY OF SUCH DAMAGE.
                     34:  */
                     35: 
                     36: #include <tme/common.h>
1.1.1.2 ! root       37: _TME_RCSID("$Id: mk48txx.c,v 1.4 2010/06/05 14:54:10 fredette Exp $");
1.1       root       38: 
                     39: /* includes: */
                     40: #include <tme/generic/bus-device.h>
                     41: #include <tme/ic/mk48txx.h>
                     42: #include <tme/misc.h>
                     43: #include <time.h>
                     44: #include <sys/time.h>
                     45: 
                     46: /* macros: */
                     47: 
                     48: /* the different parts: */
                     49: #define TME_MK48TXX_PART_02    (02)
1.1.1.2 ! root       50: #define TME_MK48TXX_PART_59    (59)
1.1       root       51: 
                     52: /* register addresses: */
1.1.1.2 ! root       53: #define TME_MK48TXX_REGS_COUNT (16)            /* maximum number of registers */
1.1       root       54: #define TME_MK48TXX_REG_YEAR   (TME_MK48TXX_REGS_COUNT - 1)    /* BCD year */
                     55: #define TME_MK48TXX_REG_MON    (TME_MK48TXX_REGS_COUNT - 2)    /* BCD month */
                     56: #define TME_MK48TXX_REG_DAY    (TME_MK48TXX_REGS_COUNT - 3)    /* BCD day in month */
                     57: #define TME_MK48TXX_REG_WDAY   (TME_MK48TXX_REGS_COUNT - 4)    /* weekday */
                     58: #define TME_MK48TXX_REG_HOUR   (TME_MK48TXX_REGS_COUNT - 5)    /* BCD hour */
                     59: #define TME_MK48TXX_REG_MIN    (TME_MK48TXX_REGS_COUNT - 6)    /* BCD minutes */
                     60: #define TME_MK48TXX_REG_SEC    (TME_MK48TXX_REGS_COUNT - 7)    /* BCD seconds */
                     61: #define TME_MK48TXX_REG_CSR    (TME_MK48TXX_REGS_COUNT - 8)    /* control register */
1.1.1.2 ! root       62: #define TME_MK48TXX_REG_WDOG   (TME_MK48TXX_REGS_COUNT - 9)    /* watchdog */
        !            63: #define TME_MK48TXX_REG_INTR   (TME_MK48TXX_REGS_COUNT - 10)   /* interrupts */
        !            64: #define TME_MK48TXX_REG_ADAY   (TME_MK48TXX_REGS_COUNT - 11)   /* BCD alarm day */
        !            65: #define TME_MK48TXX_REG_AHOUR  (TME_MK48TXX_REGS_COUNT - 12)   /* BCD alarm hour */
        !            66: #define TME_MK48TXX_REG_AMIN   (TME_MK48TXX_REGS_COUNT - 13)   /* BCD alarm minutes */
        !            67: #define TME_MK48TXX_REG_ASEC   (TME_MK48TXX_REGS_COUNT - 14)   /* BCD alarm seconds */
        !            68:                             /* (TME_MK48TXX_REGS_COUNT - 15)      unused */
        !            69: #define TME_MK48TXX_REG_FLAGS  (TME_MK48TXX_REGS_COUNT - 16)   /* flags */
1.1       root       70: 
                     71: /* the first register implemented by a part: */
1.1.1.2 ! root       72: #define TME_MK48TXX_REG_FIRST(part)    \
        !            73:   ((part) == TME_MK48TXX_PART_59       \
        !            74:    ? TME_MK48TXX_REG_FLAGS             \
        !            75:    : TME_MK48TXX_REG_CSR)
1.1       root       76: 
                     77: /* bits in the CSR: */
                     78: #define TME_MK48TXX_CSR_WRITE  TME_BIT(7)      /* start writing */
                     79: #define TME_MK48TXX_CSR_READ   TME_BIT(6)      /* start reading */
                     80: 
                     81: /* bits in the weekday register: */
                     82: #define TME_MK48TXX_WDAY_FTEST TME_BIT(6)      /* 512Hz frequency test */
                     83: 
                     84: /* bits in the seconds register: */
                     85: #define TME_MK48TXX_SEC_STOP   TME_BIT(7)      /* all stop */
                     86: 
                     87: #define TME_MK48TXX_LOG_HANDLE(am) (&(am)->tme_mk48txx_element->tme_element_log_handle)
                     88: 
                     89: /* structures: */
                     90: struct tme_mk48txx {
                     91: 
                     92:   /* our simple bus device header: */
                     93:   struct tme_bus_device tme_mk48txx_device;
                     94: #define tme_mk48txx_element tme_mk48txx_device.tme_bus_device_element
                     95: 
                     96:   /* our socket: */
                     97:   struct tme_mk48txx_socket tme_mk48txx_socket;
                     98: #define tme_mk48txx_addr_shift tme_mk48txx_socket.tme_mk48txx_socket_addr_shift
                     99: #define tme_mk48txx_port_least_lane tme_mk48txx_socket.tme_mk48txx_socket_port_least_lane
                    100: #define tme_mk48txx_year_zero tme_mk48txx_socket.tme_mk48txx_socket_year_zero
                    101: 
                    102:   /* our mutex: */
                    103:   tme_mutex_t tme_mk48txx_mutex;
                    104: 
                    105:   /* the part emulated: */
                    106:   unsigned int tme_mk48txx_part;
                    107: 
                    108:   /* our timer condition: */
                    109:   tme_cond_t tme_mk48txx_cond_timer;
                    110: 
                    111:   /* it's easiest to just model the chip as a chunk of memory: */
                    112:   tme_uint8_t tme_mk48txx_regs[TME_MK48TXX_REGS_COUNT];
                    113: 
                    114:   /* if nonzero, the internal time-of-day needs to be updated: */
                    115:   tme_uint8_t tme_mk48txx_tod_update;
                    116: };
                    117: 
                    118: /* the mk48txx bus router: */
                    119: static const tme_bus_lane_t tme_mk48txx_router[TME_BUS_ROUTER_SIZE(TME_BUS8_LOG2)] = {
                    120:   
                    121:   /* [gen]  initiator port size: 8 bits
                    122:      [gen]  initiator port least lane: 0: */
                    123:   /* D7-D0 */  TME_BUS_LANE_ROUTE(0),
                    124: };
                    125: 
                    126: /* these convert values to and from BCD: */
                    127: static inline tme_uint8_t
                    128: _tme_mk48txx_bcd_out(unsigned int value)
                    129: {
                    130:   return ((value % 10)
                    131:          + ((value / 10) * 16));
                    132: }
                    133: static inline unsigned int
                    134: _tme_mk48txx_bcd_in(tme_uint8_t value)
                    135: {
                    136:   return ((value % 16)
                    137:          + ((value / 16) * 10));
                    138: }
                    139: 
                    140: /* this resets an mk48txx: */
                    141: static void
                    142: _tme_mk48txx_reset(struct tme_mk48txx *mk48txx)
                    143: {
                    144: 
                    145:   /* clear the CSR: */
                    146:   mk48txx->tme_mk48txx_regs[TME_MK48TXX_REG_CSR] = 0;
                    147: 
                    148:   /* start the clock running normally: */
                    149:   mk48txx->tme_mk48txx_regs[TME_MK48TXX_REG_WDAY] = 0;
1.1.1.2 ! root      150:   mk48txx->tme_mk48txx_regs[TME_MK48TXX_REG_SEC] = !TME_MK48TXX_SEC_STOP;
1.1       root      151: }
                    152: 
                    153: /* the mk48txx bus cycle handler: */
                    154: static int
                    155: _tme_mk48txx_bus_cycle(void *_mk48txx, struct tme_bus_cycle *cycle_init)
                    156: {
                    157:   struct tme_mk48txx *mk48txx;
1.1.1.2 ! root      158:   tme_bus_addr32_t address, mk48txx_address_last;
1.1       root      159:   tme_uint8_t buffer, value;
                    160:   struct tme_bus_cycle cycle_resp;
                    161:   unsigned int reg;
                    162:   struct timeval now;
                    163:   time_t _now;
                    164:   struct tm *now_tm, now_tm_buffer;
                    165: 
                    166:   /* recover our data structure: */
                    167:   mk48txx = (struct tme_mk48txx *) _mk48txx;
                    168: 
                    169:   /* the requested cycle must be within range: */
                    170:   mk48txx_address_last = mk48txx->tme_mk48txx_device.tme_bus_device_address_last;
                    171:   assert(cycle_init->tme_bus_cycle_address <= mk48txx_address_last);
                    172:   assert(cycle_init->tme_bus_cycle_size <= (mk48txx_address_last - cycle_init->tme_bus_cycle_address) + 1);
                    173: 
                    174:   /* get the register being accessed: */
                    175:   address = cycle_init->tme_bus_cycle_address;
                    176:   reg = (address >> mk48txx->tme_mk48txx_addr_shift) + TME_MK48TXX_REG_FIRST(mk48txx->tme_mk48txx_part);
                    177: 
                    178:   /* lock the mutex: */
                    179:   tme_mutex_lock(&mk48txx->tme_mk48txx_mutex);
                    180: 
                    181:   /* if the clock is not being read or written: */
                    182:   if ((mk48txx->tme_mk48txx_regs[TME_MK48TXX_REG_CSR]
                    183:        & (TME_MK48TXX_CSR_READ
                    184:          | TME_MK48TXX_CSR_WRITE)) == 0) {
                    185: 
                    186:     /* sample the time of day: */
                    187:     gettimeofday(&now, NULL);
                    188:     _now = now.tv_sec;
                    189:     now_tm = gmtime_r(&_now, &now_tm_buffer);
                    190: 
                    191:     /* put the time-of-day into the registers: */
                    192:     mk48txx->tme_mk48txx_regs[TME_MK48TXX_REG_HOUR] = _tme_mk48txx_bcd_out(now_tm->tm_hour);
                    193:     mk48txx->tme_mk48txx_regs[TME_MK48TXX_REG_MIN] = _tme_mk48txx_bcd_out(now_tm->tm_min);
                    194:     mk48txx->tme_mk48txx_regs[TME_MK48TXX_REG_SEC] = _tme_mk48txx_bcd_out(now_tm->tm_sec);
                    195:     mk48txx->tme_mk48txx_regs[TME_MK48TXX_REG_MON] = _tme_mk48txx_bcd_out(now_tm->tm_mon + 1);
                    196:     mk48txx->tme_mk48txx_regs[TME_MK48TXX_REG_DAY] = _tme_mk48txx_bcd_out(now_tm->tm_mday);
                    197:     mk48txx->tme_mk48txx_regs[TME_MK48TXX_REG_YEAR]
                    198:       = _tme_mk48txx_bcd_out((1900 + now_tm->tm_year) - mk48txx->tme_mk48txx_year_zero);
                    199:     mk48txx->tme_mk48txx_regs[TME_MK48TXX_REG_WDAY] = now_tm->tm_wday;
                    200:   }
                    201: 
                    202:   /* if this is a write: */
                    203:   if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
                    204: 
                    205:     /* run the bus cycle: */
                    206:     cycle_resp.tme_bus_cycle_buffer = &buffer;
                    207:     cycle_resp.tme_bus_cycle_lane_routing = tme_mk48txx_router;
                    208:     cycle_resp.tme_bus_cycle_address = 0;
                    209:     cycle_resp.tme_bus_cycle_buffer_increment = 1;
                    210:     cycle_resp.tme_bus_cycle_type = TME_BUS_CYCLE_READ;
                    211:     cycle_resp.tme_bus_cycle_size = sizeof(buffer);
                    212:     cycle_resp.tme_bus_cycle_port = 
                    213:       TME_BUS_CYCLE_PORT(mk48txx->tme_mk48txx_port_least_lane,
                    214:                         TME_BUS8_LOG2);
                    215:     tme_bus_cycle_xfer(cycle_init, &cycle_resp);
                    216:     value = buffer;
                    217:     
                    218:     /* log this write: */
                    219:     tme_log(TME_MK48TXX_LOG_HANDLE(mk48txx), 100000, TME_OK,
                    220:            (TME_MK48TXX_LOG_HANDLE(mk48txx),
                    221:             "reg %d write %02x",
                    222:             reg, value));
                    223: 
                    224:     /* dispatch on the register: */
                    225:     switch (reg) {
                    226: 
                    227:     case TME_MK48TXX_REG_WDAY:
                    228:       
                    229:       /* flag that the time-of-day needs to be updated: */
                    230:       mk48txx->tme_mk48txx_tod_update = TRUE;
                    231: 
                    232:       /* update the register: */
                    233:       mk48txx->tme_mk48txx_regs[reg] = value;
                    234:       break;
                    235: 
                    236:     case TME_MK48TXX_REG_HOUR:
                    237:     case TME_MK48TXX_REG_MIN:
                    238:     case TME_MK48TXX_REG_SEC:
                    239:     case TME_MK48TXX_REG_MON:
                    240:     case TME_MK48TXX_REG_DAY:
                    241:     case TME_MK48TXX_REG_YEAR:
                    242: 
                    243:       /* flag that the time-of-day needs to be updated: */
                    244:       mk48txx->tme_mk48txx_tod_update = TRUE;
                    245: 
                    246:       /* update the register: */
                    247:       mk48txx->tme_mk48txx_regs[reg] = value;
                    248:       break;
                    249: 
                    250:     case TME_MK48TXX_REG_CSR:
                    251: 
                    252:       /* update the CSR: */
                    253:       mk48txx->tme_mk48txx_regs[TME_MK48TXX_REG_CSR] = value;
                    254: 
                    255:       break;
                    256: 
1.1.1.2 ! root      257:     case TME_MK48TXX_REG_ADAY:
        !           258:     case TME_MK48TXX_REG_AHOUR:
        !           259:     case TME_MK48TXX_REG_AMIN:
        !           260:     case TME_MK48TXX_REG_ASEC:
        !           261:     case TME_MK48TXX_REG_WDOG:
        !           262:     case TME_MK48TXX_REG_INTR:
        !           263:     case TME_MK48TXX_REG_FLAGS:
        !           264: 
        !           265:       /* update the register: */
        !           266:       mk48txx->tme_mk48txx_regs[reg] = value;
        !           267:       break;
        !           268: 
1.1       root      269:     default:
                    270:       /* ignore */
                    271:       break;
                    272:     }
                    273:   }
                    274: 
                    275:   /* otherwise, this is a read: */
                    276:   else {
                    277:     assert(cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
                    278:     
                    279:     /* dispatch on the register: */
                    280:     switch (reg) {
                    281: 
                    282:     case TME_MK48TXX_REG_HOUR:
                    283:     case TME_MK48TXX_REG_MIN:
                    284:     case TME_MK48TXX_REG_SEC:
                    285:     case TME_MK48TXX_REG_MON:
                    286:     case TME_MK48TXX_REG_DAY:
                    287:     case TME_MK48TXX_REG_YEAR:
                    288:     case TME_MK48TXX_REG_WDAY:
1.1.1.2 ! root      289:     case TME_MK48TXX_REG_ADAY:
        !           290:     case TME_MK48TXX_REG_AHOUR:
        !           291:     case TME_MK48TXX_REG_AMIN:
        !           292:     case TME_MK48TXX_REG_ASEC:
        !           293:     case TME_MK48TXX_REG_WDOG:
        !           294:     case TME_MK48TXX_REG_INTR:
        !           295:     case TME_MK48TXX_REG_FLAGS:
1.1       root      296: 
                    297:       /* read the register: */
                    298:       value = mk48txx->tme_mk48txx_regs[reg];
                    299:       break;
                    300: 
                    301:     case TME_MK48TXX_REG_CSR:
                    302: 
                    303:       /* read the register: */
                    304:       value = mk48txx->tme_mk48txx_regs[reg];
                    305:       break;
                    306: 
                    307:       /* undefined registers return garbage when read: */
                    308:     default:
                    309:       value = 0xff;
                    310:       break;
                    311:     }
                    312: 
                    313:     /* log this read: */
                    314:     tme_log(TME_MK48TXX_LOG_HANDLE(mk48txx), 100000, TME_OK,
                    315:            (TME_MK48TXX_LOG_HANDLE(mk48txx),
                    316:             "reg %d read %02x",
                    317:             reg, value));
                    318: 
                    319:     /* run the bus cycle: */
                    320:     buffer = value;
                    321:     cycle_resp.tme_bus_cycle_buffer = &buffer;
                    322:     cycle_resp.tme_bus_cycle_lane_routing = tme_mk48txx_router;
                    323:     cycle_resp.tme_bus_cycle_address = 0;
                    324:     cycle_resp.tme_bus_cycle_buffer_increment = 1;
                    325:     cycle_resp.tme_bus_cycle_type = TME_BUS_CYCLE_WRITE;
                    326:     cycle_resp.tme_bus_cycle_size = sizeof(buffer);
                    327:     cycle_resp.tme_bus_cycle_port = 
                    328:       TME_BUS_CYCLE_PORT(mk48txx->tme_mk48txx_port_least_lane,
                    329:                         TME_BUS8_LOG2);
                    330:     tme_bus_cycle_xfer(cycle_init, &cycle_resp);
                    331:   }
                    332: 
                    333:   /* if the time-of-day registers have been updated, and the clock
                    334:      is running: */
                    335:   if (mk48txx->tme_mk48txx_tod_update
                    336:       && ((mk48txx->tme_mk48txx_regs[TME_MK48TXX_REG_CSR]
                    337:           & (TME_MK48TXX_CSR_READ
                    338:              | TME_MK48TXX_CSR_WRITE)) == 0)) {
                    339:     
                    340:     /* XXX update the host's time-of-day clock? */
                    341:     mk48txx->tme_mk48txx_tod_update = FALSE;
                    342:   }
                    343:     
                    344:   /* unlock the mutex: */
                    345:   tme_mutex_unlock(&mk48txx->tme_mk48txx_mutex);
                    346: 
                    347:   /* no faults: */
                    348:   return (TME_OK);
                    349: }
                    350: 
                    351: /* the mk48txx TLB filler: */
                    352: static int
                    353: _tme_mk48txx_tlb_fill(void *_mk48txx, struct tme_bus_tlb *tlb, 
                    354:                     tme_bus_addr_t address, unsigned int cycles)
                    355: {
                    356:   struct tme_mk48txx *mk48txx;
1.1.1.2 ! root      357:   tme_bus_addr32_t mk48txx_address_last;
1.1       root      358: 
                    359:   /* recover our data structure: */
                    360:   mk48txx = (struct tme_mk48txx *) _mk48txx;
                    361: 
                    362:   /* the address must be within range: */
                    363:   mk48txx_address_last = mk48txx->tme_mk48txx_device.tme_bus_device_address_last;
                    364:   assert(address <= mk48txx_address_last);
                    365: 
                    366:   /* initialize the TLB entry: */
                    367:   tme_bus_tlb_initialize(tlb);
                    368: 
                    369:   /* this TLB entry can cover the whole device: */
                    370:   tlb->tme_bus_tlb_addr_first = 0;
                    371:   tlb->tme_bus_tlb_addr_last = mk48txx_address_last;
                    372: 
                    373:   /* allow reading and writing: */
                    374:   tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
                    375: 
                    376:   /* our bus cycle handler: */
                    377:   tlb->tme_bus_tlb_cycle_private = mk48txx;
                    378:   tlb->tme_bus_tlb_cycle = _tme_mk48txx_bus_cycle;
                    379: 
                    380:   return (TME_OK);
                    381: }
                    382: 
                    383: /* the new mk48txx element function: */
                    384: static int
                    385: _tme_mk48txx_new(struct tme_element *element,
                    386:                 const char * const *args,
                    387:                 const void *extra,
                    388:                 char **_output,
                    389:                 unsigned int part)
                    390: {
                    391:   const struct tme_mk48txx_socket *socket;
                    392:   struct tme_mk48txx *mk48txx;
                    393:   struct tme_mk48txx_socket socket_real;
                    394:   tme_bus_addr_t address_mask;
                    395:   int arg_i;
                    396:   int usage;
                    397: 
                    398:   /* dispatch on our socket version: */
                    399:   socket = (const struct tme_mk48txx_socket *) extra;
                    400:   if (socket == NULL) {
                    401:     tme_output_append_error(_output, _("need an ic socket"));
                    402:     return (ENXIO);
                    403:   }
                    404:   switch (socket->tme_mk48txx_socket_version) {
                    405:   case TME_MK48TXX_SOCKET_0:
                    406:     socket_real = *socket;
                    407:     break;
                    408:   default: 
                    409:     tme_output_append_error(_output, _("socket type"));
                    410:     return (EOPNOTSUPP);
                    411:   }
                    412:     
                    413:   /* check our arguments: */
                    414:   usage = 0;
                    415:   arg_i = 1;
                    416:   for (;;) {
                    417: 
                    418:     if (0) {
                    419:     }
                    420: 
                    421:     /* if we ran out of arguments: */
                    422:     else if (args[arg_i] == NULL) {
                    423: 
                    424:       break;
                    425:     }
                    426: 
                    427:     /* otherwise this is a bad argument: */
                    428:     else {
                    429:       tme_output_append_error(_output,
                    430:                              "%s %s, ",
                    431:                              args[arg_i],
                    432:                              _("unexpected"));
                    433:       usage = TRUE;
                    434:       break;
                    435:     }
                    436:   }
                    437: 
                    438:   if (usage) {
                    439:     tme_output_append_error(_output, 
                    440:                            "%s %s",
                    441:                            _("usage:"),
                    442:                            args[0]);
                    443:     return (EINVAL);
                    444:   }
                    445: 
                    446:   /* start the mk48txx structure: */
                    447:   mk48txx = tme_new0(struct tme_mk48txx, 1);
                    448:   tme_mutex_init(&mk48txx->tme_mk48txx_mutex);
                    449:   mk48txx->tme_mk48txx_part = part;
                    450:   mk48txx->tme_mk48txx_socket = socket_real;
                    451:   mk48txx->tme_mk48txx_element = element;
                    452:   _tme_mk48txx_reset(mk48txx);
                    453: 
                    454:   /* figure our address mask, up to the nearest power of two: */
                    455:   address_mask = (TME_MK48TXX_REGS_COUNT - TME_MK48TXX_REG_FIRST(part)) << mk48txx->tme_mk48txx_addr_shift;
                    456:   if (address_mask & (address_mask - 1)) {
                    457:     for (; address_mask & (address_mask - 1); address_mask &= (address_mask - 1));
                    458:     address_mask <<= 1;
                    459:   }
                    460:   address_mask -= 1;
                    461: 
                    462:   /* initialize our simple bus device descriptor: */
                    463:   mk48txx->tme_mk48txx_device.tme_bus_device_tlb_fill = _tme_mk48txx_tlb_fill;
                    464:   mk48txx->tme_mk48txx_device.tme_bus_device_address_last = address_mask;
                    465: 
                    466:   /* fill the element: */
                    467:   element->tme_element_private = mk48txx;
                    468:   element->tme_element_connections_new = tme_bus_device_connections_new;
                    469: 
                    470:   return (TME_OK);
                    471: }
                    472: 
                    473: TME_ELEMENT_X_NEW_DECL(tme_ic_,mk48txx,mk48t02) {
                    474:   return (_tme_mk48txx_new(element, args, extra, _output, TME_MK48TXX_PART_02));
                    475: }
1.1.1.2 ! root      476: 
        !           477: TME_ELEMENT_X_NEW_DECL(tme_ic_,mk48txx,mk48t59) {
        !           478:   return (_tme_mk48txx_new(element, args, extra, _output, TME_MK48TXX_PART_59));
        !           479: }

unix.superglobalmegacorp.com

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