dodiskwrite.c
4.44 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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#include <PR/leosp.h>
#include "ddwrite.h"
#include "ddwriteint.h"
/*
* static functions prototypes
*/
static void existGetData(DDCmd *command);
static void notExistGetData(DDCmd *command);
/*
* 実際にディスクに書き込むための関数。
*/
void __ddDoDiskWrite(DDCmd *command)
{
if ( command->getdata != (s32 (*)(void *, u32))0 )
existGetData(command);
else
notExistGetData(command);
return;
} /* doDiskWrite() */
/*
* getdata メンバが指定されていた場合、totalSize を何回かに分けて
* RDRAM に転送して書き込む
*/
static void existGetData(DDCmd *command)
{
LEOCmd cmdBlock;
LEOError error = 0;
u32 nblocks, nbytes;
__byteInfo_s byteInfo;
s32 restbytes;
s32 trError;
s32 curLba;
/* あと何バイト残っているか? */
restbytes = (s32)command->totalSize;
curLba = (s32)command->startLBA;
while (restbytes > 0)
{
/*
* まずは、用意されたバッファ内に何バイト、何ブロック分データを格納す
* ることが可能かを調べる。
*/
__ddGetnBlksInArea(&byteInfo, (u32)__ddInfo.diskType,
curLba, command->writeSize);
nblocks = (u32)byteInfo.inNlbas;
nbytes = (u32)byteInfo.inNbytes;
if ( nbytes == 0 )
{
__ddWriteError = DDWRITE_ERROR_INSUFFICIENT_BUFFERSIZE;
return;
}
/*
* 残りのデータを全部格納できるのなら、最後のループになる。(LBA 境界に
* 満たない部分を 0xff で埋めることに注意。
*/
if (nbytes > (u32)restbytes)
{
/*
* あと少しである。
*/
trError = (*command->getdata)(command->writeBuf, (u32)restbytes);
if (trError)
{
__ddWriteError = trError;
return;
}
__ddGetnBlksInArea(&byteInfo, (u32)__ddInfo.diskType,
curLba, (u32)restbytes);
/*
* nbytes, nblocks の意味は「このループで転送するバイト数、
* ブロック数」である。
*/
nbytes = byteInfo.outNbytes;
nblocks = byteInfo.outNlbas;
/* キリの良くない部分を 0xff で埋める */
__ddBfill((void *)((u32)command->writeBuf + (u32)restbytes),
nbytes - (u32)restbytes, 0xffffffff);
}
else
{
/*
* まだまだありそう。とりあえずバッファに格納できるだけ転送する。
*/
trError = (*command->getdata)(command->writeBuf, nbytes);
if (trError)
{
__ddWriteError = trError;
return;
}
}
/* 書き込み */
LeoSysReadWrite(&cmdBlock, OS_WRITE, curLba,
command->writeBuf, nblocks, &__ddDiskQ);
osRecvMesg(&__ddDiskQ, (OSMesg)&error, OS_MESG_BLOCK);
if (error)
{
__ddWriteError = (s32)error;
return;
}
restbytes -= (s32)nbytes;
curLba += (s32)nblocks;
} /* while (restbytes > 0) */
__ddWriteError = (s32)0;
return;
} /* existGetData() */
/*
* getdata メンバが指定されていない場合、RDRAM 上にデータが格納
* されている。
*
* 2段階に分けて書き込む。
* まずはキリのいいブロック境界まで書き込み、そのあとで残りの部分を
* 書き込む。これは、「残りの部分」の後ろを 0xff で埋めるためである。
* (実際のデータの後ろに 0xff をつけるわけには行かない(暴走する!?)
* ので、残りの部分だけ内部バッファに転送した上で処理する)
*/
static void notExistGetData(DDCmd *command)
{
LEOCmd cmdBlock;
LEOError error = 0;
u32 nblocks, nbytes;
__byteInfo_s byteInfo;
/*
* まずキリのいいブロック境界まで書き込む
*/
/* キリのいい境界とは何ブロック目、何バイト目か? */
__ddGetnBlksInArea(&byteInfo, (u32)__ddInfo.diskType,
(s32)command->startLBA, command->writeSize);
nblocks = byteInfo.inNlbas;
nbytes = byteInfo.inNbytes;
/* 書き込み */
LeoSysReadWrite(&cmdBlock, OS_WRITE, (s32)command->startLBA,
command->writeBuf, nblocks, &__ddDiskQ);
osRecvMesg(&__ddDiskQ, (OSMesg)&error, OS_MESG_BLOCK);
if (error)
{
__ddWriteError = (s32)error;
return;
}
/* 残りがなければ終了 */
if (byteInfo.restBytes == 0)
{
__ddWriteError = (s32)0;
return;
}
/*
* 残りを書き込む
*/
/* 内部バッファに転送する */
bcopy((void *)((u32)command->writeBuf + nbytes),
__ddBufp1, (int)byteInfo.restBytes );
/* キリの良くない部分を 0xff で埋める */
__ddBfill((void *)((u32)__ddBufp1 + byteInfo.restBytes),
byteInfo.oneBlockSize - byteInfo.restBytes, 0xffffffff);
/* 書き込み */
LeoSysReadWrite(&cmdBlock, OS_WRITE, (s32)(command->startLBA + nblocks),
__ddBufp1, 1, &__ddDiskQ);
osRecvMesg(&__ddDiskQ, (OSMesg)&error, OS_MESG_BLOCK);
if (error)
{
__ddWriteError = (s32)error;
return;
}
__ddWriteError = (s32)0;
return;
} /* notExistGetData() */