Annotation of qemu/hw/m48t59.c, revision 1.1.1.5

1.1       root        1: /*
1.1.1.2   root        2:  * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
1.1.1.4   root        3:  *
                      4:  * Copyright (c) 2003-2005, 2007 Jocelyn Mayer
                      5:  *
1.1       root        6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
1.1.1.4   root       24: #include "hw.h"
                     25: #include "nvram.h"
                     26: #include "isa.h"
                     27: #include "qemu-timer.h"
                     28: #include "sysemu.h"
1.1       root       29: 
                     30: //#define DEBUG_NVRAM
                     31: 
                     32: #if defined(DEBUG_NVRAM)
                     33: #define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
                     34: #else
                     35: #define NVRAM_PRINTF(fmt, args...) do { } while (0)
                     36: #endif
                     37: 
1.1.1.2   root       38: /*
1.1.1.4   root       39:  * The M48T02, M48T08 and M48T59 chips are very similar. The newer '59 has
1.1.1.2   root       40:  * alarm and a watchdog timer and related control registers. In the
                     41:  * PPC platform there is also a nvram lock function.
                     42:  */
1.1       root       43: struct m48t59_t {
1.1.1.2   root       44:     /* Model parameters */
1.1.1.4   root       45:     int type; // 2 = m48t02, 8 = m48t08, 59 = m48t59
1.1       root       46:     /* Hardware parameters */
1.1.1.4   root       47:     qemu_irq IRQ;
1.1       root       48:     int mem_index;
                     49:     uint32_t io_base;
                     50:     uint16_t size;
                     51:     /* RTC management */
                     52:     time_t   time_offset;
                     53:     time_t   stop_time;
                     54:     /* Alarm & watchdog */
1.1.1.5 ! root       55:     struct tm alarm;
1.1       root       56:     struct QEMUTimer *alrm_timer;
                     57:     struct QEMUTimer *wd_timer;
                     58:     /* NVRAM storage */
                     59:     uint8_t  lock;
                     60:     uint16_t addr;
                     61:     uint8_t *buffer;
                     62: };
                     63: 
                     64: /* Fake timer functions */
                     65: /* Generic helpers for BCD */
                     66: static inline uint8_t toBCD (uint8_t value)
                     67: {
                     68:     return (((value / 10) % 10) << 4) | (value % 10);
                     69: }
                     70: 
                     71: static inline uint8_t fromBCD (uint8_t BCD)
                     72: {
                     73:     return ((BCD >> 4) * 10) + (BCD & 0x0F);
                     74: }
                     75: 
                     76: /* Alarm management */
                     77: static void alarm_cb (void *opaque)
                     78: {
1.1.1.5 ! root       79:     struct tm tm;
1.1       root       80:     uint64_t next_time;
                     81:     m48t59_t *NVRAM = opaque;
                     82: 
1.1.1.4   root       83:     qemu_set_irq(NVRAM->IRQ, 1);
                     84:     if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
1.1       root       85:        (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
                     86:        (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
                     87:        (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
1.1.1.5 ! root       88:         /* Repeat once a month */
        !            89:         qemu_get_timedate(&tm, NVRAM->time_offset);
        !            90:         tm.tm_mon++;
        !            91:         if (tm.tm_mon == 13) {
        !            92:             tm.tm_mon = 1;
        !            93:             tm.tm_year++;
        !            94:         }
        !            95:         next_time = qemu_timedate_diff(&tm) - NVRAM->time_offset;
1.1       root       96:     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
                     97:               (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
                     98:               (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
                     99:               (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
1.1.1.5 ! root      100:         /* Repeat once a day */
        !           101:         next_time = 24 * 60 * 60;
1.1       root      102:     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
                    103:               (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
                    104:               (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
                    105:               (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
1.1.1.5 ! root      106:         /* Repeat once an hour */
        !           107:         next_time = 60 * 60;
1.1       root      108:     } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
                    109:               (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
                    110:               (NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
                    111:               (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
1.1.1.5 ! root      112:         /* Repeat once a minute */
        !           113:         next_time = 60;
1.1       root      114:     } else {
1.1.1.5 ! root      115:         /* Repeat once a second */
        !           116:         next_time = 1;
1.1       root      117:     }
1.1.1.5 ! root      118:     qemu_mod_timer(NVRAM->alrm_timer, qemu_get_clock(vm_clock) +
        !           119:                     next_time * 1000);
1.1.1.4   root      120:     qemu_set_irq(NVRAM->IRQ, 0);
1.1       root      121: }
                    122: 
1.1.1.5 ! root      123: static void set_alarm (m48t59_t *NVRAM)
        !           124: {
        !           125:     int diff;
        !           126:     if (NVRAM->alrm_timer != NULL) {
        !           127:         qemu_del_timer(NVRAM->alrm_timer);
        !           128:         diff = qemu_timedate_diff(&NVRAM->alarm) - NVRAM->time_offset;
        !           129:         if (diff > 0)
        !           130:             qemu_mod_timer(NVRAM->alrm_timer, diff * 1000);
        !           131:     }
        !           132: }
1.1       root      133: 
1.1.1.5 ! root      134: /* RTC management helpers */
        !           135: static inline void get_time (m48t59_t *NVRAM, struct tm *tm)
1.1       root      136: {
1.1.1.5 ! root      137:     qemu_get_timedate(tm, NVRAM->time_offset);
1.1       root      138: }
                    139: 
1.1.1.5 ! root      140: static void set_time (m48t59_t *NVRAM, struct tm *tm)
1.1       root      141: {
1.1.1.5 ! root      142:     NVRAM->time_offset = qemu_timedate_diff(tm);
        !           143:     set_alarm(NVRAM);
1.1       root      144: }
                    145: 
                    146: /* Watchdog management */
                    147: static void watchdog_cb (void *opaque)
                    148: {
                    149:     m48t59_t *NVRAM = opaque;
                    150: 
                    151:     NVRAM->buffer[0x1FF0] |= 0x80;
                    152:     if (NVRAM->buffer[0x1FF7] & 0x80) {
                    153:        NVRAM->buffer[0x1FF7] = 0x00;
                    154:        NVRAM->buffer[0x1FFC] &= ~0x40;
                    155:         /* May it be a hw CPU Reset instead ? */
                    156:         qemu_system_reset_request();
                    157:     } else {
1.1.1.4   root      158:        qemu_set_irq(NVRAM->IRQ, 1);
                    159:        qemu_set_irq(NVRAM->IRQ, 0);
1.1       root      160:     }
                    161: }
                    162: 
                    163: static void set_up_watchdog (m48t59_t *NVRAM, uint8_t value)
                    164: {
                    165:     uint64_t interval; /* in 1/16 seconds */
                    166: 
1.1.1.4   root      167:     NVRAM->buffer[0x1FF0] &= ~0x80;
1.1       root      168:     if (NVRAM->wd_timer != NULL) {
                    169:         qemu_del_timer(NVRAM->wd_timer);
1.1.1.4   root      170:         if (value != 0) {
                    171:             interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
                    172:             qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
                    173:                            ((interval * 1000) >> 4));
                    174:         }
1.1       root      175:     }
                    176: }
                    177: 
                    178: /* Direct access to NVRAM */
1.1.1.4   root      179: void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
1.1       root      180: {
1.1.1.4   root      181:     m48t59_t *NVRAM = opaque;
1.1       root      182:     struct tm tm;
                    183:     int tmp;
                    184: 
1.1.1.2   root      185:     if (addr > 0x1FF8 && addr < 0x2000)
                    186:        NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
1.1.1.4   root      187: 
                    188:     /* check for NVRAM access */
                    189:     if ((NVRAM->type == 2 && addr < 0x7f8) ||
                    190:         (NVRAM->type == 8 && addr < 0x1ff8) ||
                    191:         (NVRAM->type == 59 && addr < 0x1ff0))
1.1.1.2   root      192:         goto do_write;
1.1.1.4   root      193: 
                    194:     /* TOD access */
1.1.1.2   root      195:     switch (addr) {
1.1       root      196:     case 0x1FF0:
                    197:         /* flags register : read-only */
                    198:         break;
                    199:     case 0x1FF1:
                    200:         /* unused */
                    201:         break;
                    202:     case 0x1FF2:
                    203:         /* alarm seconds */
1.1.1.2   root      204:         tmp = fromBCD(val & 0x7F);
                    205:         if (tmp >= 0 && tmp <= 59) {
1.1.1.5 ! root      206:             NVRAM->alarm.tm_sec = tmp;
1.1.1.2   root      207:             NVRAM->buffer[0x1FF2] = val;
1.1.1.5 ! root      208:             set_alarm(NVRAM);
1.1.1.2   root      209:         }
1.1       root      210:         break;
                    211:     case 0x1FF3:
                    212:         /* alarm minutes */
1.1.1.2   root      213:         tmp = fromBCD(val & 0x7F);
                    214:         if (tmp >= 0 && tmp <= 59) {
1.1.1.5 ! root      215:             NVRAM->alarm.tm_min = tmp;
1.1.1.2   root      216:             NVRAM->buffer[0x1FF3] = val;
1.1.1.5 ! root      217:             set_alarm(NVRAM);
1.1.1.2   root      218:         }
1.1       root      219:         break;
                    220:     case 0x1FF4:
                    221:         /* alarm hours */
1.1.1.2   root      222:         tmp = fromBCD(val & 0x3F);
                    223:         if (tmp >= 0 && tmp <= 23) {
1.1.1.5 ! root      224:             NVRAM->alarm.tm_hour = tmp;
1.1.1.2   root      225:             NVRAM->buffer[0x1FF4] = val;
1.1.1.5 ! root      226:             set_alarm(NVRAM);
1.1.1.2   root      227:         }
1.1       root      228:         break;
                    229:     case 0x1FF5:
                    230:         /* alarm date */
1.1.1.2   root      231:         tmp = fromBCD(val & 0x1F);
                    232:         if (tmp != 0) {
1.1.1.5 ! root      233:             NVRAM->alarm.tm_mday = tmp;
1.1.1.2   root      234:             NVRAM->buffer[0x1FF5] = val;
1.1.1.5 ! root      235:             set_alarm(NVRAM);
1.1.1.2   root      236:         }
1.1       root      237:         break;
                    238:     case 0x1FF6:
                    239:         /* interrupts */
1.1.1.2   root      240:         NVRAM->buffer[0x1FF6] = val;
1.1       root      241:         break;
                    242:     case 0x1FF7:
                    243:         /* watchdog */
1.1.1.2   root      244:         NVRAM->buffer[0x1FF7] = val;
                    245:         set_up_watchdog(NVRAM, val);
1.1       root      246:         break;
                    247:     case 0x1FF8:
1.1.1.4   root      248:     case 0x07F8:
1.1       root      249:         /* control */
1.1.1.4   root      250:        NVRAM->buffer[addr] = (val & ~0xA0) | 0x90;
1.1       root      251:         break;
                    252:     case 0x1FF9:
1.1.1.4   root      253:     case 0x07F9:
1.1       root      254:         /* seconds (BCD) */
                    255:        tmp = fromBCD(val & 0x7F);
                    256:        if (tmp >= 0 && tmp <= 59) {
                    257:            get_time(NVRAM, &tm);
                    258:            tm.tm_sec = tmp;
                    259:            set_time(NVRAM, &tm);
                    260:        }
1.1.1.5 ! root      261:         if ((val & 0x80) ^ (NVRAM->buffer[addr] & 0x80)) {
1.1       root      262:            if (val & 0x80) {
                    263:                NVRAM->stop_time = time(NULL);
                    264:            } else {
                    265:                NVRAM->time_offset += NVRAM->stop_time - time(NULL);
                    266:                NVRAM->stop_time = 0;
                    267:            }
                    268:        }
1.1.1.5 ! root      269:         NVRAM->buffer[addr] = val & 0x80;
1.1       root      270:         break;
                    271:     case 0x1FFA:
1.1.1.4   root      272:     case 0x07FA:
1.1       root      273:         /* minutes (BCD) */
                    274:        tmp = fromBCD(val & 0x7F);
                    275:        if (tmp >= 0 && tmp <= 59) {
                    276:            get_time(NVRAM, &tm);
                    277:            tm.tm_min = tmp;
                    278:            set_time(NVRAM, &tm);
                    279:        }
                    280:         break;
                    281:     case 0x1FFB:
1.1.1.4   root      282:     case 0x07FB:
1.1       root      283:         /* hours (BCD) */
                    284:        tmp = fromBCD(val & 0x3F);
                    285:        if (tmp >= 0 && tmp <= 23) {
                    286:            get_time(NVRAM, &tm);
                    287:            tm.tm_hour = tmp;
                    288:            set_time(NVRAM, &tm);
                    289:        }
                    290:         break;
                    291:     case 0x1FFC:
1.1.1.4   root      292:     case 0x07FC:
1.1       root      293:         /* day of the week / century */
                    294:        tmp = fromBCD(val & 0x07);
                    295:        get_time(NVRAM, &tm);
                    296:        tm.tm_wday = tmp;
                    297:        set_time(NVRAM, &tm);
1.1.1.4   root      298:         NVRAM->buffer[addr] = val & 0x40;
1.1       root      299:         break;
                    300:     case 0x1FFD:
1.1.1.4   root      301:     case 0x07FD:
1.1       root      302:         /* date */
                    303:        tmp = fromBCD(val & 0x1F);
                    304:        if (tmp != 0) {
                    305:            get_time(NVRAM, &tm);
                    306:            tm.tm_mday = tmp;
                    307:            set_time(NVRAM, &tm);
                    308:        }
                    309:         break;
                    310:     case 0x1FFE:
1.1.1.4   root      311:     case 0x07FE:
1.1       root      312:         /* month */
                    313:        tmp = fromBCD(val & 0x1F);
                    314:        if (tmp >= 1 && tmp <= 12) {
                    315:            get_time(NVRAM, &tm);
                    316:            tm.tm_mon = tmp - 1;
                    317:            set_time(NVRAM, &tm);
                    318:        }
                    319:         break;
                    320:     case 0x1FFF:
1.1.1.4   root      321:     case 0x07FF:
1.1       root      322:         /* year */
                    323:        tmp = fromBCD(val);
                    324:        if (tmp >= 0 && tmp <= 99) {
                    325:            get_time(NVRAM, &tm);
1.1.1.3   root      326:             if (NVRAM->type == 8)
                    327:                 tm.tm_year = fromBCD(val) + 68; // Base year is 1968
                    328:             else
                    329:                 tm.tm_year = fromBCD(val);
1.1       root      330:            set_time(NVRAM, &tm);
                    331:        }
                    332:         break;
                    333:     default:
                    334:         /* Check lock registers state */
1.1.1.2   root      335:         if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
1.1       root      336:             break;
1.1.1.2   root      337:         if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
1.1       root      338:             break;
1.1.1.2   root      339:     do_write:
                    340:         if (addr < NVRAM->size) {
                    341:             NVRAM->buffer[addr] = val & 0xFF;
1.1       root      342:        }
                    343:         break;
                    344:     }
                    345: }
                    346: 
1.1.1.4   root      347: uint32_t m48t59_read (void *opaque, uint32_t addr)
1.1       root      348: {
1.1.1.4   root      349:     m48t59_t *NVRAM = opaque;
1.1       root      350:     struct tm tm;
                    351:     uint32_t retval = 0xFF;
                    352: 
1.1.1.4   root      353:     /* check for NVRAM access */
                    354:     if ((NVRAM->type == 2 && addr < 0x078f) ||
                    355:         (NVRAM->type == 8 && addr < 0x1ff8) ||
                    356:         (NVRAM->type == 59 && addr < 0x1ff0))
1.1.1.2   root      357:         goto do_read;
1.1.1.4   root      358: 
                    359:     /* TOD access */
1.1.1.2   root      360:     switch (addr) {
1.1       root      361:     case 0x1FF0:
                    362:         /* flags register */
                    363:        goto do_read;
                    364:     case 0x1FF1:
                    365:         /* unused */
                    366:        retval = 0;
                    367:         break;
                    368:     case 0x1FF2:
                    369:         /* alarm seconds */
                    370:        goto do_read;
                    371:     case 0x1FF3:
                    372:         /* alarm minutes */
                    373:        goto do_read;
                    374:     case 0x1FF4:
                    375:         /* alarm hours */
                    376:        goto do_read;
                    377:     case 0x1FF5:
                    378:         /* alarm date */
                    379:        goto do_read;
                    380:     case 0x1FF6:
                    381:         /* interrupts */
                    382:        goto do_read;
                    383:     case 0x1FF7:
                    384:        /* A read resets the watchdog */
                    385:        set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
                    386:        goto do_read;
                    387:     case 0x1FF8:
1.1.1.4   root      388:     case 0x07F8:
1.1       root      389:         /* control */
                    390:        goto do_read;
                    391:     case 0x1FF9:
1.1.1.4   root      392:     case 0x07F9:
1.1       root      393:         /* seconds (BCD) */
                    394:         get_time(NVRAM, &tm);
1.1.1.4   root      395:         retval = (NVRAM->buffer[addr] & 0x80) | toBCD(tm.tm_sec);
1.1       root      396:         break;
                    397:     case 0x1FFA:
1.1.1.4   root      398:     case 0x07FA:
1.1       root      399:         /* minutes (BCD) */
                    400:         get_time(NVRAM, &tm);
                    401:         retval = toBCD(tm.tm_min);
                    402:         break;
                    403:     case 0x1FFB:
1.1.1.4   root      404:     case 0x07FB:
1.1       root      405:         /* hours (BCD) */
                    406:         get_time(NVRAM, &tm);
                    407:         retval = toBCD(tm.tm_hour);
                    408:         break;
                    409:     case 0x1FFC:
1.1.1.4   root      410:     case 0x07FC:
1.1       root      411:         /* day of the week / century */
                    412:         get_time(NVRAM, &tm);
1.1.1.4   root      413:         retval = NVRAM->buffer[addr] | tm.tm_wday;
1.1       root      414:         break;
                    415:     case 0x1FFD:
1.1.1.4   root      416:     case 0x07FD:
1.1       root      417:         /* date */
                    418:         get_time(NVRAM, &tm);
                    419:         retval = toBCD(tm.tm_mday);
                    420:         break;
                    421:     case 0x1FFE:
1.1.1.4   root      422:     case 0x07FE:
1.1       root      423:         /* month */
                    424:         get_time(NVRAM, &tm);
                    425:         retval = toBCD(tm.tm_mon + 1);
                    426:         break;
                    427:     case 0x1FFF:
1.1.1.4   root      428:     case 0x07FF:
1.1       root      429:         /* year */
                    430:         get_time(NVRAM, &tm);
1.1.1.4   root      431:         if (NVRAM->type == 8)
1.1.1.3   root      432:             retval = toBCD(tm.tm_year - 68); // Base year is 1968
                    433:         else
                    434:             retval = toBCD(tm.tm_year);
1.1       root      435:         break;
                    436:     default:
                    437:         /* Check lock registers state */
1.1.1.2   root      438:         if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
1.1       root      439:             break;
1.1.1.2   root      440:         if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
1.1       root      441:             break;
1.1.1.2   root      442:     do_read:
                    443:         if (addr < NVRAM->size) {
                    444:             retval = NVRAM->buffer[addr];
1.1       root      445:        }
                    446:         break;
                    447:     }
1.1.1.2   root      448:     if (addr > 0x1FF9 && addr < 0x2000)
1.1.1.4   root      449:        NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
1.1       root      450: 
                    451:     return retval;
                    452: }
                    453: 
1.1.1.4   root      454: void m48t59_set_addr (void *opaque, uint32_t addr)
1.1       root      455: {
1.1.1.4   root      456:     m48t59_t *NVRAM = opaque;
                    457: 
1.1       root      458:     NVRAM->addr = addr;
                    459: }
                    460: 
1.1.1.4   root      461: void m48t59_toggle_lock (void *opaque, int lock)
1.1       root      462: {
1.1.1.4   root      463:     m48t59_t *NVRAM = opaque;
                    464: 
1.1       root      465:     NVRAM->lock ^= 1 << lock;
                    466: }
                    467: 
                    468: /* IO access to NVRAM */
                    469: static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val)
                    470: {
                    471:     m48t59_t *NVRAM = opaque;
                    472: 
                    473:     addr -= NVRAM->io_base;
1.1.1.4   root      474:     NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
1.1       root      475:     switch (addr) {
                    476:     case 0:
                    477:         NVRAM->addr &= ~0x00FF;
                    478:         NVRAM->addr |= val;
                    479:         break;
                    480:     case 1:
                    481:         NVRAM->addr &= ~0xFF00;
                    482:         NVRAM->addr |= val << 8;
                    483:         break;
                    484:     case 3:
1.1.1.2   root      485:         m48t59_write(NVRAM, val, NVRAM->addr);
1.1       root      486:         NVRAM->addr = 0x0000;
                    487:         break;
                    488:     default:
                    489:         break;
                    490:     }
                    491: }
                    492: 
                    493: static uint32_t NVRAM_readb (void *opaque, uint32_t addr)
                    494: {
                    495:     m48t59_t *NVRAM = opaque;
                    496:     uint32_t retval;
                    497: 
                    498:     addr -= NVRAM->io_base;
                    499:     switch (addr) {
                    500:     case 3:
1.1.1.2   root      501:         retval = m48t59_read(NVRAM, NVRAM->addr);
1.1       root      502:         break;
                    503:     default:
                    504:         retval = -1;
                    505:         break;
                    506:     }
1.1.1.4   root      507:     NVRAM_PRINTF("%s: 0x%08x <= 0x%08x\n", __func__, addr, retval);
1.1       root      508: 
                    509:     return retval;
                    510: }
                    511: 
                    512: static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
                    513: {
                    514:     m48t59_t *NVRAM = opaque;
1.1.1.4   root      515: 
1.1.1.2   root      516:     m48t59_write(NVRAM, addr, value & 0xff);
1.1       root      517: }
                    518: 
                    519: static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
                    520: {
                    521:     m48t59_t *NVRAM = opaque;
1.1.1.4   root      522: 
1.1.1.2   root      523:     m48t59_write(NVRAM, addr, (value >> 8) & 0xff);
                    524:     m48t59_write(NVRAM, addr + 1, value & 0xff);
1.1       root      525: }
                    526: 
                    527: static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
                    528: {
                    529:     m48t59_t *NVRAM = opaque;
1.1.1.4   root      530: 
1.1.1.2   root      531:     m48t59_write(NVRAM, addr, (value >> 24) & 0xff);
                    532:     m48t59_write(NVRAM, addr + 1, (value >> 16) & 0xff);
                    533:     m48t59_write(NVRAM, addr + 2, (value >> 8) & 0xff);
                    534:     m48t59_write(NVRAM, addr + 3, value & 0xff);
1.1       root      535: }
                    536: 
                    537: static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
                    538: {
                    539:     m48t59_t *NVRAM = opaque;
1.1.1.2   root      540:     uint32_t retval;
1.1.1.4   root      541: 
1.1.1.2   root      542:     retval = m48t59_read(NVRAM, addr);
1.1       root      543:     return retval;
                    544: }
                    545: 
                    546: static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
                    547: {
                    548:     m48t59_t *NVRAM = opaque;
1.1.1.2   root      549:     uint32_t retval;
1.1.1.4   root      550: 
1.1.1.2   root      551:     retval = m48t59_read(NVRAM, addr) << 8;
                    552:     retval |= m48t59_read(NVRAM, addr + 1);
1.1       root      553:     return retval;
                    554: }
                    555: 
                    556: static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
                    557: {
                    558:     m48t59_t *NVRAM = opaque;
1.1.1.2   root      559:     uint32_t retval;
1.1       root      560: 
1.1.1.2   root      561:     retval = m48t59_read(NVRAM, addr) << 24;
                    562:     retval |= m48t59_read(NVRAM, addr + 1) << 16;
                    563:     retval |= m48t59_read(NVRAM, addr + 2) << 8;
                    564:     retval |= m48t59_read(NVRAM, addr + 3);
1.1       root      565:     return retval;
                    566: }
                    567: 
                    568: static CPUWriteMemoryFunc *nvram_write[] = {
                    569:     &nvram_writeb,
                    570:     &nvram_writew,
                    571:     &nvram_writel,
                    572: };
                    573: 
                    574: static CPUReadMemoryFunc *nvram_read[] = {
                    575:     &nvram_readb,
                    576:     &nvram_readw,
                    577:     &nvram_readl,
                    578: };
1.1.1.2   root      579: 
1.1.1.4   root      580: static void m48t59_save(QEMUFile *f, void *opaque)
                    581: {
                    582:     m48t59_t *s = opaque;
                    583: 
                    584:     qemu_put_8s(f, &s->lock);
                    585:     qemu_put_be16s(f, &s->addr);
                    586:     qemu_put_buffer(f, s->buffer, s->size);
                    587: }
                    588: 
                    589: static int m48t59_load(QEMUFile *f, void *opaque, int version_id)
                    590: {
                    591:     m48t59_t *s = opaque;
                    592: 
                    593:     if (version_id != 1)
                    594:         return -EINVAL;
                    595: 
                    596:     qemu_get_8s(f, &s->lock);
                    597:     qemu_get_be16s(f, &s->addr);
                    598:     qemu_get_buffer(f, s->buffer, s->size);
                    599: 
                    600:     return 0;
                    601: }
                    602: 
                    603: static void m48t59_reset(void *opaque)
                    604: {
                    605:     m48t59_t *NVRAM = opaque;
                    606: 
1.1.1.5 ! root      607:     NVRAM->addr = 0;
        !           608:     NVRAM->lock = 0;
1.1.1.4   root      609:     if (NVRAM->alrm_timer != NULL)
                    610:         qemu_del_timer(NVRAM->alrm_timer);
                    611: 
                    612:     if (NVRAM->wd_timer != NULL)
                    613:         qemu_del_timer(NVRAM->wd_timer);
                    614: }
                    615: 
1.1       root      616: /* Initialisation routine */
1.1.1.4   root      617: m48t59_t *m48t59_init (qemu_irq IRQ, target_phys_addr_t mem_base,
1.1.1.2   root      618:                        uint32_t io_base, uint16_t size,
                    619:                        int type)
1.1       root      620: {
                    621:     m48t59_t *s;
1.1.1.4   root      622:     target_phys_addr_t save_base;
1.1       root      623: 
                    624:     s = qemu_mallocz(sizeof(m48t59_t));
                    625:     s->buffer = qemu_mallocz(size);
                    626:     s->IRQ = IRQ;
                    627:     s->size = size;
                    628:     s->io_base = io_base;
1.1.1.2   root      629:     s->type = type;
                    630:     if (io_base != 0) {
                    631:         register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s);
                    632:         register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s);
                    633:     }
1.1       root      634:     if (mem_base != 0) {
                    635:         s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
1.1.1.4   root      636:         cpu_register_physical_memory(mem_base, size, s->mem_index);
1.1       root      637:     }
1.1.1.2   root      638:     if (type == 59) {
                    639:         s->alrm_timer = qemu_new_timer(vm_clock, &alarm_cb, s);
                    640:         s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s);
                    641:     }
1.1.1.5 ! root      642:     qemu_get_timedate(&s->alarm, 0);
1.1       root      643: 
1.1.1.4   root      644:     qemu_register_reset(m48t59_reset, s);
                    645:     save_base = mem_base ? mem_base : io_base;
                    646:     register_savevm("m48t59", save_base, 1, m48t59_save, m48t59_load, s);
                    647: 
1.1       root      648:     return s;
                    649: }

unix.superglobalmegacorp.com