Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelv...
[pandora-kernel.git] / drivers / staging / keucr / ms.c
1 #include <linux/slab.h>
2 #include "usb.h"
3 #include "scsiglue.h"
4 #include "transport.h"
5 #include "ms.h"
6
7 //----- MS_ReaderCopyBlock() ------------------------------------------
8 int MS_ReaderCopyBlock(struct us_data *us, WORD oldphy, WORD newphy, WORD PhyBlockAddr, BYTE PageNum, PBYTE buf, WORD len)
9 {
10         struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
11         int     result;
12
13         //printk("MS_ReaderCopyBlock --- PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum);
14         result = ENE_LoadBinCode(us, MS_RW_PATTERN);
15         if (result != USB_STOR_XFER_GOOD)
16                 return USB_STOR_TRANSPORT_ERROR;
17
18         memset(bcb, 0, sizeof(bcb));
19         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
20         bcb->DataTransferLength = 0x200*len;
21         bcb->Flags                      = 0x00;
22         bcb->CDB[0]                     = 0xF0;
23         bcb->CDB[1]                     = 0x08;
24         bcb->CDB[4]                     = (BYTE)(oldphy);
25         bcb->CDB[3]                     = (BYTE)(oldphy>>8);
26         bcb->CDB[2]                     = (BYTE)(oldphy>>16);
27         bcb->CDB[7]                     = (BYTE)(newphy);
28         bcb->CDB[6]                     = (BYTE)(newphy>>8);
29         bcb->CDB[5]                     = (BYTE)(newphy>>16);
30         bcb->CDB[9]                     = (BYTE)(PhyBlockAddr);
31         bcb->CDB[8]                     = (BYTE)(PhyBlockAddr>>8);
32         bcb->CDB[10]            = PageNum;
33
34         result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
35         if (result != USB_STOR_XFER_GOOD)
36                 return USB_STOR_TRANSPORT_ERROR;
37
38         return USB_STOR_TRANSPORT_GOOD;
39 }
40
41 //----- MS_ReaderReadPage() ------------------------------------------
42 int MS_ReaderReadPage(struct us_data *us, DWORD PhyBlockAddr, BYTE PageNum, PDWORD PageBuf, MS_LibTypeExtdat *ExtraDat)
43 {
44         struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
45         int     result;
46         BYTE    ExtBuf[4];
47         DWORD   bn = PhyBlockAddr * 0x20 + PageNum;
48
49         //printk("MS --- MS_ReaderReadPage,  PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum);
50
51         result = ENE_LoadBinCode(us, MS_RW_PATTERN);
52         if (result != USB_STOR_XFER_GOOD)
53                 return USB_STOR_TRANSPORT_ERROR;
54
55         // Read Page Data
56         memset(bcb, 0, sizeof(bcb));
57         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
58         bcb->DataTransferLength = 0x200;
59         bcb->Flags                      = 0x80;
60         bcb->CDB[0]                     = 0xF1;
61         bcb->CDB[1]                     = 0x02;
62         bcb->CDB[5]                     = (BYTE)(bn);
63         bcb->CDB[4]                     = (BYTE)(bn>>8);
64         bcb->CDB[3]                     = (BYTE)(bn>>16);
65         bcb->CDB[2]                     = (BYTE)(bn>>24);
66         
67         result = ENE_SendScsiCmd(us, FDIR_READ, PageBuf, 0);
68         if (result != USB_STOR_XFER_GOOD)
69                 return USB_STOR_TRANSPORT_ERROR;
70
71         // Read Extra Data
72         memset(bcb, 0, sizeof(bcb));
73         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
74         bcb->DataTransferLength = 0x4;
75         bcb->Flags                      = 0x80;
76         bcb->CDB[0]                     = 0xF1;
77         bcb->CDB[1]                     = 0x03;
78         bcb->CDB[5]                     = (BYTE)(PageNum);
79         bcb->CDB[4]                     = (BYTE)(PhyBlockAddr);
80         bcb->CDB[3]                     = (BYTE)(PhyBlockAddr>>8);
81         bcb->CDB[2]                     = (BYTE)(PhyBlockAddr>>16);
82         bcb->CDB[6]                     = 0x01;
83
84         result = ENE_SendScsiCmd(us, FDIR_READ, &ExtBuf, 0);
85         if (result != USB_STOR_XFER_GOOD)
86                 return USB_STOR_TRANSPORT_ERROR;
87
88         ExtraDat->reserved = 0;
89         ExtraDat->intr     = 0x80;  // Not yet, ¥ý°²³], µ¥ fireware support
90         ExtraDat->status0  = 0x10;  // Not yet, ¥ý°²³], µ¥ fireware support
91         ExtraDat->status1  = 0x00;  // Not yet, ¥ý°²³], µ¥ fireware support
92         ExtraDat->ovrflg   = ExtBuf[0];
93         ExtraDat->mngflg   = ExtBuf[1];
94         ExtraDat->logadr   = MemStickLogAddr(ExtBuf[2], ExtBuf[3]);
95
96         return USB_STOR_TRANSPORT_GOOD;
97 }
98
99 //----- MS_ReaderEraseBlock() ----------------------------------------
100 int MS_ReaderEraseBlock(struct us_data *us, DWORD PhyBlockAddr)
101 {
102         struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
103         int     result;
104         DWORD   bn = PhyBlockAddr;
105
106         //printk("MS --- MS_ReaderEraseBlock,  PhyBlockAddr = %x\n", PhyBlockAddr);
107         result = ENE_LoadBinCode(us, MS_RW_PATTERN);
108         if (result != USB_STOR_XFER_GOOD)
109                 return USB_STOR_TRANSPORT_ERROR;
110
111         memset(bcb, 0, sizeof(bcb));
112         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
113         bcb->DataTransferLength = 0x200;
114         bcb->Flags                      = 0x80;
115         bcb->CDB[0]                     = 0xF2;
116         bcb->CDB[1]                     = 0x06;
117         bcb->CDB[4]                     = (BYTE)(bn);
118         bcb->CDB[3]                     = (BYTE)(bn>>8);
119         bcb->CDB[2]                     = (BYTE)(bn>>16);
120         
121         result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
122         if (result != USB_STOR_XFER_GOOD)
123                 return USB_STOR_TRANSPORT_ERROR;
124
125         return USB_STOR_TRANSPORT_GOOD;
126 }
127
128 //----- MS_CardInit() ------------------------------------------------
129 int MS_CardInit(struct us_data *us)
130 {
131         DWORD                   result=0;
132         WORD                    TmpBlock;
133         PBYTE                   PageBuffer0 = NULL, PageBuffer1 = NULL;
134         MS_LibTypeExtdat        extdat;
135         WORD                    btBlk1st, btBlk2nd;
136         DWORD                   btBlk1stErred;
137
138         printk("MS_CardInit start\n");
139
140         MS_LibFreeAllocatedArea(us);
141
142         if (((PageBuffer0 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL)) == NULL) ||
143             ((PageBuffer1 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL)) == NULL))
144         {
145                 result = MS_NO_MEMORY_ERROR;
146                 goto exit;
147         }
148
149         btBlk1st = btBlk2nd = MS_LB_NOT_USED;
150         btBlk1stErred = 0;
151
152         for (TmpBlock=0; TmpBlock < MS_MAX_INITIAL_ERROR_BLOCKS+2; TmpBlock++)
153         {
154                 switch (MS_ReaderReadPage(us, TmpBlock, 0, (DWORD *)PageBuffer0, &extdat))
155                 {
156                         case MS_STATUS_SUCCESS:
157                         break;
158                         case MS_STATUS_INT_ERROR:
159                         break;
160                         case MS_STATUS_ERROR:
161                         default:
162                         continue;
163                 }
164
165                 if ((extdat.ovrflg & MS_REG_OVR_BKST) == MS_REG_OVR_BKST_NG)
166                         continue;
167
168                 if (((extdat.mngflg & MS_REG_MNG_SYSFLG) == MS_REG_MNG_SYSFLG_USER) ||
169                         (BigEndianWORD(((MemStickBootBlockPage0 *)PageBuffer0)->header.wBlockID) != MS_BOOT_BLOCK_ID) ||
170                         (BigEndianWORD(((MemStickBootBlockPage0 *)PageBuffer0)->header.wFormatVersion) != MS_BOOT_BLOCK_FORMAT_VERSION) ||
171                         (((MemStickBootBlockPage0 *)PageBuffer0)->header.bNumberOfDataEntry != MS_BOOT_BLOCK_DATA_ENTRIES))
172                                 continue;
173
174                 if (btBlk1st != MS_LB_NOT_USED)
175                 {
176                         btBlk2nd = TmpBlock;
177                         break;
178                 }
179
180                 btBlk1st = TmpBlock;
181                 memcpy(PageBuffer1, PageBuffer0, MS_BYTES_PER_PAGE);
182                 if (extdat.status1 & (MS_REG_ST1_DTER | MS_REG_ST1_EXER | MS_REG_ST1_FGER))
183                         btBlk1stErred = 1;
184         }
185
186         if (btBlk1st == MS_LB_NOT_USED)
187         {
188                 result = MS_STATUS_ERROR;
189                 goto exit;
190         }
191
192         // write protect
193         if ((extdat.status0 & MS_REG_ST0_WP) == MS_REG_ST0_WP_ON)
194                 MS_LibCtrlSet(us, MS_LIB_CTRL_WRPROTECT);
195
196         result = MS_STATUS_ERROR;
197         // 1st Boot Block
198         if (btBlk1stErred == 0)
199                 result = MS_LibProcessBootBlock(us, btBlk1st, PageBuffer1);   // 1st
200         // 2nd Boot Block
201         if (result && (btBlk2nd != MS_LB_NOT_USED))
202                 result = MS_LibProcessBootBlock(us, btBlk2nd, PageBuffer0);
203
204         if (result)
205         {
206                 result = MS_STATUS_ERROR;
207                 goto exit;
208         }
209
210         for (TmpBlock = 0; TmpBlock < btBlk1st; TmpBlock++)
211                 us->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR;
212
213         us->MS_Lib.Phy2LogMap[btBlk1st] = MS_LB_BOOT_BLOCK;
214
215         if (btBlk2nd != MS_LB_NOT_USED)
216         {
217                 for (TmpBlock = btBlk1st + 1; TmpBlock < btBlk2nd; TmpBlock++)
218                         us->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR;
219                 us->MS_Lib.Phy2LogMap[btBlk2nd] = MS_LB_BOOT_BLOCK;
220         }
221
222         result = MS_LibScanLogicalBlockNumber(us, btBlk1st);
223         if (result)
224                 goto exit;
225
226         for (TmpBlock=MS_PHYSICAL_BLOCKS_PER_SEGMENT; TmpBlock<us->MS_Lib.NumberOfPhyBlock; TmpBlock+=MS_PHYSICAL_BLOCKS_PER_SEGMENT)
227         {
228                 if (MS_CountFreeBlock(us, TmpBlock) == 0)
229                 {
230                         MS_LibCtrlSet(us, MS_LIB_CTRL_WRPROTECT);
231                         break;
232                 }
233         }
234
235         // write
236         if (MS_LibAllocWriteBuf(us))
237         {
238                 result = MS_NO_MEMORY_ERROR;
239                 goto exit;
240         }
241
242         result = MS_STATUS_SUCCESS;
243
244 exit:
245         if (PageBuffer1)                kfree(PageBuffer1);
246         if (PageBuffer0)                kfree(PageBuffer0);
247
248         printk("MS_CardInit end\n");
249         return result;
250 }
251
252 //----- MS_LibCheckDisableBlock() ------------------------------------
253 int MS_LibCheckDisableBlock(struct us_data *us, WORD PhyBlock)
254 {
255         PWORD                   PageBuf=NULL;
256         DWORD                   result=MS_STATUS_SUCCESS;
257         DWORD                   blk, index=0;
258         MS_LibTypeExtdat        extdat;
259
260         if (((PageBuf = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL)) == NULL))
261         {
262                 result = MS_NO_MEMORY_ERROR;
263                 goto exit;
264         }
265
266         MS_ReaderReadPage(us, PhyBlock, 1, (DWORD *)PageBuf, &extdat);
267         do
268         {
269                 blk = BigEndianWORD(PageBuf[index]);
270                 if (blk == MS_LB_NOT_USED)
271                         break;
272                 if (blk == us->MS_Lib.Log2PhyMap[0])
273                 {
274                         result = MS_ERROR_FLASH_READ;
275                         break;
276                 }
277                 index++;
278         } while(1);
279
280 exit:
281         if (PageBuf)    kfree(PageBuf);
282         return result;
283 }
284
285 //----- MS_LibFreeAllocatedArea() ------------------------------------
286 void MS_LibFreeAllocatedArea(struct us_data *us)
287 {
288         MS_LibFreeWriteBuf(us);
289         MS_LibFreeLogicalMap(us);
290
291         us->MS_Lib.flags                        = 0;
292         us->MS_Lib.BytesPerSector       = 0;
293         us->MS_Lib.SectorsPerCylinder   = 0;
294
295         us->MS_Lib.cardType             = 0;
296         us->MS_Lib.blockSize            = 0;
297         us->MS_Lib.PagesPerBlock        = 0;
298
299         us->MS_Lib.NumberOfPhyBlock     = 0;
300         us->MS_Lib.NumberOfLogBlock     = 0;
301 }
302
303 //----- MS_LibFreeWriteBuf() -----------------------------------------
304 void MS_LibFreeWriteBuf(struct us_data *us)
305 {
306         us->MS_Lib.wrtblk = (WORD)-1; //set to -1
307         MS_LibClearPageMap(us); // memset((fdoExt)->MS_Lib.pagemap, 0, sizeof((fdoExt)->MS_Lib.pagemap))
308
309         if (us->MS_Lib.blkpag)
310         {
311                 kfree((BYTE *)(us->MS_Lib.blkpag));  // Arnold test ...
312                 us->MS_Lib.blkpag = NULL;
313         }
314
315         if (us->MS_Lib.blkext)
316         {
317                 kfree((BYTE *)(us->MS_Lib.blkext));  // Arnold test ...
318                 us->MS_Lib.blkext = NULL;
319         }
320 }
321
322 //----- MS_LibFreeLogicalMap() ---------------------------------------
323 int MS_LibFreeLogicalMap(struct us_data *us)
324 {
325         if (us->MS_Lib.Phy2LogMap)
326         {
327                 kfree(us->MS_Lib.Phy2LogMap);
328                 us->MS_Lib.Phy2LogMap = NULL;
329         }
330
331         if (us->MS_Lib.Log2PhyMap)
332         {
333                 kfree(us->MS_Lib.Log2PhyMap);
334                 us->MS_Lib.Log2PhyMap = NULL;
335         }
336
337     return 0;
338 }
339
340 //----- MS_LibProcessBootBlock() -------------------------------------
341 int MS_LibProcessBootBlock(struct us_data *us, WORD PhyBlock, BYTE *PageData)
342 {
343         MemStickBootBlockSysEnt  *SysEntry;
344         MemStickBootBlockSysInf  *SysInfo;
345         DWORD                    i, result;
346         BYTE                     PageNumber;
347         BYTE                     *PageBuffer;
348         MS_LibTypeExtdat         ExtraData;
349
350         if ((PageBuffer = (BYTE *)kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL))==NULL)
351                 return (DWORD)-1;
352
353         result = (DWORD)-1;
354
355         SysInfo= &(((MemStickBootBlockPage0 *)PageData)->sysinf);
356
357         if ((SysInfo->bMsClass != MS_SYSINF_MSCLASS_TYPE_1)                                   ||
358                 (BigEndianWORD(SysInfo->wPageSize) != MS_SYSINF_PAGE_SIZE)                       ||
359                 ((SysInfo->bSecuritySupport & MS_SYSINF_SECURITY) == MS_SYSINF_SECURITY_SUPPORT) ||
360                 (SysInfo->bReserved1 != MS_SYSINF_RESERVED1)                                     ||
361                 (SysInfo->bReserved2 != MS_SYSINF_RESERVED2)                                     ||
362                 (SysInfo->bFormatType!= MS_SYSINF_FORMAT_FAT)                                    ||
363                 (SysInfo->bUsage != MS_SYSINF_USAGE_GENERAL))
364                 goto exit;
365
366         switch (us->MS_Lib.cardType = SysInfo->bCardType)
367         {
368                 case MS_SYSINF_CARDTYPE_RDONLY:
369                         MS_LibCtrlSet(us, MS_LIB_CTRL_RDONLY);
370                         break;
371                 case MS_SYSINF_CARDTYPE_RDWR:
372                         MS_LibCtrlReset(us, MS_LIB_CTRL_RDONLY);
373                         break;
374                 case MS_SYSINF_CARDTYPE_HYBRID:
375                 default:
376                         goto exit;
377         }
378
379         us->MS_Lib.blockSize        = BigEndianWORD(SysInfo->wBlockSize);
380         us->MS_Lib.NumberOfPhyBlock = BigEndianWORD(SysInfo->wBlockNumber);
381         us->MS_Lib.NumberOfLogBlock = BigEndianWORD(SysInfo->wTotalBlockNumber)- 2;
382         us->MS_Lib.PagesPerBlock    = us->MS_Lib.blockSize * SIZE_OF_KIRO / MS_BYTES_PER_PAGE;
383         us->MS_Lib.NumberOfSegment  = us->MS_Lib.NumberOfPhyBlock / MS_PHYSICAL_BLOCKS_PER_SEGMENT;
384         us->MS_Model                = BigEndianWORD(SysInfo->wMemorySize);
385
386         if (MS_LibAllocLogicalMap(us))                  //Allocate to all number of logicalblock and physicalblock
387                 goto exit;
388
389         MS_LibSetBootBlockMark(us, PhyBlock);           //Mark the book block
390
391         SysEntry = &(((MemStickBootBlockPage0 *)PageData)->sysent);
392
393         for (i=0; i<MS_NUMBER_OF_SYSTEM_ENTRY; i++)
394         {
395                 DWORD  EntryOffset, EntrySize;
396
397                 if ((EntryOffset = BigEndianDWORD(SysEntry->entry[i].dwStart)) == 0xffffff)
398                         continue;
399
400                 if ((EntrySize = BigEndianDWORD(SysEntry->entry[i].dwSize)) == 0)
401                         continue;
402
403                 if (EntryOffset + MS_BYTES_PER_PAGE + EntrySize > us->MS_Lib.blockSize * (DWORD)SIZE_OF_KIRO)
404                         continue;
405
406                 if (i == 0)
407                 {
408                         BYTE  PrevPageNumber = 0;
409                         WORD  phyblk;
410
411                         if (SysEntry->entry[i].bType != MS_SYSENT_TYPE_INVALID_BLOCK)
412                                 goto exit;
413
414                         while (EntrySize > 0)
415                         {
416                                 if ((PageNumber = (BYTE)(EntryOffset / MS_BYTES_PER_PAGE + 1)) != PrevPageNumber)
417                                 {
418                                         switch (MS_ReaderReadPage(us, PhyBlock, PageNumber, (DWORD *)PageBuffer, &ExtraData))
419                                         {
420                                                 case MS_STATUS_SUCCESS:
421                                                         break;
422                                                 case MS_STATUS_WRITE_PROTECT:
423                                                 case MS_ERROR_FLASH_READ:
424                                                 case MS_STATUS_ERROR:
425                                                 default:
426                                                         goto exit;
427                                         }
428
429                                         PrevPageNumber = PageNumber;
430                                 }
431
432                                 if ((phyblk = BigEndianWORD(*(WORD *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE)))) < 0x0fff)
433                                         MS_LibSetInitialErrorBlock(us, phyblk);
434
435                                 EntryOffset += 2;
436                                 EntrySize -= 2;
437                         }
438                 }
439                 else if (i == 1)
440                 {  // CIS/IDI
441                         MemStickBootBlockIDI  *idi;
442
443                         if (SysEntry->entry[i].bType != MS_SYSENT_TYPE_CIS_IDI)
444                                 goto exit;
445
446                         switch (MS_ReaderReadPage(us, PhyBlock, (BYTE)(EntryOffset / MS_BYTES_PER_PAGE + 1), (DWORD *)PageBuffer, &ExtraData))
447                         {
448                                 case MS_STATUS_SUCCESS:
449                                         break;
450                                 case MS_STATUS_WRITE_PROTECT:
451                                 case MS_ERROR_FLASH_READ:
452                                 case MS_STATUS_ERROR:
453                                 default:
454                                         goto exit;
455                         }
456
457                         idi = &((MemStickBootBlockCIS_IDI *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE)))->idi.idi;
458                         if (LittleEndianWORD(idi->wIDIgeneralConfiguration) != MS_IDI_GENERAL_CONF)
459                                 goto exit;
460
461                         us->MS_Lib.BytesPerSector = LittleEndianWORD(idi->wIDIbytesPerSector);
462                         if (us->MS_Lib.BytesPerSector != MS_BYTES_PER_PAGE)
463                                 goto exit;
464                 }
465         } // End for ..
466
467         result = 0;
468
469 exit:
470         if (result)             MS_LibFreeLogicalMap(us);
471         if (PageBuffer) kfree(PageBuffer);
472
473         result = 0;
474         return result;
475 }
476
477 //----- MS_LibAllocLogicalMap() --------------------------------------
478 int MS_LibAllocLogicalMap(struct us_data *us)
479 {
480         DWORD  i;
481
482
483         us->MS_Lib.Phy2LogMap = (WORD *)kmalloc(us->MS_Lib.NumberOfPhyBlock * sizeof(WORD), GFP_KERNEL);
484         us->MS_Lib.Log2PhyMap = (WORD *)kmalloc(us->MS_Lib.NumberOfLogBlock * sizeof(WORD), GFP_KERNEL);
485
486         if ((us->MS_Lib.Phy2LogMap == NULL) || (us->MS_Lib.Log2PhyMap == NULL))
487         {
488                 MS_LibFreeLogicalMap(us);
489                 return (DWORD)-1;
490         }
491
492         for (i = 0; i < us->MS_Lib.NumberOfPhyBlock; i++)
493                 us->MS_Lib.Phy2LogMap[i] = MS_LB_NOT_USED;
494
495         for (i = 0; i < us->MS_Lib.NumberOfLogBlock; i++)
496         us->MS_Lib.Log2PhyMap[i] = MS_LB_NOT_USED;
497
498         return 0;
499 }
500
501 //----- MS_LibSetBootBlockMark() -------------------------------------
502 int MS_LibSetBootBlockMark(struct us_data *us, WORD phyblk)
503 {
504     return MS_LibSetLogicalBlockMark(us, phyblk, MS_LB_BOOT_BLOCK);
505 }
506
507 //----- MS_LibSetLogicalBlockMark() ----------------------------------
508 int MS_LibSetLogicalBlockMark(struct us_data *us, WORD phyblk, WORD mark)
509 {
510     if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
511         return (DWORD)-1;
512
513     us->MS_Lib.Phy2LogMap[phyblk] = mark;
514
515     return 0;
516 }
517
518 //----- MS_LibSetInitialErrorBlock() ---------------------------------
519 int MS_LibSetInitialErrorBlock(struct us_data *us, WORD phyblk)
520 {
521     return MS_LibSetLogicalBlockMark(us, phyblk, MS_LB_INITIAL_ERROR);
522 }
523
524 //----- MS_LibScanLogicalBlockNumber() -------------------------------
525 int MS_LibScanLogicalBlockNumber(struct us_data *us, WORD btBlk1st)
526 {
527         WORD                    PhyBlock, newblk, i;
528         WORD                    LogStart, LogEnde;
529         MS_LibTypeExtdat        extdat;
530         BYTE                    buf[0x200];
531         DWORD                   count=0, index=0;
532
533         for (PhyBlock = 0; PhyBlock < us->MS_Lib.NumberOfPhyBlock;)
534         {
535                 MS_LibPhy2LogRange(PhyBlock, &LogStart, &LogEnde);
536
537                 for (i=0; i<MS_PHYSICAL_BLOCKS_PER_SEGMENT; i++, PhyBlock++)
538                 {
539                         switch (MS_LibConv2Logical(us, PhyBlock))
540                         {
541                                 case MS_STATUS_ERROR:
542                                         continue;
543                                 default:
544                                         break;
545                         }
546
547                         if (count == PhyBlock)
548                         {
549                                 MS_LibReadExtraBlock(us, PhyBlock, 0, 0x80, &buf);
550                                 count += 0x80;
551                         }
552                         index = (PhyBlock % 0x80) * 4;
553
554                         extdat.ovrflg = buf[index];
555                         extdat.mngflg = buf[index+1];
556                         extdat.logadr = MemStickLogAddr(buf[index+2], buf[index+3]);
557
558                         if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK)
559                         {
560                                 MS_LibSetAcquiredErrorBlock(us, PhyBlock);
561                                 continue;
562                         }
563
564                         if ((extdat.mngflg & MS_REG_MNG_ATFLG) == MS_REG_MNG_ATFLG_ATTBL)
565                         {
566                                 MS_LibErasePhyBlock(us, PhyBlock);
567                                 continue;
568                         }
569
570                         if (extdat.logadr != MS_LB_NOT_USED)
571                         {
572                                 if ((extdat.logadr < LogStart) || (LogEnde <= extdat.logadr))
573                                 {
574                                         MS_LibErasePhyBlock(us, PhyBlock);
575                                         continue;
576                                 }
577
578                                 if ((newblk = MS_LibConv2Physical(us, extdat.logadr)) != MS_LB_NOT_USED)
579                                 {
580                                         if (extdat.logadr==0)
581                                         {
582                                                 MS_LibSetLogicalPair(us, extdat.logadr, PhyBlock);
583                                                 if ( MS_LibCheckDisableBlock(us, btBlk1st) )
584                                                 {
585                                                         MS_LibSetLogicalPair(us, extdat.logadr, newblk);
586                                                         continue;
587                                                 }
588                                         }
589
590                                         MS_LibReadExtra(us, newblk, 0, &extdat);
591                                         if ((extdat.ovrflg & MS_REG_OVR_UDST) == MS_REG_OVR_UDST_UPDATING)
592                                         {
593                                                 MS_LibErasePhyBlock(us, PhyBlock);
594                                                 continue;
595                                         }
596                                         else
597                                                 MS_LibErasePhyBlock(us, newblk);
598                                 }
599
600                                 MS_LibSetLogicalPair(us, extdat.logadr, PhyBlock);
601                         }
602                 }
603         } //End for ...
604
605         return MS_STATUS_SUCCESS;
606 }
607
608 //----- MS_LibAllocWriteBuf() ----------------------------------------
609 int MS_LibAllocWriteBuf(struct us_data *us)
610 {
611         us->MS_Lib.wrtblk = (WORD)-1;
612
613         us->MS_Lib.blkpag = (BYTE *)kmalloc(us->MS_Lib.PagesPerBlock * us->MS_Lib.BytesPerSector, GFP_KERNEL);
614         us->MS_Lib.blkext = (MS_LibTypeExtdat *)kmalloc(us->MS_Lib.PagesPerBlock * sizeof(MS_LibTypeExtdat), GFP_KERNEL);
615
616         if ((us->MS_Lib.blkpag == NULL) || (us->MS_Lib.blkext == NULL))
617         {
618                 MS_LibFreeWriteBuf(us);
619                 return (DWORD)-1;
620         }
621
622         MS_LibClearWriteBuf(us);
623
624         return 0;
625 }
626
627 //----- MS_LibClearWriteBuf() ----------------------------------------
628 void MS_LibClearWriteBuf(struct us_data *us)
629 {
630         int i;
631
632         us->MS_Lib.wrtblk = (WORD)-1;
633         MS_LibClearPageMap(us);
634
635         if (us->MS_Lib.blkpag)
636                 memset(us->MS_Lib.blkpag, 0xff, us->MS_Lib.PagesPerBlock * us->MS_Lib.BytesPerSector);
637
638         if (us->MS_Lib.blkext)
639         {
640                 for (i = 0; i < us->MS_Lib.PagesPerBlock; i++)
641                 {
642                         us->MS_Lib.blkext[i].status1 = MS_REG_ST1_DEFAULT;
643                         us->MS_Lib.blkext[i].ovrflg = MS_REG_OVR_DEFAULT;
644                         us->MS_Lib.blkext[i].mngflg = MS_REG_MNG_DEFAULT;
645                         us->MS_Lib.blkext[i].logadr = MS_LB_NOT_USED;
646                 }
647         }
648 }
649
650 //----- MS_LibPhy2LogRange() -----------------------------------------
651 void MS_LibPhy2LogRange(WORD PhyBlock, WORD *LogStart, WORD *LogEnde)
652 {
653         PhyBlock /= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
654
655         if (PhyBlock)
656         {
657                 *LogStart = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT + (PhyBlock - 1) * MS_LOGICAL_BLOCKS_PER_SEGMENT;//496
658                 *LogEnde = *LogStart + MS_LOGICAL_BLOCKS_PER_SEGMENT;//496
659         }
660         else
661         {
662                 *LogStart = 0;
663                 *LogEnde = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT;//494
664         }
665 }
666
667 //----- MS_LibReadExtraBlock() --------------------------------------------
668 int MS_LibReadExtraBlock(struct us_data *us, DWORD PhyBlock, BYTE PageNum, BYTE blen, void *buf)
669 {
670         struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
671         int     result;
672
673         //printk("MS_LibReadExtraBlock --- PhyBlock = %x, PageNum = %x, blen = %x\n", PhyBlock, PageNum, blen);
674
675         // Read Extra Data
676         memset(bcb, 0, sizeof(bcb));
677         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
678         bcb->DataTransferLength = 0x4 * blen;
679         bcb->Flags                      = 0x80;
680         bcb->CDB[0]                     = 0xF1;
681         bcb->CDB[1]                     = 0x03;
682         bcb->CDB[5]                     = (BYTE)(PageNum);
683         bcb->CDB[4]                     = (BYTE)(PhyBlock);
684         bcb->CDB[3]                     = (BYTE)(PhyBlock>>8);
685         bcb->CDB[2]                     = (BYTE)(PhyBlock>>16);
686         bcb->CDB[6]                     = blen;
687
688         result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
689         if (result != USB_STOR_XFER_GOOD)
690                 return USB_STOR_TRANSPORT_ERROR;
691
692         return USB_STOR_TRANSPORT_GOOD;
693 }
694
695 //----- MS_LibReadExtra() --------------------------------------------
696 int MS_LibReadExtra(struct us_data *us, DWORD PhyBlock, BYTE PageNum, MS_LibTypeExtdat *ExtraDat)
697 {
698         struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
699         int     result;
700         BYTE    ExtBuf[4];
701
702         //printk("MS_LibReadExtra --- PhyBlock = %x, PageNum = %x\n", PhyBlock, PageNum);
703         memset(bcb, 0, sizeof(bcb));
704         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
705         bcb->DataTransferLength = 0x4;
706         bcb->Flags                      = 0x80;
707         bcb->CDB[0]                     = 0xF1;
708         bcb->CDB[1]                     = 0x03;
709         bcb->CDB[5]                     = (BYTE)(PageNum);
710         bcb->CDB[4]                     = (BYTE)(PhyBlock);
711         bcb->CDB[3]                     = (BYTE)(PhyBlock>>8);
712         bcb->CDB[2]                     = (BYTE)(PhyBlock>>16);
713         bcb->CDB[6]                     = 0x01;
714         
715         result = ENE_SendScsiCmd(us, FDIR_READ, &ExtBuf, 0);
716         if (result != USB_STOR_XFER_GOOD)
717                 return USB_STOR_TRANSPORT_ERROR;
718
719         ExtraDat->reserved = 0;
720         ExtraDat->intr     = 0x80;  // Not yet, waiting for fireware support
721         ExtraDat->status0  = 0x10;  // Not yet, waiting for fireware support
722         ExtraDat->status1  = 0x00;  // Not yet, waiting for fireware support
723         ExtraDat->ovrflg   = ExtBuf[0];
724         ExtraDat->mngflg   = ExtBuf[1];
725         ExtraDat->logadr   = MemStickLogAddr(ExtBuf[2], ExtBuf[3]);
726         
727         return USB_STOR_TRANSPORT_GOOD;
728 }
729
730 //----- MS_LibSetAcquiredErrorBlock() --------------------------------
731 int MS_LibSetAcquiredErrorBlock(struct us_data *us, WORD phyblk)
732 {
733         WORD log;
734
735         if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
736                 return (DWORD)-1;
737
738         if ((log = us->MS_Lib.Phy2LogMap[phyblk]) < us->MS_Lib.NumberOfLogBlock)
739                 us->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED;
740
741         if (us->MS_Lib.Phy2LogMap[phyblk] != MS_LB_INITIAL_ERROR)
742                 us->MS_Lib.Phy2LogMap[phyblk] = MS_LB_ACQUIRED_ERROR;
743
744         return 0;
745 }
746
747 //----- MS_LibErasePhyBlock() ----------------------------------------
748 int MS_LibErasePhyBlock(struct us_data *us, WORD phyblk)
749 {
750         WORD  log;
751
752         if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
753                 return MS_STATUS_ERROR;
754
755         if ((log = us->MS_Lib.Phy2LogMap[phyblk]) < us->MS_Lib.NumberOfLogBlock)
756                 us->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED;
757
758         us->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED;
759
760         if (MS_LibIsWritable(us))
761         {
762                 switch (MS_ReaderEraseBlock(us, phyblk))
763                 {
764                         case MS_STATUS_SUCCESS:
765                                 us->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED_ERASED;
766                                 return MS_STATUS_SUCCESS;
767                         case MS_ERROR_FLASH_ERASE:
768                         case MS_STATUS_INT_ERROR :
769                                 MS_LibErrorPhyBlock(us, phyblk);
770                                 return MS_ERROR_FLASH_ERASE;
771                         case MS_STATUS_ERROR:
772                         default:
773                                 MS_LibCtrlSet(us, MS_LIB_CTRL_RDONLY);
774                                 MS_LibSetAcquiredErrorBlock(us, phyblk);
775                                 return MS_STATUS_ERROR;
776                 }
777         }
778
779         MS_LibSetAcquiredErrorBlock(us, phyblk);
780
781         return MS_STATUS_SUCCESS;
782 }
783
784 //----- MS_LibErrorPhyBlock() ----------------------------------------
785 int MS_LibErrorPhyBlock(struct us_data *us, WORD phyblk)
786 {
787     if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
788         return MS_STATUS_ERROR;
789
790     MS_LibSetAcquiredErrorBlock(us, phyblk);
791
792     if (MS_LibIsWritable(us))
793         return MS_LibOverwriteExtra(us, phyblk, 0, (BYTE)(~MS_REG_OVR_BKST));
794
795
796     return MS_STATUS_SUCCESS;
797 }
798
799 //----- MS_LibOverwriteExtra() ---------------------------------------
800 int MS_LibOverwriteExtra(struct us_data *us, DWORD PhyBlockAddr, BYTE PageNum, BYTE OverwriteFlag)
801 {
802         struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
803         int     result;
804
805         //printk("MS --- MS_LibOverwriteExtra,  PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum);
806         result = ENE_LoadBinCode(us, MS_RW_PATTERN);
807         if (result != USB_STOR_XFER_GOOD)
808                 return USB_STOR_TRANSPORT_ERROR;
809
810         memset(bcb, 0, sizeof(bcb));
811         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
812         bcb->DataTransferLength = 0x4;
813         bcb->Flags                      = 0x80;
814         bcb->CDB[0]                     = 0xF2;
815         bcb->CDB[1]                     = 0x05;
816         bcb->CDB[5]                     = (BYTE)(PageNum);
817         bcb->CDB[4]                     = (BYTE)(PhyBlockAddr);
818         bcb->CDB[3]                     = (BYTE)(PhyBlockAddr>>8);
819         bcb->CDB[2]                     = (BYTE)(PhyBlockAddr>>16);
820         bcb->CDB[6]                     = OverwriteFlag;
821         bcb->CDB[7]                     = 0xFF;
822         bcb->CDB[8]                     = 0xFF;
823         bcb->CDB[9]                     = 0xFF;
824         
825         result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
826         if (result != USB_STOR_XFER_GOOD)
827                 return USB_STOR_TRANSPORT_ERROR;
828
829         return USB_STOR_TRANSPORT_GOOD;
830 }
831
832 //----- MS_LibForceSetLogicalPair() ----------------------------------
833 int MS_LibForceSetLogicalPair(struct us_data *us, WORD logblk, WORD phyblk)
834 {
835         if (logblk == MS_LB_NOT_USED)
836                 return 0;
837
838         if ((logblk >= us->MS_Lib.NumberOfLogBlock) || (phyblk >= us->MS_Lib.NumberOfPhyBlock))
839                 return (DWORD)-1;
840
841         us->MS_Lib.Phy2LogMap[phyblk] = logblk;
842         us->MS_Lib.Log2PhyMap[logblk] = phyblk;
843
844         return 0;
845 }
846
847 //----- MS_LibSetLogicalPair() ---------------------------------------
848 int MS_LibSetLogicalPair(struct us_data *us, WORD logblk, WORD phyblk)
849 {
850         if ((logblk >= us->MS_Lib.NumberOfLogBlock) || (phyblk >= us->MS_Lib.NumberOfPhyBlock))
851                 return (DWORD)-1;
852
853         us->MS_Lib.Phy2LogMap[phyblk] = logblk;
854         us->MS_Lib.Log2PhyMap[logblk] = phyblk;
855
856         return 0;
857 }
858
859 //----- MS_CountFreeBlock() ------------------------------------------
860 int MS_CountFreeBlock(struct us_data *us, WORD PhyBlock)
861 {
862         DWORD Ende, Count;
863
864         Ende = PhyBlock + MS_PHYSICAL_BLOCKS_PER_SEGMENT;
865         for (Count = 0; PhyBlock < Ende; PhyBlock++)
866         {
867                 switch (us->MS_Lib.Phy2LogMap[PhyBlock])
868                 {
869                         case MS_LB_NOT_USED:
870                         case MS_LB_NOT_USED_ERASED:
871                                 Count++;
872                         default:
873                                 break;
874                 }
875         }
876
877         return Count;
878 }
879
880 //----- MS_LibSearchBlockFromPhysical() ------------------------------
881 int MS_LibSearchBlockFromPhysical(struct us_data *us, WORD phyblk)
882 {
883         WORD                    Newblk;
884         WORD                    blk;
885         MS_LibTypeExtdat        extdat;
886
887         if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
888                 return MS_LB_ERROR;
889
890         for (blk = phyblk + 1; blk != phyblk; blk++)
891         {
892                 if ((blk & MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK) == 0)
893                         blk -= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
894
895                 Newblk = us->MS_Lib.Phy2LogMap[blk];
896                 if (us->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED_ERASED)
897                         return blk;
898                 else if (us->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED)
899                 {
900                         switch (MS_LibReadExtra(us, blk, 0, &extdat))
901                         {
902                                 case MS_STATUS_SUCCESS :
903                                 case MS_STATUS_SUCCESS_WITH_ECC:
904                                         break;
905                                 case MS_NOCARD_ERROR:
906                                         return MS_NOCARD_ERROR;
907                                 case MS_STATUS_INT_ERROR:
908                                         return MS_LB_ERROR;
909                                 case MS_ERROR_FLASH_READ:
910                                 default:
911                                         MS_LibSetAcquiredErrorBlock(us, blk);     // MS_LibErrorPhyBlock(fdoExt, blk);
912                                         continue;
913                         } // End switch
914
915                         if ((extdat.ovrflg & MS_REG_OVR_BKST) != MS_REG_OVR_BKST_OK)
916                         {
917                                 MS_LibSetAcquiredErrorBlock(us, blk);
918                                 continue;
919                         }
920
921                         switch (MS_LibErasePhyBlock(us, blk))
922                         {
923                                 case MS_STATUS_SUCCESS:
924                                         return blk;
925                                 case MS_STATUS_ERROR:
926                                         return MS_LB_ERROR;
927                                 case MS_ERROR_FLASH_ERASE:
928                                 default:
929                                         MS_LibErrorPhyBlock(us, blk);
930                                         break;
931                         }
932                 }
933         } // End for
934
935         return MS_LB_ERROR;
936 }
937
938 //----- MS_LibSearchBlockFromLogical() -------------------------------
939 int MS_LibSearchBlockFromLogical(struct us_data *us, WORD logblk)
940 {
941         WORD phyblk;
942
943         if ((phyblk=MS_LibConv2Physical(us, logblk)) >= MS_LB_ERROR)
944         {
945                 if (logblk >= us->MS_Lib.NumberOfLogBlock)
946                         return MS_LB_ERROR;
947
948                 phyblk = (logblk + MS_NUMBER_OF_BOOT_BLOCK) / MS_LOGICAL_BLOCKS_PER_SEGMENT;
949                 phyblk *= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
950                 phyblk += MS_PHYSICAL_BLOCKS_PER_SEGMENT - 1;
951         }
952
953         return MS_LibSearchBlockFromPhysical(us, phyblk);
954 }
955
956