デバイスが正常に機能するには、デバイスのファームウェアとデバイスドライバの互換性がなければなりません。デバイスドライバをインストールまたはアップグレードする前に、ファームウェアとの互換性をチェックする必要があります。互換性のあるファームウェアが見つからない場合は、デバイスドライバの実装によって、デバイスドライバがインストールまたはアップグレードされないように保証する必要があります。
好ましいデバイスドライバの設計では、1 つ以上の ELF (実行可能リンク形式) モジュール内にファームウェアをカプセル化し、attach() 関数を使用してファームウェアのバージョンを管理します。ELF モジュール内にファームウェアをカプセル化するには、elfwrap(1) コマンドを使用します。ファームウェア ELF モジュールは、misc モジュールとしてモジュールリンケージスタブとリンクされます。ファームウェアモジュールは /kernel/misc ディレクトリに存在します。
次のフローチャートに、デバイスドライバの attach() 関数でファームウェアのバージョンを管理する方法を示します。
図 1-1 attach() 関数でのファームウェアのバージョン管理
詳細は、 attach (9E) 、 ddi_modopen (9F) 、 ddi_modsym (9F) 、および ddi_modclose (9F) のマニュアルページを参照してください。
ファームウェアのバージョンをチェックする attach() 関数の一般的な疑似コードは次のとおりです。
static int xxxx_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
.....
ddi_modhandle_t modfn;
int errno;
uint32_t *fwvp;
.....
long fw_version;
.....
/* Check if firmware update is disabled.
* If firmware update is disabled, return.
* The setting is stored in a config file.
*/
if(dip->firmware_disable_update){
return (0);
}
/* Get the current firmware version. */
fw_version = xxxx_get_firmware_version(dip,...);
/* Check if the firmware version is correct and if force update is disabled. */
if(fw_version == REQUIRED_FIRMWARE_VERSION){
if(dip->firmware_force_update == 0){
return (0);
}
/* Even though the firmware version matches, update is forced. */
}
/* Open the firmware file by using ddi_modopen. */
modfn = ddi_modopen(FIRMWARE_FILENAME, KRTLD_MODE_FIRST, &errno);
if (errno){
/* handle error */
}
/* locate the firmware */
fwvp = ddi_modsym(modfn, FIRMWARE_VERSION_NAME, &errno);
if (errno){
/* handle error */
(void) ddi_modclose(modfn);
}
/* Check if the firmware version in the module is correct. */
if (*fwvp != REQUIRED_FIRMWARE_VERSION){
if(dip->firmware_force_update == 0){
/* close the firmware module file */
(void) ddi_modclose(modfn);
return (0);
}
/* Even tough the firmware version in the module does not match,
* update is forced.
*/
}
/* Update the firmware. */
xxx_update_firmware(dip,....);
/* Close the FIRMWARE file */
(void) ddi_modclose(modfn);
.....
// resume attach
}