2021年5月7日金曜日

YAMAHA RTX1100のファームウェアを更新する

YAMAHA RTX1100という有線ルーターを中古で入手しました。

かなり古い製品で、3つあるいずれのLANポートとも100Mbpsまでの対応ですが、家庭向けの簡易的なルーターとは違い、3つのネットワークのルーティングができたり、内向きのDNS機能があったりと、なかなか高性能です。

また、YAMAHAの製品に対するサポートは非常に充実しており、販売終了して10年以上経つ商品についても、マニュアルやファームウェアをダウンロード提供しています。

こういう姿勢、非常に好感が持てますよね。

さて、このRTX1100ですが、中級者~上級者向けの製品なので、BUFFALOのルータみたいに、デフォルトでIPアドレスが振られていたりはしません。

また、設定はシリアルコンソールを通じて行う必要があります。

正確には、telnetやsshでもできるのですが、これらを有効にするために、シリアルコンソールで設定を行う必要があります。

まず、前のオーナーの設定が残っていると諸々問題があるので、工場出荷時の設定に変更します。

その後、ファームウェアを最新のものに更新します。

工場出荷時の設定に戻すには、背面のINITを爪楊枝で押したまま、電源を投入します。

その後、シリアルケーブル(クロス/インターリンク)でRTX1100とPCを繋ぎます。

PCでは、Tera Termなどを使ってRTX1100のシリアルコンソールにアクセスします。

シリアルの設定は以下の通りです。

Speed    : 9600bps
Data     : 8bit
Parity   : none
Stop Bit : 1bit
Flow Ctl : none

また、RTX1100はデフォルトではSJISの日本語のエラーメッセージを吐くので、Tera Termの設定で「漢字-受信」を「SJIS」に設定するのもお忘れなく。

本体が生きていれば、電源を投入すると、シリアルコンソールにメッセージが表示されます。

ENTERを押すと、ユーザのパスワードの入力を求められるので、何も入力せずに「ENTER」を押します。(デフォルトはパスワードなしです。)

続いて、本体のIPアドレスを設定します。

本体の動作にかかわる設定については、管理者モードに入る必要があります。

    administrator

と入力し「ENTER」を押すと、管理者のパスワードパスワードの入力を求められるので、何も入力せずに「ENTER」押します。(デフォルトはパスワードなし)

RTX1100には3つのLANポートがありますが、まずはLAN1(ハブ経由で4ポートあります)にIPアドレスを割り当て、TFTPでファームウェア更新ができるようにします。

    ip lan1 address 192.168.0.8/24
    tftp host 192.168.0.9
    save

これで、LAN1に192.168.0.8というIPアドレスが割り当てられます。

また、192.168.0.9からTFTPで更新するファームウェアの受け取りを許可します。

あとは、Windows10やUbuntu、FreeBSDなどからtftpコマンドでファームウェアをアップロードしてやればOKです。

Windows 10 64bitで使えるSCSIカードを求めて

 ふとしたことから、SCSI接続のMOドライブを使って、MOに記録されたデータを読み出したいニーズが出てきました。
SCSI規格は、2000年ごろは全盛だったのですが、今となっては失われたテクノロジーとなっています。

SCSI接続のデバイスを利用するには、SCSI-USB変換ケーブルや、PCI接続のSCSIカードに接続する方法があります。

ノートPCならば前者が必須ですが、入手性が非常に悪く、むしろUSB接続のMOドライブを探すほうが簡単です。
一方、デスクトップPCならば、前者のSCSI-USB変換ケーブルに加え、PCI拡張スロットがあれば、後者のSCSIカードを利用することができます。

SCSIカードの有名どころといえばAdaptecで、SCSIデバイスのメーカが動作確認・保証するのは決まってこのAdaptec製のSCSIカードでした。
しかし、Adaptec(現在はMICROCHIPの製造元であるMicrosemiの一部門になっている)のSCSIカードは、多くはWindows 7 32bitまでのドライバしか提供されておらず、64bit環境での利用は出来ません。

今メインで利用している、Windows 10 64bitがインストールされているPCで利用できるSCSIカードがないか、いろいろ探してみたところ、Symbios/LSILogic 53C8XXベースのSCSIカードはWindows 10 64bit環境で使えそうなのがわかってきました。

どうも、Dawicontrolというストレージメーカが、自社製のSCSIカードをWindows 10 64bitで使えるようドライバを書いてくれているようで、大変ありがたいことです。

Symbios/LSILogic 53C8XX、具体的には53C860、53C870、53C875、53C895あたりは、IO-DATA製のSCSIカードに多く採用されていました。
これらのSCSIカードは、過去多数流通しており、今でもメルカリなどで出品されていたりするので、試しに一つ入手して試すことにしてみました。

入手したのは、SC-UPCINというカードで、搭載しているのは「LSI 53C870」というチップです。
基板の刻印は「SC-UPCIN-1」となっていました。

DawicontrolのドライバはSCSI BIOSが有効になっているとリソースの競合が起こるため、これを無効化する必要があります。
IO-DATAのSCSIカードであるSC-UPCI、及びそのバリエーションには、だいたいジャンパーがあり、JP1にある2つのジャンパーを両方ともOPENにすることにより、SCSI BIOS(AT互換機用/PC-98用)を無効化出来ます。
(JP2は内蔵ターミネーターの有効/無効の設定で、AUTOを意味する1-2のまま変更しません。)

JP2を変更し、SCSI BIOSの無効化の設定をしたら、あとはSC-UPCINをデスクトップPCのPCI拡張スロットに挿し、SCSIデバイスを接続してからPC本体を起動させるだけです。

無事、

Daiwacontrol DC-2975U/2976UW SCSI Hostadapter

と認識されました。

 Windows 10 64bitは未署名のドライバを弾くのですが、このドライバはちゃんと署名されているようで、何もせずに適用されます。


Daiwacontrolには本当に感謝の言葉しかないですね。

2021年4月1日木曜日

headless firefoxがFreeBSD jail環境でcoreを吐く件

いくつかのWebページをチェックするために、firefoxをheadlessモードかつmarionetteで制御してクローラーとして使っています。
FreeBSDをインストールしたシステム上にjail環境を作り、その上でfirefoxを導入して動かしている感じです。

先日、firefoxを86.01あたりにpkg upgradeしたところ、firefoxが起動する度にcoreを吐くようになりました。
クローリング自体は無事に終わっているのですが、気持ち悪いのでいろいろ試行錯誤してみました。
結果、jail環境から/devへのアクセスを許可したことにより、問題が解消されました。

昔書いたまとめがありますので、ご参考まで。

ご参考までに、coreを吐いているのは、以下のメッセージが出ているあたりです。

Crash Annotation GraphicsCriticalError: |[0][GFX1-]: No GPUs detected via PCI (t=1.23038) [GFX1-]: No GPUs detected via PCI
Crash Annotation GraphicsCriticalError: |[0][GFX1-]: No GPUs detected via PCI (t=1.23038) |[1][GFX1-]: glxtest: process failed (received signal 11) (t=1.23147) [GFX1-]: glxtest: process failed (received signal 11)

比較のために、別の環境にFreeBSDを導入し、jailを介さずにfirefoxを起動したところ、メッセージは以下の通りでした。

Crash Annotation GraphicsCriticalError: |[0][GFX1-]: glxtest: libpci missing (t=7.06715) [GFX1-]: glxtest: libpci missing
Crash Annotation GraphicsCriticalError: |[0][GFX1-]: glxtest: libpci missing (t=7.06715) |[1][GFX1-]: No GPUs detected via PCI  (t=7.09677) [GFX1-]: No GPUs detected via PCI

初めは、firefoxのabout:configで、ハードウェアアクセラレーションを無効化したり色々試行錯誤したのですが、どうやってもPCIにGPUを探しにいく振る舞いを止めることはできませんでした。

仮想環境で動かすこともあるんだから、ハードウェアアクセラレーションを切ったら、PCI見に行くのは止めて欲しいです、ほんとに。

2020年8月2日日曜日

Raspberry pi 2とFreeBSDで7セグLED時計を作る - プログラミング編


の続きです。

前回まででRaspberry pi 2のFreeBSDの設定は、ハード・ソフトともに終了しました。
最後は、時計のプログラムを書いて終了です。
はじめはSPIを使って制御しようと思ったのですが、1つしかないSPIを使うのは勿体無いので、GPIOを4つ使うことにしました。

GPIOの制御はgpioctlを使ってもできるのですが、シェルスクリプトで時計を書くのはちょっと面倒なので、C言語で書くことにします。

C言語でのGPIOの制御の仕方は、gpio(3)のmanを見ると良いと思います。

サンプルコードはこんな感じです。
コンパイルには、libgpio.hとgpio.cが必要です。
FreeBSDのソースツリーから持ってくるか、以下から入手してください。


clock.c

#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>

#include "libgpio.h"

#define CLOCK_PIN_MOSI  (17)
#define CLOCK_PIN_SCLK  (27)
#define CLOCK_PIN_LATCH (23)
#define CLOCK_PIN_BLINK (24)

#define CLOCK_INTERRUPTION (20)

unsigned char iTable[256];

void CLOCK_initTable(void)
{
    for(int tCount1=0;tCount1<256;tCount1++)
    {
        iTable[tCount1]=0x00;
    }

    iTable['0']=0x3f;
    iTable['1']=0x06;
    iTable['2']=0x5b;
    iTable['3']=0x4f;
    iTable['4']=0x66;
    iTable['5']=0x6d;
    iTable['6']=0x7d;
    iTable['7']=0x27;
    iTable['8']=0x7f;
    iTable['9']=0x6f;
    iTable['C']=0x39;
    iTable['E']=0x79;
    iTable['G']=0x3d;
    iTable['H']=0x76;
    iTable['I']=0x06;
    iTable['J']=0x1e;
    iTable['L']=0x38;
    iTable['O']=0x3f;
    iTable['P']=0x73;
    iTable['T']=0x31;
    iTable['U']=0x3e;
    iTable['Y']=0x66;
    iTable['a']=0x77;
    iTable['b']=0x7c;
    iTable['c']=0x58;
    iTable['d']=0x5e;
    iTable['e']=0x7b;
    iTable['f']=0x71;
    iTable['g']=0x6f;
    iTable['h']=0x74;
    iTable['i']=0x05;
    iTable['j']=0x0d;
    iTable['l']=0x18;
    iTable['n']=0x54;
    iTable['o']=0x5c;
    iTable['p']=0x73;
    iTable['q']=0x67;
    iTable['r']=0x50;
    iTable['s']=0x6d;
    iTable['t']=0x78;
    iTable['u']=0x1c;
    iTable['y']=0x6e;
    iTable['=']=0x09;
    iTable['-']=0x40;
}

void CLOCK_sendChar(gpio_handle_t aHandle,unsigned char aChar)
{
    for(int tCount1=0;tCount1<8;tCount1++)
    {
        gpio_pin_low(aHandle,CLOCK_PIN_SCLK);

        if(iTable[aChar]&(0x80>>tCount1))
        {
            gpio_pin_high(aHandle,CLOCK_PIN_MOSI);
        }
        else
        {
            gpio_pin_low(aHandle,CLOCK_PIN_MOSI);
        }

        gpio_pin_high(aHandle,CLOCK_PIN_SCLK);
    }
}

void CLOCK_reflect(gpio_handle_t aHandle)
{
    gpio_pin_high(aHandle,CLOCK_PIN_LATCH);
    gpio_pin_low(aHandle,CLOCK_PIN_LATCH);
}

volatile sig_atomic_t iEFlag=0;

void signal_handler(int aSig, siginfo_t *aInfo, void *aCtx)
{
    iEFlag=1;
}

int main(void)
{
    gpio_handle_t tHandle;
    char tDateString[64];
    char tDateSecond;
    time_t tEpocMinites;
    struct timeval tCurrentTime;
    int tToggleCount;
    long tInterruption;

    struct sigaction tSASigAbrt,tSASigTerm;

    memset(&tSASigAbrt,0,sizeof(tSASigAbrt));
    memset(&tSASigTerm,0,sizeof(tSASigTerm));

    tSASigAbrt.sa_sigaction=signal_handler;
    tSASigAbrt.sa_flags=SA_SIGINFO;

    tSASigTerm.sa_sigaction=signal_handler;
    tSASigTerm.sa_flags=SA_SIGINFO;

    if(sigaction(SIGINT,&tSASigAbrt,NULL)<0)
    {
        exit(1);
    }

    if(sigaction(SIGTERM,&tSASigTerm,NULL)<0)
    {
        exit(1);
    }

    CLOCK_initTable();

    tHandle=gpio_open(0);

    gpio_pin_output(tHandle,CLOCK_PIN_MOSI);
    gpio_pin_output(tHandle,CLOCK_PIN_SCLK);
    gpio_pin_output(tHandle,CLOCK_PIN_LATCH);
    gpio_pin_output(tHandle,CLOCK_PIN_BLINK);

    gpio_pin_low(tHandle,CLOCK_PIN_MOSI);
    gpio_pin_low(tHandle,CLOCK_PIN_SCLK);
    gpio_pin_low(tHandle,CLOCK_PIN_LATCH);
    gpio_pin_low(tHandle,CLOCK_PIN_BLINK);

    tInterruption=(1000000/CLOCK_INTERRUPTION);
    tToggleCount=0;

    tDateSecond=0x00;

    while(1)
    {
        gettimeofday(&tCurrentTime,NULL);

        tEpocMinites=(time_t)tCurrentTime.tv_sec;

        strftime(tDateString,sizeof(tDateString),"%H%M%S",localtime(&tEpocMinites));

        if(tDateSecond!=tDateString[5])
        {
            tDateSecond=tDateString[5];

            if(tDateString[0]=='0')
            {
                tDateString[0]=0x00;
            }

            for(int tCount1=0;tCount1<6;tCount1++)
            {
                CLOCK_sendChar(tHandle,tDateString[tCount1]);
            }

            CLOCK_reflect(tHandle);

            gpio_pin_high(tHandle,CLOCK_PIN_BLINK);
            tToggleCount=0;
        }

        if(tToggleCount==(CLOCK_INTERRUPTION/2))
        {
            gpio_pin_low(tHandle,CLOCK_PIN_BLINK);
        }

        tToggleCount++;

        usleep(tInterruption);

        if(iEFlag)
        {
            for(int tCount1=0;tCount1<6;tCount1++)
            {
                CLOCK_sendChar(tHandle,0x00);
            }

            CLOCK_reflect(tHandle);

            gpio_pin_low(tHandle,CLOCK_PIN_MOSI);
            gpio_pin_low(tHandle,CLOCK_PIN_SCLK);
            gpio_pin_low(tHandle,CLOCK_PIN_LATCH);
            gpio_pin_low(tHandle,CLOCK_PIN_BLINK);

            gpio_close(tHandle);

            exit(1);           
        }

    }

    gpio_close(tHandle);

    return 0;
}

冒頭のdefineで設定しているのは、GPIOのピン番号です。
物理ピン番号ではなく、論理ピン番号(=BCMピン番号)ですので注意してください。

冒頭に制作したLED時計との接続は、以下の通りです。

Vcc       ----  物理ピン 4番
SDI       ----  物理ピン11番(GPIO 17)
CLK      ----  物理ピン13番(GPIO 27)
BLK      ----  物理ピン16番(GPIO 23)
LATCH ----  物理ピン18番(GPIO 24)
GND     ----  物理ピン 6番


このプログラムでは、論理ピン番号17、27のGPIOで、SPIをエミュレートしています。

大したことをしていないプログラムですので、読めばわかると思いますが、比較的わかりにくい部分だけ解説すると、

iTable                           7セグLED用のフォントデータ
CLOCK_sendChar   CLKに8クロックを出力して1文字分のコードを送る関数
CLOCK_reflect          LATCHに立ち上がりクロックを出力して、シフトレジスタに蓄積された文字を7セグLEDに反映させる関数

です。

mainでは、1/CLOCK_INTERRUPTION秒毎に現在の時間を取得し、前回の取得時から1秒進んでいた場合に、時計の再描画を掛けています。

やる気のないビルド用スクリプトもつけておきますので、これを使ってビルドしてください。

build.sh

#!/bin/sh

rm *.o

cc -c gpio.c
cc -c main.c
cc -o clock gpio.o main.o

特に問題なければ、clockという実行ファイルができるので、これを実行すれば7セグLED時計は動作するはずです。

2020年7月31日金曜日

Raspberry pi 2とFreeBSDで7セグLED時計を作る - ソフトウェア設定編



の続きです。

Raspberry pi 2にインストールした後の設定方法は、一般的なi386/AMD64のFreeBSDとほぼ同じです。

rootのパスワードの変更は以下のコマンドで行います。

passwd

Raspberry pi 2版のFreeBSDでは、予めfreebsdというユーザが作られているので、必要に応じてrmuserで削除します。

rmuser freebsd

私の環境では、/etc/rc.confに以下の記述を追記しています。

Raspberry piには標準でRTCが搭載されていない為、再起動するたびに時間がクリアされてしまうため、起動毎にntpdateで時計合わせをするようにしています。
また、標準のkeypmapはUS配列ですので、これを106キー日本語配列に設定しています。

keymap="jp.kbd"
ntpdate_enable="YES"
ntpdate_flags="-b NTPサーバのIPアドレス"

タイムゾーンをJSTに変更するには、以下のようにします。

cp -p /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

これぐらいしておけば、あとはほぼ一般的なi386/AMD64版のFreeBSDと同じように使うことができると思います。

2020年7月30日木曜日

Raspberry pi 2とFreeBSDで7セグLED時計を作る - ハードウェア設定編


の続きです。

FreeBSDをインストールしただけでは、Raspberry pi 2が持っている性能や機能をすべて使うことはできません。
いくつかの設定/チューニングが必要です。

まず、RPI2版のFreeBSDでは、デフォルトのCPUクロックが600MHzと低く設定されている為、これを標準の900MHzに設定します。
「/boot/msdos/config.txt」に以下の記述を追加します。

force_turbo=1
arm_freq=900
arm_freq_min=600

また、RPI2版のFreeBSDは、標準の状態ではGPIOは有効化されていますが、I2CやSPIは無効化されている為、必要に応じてこれを有効化します。
I2Cを有効にするには、config.txtに以下の記述を追加します。

dtparam=i2c=on

SPIを有効にするには、/boot/loader.confに以下の記述を追加します。

fdt_overlays="spigen-rpi2.dtbo"

I2CおよびSPIが有効されているかは、再起動後、以下のようにして確認してください。

dmesg | grep iic
dmesg | grep spigen

何らかの表示がされればOKです。

2020年7月27日月曜日

Raspberry pi 2とFreeBSDで7セグLED時計を作る - OSインストール編

Raspberry pi 2とFreeBSDで7セグLED時計を作る - はじめに
Raspberry pi 2とFreeBSDで7セグLED時計を作る - ハードウェア制作

の続きです。

前回までで、ハードウェアの制作が終わりましたので、次にRaspberry pi 2にFreeBSDをインストールしたいと思います。

先に言っておきますが、Raspberry piで手っ取り早く色々やろうとするならば、公式のOSであるRaspbianを使うのが圧倒的に便利です。
インターネット上に情報も多いですし、書籍もたくさん出ています。
どうしてもFreeBSDじゃなきゃ嫌、という人でない限り、Raspbianか他のLinuxディストリビューションを使うことをおすすめします。

Raspberry pi向けのFreeBSDですが、私の知る限りここに情報が集まっています。

https://wiki.freebsd.org/arm/Raspberry%20Pi

2020/07/25現在、FreeBSDでまともに使える/使えそうなRaspberry piは、

Raspberry pi B/B+
Raspberry pi 2
Raspberry pi 3
Raspberry pi Zero(W含む)

です、またRaspberry pi 3およびZero WのWi-Fi機能はFreeBSDでは使えません。
(Wi-Fi機能を提供しているICはSDIO接続で、FreeBSDがSDIOをまともにサポートしていないのが原因です。)

このページでは、私の手元にあるRaspberry pi 2の情報を中心にまとめていきたいと思います。

Raspberry pi 2をFreeBSDで使うには、本体にあったOSイメージをダウンロードしてSDカードに焼く必要があります。

OSイメージですが、FreeBSD 11ではRaspberry pi B/B+および2向けが、FreeBSD 12以降ではB/B+、2、3向けが提供されています。
Raspberry pi 2はarmv7でビルドされていて32bitをターゲットとしています。

Raspberry piに対応したFreeBSDは、以下からダウンロードできます。

https://www.freebsd.org/ja/where.html

RPI-B、RPI2、RPI3がそれぞれRaspberry pi B/B+、2、3に対応したSDイメージになります。

FreeBSDにおいてarm版はTier-2ですので、freebsd-updateが利用できません。
RELEASE版よりも、最新のSTABLE版をダウンロードして利用することをオススメします。
(常に最新の機能を追いかけるのならば、CURRENT版を使って下さい。)

FreeBSD-12.1-STABLE-arm-armv7-RPI2-202XXXXX-rXXXXXX.img.xz

xzアーカイブを解凍してimgファイルにします。
xzコマンドで展開できます。

xz -dv FreeBSD-12.1-STABLE-arm-armv7-RPI2-202XXXXX-rXXXXXX.img.xz

以下のようにしてSD/microSDカードに書き込みます。
(「da0」はご利用の環境によって変わります、dmesg等でSD/microSDカードに割り当てられるデバイス名を確認してから指定してください。)

dd if='PATH TO IMG FILE` of=/dev/da0 bs=16M

作成したSD/microSDカードをRaspberry pi本体にセットして電源を入れれば、FreeBSDがブートするはずです。

尚、rootのデフォルトのパスワードはrootになっています。