osPfsInitPak.htm
8.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
<HTML>
<HEAD>
<TITLE>HTML 文書</TITLE>
<META NAME="GENERATOR" CONTENT="mitu">
</HEAD>
<BODY>
<P>
<B><FONT FACE="Arial">osPfsInitPak(3P)<BR>
</FONT></B>
<P>
<B>関数名<BR>
</B>
<P>
osPfsInitPak
<P>
→ コントローラパックのファイルハンドルの初期化<BR>
<P>
<B>構文<BR>
</B>
<P>
#include <ultra64.h><BR>
<P>
<B>s32 osPfsInitPak (OSMesgQueue *mq, OSPfs *pfs, int controller_no);<BR></B>
<P>
<B>説明<BR>
</B>
<P>
コントローラパックを扱うためのファイルハンドルであるOSPfs構造体pfsの初期化を行います。一番初めにコントローラパックを扱う場合や、新しくコントローラパックが差し込まれた場合、まず最初にこの関数を呼んでください。
<BR>
<P>
コントローラパック関数では、ファイルシステムを制御するときに、OSPfs構造体pfsをファイルハンドルのように用いてアクセスを行います。関数osPfsInitPakはこのOSpfs構造体を初期化します。controller_noはコントローラパックが挿し込まれているコントローラの番号(0〜3)を指定します。mqはOS_EVENT_SIと関連付けられた初期化されたメッセージ待ち行列です。この関連付けの方法に関しては、<A HREF="osSetEventMesg.htm">osSetEventMesg</A>,(3P)を参照してください。関数osPfsInitPakの内部では、mqでメッセージ待ちを行っていますので、このmqを共有しないようにしてください。また、OSの低レベルでの同期の初期化のため、osPfsInitPakの呼び出しを行う前に、先に<A HREF="osContInit.htm">osContInit</A>,(3P)を呼び出しておく必要があります。
<BR>
<P>
関数osPfsInitPakの内部では次のような処理を行っています。まずステータスとID領域を調べにいきます。そして、IDが認識できた場合、続いて、関数osPfsCheckerを呼んでいますので、ファイル管理領域が破壊されていた場合、自動的に修復を行っています。
<BR>
<P>
旧来のPFS初期化関数osPfsInitは、ID領域が完全に破壊されていた場合、自動修復を行っていましたが、関数osPfsInitPakでは自動修復を行いません。IDを修復するには、別途に関数osPfsRepairIdの呼び出しが必要となります。以後、通常コントローラパックを初期化する場合には、関数osPfsInitを使用せずに、関数osPfsInitPakの方をご使用ください。また、必ず、関数osPfsRepairIdと組み合わせてお使いください。
<BR>
<P>
この理由としては、次のような可能性があるからです。
<BR>
<P>
接続端子の接触不良などの理由で、一部のアドレスが不定になってしまうことがあります。関数osPfsInitでは最初ID領域を調べにいくのですが、このような場合では、ID領域を調べにいったつもりが、別のアドレスのデータを見てしまい、それがIDではないと判断されてしまいます。そして、旧来のosPfsInitでは、IDを新たに自動的に割り当てるために、その間違ったアドレスに新規IDを書き込んでしまいます。つまり、コントローラパックの内容を破壊してしまうかもしれないのです。
<BR>
<P>
このため、コントローラパックのイニシャライズでは、必ず次のような手順を踏んでください。
<BR>
<P>
まず、関数osPfsInitPakを呼び出してください。エラーコードとして0が返ってきた場合は正常終了です。
<BR>
<P>
エラーコードとして、PFS_ERR_ID_FATALが返った場合には、次のようないくつかの可能性があります。コントローラパックのID領域が破壊されている場合、コントローラパックが正しく接続されていない場合、端子が汚れており、IDを読み出せない場合、コントローラのジョイバスやコントローラパックが故障している場合などです。そのため、この場合、まず、画面上に、「コントローラ、または、コントローラパックに異常があります。きちんと挿し込まれていないか、内容が壊れています」などのメッセージと、「接続しなおす」「修復する(コントローラパックの内容が消去される可能性があります)」という2種類の選択肢を表示します。ユーザが「接続しなおす」を選んだ場合には、関数osPfsInitPakの再呼び出し、「修復する」を選んだ場合には、関数osPfsRepairIdを呼び出し、再び関数osPfsInitPakの呼び出しを行ってください。
<BR>
<P>
エラーが発生したときに返り値として返されるエラーコードには以下のものがあります。<BR>
<P>
<B>PFS_ERR_NOPACK</B>
<P>
指定したコントローラにコントローラパックが挿し込まれていません。あるいは、コントローラが挿し込まれていないなど、何らかのPIfエラーが発生しました。このどちらであるのかを調べる場合には、関数osContStartQuery&osContGetQueryなどを使用してください。
<BR>
<P>
<B>PFS_ERR_NEW_PACK</B>
<P>
コントローラパックが別のコントローラパックに挿し替わっています。このまま、このコントローラパックを使用する場合には、osPfsInitPak(3P)を呼び出して、コントローラパックを初期化してください。
<BR>
<P>
<B>PFS_ERR_CONTRFAIL</B>
<P>
コントローラとのデータ転送の失敗です。関数の内部では、転送エラーが発生した場合、最大3回転送のやり直しを行っています。そのため、このエラーが発生することはあまりありません。このエラーが返る場合、コントローラが正しく接続されていないか、あるは、コントローラパックかコントローラコネクタに異常がある可能性があります。
<BR>
<P>
<B>PFS_ERR_ID_FATAL</B>
<P>
ファイルシステムの初期化を試みましたが、ID領域が壊れていました。コントローラパックが故障しているか、きちんと接続できていないか、あるいは、SRAMを持たない周辺機器が挿し込まれています。
<BR>
<P>
このエラーコードが返ってきた場合、コントローラパックを初期化してもいいかどうか(新しくIDを割り振るか)、あるいは、もう一度コントローラパックの接続を確認してもらうかのどちかかを、まず、ユーザに尋ねてください。そして、コントローラパックを初期化してもよいとユーザが答えた場合には、関数osPfsRepairIdを呼び出してください。
<BR>
<P>
<B>PFS_ERR_DEVICE</B>
<P>
ファイルシステム初期化時に、ページ0にあるID領域中のデバイスIDをチェックしたところ、コントローラパックのデバイスIDではありませんでした。つまり、コントローラパック以外の機器がコントローラに挿さっています。
<BR>
<P>
参考
<BR>
<P>
PFS_ERR_ID_FATALとPFS_ERR_DEVICEの違いは次の通りです。
<BR>
<P>
関数osPfsInitPakで初期化する場合、まず最初に、ID管理領域を調べます。このとき、ID管理領域が壊れていた場合に発生するエラーがPFS_ERR_ID_FATALです。壊れていなかった場合、次にID管理領域中のデバイスIDをチェックします。もし、デバイスIDにコントローラパックを示すビットが立てられていなかった場合に返るのが、PFS_ERR_DEVICEです。
<BR>
<P>
ちなみに、振動パックの場合には、ID管理領域自体が存在しませんので、PFS_ID_FATALが返ります。
<BR>
<PRE WIDTH=132>
<FONT SIZE=6>例
</FONT><FONT SIZE=4 FACE="MS ゴシック">
void
mainproc(void) {
int i;
u8 contpat;
OSContStatus contstat[MAXCONTROLLERS];
OSPfs pfs[MAXCONTROLLERS];
osContInit(&n_siMessageQ, &contpat, contstat);
for (i = 0 ; i < MAXCONTROLLERS ; i ++) {
if ((contpat >> i) & 1) {
if ((contstat[i].type & CONT_JOYPORT) != 0 &&
(contstat[i].type & CONT_ABSOLUTE) != 0) {
do {
ret = osPfsInitPak(&n_siMessageQ, &pfs[i], i);
switch(ret) {
case 0:
osSyncPrintf("PORT %dにコントローラパックがささっています\n", i);
break;
case PFS_ERR_NOPACK:
osSyncPrintf("PORT %dにはコントローラパックがささっていません\n", i);
osSyncPrintf("コントローラパックをさしてください\n");
break;
case PFS_ERR_NEW_PACK:
osSyncPrintf("PORT %dのコントローラパックがさしかえられました\n", i);
osSyncPrintf("このコントローラパックを使います\n");
break;
case PFS_ERR_CONTRFAIL:
osSyncPrintf("PORT %dのコントローラの接続に異常があります\n", i);
osSyncPrintf("コントローラが正しく差し込まれているか確認してください\n");
break;
case PFS_ERR_DEVICE:
osSyncPrintf("PORT %dのコントローラパックにはセーブできません\n", i);
osSyncPrintf("コントローラパックが正しく差し込まれているか確認してください\n");
break;
case PFS_ERR_ID_FATAL:
osSyncPrintf("PORT %dのコントローラパックに異常があります\n", i);
osSyncPrintf(" Aボタン ...修復を試してみる\n");
osSyncPrintf(" その他のボタン...さしなおす\n");
if (AskQuestion(i) == A_BUTTON) {
osPfsRepairId(&pfs[i]);
}
break;
}
WaitForPushingAnyButton(i);
} while (ret != 0) ;
} else {
osSyncPrintf("PORT %dは通常のコントローラではありません\n", i);
}
} else {
osSyncPrintf("PORT %dにはコントローラがささっていません\n", i);
}
}
</FONT></PRE>
<P>
<B>参照<BR>
</B>
<A HREF="osPfsRepairId.htm">osPfsRepairId</A>(3P),
<A HREF="osPfsAllocateFile.htm">osPfsAllocateFile</A>(3P),
<A HREF="osPfsChecker.htm">osPfsChecker</A>(3P),
<A HREF="osPfsFileState.htm">osPfsFileState</A>(3P),
<A HREF="osPfsFreeBlocks.htm">osPfsFreeBlocks</A>(3P),
<A HREF="osPfsIsPlug.htm">osPfsIsPlug</A>(3P),
<A HREF="osPfsReSizeFile.htm">osPfsReSizeFile</A>(3P),
<A HREF="osPfsReadWriteFile.htm">osPfsReadWriteFile</A>(3P),
<A HREF="osPfsSetLabel.htm">osPfsSetLabel</A>(3P),
</BODY>
</HTML>