Annotation of nono/vm/mk48t02.cpp, revision 1.1.1.17

1.1       root        1: //
                      2: // nono
1.1.1.4   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: //
1.1.1.12  root        8: // NVRAM/RTC (MK48T02)
1.1       root        9: //
1.1.1.12  root       10: 
1.1       root       11: // SRAM 部分はビッグエンディアンのままメモリに置かれるので、
                     12: // 必要ならアクセス時に都度変換すること。
                     13: //
                     14: // 仕様は 0x45000000 から 2KB だが、
1.1.1.13  root       15: // LUNA-I   では 0x44000000 から 0x47ffffff まで 2KB 単位でミラーが見える。
                     16: // LUNA-88K では 0x44000000 から 0x45ffffff までが
                     17: // (こちらはロングワード配置なので) 8KB 単位のミラーに見える。
1.1       root       18: 
1.1.1.12  root       19: #include "mk48t02.h"
                     20: #include "bitops.h"
                     21: #include "config.h"
                     22: #include "mainapp.h"
1.1.1.17! root       23: #include "mainbus.h"
1.1.1.16  root       24: #include "monitor.h"
1.1.1.12  root       25: #include <fcntl.h>
                     26: #include <unistd.h>
                     27: #include <sys/stat.h>
                     28: #include <array>
                     29: 
                     30: // コンストラクタ
1.1       root       31: MK48T02Device::MK48T02Device()
1.1.1.13  root       32:        : inherited()
1.1       root       33: {
1.1.1.13  root       34:        SetName("MK48T02");
1.1.1.9   root       35: 
1.1.1.13  root       36:        AddAlias("MK48T02");
                     37:        AddAlias("NVRAM");
1.1.1.9   root       38: 
1.1.1.12  root       39:        // 今の所 UTC として使うケースだけのようだ。
1.1.1.10  root       40:        use_localtime = false;
                     41: 
1.1.1.16  root       42:        monitor = gMonitorManager->Regist(ID_MONITOR_MK48T02, this);
1.1.1.17! root       43:        monitor->SetCallback(&MK48T02Device::MonitorScreen);
1.1.1.16  root       44:        monitor->SetSize(40, 13);
1.1       root       45: }
                     46: 
1.1.1.12  root       47: // デストラクタ
1.1       root       48: MK48T02Device::~MK48T02Device()
                     49: {
                     50: }
                     51: 
1.1.1.13  root       52: // 初期化
1.1       root       53: bool
                     54: MK48T02Device::Init()
                     55: {
1.1.1.13  root       56:        if (inherited::Init() == false) {
                     57:                return false;
                     58:        }
                     59: 
1.1.1.12  root       60:        struct stat st;
                     61: 
                     62:        // NetBSD/luna68k, OpenBSD/luna88k ともに epoch を 1970年としている
                     63:        // (2021/07 現在) 一方、4.4BSD (luna68k 版?) は 1900年としている。
                     64:        // MK48T02 本来定義は 0 というか 1900 というか。DecodeYear() も参照。
                     65:        const ConfigItem& item = gConfig->Find("rtc-epoch-year");
                     66:        int year_epoch_val;
                     67:        if (item.TryInt(&year_epoch_val) == false) {
                     68:                item.Err();
1.1.1.10  root       69:                return false;
                     70:        }
1.1.1.12  root       71:        // 雑にチェック
                     72:        if (year_epoch_val < 1900) {
1.1.1.13  root       73:                item.Err("Must be >= 1900");
1.1.1.12  root       74:                return false;
                     75:        }
                     76:        year_epoch = (uint)year_epoch_val;
1.1.1.10  root       77: 
                     78:        // MK48T02 のデータシートには年には西暦年の下位2桁を設定するように
1.1.1.12  root       79:        // 指示されており、4.4BSD (luna68k) はこの通りになっている。
1.1.1.10  root       80:        // しかし CMU Mach luna88k, NetBSD/luna68k, OpenBSD/luna88k はいずれも
                     81:        // 西暦年から 1970 引いた値を設定するようになっている (2021/07 現在)。
                     82:        // このため、うるう年が2年ずれた状態になる。
                     83:        //
                     84:        // NetBSD で MK48T02 を採用している luna68k 以外の port は
                     85:        // ソースコード上の変数 year0 もしくは YEAR0 に
                     86:        //  newsmips, news68k: 1900 (データシート規定通り)
                     87:        //  sun3, sparc, mvme68k: 1968 (1968 はうるう年なので問題ない)
                     88:        // を採用しており、バグっていない。
                     89:        // この year0 は UNIX EPOCH とは直接関係がない RTC ハードウェアに
                     90:        // 依存する値なのだが、LUNA では混同したのだろうか?
                     91:        //
                     92:        // たぶんこのバグはもう修正されることはないだろうから、こちらで補正する
                     93:        // スイッチを用意した。
1.1.1.13  root       94:        if (gMainApp.Has(VMCap::LUNA)) {
1.1.1.17! root       95:                if (gConfig->Find("luna-adjust-misused-epoch").AsBool()) {
1.1.1.13  root       96:                        // エポック年のうるう年カウンタ相当を補正項として持つ
                     97:                        adjust_leap = year_epoch % 4;
                     98:                } else {
                     99:                        adjust_leap = 0;
                    100:                }
                    101:        }
1.1.1.10  root      102: 
1.1.1.13  root      103:        // MSX-DOS モードなら NVRAM 不要なのでここでダミーのメモリだけ用意。
                    104:        if (gMainApp.msxdos_mode) {
                    105:                // XXX アプリケーション寿命まで解放してないけど、まあいいか
                    106:                mem = (uint8 *)malloc(16 * 1024);
                    107:                return true;
1.1.1.10  root      108:        }
                    109: 
1.1.1.12  root      110:        // ファイルサイズを更新。
                    111:        // ver 0.2.3 までの NVRAM.DAT は 2040 バイトだったが、ver 0.2.4 以降は
                    112:        // 2048 バイトになるため、ここでファイルがあって 2040 バイトなら 2048
                    113:        // バイトに拡張する。失敗したらここでは何もしない。
1.1.1.3   root      114:        filename = gMainApp.GetVMDir() + "NVRAM.DAT";
1.1.1.12  root      115:        std::string dispname = string_format("NVRAM \"%s\"", filename.c_str());
                    116:        if (stat(filename.c_str(), &st) == 0 && st.st_size == 2040) {
                    117:                int fd;
                    118:                fd = open(filename.c_str(), O_WRONLY | O_APPEND);
                    119:                if (fd >= 0) {
                    120:                        std::array<uint8, 8> zerobuf {};
                    121:                        write(fd, &zerobuf[0], zerobuf.size());
                    122:                        close(fd);
                    123:                        stat(filename.c_str(), &st);
                    124:                        warnx("%s extended to %jd bytes",
                    125:                                dispname.c_str(), (intmax_t)st.st_size);
                    126:                }
                    127:        }
                    128: 
                    129:        // ファイルのロード
1.1.1.4   root      130:        file.SetFilename(filename);
1.1.1.12  root      131:        file.SetDispname(dispname);
                    132:        mem = file.OpenCreate(2048);
1.1.1.4   root      133:        if (mem == NULL) {
1.1.1.17! root      134:                // エラーメッセージは表示済み。
1.1       root      135:                return false;
                    136:        }
                    137: 
1.1.1.13  root      138:        return true;
1.1.1.12  root      139: }
                    140: 
                    141: void
                    142: MK48T02Device::StartTime()
                    143: {
                    144:        inherited::StartTime();
                    145: 
                    146:        // 内部カレンダをメモリに反映
                    147:        Store(reg.in);
1.1       root      148: }
                    149: 
                    150: // バイナリ表現を BCD 表現に変換する
                    151: /*static*/ inline uint8
                    152: MK48T02Device::num2BCD(uint8 num)
                    153: {
                    154:        return ((num / 10) << 4) + (num % 10);
                    155: }
                    156: 
                    157: // BCD 表現をバイナリ表現に変換する
                    158: /*static*/ inline uint8
                    159: MK48T02Device::BCD2num(uint8 bcd)
                    160: {
                    161:        return (bcd >> 4) * 10 + (bcd & 0x0f);
                    162: }
                    163: 
1.1.1.14  root      164: busdata
1.1.1.15  root      165: MK48T02Device::ReadPort(uint32 offset)
1.1       root      166: {
1.1.1.14  root      167:        busdata data;
1.1       root      168: 
1.1.1.12  root      169:        data = mem[offset];
1.1.1.17! root      170:        putlog(3, "$%08x -> $%02x", GetMainbusDevice()->GetPaddr(), data.Data());
1.1       root      171: 
1.1.1.14  root      172:        // XXX wait?
1.1.1.15  root      173:        data |= BusData::Size1;
1.1       root      174:        return data;
                    175: }
                    176: 
1.1.1.14  root      177: busdata
1.1.1.15  root      178: MK48T02Device::WritePort(uint32 offset, uint32 data)
1.1       root      179: {
1.1.1.17! root      180:        putlog(3, "$%08x <- $%02x", GetMainbusDevice()->GetPaddr(), data);
1.1.1.10  root      181: 
1.1.1.12  root      182:        switch (offset - 2040) {
                    183:         case 0:        // コントロール
                    184:                WriteCtrl(data);
                    185:                break;
                    186:         case 1:        // 秒 (b7 は STOP BIT)
                    187:                reg.stop = data & MK48T02Clock::STOP;
                    188:                break;
                    189:         case 2:        // 分
                    190:                break;
                    191:         case 3:        // 時 (b7 は KICK START)
                    192:                reg.kickstart = data & MK48T02Clock::KICKSTART;
                    193:                break;
                    194:         case 4:        // 曜日 (b6 は Frequency Test (未実装))
                    195:                // データシートでは b7, b5, b4 は '0' とあるが実際には '1' が
                    196:                // 書き込める。書き込んだ '1' が内部クロックの更新でどうなるか
                    197:                // 未確認のため、とりあえず放置。
                    198:                reg.freqtest = data & MK48T02Clock::FREQTEST;
                    199:                break;
                    200:         case 5:        // 日
                    201:                // データシートでは b7, b6 は '0' とあるが実際には b7 には '1' が
                    202:                // 書き込める (b6 には書き込めない)。b7 に書き込んだ '1' が内部
                    203:                // クロックの更新でどうなるか未確認のため、とりあえずは放置。
                    204:                break;
                    205:         case 6:        // 月
                    206:                break;
                    207:         case 7:        // 年
                    208:                break;
                    209:         default:
                    210:                break;
1.1       root      211:        }
1.1.1.12  root      212: 
                    213:        mem[offset] = data;
                    214: 
1.1.1.14  root      215:        // XXX wait?
1.1.1.15  root      216:        busdata r = BusData::Size1;
                    217:        return r;
1.1       root      218: }
                    219: 
1.1.1.14  root      220: busdata
1.1.1.15  root      221: MK48T02Device::PeekPort(uint32 offset)
1.1       root      222: {
1.1.1.12  root      223:        return mem[offset];
1.1       root      224: }
                    225: 
1.1.1.14  root      226: bool
1.1.1.15  root      227: MK48T02Device::PokePort(uint32 offset, uint32 data)
1.1.1.13  root      228: {
                    229:        // 時計部分にはコントロールレジスタもあるので書き込み不可。
                    230:        if (offset >= 2040) {
1.1.1.14  root      231:                return false;
1.1.1.13  root      232:        } else {
                    233:                if ((int32)data >= 0) {
                    234:                        mem[offset] = data;
                    235:                }
1.1.1.14  root      236:                return true;
1.1.1.13  root      237:        }
                    238: }
                    239: 
1.1.1.5   root      240: void
1.1.1.17! root      241: MK48T02Device::MonitorScreen(Monitor *, TextScreen& screen)
1.1       root      242: {
1.1.1.10  root      243:        uint32 addr;
                    244:        uint32 v;
                    245:        int y = 0;
                    246: 
1.1.1.9   root      247:        screen.Clear();
1.1       root      248: 
1.1.1.10  root      249:        // BCD なので %x で表示する
                    250:        screen.Print(0, y++,
1.1.1.15  root      251:                "Internal: %04u[%02x]/%02x/%02x(%s) %02x:%02x:%02x.%1x",
1.1.1.10  root      252:                DecodeYear(reg.in.year), reg.in.year,
                    253:                reg.in.mon, reg.in.mday, wdays[reg.in.wday],
                    254:                reg.in.hour, reg.in.min, reg.in.sec, (uint32)((cnt >> 1) & 0xf));
1.1.1.12  root      255: 
                    256:        auto ex = Load();
1.1.1.10  root      257:        screen.Print(0, y++,
1.1.1.15  root      258:                "Register: %04u[%02x]/%02x/%02x(%s) %02x:%02x:%02x",
1.1.1.12  root      259:                DecodeYear(ex.year), ex.year,
                    260:                ex.mon, ex.mday, wdays[ex.wday],
                    261:                ex.hour, ex.min, ex.sec);
                    262: 
1.1.1.10  root      263:        screen.Print(0, y++, "TimeZone: %s",
                    264:                use_localtime ? "Local" : "UTC");
1.1.1.15  root      265:        screen.Print(0, y++, "Epoch   : %4u  (Adjust Leap: %u)",
1.1.1.10  root      266:                year_epoch, adjust_leap);
                    267:        y++;
                    268: 
                    269:        addr = 0x800;
1.1.1.15  root      270:        v = PeekPort(--addr);
1.1.1.10  root      271:        screen.Print(0, y++, "$%3x: $%02x (year=%02x)", addr, v, v);
1.1.1.15  root      272:        v = PeekPort(--addr);
1.1.1.10  root      273:        screen.Print(0, y++, "$%3x: $%02x (mon =%02x)", addr, v, v);
1.1.1.15  root      274:        v = PeekPort(--addr);
1.1.1.10  root      275:        screen.Print(0, y++, "$%3x: $%02x (date=%02x)", addr, v, v);
1.1.1.15  root      276:        v = PeekPort(--addr);
                    277:        screen.Print(0, y++, "$%3x: $%02x (wday=%02x  FT=%u)",
1.1.1.10  root      278:                addr, v, (v & 0x07), (v & MK48T02Clock::FREQTEST) ? 1 : 0);
1.1.1.15  root      279:        v = PeekPort(--addr);
                    280:        screen.Print(0, y++, "$%3x: $%02x (hour=%02x  KS=%u)",
1.1.1.10  root      281:                addr, v, (v & 0x3f), (v & MK48T02Clock::KICKSTART) ? 1 : 0);
1.1.1.15  root      282:        v = PeekPort(--addr);
1.1.1.10  root      283:        screen.Print(0, y++, "$%3x: $%02x (min =%02x)", addr, v, (v & 0x7f));
1.1.1.15  root      284:        v = PeekPort(--addr);
                    285:        screen.Print(0, y++, "$%3x: $%02x (sec =%02x  ST=%u)",
1.1.1.10  root      286:                addr, v, (v & 0x7f), (v & MK48T02Clock::STOP) ? 1 : 0);
1.1.1.15  root      287:        v = PeekPort(--addr);
                    288:        screen.Print(0, y++, "$%3x: $%02x (W=%u R=%u)",
1.1.1.10  root      289:                addr, v,
                    290:                (v & MK48T02Clock::WRITE) ? 1 : 0,
                    291:                (v & MK48T02Clock::READ)  ? 1 : 0);
1.1       root      292: }
                    293: 
                    294: // コントロールレジスタへの書き込み
                    295: void
                    296: MK48T02Device::WriteCtrl(uint32 data)
                    297: {
1.1.1.12  root      298:        uint8 old = mem[0x7f8];
1.1.1.10  root      299: 
1.1.1.12  root      300:        bool write_fall = bit_falling(old, data, MK48T02Clock::WRITE);
1.1       root      301: 
1.1.1.10  root      302:        // ホールドしているかどうかは状態なのでエッジではない
1.1.1.12  root      303:        hold = (data & (MK48T02Clock::READ | MK48T02Clock::WRITE));
1.1.1.10  root      304: 
                    305:        if (write_fall) {
1.1.1.12  root      306:                // WRITE ビットの立ち下がりエッジでメモリから内部カウンタへロード
                    307:                reg.in = Load();
                    308: 
1.1.1.10  root      309:                // 分周段は規定されていないが意味的にクリアするほうが良いだろう
                    310:                cnt = 0;
1.1       root      311:        }
                    312: }
                    313: 
1.1.1.12  root      314: // NVRAM からカレンダをロード
                    315: MK48T02Clock::calendar
                    316: MK48T02Device::Load() const
                    317: {
                    318:        MK48T02Clock::calendar cal;
                    319: 
                    320:        cal.sec = mem[0x7f9] & 0x7f;
                    321:        cal.min = mem[0x7fa] & 0x7f;
                    322:        cal.hour = mem[0x7fb] & 0x3f;
                    323:        cal.wday = mem[0x7fc] & 0x07;
                    324:        cal.mday = mem[0x7fd] & 0x3f;
                    325:        cal.mon = mem[0x7fe] & 0x1f;
                    326:        cal.year = mem[0x7ff];
                    327: 
                    328:        return cal;
                    329: }
                    330: 
                    331: // カレンダを NVRAM にストア
                    332: void
                    333: MK48T02Device::Store(const MK48T02Clock::calendar& cal)
                    334: {
                    335:        mem[0x7f9] = (mem[0x7f9] & ~0x7f) | cal.sec;
                    336:        mem[0x7fa] = (mem[0x7fa] & ~0x7f) | cal.min;
                    337:        mem[0x7fb] = (mem[0x7fb] & ~0x3f) | cal.hour;
                    338:        mem[0x7fc] = (mem[0x7fc] & ~0x07) | cal.wday;
                    339:        mem[0x7fd] = (mem[0x7fd] & ~0x3f) | cal.mday;
                    340:        mem[0x7fe] = (mem[0x7fe] & ~0x1f) | cal.mon;
                    341:        mem[0x7ff] = cal.year;
                    342: }
                    343: 
1.1.1.10  root      344: uint
                    345: MK48T02Device::GetSec() const
                    346: {
                    347:        return BCD2num(reg.in.sec);
                    348: }
                    349: 
                    350: void
                    351: MK48T02Device::SetSec(uint v)
                    352: {
                    353:        reg.in.sec = num2BCD(v);
                    354: }
                    355: 
                    356: uint
                    357: MK48T02Device::GetMin() const
                    358: {
                    359:        return BCD2num(reg.in.min);
                    360: }
                    361: 
                    362: void
                    363: MK48T02Device::SetMin(uint v)
                    364: {
                    365:        reg.in.min = num2BCD(v);
                    366: }
                    367: 
                    368: uint
                    369: MK48T02Device::GetHour() const
                    370: {
                    371:        return BCD2num(reg.in.hour);
                    372: }
                    373: 
                    374: void
                    375: MK48T02Device::SetHour(uint v)
                    376: {
                    377:        reg.in.hour = num2BCD(v);
                    378: }
                    379: 
                    380: uint
                    381: MK48T02Device::GetWday() const
                    382: {
                    383:        // データシートの正規の値範囲は 1..7 だが 0 も問題なく保持できて、
                    384:        // NetBSD/luna68k, OpenBSD/luna88k は日付を日曜に変更する際には 0 を
                    385:        // レジスタに書き込んでいる。そのためレジスタ値は 0 と 7 を日曜、
                    386:        // 1を月曜…という運用ということにする。
                    387:        // 戻り値は 0..6 (0が日曜)。
                    388: 
1.1.1.15  root      389:        uint v = reg.in.wday;
1.1.1.10  root      390:        if (v == 7) {
                    391:                v = 0;
                    392:        }
                    393:        return v;
                    394: }
                    395: 
                    396: void
                    397: MK48T02Device::SetWday(uint v)
                    398: {
                    399:        // 引数は 0..6 (0が日曜)、MK48T02 の正規の範囲は 1..7 で曜日との対応は
                    400:        // 運用依存のようだ。NetBSD/luna68k, OpenBSD/luna88k は 0 を日曜、1 を
                    401:        // 月曜…と扱っているが、MK48T02 の曜日レジスタは 7 の翌日 1 に繰り上がる
                    402:        // 動作なので、ここでもレジスタには 1..7 (1が月曜、7が日曜) をセットする。
                    403:        if (v == 0)
                    404:                v = 7;
                    405:        reg.in.wday = v;
                    406: }
                    407: 
                    408: uint
                    409: MK48T02Device::GetMday() const
                    410: {
                    411:        return BCD2num(reg.in.mday);
                    412: }
                    413: 
                    414: void
                    415: MK48T02Device::SetMday(uint v)
                    416: {
                    417:        reg.in.mday = num2BCD(v);
                    418: }
                    419: 
                    420: uint
                    421: MK48T02Device::GetMon() const
                    422: {
                    423:        return BCD2num(reg.in.mon);
                    424: }
                    425: 
                    426: void
                    427: MK48T02Device::SetMon(uint v)
                    428: {
                    429:        reg.in.mon = num2BCD(v);
                    430: }
                    431: 
                    432: uint
                    433: MK48T02Device::DecodeYear(uint bcd_year) const
                    434: {
                    435:        uint y = BCD2num(bcd_year);
                    436:        y += year_epoch;
                    437: 
                    438:        // 1970年より前を 2000 年代とみなすのはシステム依存だが
                    439:        // UNIX 系はみんなこう(?)
                    440:        // XXX ここの 1970 と RTC エポックを一致させれば端折れるじゃん!と
                    441:        //     思いついたのかしら?
                    442:        if (y < 1970) {
                    443:                y += 100;
                    444:        }
                    445:        return y;
                    446: }
                    447: 
                    448: uint
                    449: MK48T02Device::GetYear() const
                    450: {
                    451:        // see DecodeYear()
                    452:        return DecodeYear(reg.in.year);
                    453: }
                    454: 
                    455: void
                    456: MK48T02Device::SetYear(uint v)
                    457: {
                    458:        // see DecodeYear()
                    459:        v -= year_epoch;
                    460:        reg.in.year = num2BCD(v % 100);
                    461: }
                    462: 
                    463: uint
                    464: MK48T02Device::GetLeap() const
                    465: {
                    466:        // 補正項込みで計算
                    467:        return (BCD2num(reg.in.year) + adjust_leap) & 3;
                    468: }
                    469: 
                    470: void
                    471: MK48T02Device::SetLeap(uint v)
                    472: {
                    473:        // nop
                    474:        // MK48T02 ではうるう年カウンタはなく、西暦年でうるう年を判断している。
                    475: }
                    476: 
                    477: // 1Hz 仮想 RTC からのコール
1.1.1.12  root      478: // (分周段 0/32 秒でコールされる)
1.1.1.10  root      479: void
                    480: MK48T02Device::Tick1Hz()
                    481: {
                    482:        if (reg.stop) {
                    483:                // 実機は電力消費を抑えるため発振器ごと止めるが、
                    484:                // 分周段が規定されていないので秒カウントを止めれば十分なはず
                    485:                //nop
                    486:        } else {
                    487:                CountUpSec();
                    488:        }
                    489: 
                    490:        if (hold == false) {
1.1.1.12  root      491:                // 秒の更新でメモリにコピーする (Datasheet p2)
                    492:                Store(reg.in);
1.1.1.10  root      493:        }
1.1       root      494: }
1.1.1.3   root      495: 
                    496: // 指定したアドレスからのゼロ終端文字列を返す
                    497: // (内蔵 ROM からのアクセス用)
                    498: std::string
                    499: MK48T02Device::PeekString(uint32 addr) const
                    500: {
                    501:        std::string rv = "";
                    502: 
1.1.1.7   root      503:        addr &= 0x7ff;
                    504:        for (; mem[addr]; addr++) {
                    505:                rv += mem[addr];
1.1.1.3   root      506:        }
                    507:        return rv;
                    508: }
                    509: 
                    510: // 指定したアドレスに文字列を書き込み、
                    511: // 16 バイトに満たないところはゼロでパディングする。
                    512: // 書き込めれば true を、書き込めなければ false を返す。
                    513: // (内蔵 ROM からの書き込み用)
                    514: bool
                    515: MK48T02Device::WriteString(uint32 addr, const std::string& data)
                    516: {
                    517:        int i = 0;
                    518: 
1.1.1.9   root      519:        // ここの文字列は16バイト未満なら一見ゼロ終端のようだが、
                    520:        // 16バイトならゼロ終端せず16文字とするフォーマット。
                    521: 
                    522:        if (data.length() > 16) {
1.1.1.3   root      523:                return false;
                    524:        }
                    525: 
                    526:        addr &= 0x7ff;
                    527:        for (; i < data.length(); i++) {
1.1.1.9   root      528:                mem[addr + i] = data[i];
1.1.1.3   root      529:        }
                    530:        for (; i < 16; i++) {
1.1.1.9   root      531:                mem[addr + i] = 0;
1.1.1.3   root      532:        }
                    533:        return true;
                    534: }
1.1.1.9   root      535: 
                    536: // 全域をゼロクリアする。
                    537: // クリアするだけなので、その後何か書いたりチェックサムを計算したりする
                    538: // 必要はある。
                    539: // (内蔵 ROM からの書き込み用)
                    540: void
                    541: MK48T02Device::ClearAll()
                    542: {
                    543:        for (int i = 0, sz = file.GetMemSize(); i < sz; i++) {
                    544:                mem[i] = 0;
                    545:        }
                    546: }

unix.superglobalmegacorp.com

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