Annotation of tme/ic/mm58167.c, revision 1.1.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.