Annotation of tme/ic/mm58167.c, revision 1.1

1.1     ! root        1: /* $Id: mm58167.c,v 1.4 2003/05/16 21:48:10 fredette Exp $ */
        !             2: 
        !             3: /* ic/ic-vol0/mm58167.c - implementation of National Semiconductor MM58167 emulation: */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2003 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: mm58167.c,v 1.4 2003/05/16 21:48:10 fredette Exp $");
        !            38: 
        !            39: /* includes: */
        !            40: #include <tme/generic/bus-device.h>
        !            41: #include <tme/ic/mm58167.h>
        !            42: #include <time.h>
        !            43: 
        !            44: /* macros: */
        !            45: 
        !            46: /* register addresses: */
        !            47: #define TME_MM58167_REG_MSEC_XXX       (0)
        !            48: #define TME_MM58167_REG_CSEC           (1)
        !            49: #define TME_MM58167_REG_SEC            (2)
        !            50: #define TME_MM58167_REG_MIN            (3)
        !            51: #define TME_MM58167_REG_HOUR           (4)
        !            52: #define TME_MM58167_REG_WDAY           (5)
        !            53: #define TME_MM58167_REG_DAY            (6)
        !            54: #define TME_MM58167_REG_MON            (7)
        !            55: #define TME_MM58167_REG_STATUS         (20)
        !            56: #define TME_MM58167_REG_GO             (21)
        !            57: #define TME_MM58167_REG_BANK_SZ                (24)
        !            58: 
        !            59: /* bits in the status register: */
        !            60: #define TME_MM58167_STATUS_RIPPLING    TME_BIT(0)      
        !            61: 
        !            62: #define TME_MM58167_LOG_HANDLE(mm) (&(mm)->tme_mm58167_element->tme_element_log_handle)
        !            63: 
        !            64: /* structures: */
        !            65: 
        !            66: struct tme_mm58167 {
        !            67: 
        !            68:   /* our simple bus device header: */
        !            69:   struct tme_bus_device tme_mm58167_device;
        !            70: #define tme_mm58167_element tme_mm58167_device.tme_bus_device_element
        !            71: 
        !            72:   /* our socket: */
        !            73:   struct tme_mm58167_socket tme_mm58167_socket;
        !            74: #define tme_mm58167_addr_shift tme_mm58167_socket.tme_mm58167_socket_addr_shift
        !            75: #define tme_mm58167_port_least_lane tme_mm58167_socket.tme_mm58167_socket_port_least_lane
        !            76: 
        !            77:   /* the mutex protecting the chip: */
        !            78:   tme_mutex_t tme_mm58167_mutex;
        !            79: 
        !            80:   /* the last time sampled: */
        !            81:   time_t tme_mm58167_sampled_time;
        !            82: 
        !            83:   /* the struct tm for the last time sampled: */
        !            84:   struct tm tme_mm58167_sampled_tm;
        !            85: 
        !            86:   /* the status register: */
        !            87:   tme_uint8_t tme_mm58167_status;
        !            88: };
        !            89: 
        !            90: /* the mm58167 bus router: */
        !            91: static const tme_bus_lane_t tme_mm58167_router[TME_BUS_ROUTER_SIZE(TME_BUS8_LOG2)] = {
        !            92:   
        !            93:   /* [gen]  initiator port size: 8 bits
        !            94:      [gen]  initiator port least lane: 0: */
        !            95:   /* D7-D0 */  TME_BUS_LANE_ROUTE(0),
        !            96: };
        !            97: 
        !            98: /* the mm58167 bus cycle handler: */
        !            99: static int
        !           100: _tme_mm58167_bus_cycle(void *_mm58167, struct tme_bus_cycle *cycle_init)
        !           101: {
        !           102:   struct tme_mm58167 *mm58167;
        !           103:   tme_bus_addr_t address, mm58167_address_last;
        !           104:   tme_uint8_t buffer, value;
        !           105:   struct tme_bus_cycle cycle_resp;
        !           106:   unsigned int reg;
        !           107:   time_t now;
        !           108:   struct tm *now_tm;
        !           109:   int reg_is_bcd;
        !           110: 
        !           111:   /* recover our data structure: */
        !           112:   mm58167 = (struct tme_mm58167 *) _mm58167;
        !           113: 
        !           114:   /* the requested cycle must be within range: */
        !           115:   mm58167_address_last = mm58167->tme_mm58167_device.tme_bus_device_address_last;
        !           116:   assert(cycle_init->tme_bus_cycle_address <= mm58167_address_last);
        !           117:   assert(cycle_init->tme_bus_cycle_size <= (mm58167_address_last - cycle_init->tme_bus_cycle_address) + 1);
        !           118: 
        !           119:   /* get the register being accessed: */
        !           120:   address = cycle_init->tme_bus_cycle_address;
        !           121:   reg = address >> mm58167->tme_mm58167_addr_shift;
        !           122:   reg_is_bcd = (reg <= TME_MM58167_REG_MON);
        !           123: 
        !           124:   /* lock the mutex: */
        !           125:   tme_mutex_lock(&mm58167->tme_mm58167_mutex);
        !           126: 
        !           127:   /* sample the time.  if it's changed, update our status: */
        !           128:   now = time(NULL);
        !           129:   if (now == mm58167->tme_mm58167_sampled_time) {
        !           130:     now_tm = &mm58167->tme_mm58167_sampled_tm;
        !           131:   }
        !           132:   else {
        !           133:     mm58167->tme_mm58167_status |= TME_MM58167_STATUS_RIPPLING;
        !           134:     mm58167->tme_mm58167_sampled_time = now;
        !           135:     now_tm = gmtime_r(&now, &mm58167->tme_mm58167_sampled_tm);
        !           136:     if (now_tm != &mm58167->tme_mm58167_sampled_tm) {
        !           137:       mm58167->tme_mm58167_sampled_tm = *now_tm;
        !           138:     }
        !           139:   }
        !           140: 
        !           141:   /* if this is a write: */
        !           142:   if (cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
        !           143: 
        !           144:     /* run the bus cycle: */
        !           145:     cycle_resp.tme_bus_cycle_buffer = &buffer;
        !           146:     cycle_resp.tme_bus_cycle_lane_routing = tme_mm58167_router;
        !           147:     cycle_resp.tme_bus_cycle_address = 0;
        !           148:     cycle_resp.tme_bus_cycle_buffer_increment = 1;
        !           149:     cycle_resp.tme_bus_cycle_type = TME_BUS_CYCLE_READ;
        !           150:     cycle_resp.tme_bus_cycle_size = sizeof(buffer);
        !           151:     cycle_resp.tme_bus_cycle_port = 
        !           152:       TME_BUS_CYCLE_PORT(mm58167->tme_mm58167_port_least_lane,
        !           153:                         TME_BUS8_LOG2);
        !           154:     tme_bus_cycle_xfer(cycle_init, &cycle_resp);
        !           155:     value = buffer;
        !           156:     
        !           157:     /* log this write: */
        !           158:     tme_log(TME_MM58167_LOG_HANDLE(mm58167), 100000, TME_OK,
        !           159:            (TME_MM58167_LOG_HANDLE(mm58167),
        !           160:             "reg %d write %02x",
        !           161:             reg, value));
        !           162: 
        !           163:     /* otherwise, ignore writes for now: */
        !           164:   }
        !           165: 
        !           166: 
        !           167:   /* otherwise, this is a read: */
        !           168:   else {
        !           169:     assert(cycle_init->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
        !           170:     
        !           171:     /* dispatch on the register: */
        !           172:     switch (reg) {
        !           173:     case TME_MM58167_REG_MSEC_XXX:
        !           174:     case TME_MM58167_REG_CSEC:
        !           175:       value = 0;
        !           176:       break;
        !           177:     case TME_MM58167_REG_SEC:
        !           178:       value = now_tm->tm_sec;
        !           179:       break;
        !           180:     case TME_MM58167_REG_MIN:
        !           181:       value = now_tm->tm_min;
        !           182:       break;
        !           183:     case TME_MM58167_REG_HOUR:
        !           184:       value = now_tm->tm_hour;
        !           185:       break;
        !           186:     case TME_MM58167_REG_WDAY:
        !           187:       value = now_tm->tm_wday;
        !           188:       break;
        !           189:     case TME_MM58167_REG_DAY:
        !           190:       value = now_tm->tm_mday;
        !           191:       break;
        !           192:     case TME_MM58167_REG_MON:
        !           193:       value = now_tm->tm_mon + 1;
        !           194:       break;
        !           195:     case TME_MM58167_REG_STATUS:
        !           196:       value = mm58167->tme_mm58167_status;
        !           197:       mm58167->tme_mm58167_status = 0;
        !           198:       break;
        !           199:     default:
        !           200:       abort();
        !           201:     }
        !           202: 
        !           203:     /* if needed, convert this value to BCD: */
        !           204:     if (reg_is_bcd) {
        !           205:       value = (value % 10) + ((value / 10) << 4);
        !           206:     }
        !           207: 
        !           208:     /* log this read: */
        !           209:     tme_log(TME_MM58167_LOG_HANDLE(mm58167), 100000, TME_OK,
        !           210:            (TME_MM58167_LOG_HANDLE(mm58167),
        !           211:             "reg %d read %02x",
        !           212:             reg, value));
        !           213: 
        !           214:     /* run the bus cycle: */
        !           215:     buffer = value;
        !           216:     cycle_resp.tme_bus_cycle_buffer = &buffer;
        !           217:     cycle_resp.tme_bus_cycle_lane_routing = tme_mm58167_router;
        !           218:     cycle_resp.tme_bus_cycle_address = 0;
        !           219:     cycle_resp.tme_bus_cycle_buffer_increment = 1;
        !           220:     cycle_resp.tme_bus_cycle_type = TME_BUS_CYCLE_WRITE;
        !           221:     cycle_resp.tme_bus_cycle_size = sizeof(buffer);
        !           222:     cycle_resp.tme_bus_cycle_port = 
        !           223:       TME_BUS_CYCLE_PORT(mm58167->tme_mm58167_port_least_lane,
        !           224:                         TME_BUS8_LOG2);
        !           225:     tme_bus_cycle_xfer(cycle_init, &cycle_resp);
        !           226:   }
        !           227:     
        !           228:   /* unlock the mutex: */
        !           229:   tme_mutex_unlock(&mm58167->tme_mm58167_mutex);
        !           230: 
        !           231:   /* no faults: */
        !           232:   return (TME_OK);
        !           233: }
        !           234: 
        !           235: /* the mm58167 TLB filler: */
        !           236: static int
        !           237: _tme_mm58167_tlb_fill(void *_mm58167, struct tme_bus_tlb *tlb, 
        !           238:                     tme_bus_addr_t address, unsigned int cycles)
        !           239: {
        !           240:   struct tme_mm58167 *mm58167;
        !           241:   tme_bus_addr_t mm58167_address_last;
        !           242: 
        !           243:   /* recover our data structure: */
        !           244:   mm58167 = (struct tme_mm58167 *) _mm58167;
        !           245: 
        !           246:   /* the address must be within range: */
        !           247:   mm58167_address_last = mm58167->tme_mm58167_device.tme_bus_device_address_last;
        !           248:   assert(address <= mm58167_address_last);
        !           249: 
        !           250:   /* initialize the TLB entry: */
        !           251:   tme_bus_tlb_initialize(tlb);
        !           252: 
        !           253:   /* this TLB entry can cover the whole device: */
        !           254:   TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_first, 0);
        !           255:   TME_ATOMIC_WRITE(tme_bus_addr_t, tlb->tme_bus_tlb_addr_last, mm58167_address_last);
        !           256: 
        !           257:   /* allow reading and writing: */
        !           258:   tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
        !           259: 
        !           260:   /* our bus cycle handler: */
        !           261:   tlb->tme_bus_tlb_cycle_private = mm58167;
        !           262:   tlb->tme_bus_tlb_cycle = _tme_mm58167_bus_cycle;
        !           263: 
        !           264:   return (TME_OK);
        !           265: }
        !           266: 
        !           267: /* the new mm58167 function: */
        !           268: TME_ELEMENT_NEW_DECL(tme_ic_mm58167) {
        !           269:   const struct tme_mm58167_socket *socket;
        !           270:   struct tme_mm58167 *mm58167;
        !           271:   struct tme_mm58167_socket socket_real;
        !           272:   tme_bus_addr_t address_mask;
        !           273: 
        !           274:   /* dispatch on our socket version: */
        !           275:   socket = (const struct tme_mm58167_socket *) extra;
        !           276:   if (socket == NULL) {
        !           277:     tme_output_append_error(_output, _("need an ic socket"));
        !           278:     return (ENXIO);
        !           279:   }
        !           280:   switch (socket->tme_mm58167_socket_version) {
        !           281:   case TME_MM58167_SOCKET_0:
        !           282:     socket_real = *socket;
        !           283:     break;
        !           284:   default: 
        !           285:     tme_output_append_error(_output, _("socket type"));
        !           286:     return (EOPNOTSUPP);
        !           287:   }
        !           288:     
        !           289:   /* we take no arguments: */
        !           290:   if (args[1] != NULL) {
        !           291:     tme_output_append_error(_output,
        !           292:                            "%s %s, %s %s",
        !           293:                            args[1],
        !           294:                            _("unexpected"),
        !           295:                            _("usage:"),
        !           296:                            args[0]);
        !           297:     return (EINVAL);
        !           298:   }
        !           299: 
        !           300:   /* start the mm58167 structure: */
        !           301:   mm58167 = tme_new0(struct tme_mm58167, 1);
        !           302:   tme_mutex_init(&mm58167->tme_mm58167_mutex);
        !           303:   mm58167->tme_mm58167_socket = socket_real;
        !           304: 
        !           305:   /* figure our address mask, up to the nearest power of two: */
        !           306:   address_mask = TME_MM58167_REG_BANK_SZ * mm58167->tme_mm58167_addr_shift;
        !           307:   if (address_mask & (address_mask - 1)) {
        !           308:     for (; address_mask & (address_mask - 1); address_mask &= (address_mask - 1));
        !           309:     address_mask <<= 1;
        !           310:   }
        !           311:   address_mask -= 1;
        !           312: 
        !           313:   /* initialize our simple bus device descriptor: */
        !           314:   mm58167->tme_mm58167_device.tme_bus_device_element = element;
        !           315:   mm58167->tme_mm58167_device.tme_bus_device_tlb_fill = _tme_mm58167_tlb_fill;
        !           316:   mm58167->tme_mm58167_device.tme_bus_device_address_last = address_mask;
        !           317: 
        !           318:   /* fill the element: */
        !           319:   element->tme_element_private = mm58167;
        !           320:   element->tme_element_connections_new = tme_bus_device_connections_new;
        !           321: 
        !           322:   return (TME_OK);
        !           323: }

unix.superglobalmegacorp.com

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