Commit | Line | Data |
---|---|---|
126bb03b AC |
1 | #include <linux/slab.h> |
2 | #include "usb.h" | |
3 | #include "scsiglue.h" | |
4 | #include "smcommon.h" | |
5 | #include "smil.h" | |
6 | ||
96dfb4bd AG |
7 | int Check_D_LogCHS(WORD *, BYTE *, BYTE *); |
8 | void Initialize_D_Media(void); | |
9 | void PowerOff_D_Media(void); | |
10 | int Check_D_MediaPower(void); | |
11 | int Check_D_MediaExist(void); | |
12 | int Check_D_MediaWP(void); | |
13 | int Check_D_MediaFmt(struct us_data *); | |
14 | int Check_D_MediaFmtForEraseAll(struct us_data *); | |
15 | int Conv_D_MediaAddr(struct us_data *, DWORD); | |
16 | int Inc_D_MediaAddr(struct us_data *); | |
17 | int Check_D_FirstSect(void); | |
18 | int Check_D_LastSect(void); | |
19 | int Media_D_ReadOneSect(struct us_data *, WORD, BYTE *); | |
20 | int Media_D_WriteOneSect(struct us_data *, WORD, BYTE *); | |
21 | int Media_D_CopyBlockHead(struct us_data *); | |
22 | int Media_D_CopyBlockTail(struct us_data *); | |
23 | int Media_D_EraseOneBlock(void); | |
24 | int Media_D_EraseAllBlock(void); | |
126bb03b | 25 | |
96dfb4bd AG |
26 | int Copy_D_BlockAll(struct us_data *, DWORD); |
27 | int Copy_D_BlockHead(struct us_data *); | |
28 | int Copy_D_BlockTail(struct us_data *); | |
29 | int Reassign_D_BlockHead(struct us_data *); | |
126bb03b | 30 | |
96dfb4bd AG |
31 | int Assign_D_WriteBlock(void); |
32 | int Release_D_ReadBlock(struct us_data *); | |
33 | int Release_D_WriteBlock(struct us_data *); | |
34 | int Release_D_CopySector(struct us_data *); | |
126bb03b | 35 | |
96dfb4bd AG |
36 | int Copy_D_PhyOneSect(struct us_data *); |
37 | int Read_D_PhyOneSect(struct us_data *, WORD, BYTE *); | |
38 | int Write_D_PhyOneSect(struct us_data *, WORD, BYTE *); | |
39 | int Erase_D_PhyOneBlock(struct us_data *); | |
126bb03b | 40 | |
96dfb4bd AG |
41 | int Set_D_PhyFmtValue(struct us_data *); |
42 | int Search_D_CIS(struct us_data *); | |
43 | int Make_D_LogTable(struct us_data *); | |
44 | void Check_D_BlockIsFull(void); | |
126bb03b | 45 | |
96dfb4bd | 46 | int MarkFail_D_PhyOneBlock(struct us_data *); |
126bb03b AC |
47 | |
48 | DWORD ErrXDCode; | |
49 | DWORD ErrCode; | |
d8aba9d5 RD |
50 | static BYTE WorkBuf[SECTSIZE]; |
51 | static BYTE Redundant[REDTSIZE]; | |
52 | static BYTE WorkRedund[REDTSIZE]; | |
1557a640 | 53 | /* 128 x 1000, Log2Phy[MAX_ZONENUM][MAX_LOGBLOCK]; */ |
4f3fff72 | 54 | static WORD *Log2Phy[MAX_ZONENUM]; |
e6288702 | 55 | static BYTE Assign[MAX_ZONENUM][MAX_BLOCKNUM / 8]; |
d8aba9d5 | 56 | static WORD AssignStart[MAX_ZONENUM]; |
126bb03b AC |
57 | WORD ReadBlock; |
58 | WORD WriteBlock; | |
59 | DWORD MediaChange; | |
d8aba9d5 | 60 | static DWORD SectCopyMode; |
126bb03b | 61 | |
1557a640 | 62 | /* BIT Control Macro */ |
a3539591 | 63 | static BYTE BitData[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; |
e6288702 AG |
64 | #define Set_D_Bit(a, b) (a[(BYTE)((b) / 8)] |= BitData[(b) % 8]) |
65 | #define Clr_D_Bit(a, b) (a[(BYTE)((b) / 8)] &= ~BitData[(b) % 8]) | |
66 | #define Chk_D_Bit(a, b) (a[(BYTE)((b) / 8)] & BitData[(b) % 8]) | |
126bb03b | 67 | |
d8aba9d5 RD |
68 | BYTE IsSSFDCCompliance; |
69 | BYTE IsXDCompliance; | |
126bb03b AC |
70 | |
71 | ||
1557a640 | 72 | /* ----- SM_FreeMem() ------------------------------------------------- */ |
126bb03b AC |
73 | int SM_FreeMem(void) |
74 | { | |
75 | int i; | |
76 | ||
548039fd | 77 | pr_info("SM_FreeMem start\n"); |
e6288702 AG |
78 | for (i = 0; i < MAX_ZONENUM; i++) { |
79 | if (Log2Phy[i] != NULL) { | |
548039fd | 80 | pr_info("Free Zone = %x, Addr = %p\n", i, Log2Phy[i]); |
126bb03b AC |
81 | kfree(Log2Phy[i]); |
82 | Log2Phy[i] = NULL; | |
83 | } | |
84 | } | |
2ef0b9c1 | 85 | return NO_ERROR; |
126bb03b AC |
86 | } |
87 | ||
1557a640 AG |
88 | /* SmartMedia Read/Write/Erase Function */ |
89 | /* ----- Media_D_ReadSector() ------------------------------------------- */ | |
99b49747 | 90 | int Media_D_ReadSector(struct us_data *us, DWORD start, WORD count, BYTE *buf) |
126bb03b AC |
91 | { |
92 | WORD len, bn; | |
93 | ||
126bb03b | 94 | if (Conv_D_MediaAddr(us, start)) |
2ef0b9c1 | 95 | return ErrCode; |
126bb03b | 96 | |
05a19ed0 | 97 | while (1) { |
126bb03b AC |
98 | len = Ssfdc.MaxSectors - Media.Sector; |
99 | if (count > len) | |
100 | bn = len; | |
101 | else | |
102 | bn = count; | |
dc606b8e | 103 | |
23f73b3a | 104 | if (Media_D_ReadOneSect(us, bn, buf)) { |
126bb03b | 105 | ErrCode = ERR_EccReadErr; |
2ef0b9c1 | 106 | return ErrCode; |
126bb03b AC |
107 | } |
108 | ||
109 | Media.Sector += bn; | |
110 | count -= bn; | |
111 | ||
e6288702 | 112 | if (count <= 0) |
126bb03b AC |
113 | break; |
114 | ||
115 | buf += bn * SECTSIZE; | |
116 | ||
117 | if (Inc_D_MediaAddr(us)) | |
2ef0b9c1 | 118 | return ErrCode; |
126bb03b AC |
119 | } |
120 | ||
2ef0b9c1 | 121 | return NO_ERROR; |
126bb03b | 122 | } |
1557a640 AG |
123 | /* here */ |
124 | /* ----- Media_D_CopySector() ------------------------------------------ */ | |
99b49747 | 125 | int Media_D_CopySector(struct us_data *us, DWORD start, WORD count, BYTE *buf) |
126bb03b | 126 | { |
126bb03b | 127 | WORD len, bn; |
126bb03b | 128 | |
548039fd | 129 | /* pr_info("Media_D_CopySector !!!\n"); */ |
126bb03b | 130 | if (Conv_D_MediaAddr(us, start)) |
2ef0b9c1 | 131 | return ErrCode; |
126bb03b | 132 | |
05a19ed0 | 133 | while (1) { |
126bb03b | 134 | if (Assign_D_WriteBlock()) |
2ef0b9c1 | 135 | return ERROR; |
126bb03b AC |
136 | |
137 | len = Ssfdc.MaxSectors - Media.Sector; | |
138 | if (count > len) | |
139 | bn = len; | |
140 | else | |
141 | bn = count; | |
142 | ||
99b49747 | 143 | if (Ssfdc_D_CopyBlock(us, bn, buf, Redundant)) { |
126bb03b | 144 | ErrCode = ERR_WriteFault; |
2ef0b9c1 | 145 | return ErrCode; |
126bb03b AC |
146 | } |
147 | ||
148 | Media.Sector = 0x1F; | |
23f73b3a | 149 | if (Release_D_CopySector(us)) { |
e6288702 | 150 | if (ErrCode == ERR_HwError) { |
126bb03b | 151 | ErrCode = ERR_WriteFault; |
2ef0b9c1 | 152 | return ErrCode; |
126bb03b AC |
153 | } |
154 | } | |
155 | count -= bn; | |
156 | ||
e6288702 | 157 | if (count <= 0) |
126bb03b AC |
158 | break; |
159 | ||
160 | buf += bn * SECTSIZE; | |
161 | ||
162 | if (Inc_D_MediaAddr(us)) | |
2ef0b9c1 | 163 | return ErrCode; |
126bb03b AC |
164 | |
165 | } | |
2ef0b9c1 | 166 | return NO_ERROR; |
126bb03b AC |
167 | } |
168 | ||
1557a640 | 169 | /* ----- Release_D_CopySector() ------------------------------------------ */ |
126bb03b AC |
170 | int Release_D_CopySector(struct us_data *us) |
171 | { | |
e6288702 AG |
172 | Log2Phy[Media.Zone][Media.LogBlock] = WriteBlock; |
173 | Media.PhyBlock = ReadBlock; | |
126bb03b | 174 | |
e6288702 AG |
175 | if (Media.PhyBlock == NO_ASSIGN) { |
176 | Media.PhyBlock = WriteBlock; | |
2ef0b9c1 | 177 | return SMSUCCESS; |
126bb03b AC |
178 | } |
179 | ||
99b49747 | 180 | Clr_D_Bit(Assign[Media.Zone], Media.PhyBlock); |
e6288702 | 181 | Media.PhyBlock = WriteBlock; |
126bb03b | 182 | |
2ef0b9c1 | 183 | return SMSUCCESS; |
126bb03b | 184 | } |
126bb03b | 185 | |
1557a640 AG |
186 | /* SmartMedia Physical Format Test Subroutine */ |
187 | /* ----- Check_D_MediaFmt() --------------------------------------------- */ | |
126bb03b AC |
188 | int Check_D_MediaFmt(struct us_data *us) |
189 | { | |
548039fd | 190 | pr_info("Check_D_MediaFmt\n"); |
126bb03b | 191 | |
126bb03b | 192 | if (!MediaChange) |
2ef0b9c1 | 193 | return SMSUCCESS; |
126bb03b AC |
194 | |
195 | MediaChange = ERROR; | |
196 | SectCopyMode = COMPLETED; | |
197 | ||
23f73b3a | 198 | if (Set_D_PhyFmtValue(us)) { |
126bb03b | 199 | ErrCode = ERR_UnknownMedia; |
2ef0b9c1 | 200 | return ERROR; |
126bb03b | 201 | } |
4f3fff72 | 202 | |
23f73b3a | 203 | if (Search_D_CIS(us)) { |
126bb03b | 204 | ErrCode = ERR_IllegalFmt; |
2ef0b9c1 | 205 | return ERROR; |
126bb03b AC |
206 | } |
207 | ||
5a5097a4 AG |
208 | MediaChange = SMSUCCESS; |
209 | return SMSUCCESS; | |
126bb03b | 210 | } |
dc606b8e | 211 | |
1557a640 AG |
212 | /* SmartMedia Physical Address Control Subroutine */ |
213 | /* ----- Conv_D_MediaAddr() --------------------------------------------- */ | |
126bb03b AC |
214 | int Conv_D_MediaAddr(struct us_data *us, DWORD addr) |
215 | { | |
216 | DWORD temp; | |
126bb03b | 217 | |
e6288702 AG |
218 | temp = addr / Ssfdc.MaxSectors; |
219 | Media.Zone = (BYTE) (temp / Ssfdc.MaxLogBlocks); | |
126bb03b | 220 | |
e6288702 | 221 | if (Log2Phy[Media.Zone] == NULL) { |
23f73b3a | 222 | if (Make_D_LogTable(us)) { |
126bb03b | 223 | ErrCode = ERR_IllegalFmt; |
2ef0b9c1 | 224 | return ERROR; |
126bb03b AC |
225 | } |
226 | } | |
227 | ||
e6288702 AG |
228 | Media.Sector = (BYTE) (addr % Ssfdc.MaxSectors); |
229 | Media.LogBlock = (WORD) (temp % Ssfdc.MaxLogBlocks); | |
126bb03b | 230 | |
e6288702 | 231 | if (Media.Zone < Ssfdc.MaxZones) { |
126bb03b AC |
232 | Clr_D_RedundantData(Redundant); |
233 | Set_D_LogBlockAddr(Redundant); | |
234 | Media.PhyBlock = Log2Phy[Media.Zone][Media.LogBlock]; | |
2ef0b9c1 | 235 | return SMSUCCESS; |
126bb03b AC |
236 | } |
237 | ||
238 | ErrCode = ERR_OutOfLBA; | |
2ef0b9c1 | 239 | return ERROR; |
126bb03b AC |
240 | } |
241 | ||
1557a640 | 242 | /* ----- Inc_D_MediaAddr() ---------------------------------------------- */ |
126bb03b AC |
243 | int Inc_D_MediaAddr(struct us_data *us) |
244 | { | |
245 | WORD LogBlock = Media.LogBlock; | |
126bb03b | 246 | |
e6288702 | 247 | if (++Media.Sector < Ssfdc.MaxSectors) |
2ef0b9c1 | 248 | return SMSUCCESS; |
126bb03b | 249 | |
e6288702 | 250 | if (Log2Phy[Media.Zone] == NULL) { |
23f73b3a | 251 | if (Make_D_LogTable(us)) { |
126bb03b | 252 | ErrCode = ERR_IllegalFmt; |
2ef0b9c1 | 253 | return ERROR; |
126bb03b AC |
254 | } |
255 | } | |
256 | ||
e6288702 | 257 | Media.Sector = 0; |
126bb03b AC |
258 | Media.LogBlock = LogBlock; |
259 | ||
e6288702 | 260 | if (++Media.LogBlock < Ssfdc.MaxLogBlocks) { |
126bb03b AC |
261 | Clr_D_RedundantData(Redundant); |
262 | Set_D_LogBlockAddr(Redundant); | |
e6288702 | 263 | Media.PhyBlock = Log2Phy[Media.Zone][Media.LogBlock]; |
2ef0b9c1 | 264 | return SMSUCCESS; |
126bb03b AC |
265 | } |
266 | ||
e6288702 | 267 | Media.LogBlock = 0; |
126bb03b | 268 | |
e6288702 AG |
269 | if (++Media.Zone < Ssfdc.MaxZones) { |
270 | if (Log2Phy[Media.Zone] == NULL) { | |
23f73b3a | 271 | if (Make_D_LogTable(us)) { |
126bb03b | 272 | ErrCode = ERR_IllegalFmt; |
2ef0b9c1 | 273 | return ERROR; |
126bb03b AC |
274 | } |
275 | } | |
276 | ||
277 | Media.LogBlock = 0; | |
278 | ||
279 | Clr_D_RedundantData(Redundant); | |
280 | Set_D_LogBlockAddr(Redundant); | |
e6288702 | 281 | Media.PhyBlock = Log2Phy[Media.Zone][Media.LogBlock]; |
2ef0b9c1 | 282 | return SMSUCCESS; |
126bb03b AC |
283 | } |
284 | ||
e6288702 | 285 | Media.Zone = 0; |
126bb03b AC |
286 | ErrCode = ERR_OutOfLBA; |
287 | ||
2ef0b9c1 | 288 | return ERROR; |
126bb03b | 289 | } |
126bb03b | 290 | |
1557a640 AG |
291 | /* SmartMedia Read/Write Subroutine with Retry */ |
292 | /* ----- Media_D_ReadOneSect() ------------------------------------------ */ | |
126bb03b AC |
293 | int Media_D_ReadOneSect(struct us_data *us, WORD count, BYTE *buf) |
294 | { | |
295 | DWORD err, retry; | |
296 | ||
297 | if (!Read_D_PhyOneSect(us, count, buf)) | |
2ef0b9c1 | 298 | return SMSUCCESS; |
e6288702 | 299 | if (ErrCode == ERR_HwError) |
2ef0b9c1 | 300 | return ERROR; |
e6288702 | 301 | if (ErrCode == ERR_DataStatus) |
2ef0b9c1 | 302 | return ERROR; |
126bb03b AC |
303 | |
304 | #ifdef RDERR_REASSIGN | |
0ea8a165 | 305 | if (Ssfdc.Attribute & MWP) { |
e6288702 | 306 | if (ErrCode == ERR_CorReadErr) |
2ef0b9c1 AG |
307 | return SMSUCCESS; |
308 | return ERROR; | |
126bb03b AC |
309 | } |
310 | ||
e6288702 AG |
311 | err = ErrCode; |
312 | for (retry = 0; retry < 2; retry++) { | |
b9594b81 AG |
313 | if (Copy_D_BlockAll(us, |
314 | (err == ERR_EccReadErr) ? REQ_FAIL : REQ_ERASE)) { | |
e6288702 | 315 | if (ErrCode == ERR_HwError) |
2ef0b9c1 | 316 | return ERROR; |
126bb03b AC |
317 | continue; |
318 | } | |
319 | ||
320 | ErrCode = err; | |
e6288702 | 321 | if (ErrCode == ERR_CorReadErr) |
2ef0b9c1 AG |
322 | return SMSUCCESS; |
323 | return ERROR; | |
126bb03b AC |
324 | } |
325 | ||
326 | MediaChange = ERROR; | |
327 | #else | |
e6288702 AG |
328 | if (ErrCode == ERR_CorReadErr) |
329 | return SMSUCCESS; | |
126bb03b AC |
330 | #endif |
331 | ||
2ef0b9c1 | 332 | return ERROR; |
126bb03b | 333 | } |
126bb03b | 334 | |
1557a640 AG |
335 | /* SmartMedia Physical Sector Data Copy Subroutine */ |
336 | /* ----- Copy_D_BlockAll() ---------------------------------------------- */ | |
126bb03b AC |
337 | int Copy_D_BlockAll(struct us_data *us, DWORD mode) |
338 | { | |
339 | BYTE sect; | |
126bb03b | 340 | |
e6288702 | 341 | sect = Media.Sector; |
126bb03b AC |
342 | |
343 | if (Assign_D_WriteBlock()) | |
2ef0b9c1 | 344 | return ERROR; |
e6288702 AG |
345 | if (mode == REQ_FAIL) |
346 | SectCopyMode = REQ_FAIL; | |
126bb03b | 347 | |
b9594b81 AG |
348 | for (Media.Sector = 0; Media.Sector < Ssfdc.MaxSectors; |
349 | Media.Sector++) { | |
23f73b3a | 350 | if (Copy_D_PhyOneSect(us)) { |
e6288702 | 351 | if (ErrCode == ERR_HwError) |
2ef0b9c1 | 352 | return ERROR; |
126bb03b | 353 | if (Release_D_WriteBlock(us)) |
2ef0b9c1 | 354 | return ERROR; |
126bb03b AC |
355 | |
356 | ErrCode = ERR_WriteFault; | |
e6288702 AG |
357 | Media.PhyBlock = ReadBlock; |
358 | Media.Sector = sect; | |
126bb03b | 359 | |
2ef0b9c1 | 360 | return ERROR; |
126bb03b AC |
361 | } |
362 | } | |
363 | ||
364 | if (Release_D_ReadBlock(us)) | |
2ef0b9c1 | 365 | return ERROR; |
126bb03b | 366 | |
e6288702 AG |
367 | Media.PhyBlock = WriteBlock; |
368 | Media.Sector = sect; | |
2ef0b9c1 | 369 | return SMSUCCESS; |
126bb03b | 370 | } |
126bb03b | 371 | |
1557a640 AG |
372 | /* SmartMedia Physical Block Assign/Release Subroutine */ |
373 | /* ----- Assign_D_WriteBlock() ------------------------------------------ */ | |
126bb03b AC |
374 | int Assign_D_WriteBlock(void) |
375 | { | |
e6288702 | 376 | ReadBlock = Media.PhyBlock; |
126bb03b | 377 | |
b9594b81 AG |
378 | for (WriteBlock = AssignStart[Media.Zone]; |
379 | WriteBlock < Ssfdc.MaxBlocks; WriteBlock++) { | |
99b49747 AG |
380 | if (!Chk_D_Bit(Assign[Media.Zone], WriteBlock)) { |
381 | Set_D_Bit(Assign[Media.Zone], WriteBlock); | |
e6288702 AG |
382 | AssignStart[Media.Zone] = WriteBlock + 1; |
383 | Media.PhyBlock = WriteBlock; | |
384 | SectCopyMode = REQ_ERASE; | |
2ef0b9c1 | 385 | return SMSUCCESS; |
126bb03b AC |
386 | } |
387 | } | |
388 | ||
b9594b81 AG |
389 | for (WriteBlock = 0; |
390 | WriteBlock < AssignStart[Media.Zone]; WriteBlock++) { | |
99b49747 AG |
391 | if (!Chk_D_Bit(Assign[Media.Zone], WriteBlock)) { |
392 | Set_D_Bit(Assign[Media.Zone], WriteBlock); | |
e6288702 AG |
393 | AssignStart[Media.Zone] = WriteBlock + 1; |
394 | Media.PhyBlock = WriteBlock; | |
395 | SectCopyMode = REQ_ERASE; | |
2ef0b9c1 | 396 | return SMSUCCESS; |
126bb03b AC |
397 | } |
398 | } | |
399 | ||
e6288702 | 400 | WriteBlock = NO_ASSIGN; |
126bb03b | 401 | ErrCode = ERR_WriteFault; |
dc606b8e | 402 | |
2ef0b9c1 | 403 | return ERROR; |
126bb03b AC |
404 | } |
405 | ||
1557a640 | 406 | /* ----- Release_D_ReadBlock() ------------------------------------------ */ |
126bb03b AC |
407 | int Release_D_ReadBlock(struct us_data *us) |
408 | { | |
409 | DWORD mode; | |
126bb03b | 410 | |
e6288702 AG |
411 | mode = SectCopyMode; |
412 | SectCopyMode = COMPLETED; | |
126bb03b | 413 | |
e6288702 | 414 | if (mode == COMPLETED) |
2ef0b9c1 | 415 | return SMSUCCESS; |
126bb03b | 416 | |
e6288702 AG |
417 | Log2Phy[Media.Zone][Media.LogBlock] = WriteBlock; |
418 | Media.PhyBlock = ReadBlock; | |
126bb03b | 419 | |
e6288702 AG |
420 | if (Media.PhyBlock == NO_ASSIGN) { |
421 | Media.PhyBlock = WriteBlock; | |
2ef0b9c1 | 422 | return SMSUCCESS; |
126bb03b AC |
423 | } |
424 | ||
e6288702 | 425 | if (mode == REQ_ERASE) { |
23f73b3a | 426 | if (Erase_D_PhyOneBlock(us)) { |
e6288702 AG |
427 | if (ErrCode == ERR_HwError) |
428 | return ERROR; | |
429 | if (MarkFail_D_PhyOneBlock(us)) | |
430 | return ERROR; | |
e1a1c480 | 431 | } else |
99b49747 | 432 | Clr_D_Bit(Assign[Media.Zone], Media.PhyBlock); |
e1a1c480 | 433 | } else if (MarkFail_D_PhyOneBlock(us)) |
2ef0b9c1 | 434 | return ERROR; |
126bb03b | 435 | |
e6288702 | 436 | Media.PhyBlock = WriteBlock; |
2ef0b9c1 | 437 | return SMSUCCESS; |
126bb03b AC |
438 | } |
439 | ||
1557a640 | 440 | /* ----- Release_D_WriteBlock() ----------------------------------------- */ |
126bb03b AC |
441 | int Release_D_WriteBlock(struct us_data *us) |
442 | { | |
e6288702 AG |
443 | SectCopyMode = COMPLETED; |
444 | Media.PhyBlock = WriteBlock; | |
126bb03b AC |
445 | |
446 | if (MarkFail_D_PhyOneBlock(us)) | |
2ef0b9c1 | 447 | return ERROR; |
126bb03b | 448 | |
e6288702 | 449 | Media.PhyBlock = ReadBlock; |
2ef0b9c1 | 450 | return SMSUCCESS; |
126bb03b AC |
451 | } |
452 | ||
1557a640 AG |
453 | /* SmartMedia Physical Sector Data Copy Subroutine */ |
454 | /* ----- Copy_D_PhyOneSect() -------------------------------------------- */ | |
126bb03b AC |
455 | int Copy_D_PhyOneSect(struct us_data *us) |
456 | { | |
457 | int i; | |
458 | DWORD err, retry; | |
126bb03b | 459 | |
548039fd | 460 | /* pr_info("Copy_D_PhyOneSect --- Secotr = %x\n", Media.Sector); */ |
e6288702 AG |
461 | if (ReadBlock != NO_ASSIGN) { |
462 | Media.PhyBlock = ReadBlock; | |
463 | for (retry = 0; retry < 2; retry++) { | |
464 | if (retry != 0) { | |
126bb03b | 465 | Ssfdc_D_Reset(us); |
b9594b81 AG |
466 | if (Ssfdc_D_ReadCisSect(us, WorkBuf, |
467 | WorkRedund)) { | |
23f73b3a | 468 | ErrCode = ERR_HwError; |
e6288702 | 469 | MediaChange = ERROR; |
23f73b3a AG |
470 | return ERROR; |
471 | } | |
126bb03b | 472 | |
99b49747 | 473 | if (Check_D_CISdata(WorkBuf, WorkRedund)) { |
23f73b3a | 474 | ErrCode = ERR_HwError; |
e6288702 | 475 | MediaChange = ERROR; |
23f73b3a AG |
476 | return ERROR; |
477 | } | |
126bb03b AC |
478 | } |
479 | ||
99b49747 | 480 | if (Ssfdc_D_ReadSect(us, WorkBuf, WorkRedund)) { |
23f73b3a | 481 | ErrCode = ERR_HwError; |
e6288702 | 482 | MediaChange = ERROR; |
23f73b3a AG |
483 | return ERROR; |
484 | } | |
485 | if (Check_D_DataStatus(WorkRedund)) { | |
e6288702 | 486 | err = ERROR; |
23f73b3a AG |
487 | break; |
488 | } | |
489 | if (!Check_D_ReadError(WorkRedund)) { | |
e6288702 | 490 | err = SMSUCCESS; |
23f73b3a AG |
491 | break; |
492 | } | |
99b49747 | 493 | if (!Check_D_Correct(WorkBuf, WorkRedund)) { |
e6288702 | 494 | err = SMSUCCESS; |
23f73b3a AG |
495 | break; |
496 | } | |
126bb03b | 497 | |
e6288702 AG |
498 | err = ERROR; |
499 | SectCopyMode = REQ_FAIL; | |
126bb03b | 500 | } |
e1a1c480 | 501 | } else { |
e6288702 AG |
502 | err = SMSUCCESS; |
503 | for (i = 0; i < SECTSIZE; i++) | |
504 | WorkBuf[i] = DUMMY_DATA; | |
126bb03b AC |
505 | Clr_D_RedundantData(WorkRedund); |
506 | } | |
507 | ||
508 | Set_D_LogBlockAddr(WorkRedund); | |
e6288702 | 509 | if (err == ERROR) { |
126bb03b AC |
510 | Set_D_RightECC(WorkRedund); |
511 | Set_D_DataStaus(WorkRedund); | |
512 | } | |
513 | ||
e6288702 | 514 | Media.PhyBlock = WriteBlock; |
126bb03b | 515 | |
23f73b3a AG |
516 | if (Ssfdc_D_WriteSectForCopy(us, WorkBuf, WorkRedund)) { |
517 | ErrCode = ERR_HwError; | |
e6288702 | 518 | MediaChange = ERROR; |
23f73b3a AG |
519 | return ERROR; |
520 | } | |
521 | if (Ssfdc_D_CheckStatus()) { | |
522 | ErrCode = ERR_WriteFault; | |
523 | return ERROR; | |
524 | } | |
126bb03b | 525 | |
e6288702 | 526 | Media.PhyBlock = ReadBlock; |
2ef0b9c1 | 527 | return SMSUCCESS; |
126bb03b AC |
528 | } |
529 | ||
1557a640 AG |
530 | /* SmartMedia Physical Sector Read/Write/Erase Subroutine */ |
531 | /* ----- Read_D_PhyOneSect() -------------------------------------------- */ | |
126bb03b AC |
532 | int Read_D_PhyOneSect(struct us_data *us, WORD count, BYTE *buf) |
533 | { | |
534 | int i; | |
535 | DWORD retry; | |
126bb03b | 536 | |
e6288702 AG |
537 | if (Media.PhyBlock == NO_ASSIGN) { |
538 | for (i = 0; i < SECTSIZE; i++) | |
539 | *buf++ = DUMMY_DATA; | |
2ef0b9c1 | 540 | return SMSUCCESS; |
126bb03b AC |
541 | } |
542 | ||
e6288702 AG |
543 | for (retry = 0; retry < 2; retry++) { |
544 | if (retry != 0) { | |
126bb03b AC |
545 | Ssfdc_D_Reset(us); |
546 | ||
99b49747 | 547 | if (Ssfdc_D_ReadCisSect(us, WorkBuf, WorkRedund)) { |
23f73b3a | 548 | ErrCode = ERR_HwError; |
e6288702 | 549 | MediaChange = ERROR; |
23f73b3a AG |
550 | return ERROR; |
551 | } | |
99b49747 | 552 | if (Check_D_CISdata(WorkBuf, WorkRedund)) { |
23f73b3a | 553 | ErrCode = ERR_HwError; |
e6288702 | 554 | MediaChange = ERROR; |
23f73b3a AG |
555 | return ERROR; |
556 | } | |
126bb03b AC |
557 | } |
558 | ||
99b49747 | 559 | if (Ssfdc_D_ReadBlock(us, count, buf, Redundant)) { |
23f73b3a | 560 | ErrCode = ERR_HwError; |
e6288702 | 561 | MediaChange = ERROR; |
23f73b3a AG |
562 | return ERROR; |
563 | } | |
564 | if (Check_D_DataStatus(Redundant)) { | |
565 | ErrCode = ERR_DataStatus; | |
566 | return ERROR; | |
567 | } | |
126bb03b AC |
568 | |
569 | if (!Check_D_ReadError(Redundant)) | |
2ef0b9c1 | 570 | return SMSUCCESS; |
126bb03b | 571 | |
99b49747 | 572 | if (!Check_D_Correct(buf, Redundant)) { |
23f73b3a AG |
573 | ErrCode = ERR_CorReadErr; |
574 | return ERROR; | |
575 | } | |
126bb03b AC |
576 | } |
577 | ||
578 | ErrCode = ERR_EccReadErr; | |
2ef0b9c1 | 579 | return ERROR; |
126bb03b | 580 | } |
126bb03b | 581 | |
1557a640 | 582 | /* ----- Erase_D_PhyOneBlock() ------------------------------------------ */ |
126bb03b AC |
583 | int Erase_D_PhyOneBlock(struct us_data *us) |
584 | { | |
23f73b3a AG |
585 | if (Ssfdc_D_EraseBlock(us)) { |
586 | ErrCode = ERR_HwError; | |
e6288702 | 587 | MediaChange = ERROR; |
23f73b3a AG |
588 | return ERROR; |
589 | } | |
590 | if (Ssfdc_D_CheckStatus()) { | |
591 | ErrCode = ERR_WriteFault; | |
592 | return ERROR; | |
593 | } | |
126bb03b | 594 | |
2ef0b9c1 | 595 | return SMSUCCESS; |
126bb03b AC |
596 | } |
597 | ||
1557a640 AG |
598 | /* SmartMedia Physical Format Check Local Subroutine */ |
599 | /* ----- Set_D_PhyFmtValue() -------------------------------------------- */ | |
126bb03b AC |
600 | int Set_D_PhyFmtValue(struct us_data *us) |
601 | { | |
5a5097a4 AG |
602 | if (Set_D_SsfdcModel(us->SM_DeviceID)) |
603 | return ERROR; | |
126bb03b | 604 | |
5a5097a4 | 605 | return SMSUCCESS; |
126bb03b AC |
606 | } |
607 | ||
1557a640 | 608 | /* ----- Search_D_CIS() ------------------------------------------------- */ |
126bb03b AC |
609 | int Search_D_CIS(struct us_data *us) |
610 | { | |
e6288702 AG |
611 | Media.Zone = 0; |
612 | Media.Sector = 0; | |
126bb03b | 613 | |
b9594b81 AG |
614 | for (Media.PhyBlock = 0; |
615 | Media.PhyBlock < (Ssfdc.MaxBlocks - Ssfdc.MaxLogBlocks - 1); | |
616 | Media.PhyBlock++) { | |
23f73b3a | 617 | if (Ssfdc_D_ReadRedtData(us, Redundant)) { |
126bb03b | 618 | Ssfdc_D_Reset(us); |
2ef0b9c1 | 619 | return ERROR; |
126bb03b AC |
620 | } |
621 | ||
622 | if (!Check_D_FailBlock(Redundant)) | |
623 | break; | |
624 | } | |
625 | ||
e6288702 | 626 | if (Media.PhyBlock == (Ssfdc.MaxBlocks - Ssfdc.MaxLogBlocks - 1)) { |
126bb03b | 627 | Ssfdc_D_Reset(us); |
2ef0b9c1 | 628 | return ERROR; |
126bb03b AC |
629 | } |
630 | ||
e6288702 | 631 | while (Media.Sector < CIS_SEARCH_SECT) { |
23f73b3a AG |
632 | if (Media.Sector) { |
633 | if (Ssfdc_D_ReadRedtData(us, Redundant)) { | |
126bb03b | 634 | Ssfdc_D_Reset(us); |
2ef0b9c1 | 635 | return ERROR; |
126bb03b AC |
636 | } |
637 | } | |
23f73b3a | 638 | if (!Check_D_DataStatus(Redundant)) { |
99b49747 | 639 | if (Ssfdc_D_ReadSect(us, WorkBuf, Redundant)) { |
126bb03b | 640 | Ssfdc_D_Reset(us); |
2ef0b9c1 | 641 | return ERROR; |
126bb03b AC |
642 | } |
643 | ||
99b49747 | 644 | if (Check_D_CISdata(WorkBuf, Redundant)) { |
126bb03b | 645 | Ssfdc_D_Reset(us); |
2ef0b9c1 | 646 | return ERROR; |
126bb03b AC |
647 | } |
648 | ||
e6288702 AG |
649 | CisArea.PhyBlock = Media.PhyBlock; |
650 | CisArea.Sector = Media.Sector; | |
126bb03b | 651 | Ssfdc_D_Reset(us); |
2ef0b9c1 | 652 | return SMSUCCESS; |
126bb03b AC |
653 | } |
654 | ||
655 | Media.Sector++; | |
656 | } | |
657 | ||
658 | Ssfdc_D_Reset(us); | |
2ef0b9c1 | 659 | return ERROR; |
126bb03b AC |
660 | } |
661 | ||
1557a640 | 662 | /* ----- Make_D_LogTable() ---------------------------------------------- */ |
126bb03b AC |
663 | int Make_D_LogTable(struct us_data *us) |
664 | { | |
99b49747 | 665 | WORD phyblock, logblock; |
126bb03b | 666 | |
e6288702 | 667 | if (Log2Phy[Media.Zone] == NULL) { |
b9594b81 AG |
668 | Log2Phy[Media.Zone] = kmalloc(MAX_LOGBLOCK * sizeof(WORD), |
669 | GFP_KERNEL); | |
548039fd CYC |
670 | /* pr_info("ExAllocatePool Zone = %x, Addr = %x\n", |
671 | Media.Zone, Log2Phy[Media.Zone]); */ | |
e6288702 | 672 | if (Log2Phy[Media.Zone] == NULL) |
2ef0b9c1 | 673 | return ERROR; |
126bb03b AC |
674 | } |
675 | ||
e6288702 | 676 | Media.Sector = 0; |
126bb03b | 677 | |
0ea8a165 JS |
678 | /* pr_info("Make_D_LogTable --- MediaZone = 0x%x\n", |
679 | Media.Zone); */ | |
680 | for (Media.LogBlock = 0; Media.LogBlock < Ssfdc.MaxLogBlocks; | |
681 | Media.LogBlock++) | |
682 | Log2Phy[Media.Zone][Media.LogBlock] = NO_ASSIGN; | |
126bb03b | 683 | |
0ea8a165 JS |
684 | for (Media.PhyBlock = 0; Media.PhyBlock < (MAX_BLOCKNUM / 8); |
685 | Media.PhyBlock++) | |
686 | Assign[Media.Zone][Media.PhyBlock] = 0x00; | |
126bb03b | 687 | |
0ea8a165 JS |
688 | for (Media.PhyBlock = 0; Media.PhyBlock < Ssfdc.MaxBlocks; |
689 | Media.PhyBlock++) { | |
690 | if ((!Media.Zone) && (Media.PhyBlock <= CisArea.PhyBlock)) { | |
99b49747 | 691 | Set_D_Bit(Assign[Media.Zone], Media.PhyBlock); |
0ea8a165 JS |
692 | continue; |
693 | } | |
126bb03b | 694 | |
0ea8a165 JS |
695 | if (Ssfdc_D_ReadRedtData(us, Redundant)) { |
696 | Ssfdc_D_Reset(us); | |
697 | return ERROR; | |
698 | } | |
699 | ||
700 | if (!Check_D_DataBlank(Redundant)) | |
701 | continue; | |
126bb03b | 702 | |
0ea8a165 | 703 | Set_D_Bit(Assign[Media.Zone], Media.PhyBlock); |
126bb03b | 704 | |
0ea8a165 JS |
705 | if (Check_D_FailBlock(Redundant)) |
706 | continue; | |
126bb03b | 707 | |
0ea8a165 JS |
708 | if (Load_D_LogBlockAddr(Redundant)) |
709 | continue; | |
126bb03b | 710 | |
0ea8a165 JS |
711 | if (Media.LogBlock >= Ssfdc.MaxLogBlocks) |
712 | continue; | |
713 | ||
714 | if (Log2Phy[Media.Zone][Media.LogBlock] == NO_ASSIGN) { | |
715 | Log2Phy[Media.Zone][Media.LogBlock] = Media.PhyBlock; | |
716 | continue; | |
717 | } | |
718 | ||
719 | phyblock = Media.PhyBlock; | |
720 | logblock = Media.LogBlock; | |
721 | Media.Sector = (BYTE)(Ssfdc.MaxSectors - 1); | |
722 | ||
723 | if (Ssfdc_D_ReadRedtData(us, Redundant)) { | |
724 | Ssfdc_D_Reset(us); | |
725 | return ERROR; | |
726 | } | |
727 | ||
728 | if (!Load_D_LogBlockAddr(Redundant) && | |
729 | (Media.LogBlock == logblock)) { | |
730 | Media.PhyBlock = Log2Phy[Media.Zone][logblock]; | |
126bb03b | 731 | |
23f73b3a AG |
732 | if (Ssfdc_D_ReadRedtData(us, Redundant)) { |
733 | Ssfdc_D_Reset(us); | |
734 | return ERROR; | |
735 | } | |
126bb03b | 736 | |
0ea8a165 JS |
737 | Media.PhyBlock = phyblock; |
738 | ||
23f73b3a | 739 | if (!Load_D_LogBlockAddr(Redundant)) { |
0ea8a165 | 740 | if (Media.LogBlock != logblock) { |
b9594b81 AG |
741 | Media.PhyBlock = |
742 | Log2Phy[Media.Zone][logblock]; | |
0ea8a165 JS |
743 | Log2Phy[Media.Zone][logblock] = |
744 | phyblock; | |
126bb03b | 745 | } |
0ea8a165 JS |
746 | } else { |
747 | Media.PhyBlock = Log2Phy[Media.Zone][logblock]; | |
748 | Log2Phy[Media.Zone][logblock] = phyblock; | |
126bb03b | 749 | } |
0ea8a165 | 750 | } |
126bb03b | 751 | |
0ea8a165 JS |
752 | Media.Sector = 0; |
753 | Media.PhyBlock = phyblock; | |
126bb03b | 754 | |
0ea8a165 | 755 | AssignStart[Media.Zone] = 0; |
126bb03b | 756 | |
1557a640 | 757 | } /* End for (Media.Zone<MAX_ZONENUM) */ |
126bb03b AC |
758 | |
759 | Ssfdc_D_Reset(us); | |
2ef0b9c1 | 760 | return SMSUCCESS; |
126bb03b AC |
761 | } |
762 | ||
1557a640 | 763 | /* ----- MarkFail_D_PhyOneBlock() --------------------------------------- */ |
126bb03b AC |
764 | int MarkFail_D_PhyOneBlock(struct us_data *us) |
765 | { | |
766 | BYTE sect; | |
126bb03b | 767 | |
e6288702 | 768 | sect = Media.Sector; |
126bb03b | 769 | Set_D_FailBlock(WorkRedund); |
126bb03b | 770 | |
b9594b81 AG |
771 | for (Media.Sector = 0; Media.Sector < Ssfdc.MaxSectors; |
772 | Media.Sector++) { | |
23f73b3a | 773 | if (Ssfdc_D_WriteRedtData(us, WorkRedund)) { |
126bb03b AC |
774 | Ssfdc_D_Reset(us); |
775 | Media.Sector = sect; | |
776 | ErrCode = ERR_HwError; | |
777 | MediaChange = ERROR; | |
2ef0b9c1 | 778 | return ERROR; |
1557a640 | 779 | } /* NO Status Check */ |
126bb03b AC |
780 | } |
781 | ||
782 | Ssfdc_D_Reset(us); | |
e6288702 | 783 | Media.Sector = sect; |
2ef0b9c1 | 784 | return SMSUCCESS; |
126bb03b | 785 | } |