Realtek cr: Add autosuspend function.
[zen-stable.git] / drivers / staging / keucr / ms.c
blob087ad73ff70f18dee8564de500ef145a50a29f9d
1 #include <linux/slab.h>
2 #include <asm/byteorder.h>
4 #include "usb.h"
5 #include "scsiglue.h"
6 #include "transport.h"
7 #include "ms.h"
9 /*
10 * MS_ReaderCopyBlock()
12 int MS_ReaderCopyBlock(struct us_data *us, WORD oldphy, WORD newphy,
13 WORD PhyBlockAddr, BYTE PageNum, PBYTE buf, WORD len)
15 struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
16 int result;
18 /* printk(KERN_INFO "MS_ReaderCopyBlock --- PhyBlockAddr = %x,
19 PageNum = %x\n", PhyBlockAddr, PageNum); */
20 result = ENE_LoadBinCode(us, MS_RW_PATTERN);
21 if (result != USB_STOR_XFER_GOOD)
22 return USB_STOR_TRANSPORT_ERROR;
24 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
25 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
26 bcb->DataTransferLength = 0x200*len;
27 bcb->Flags = 0x00;
28 bcb->CDB[0] = 0xF0;
29 bcb->CDB[1] = 0x08;
30 bcb->CDB[4] = (BYTE)(oldphy);
31 bcb->CDB[3] = (BYTE)(oldphy>>8);
32 bcb->CDB[2] = 0; /* (BYTE)(oldphy>>16) */
33 bcb->CDB[7] = (BYTE)(newphy);
34 bcb->CDB[6] = (BYTE)(newphy>>8);
35 bcb->CDB[5] = 0; /* (BYTE)(newphy>>16) */
36 bcb->CDB[9] = (BYTE)(PhyBlockAddr);
37 bcb->CDB[8] = (BYTE)(PhyBlockAddr>>8);
38 bcb->CDB[10] = PageNum;
40 result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
41 if (result != USB_STOR_XFER_GOOD)
42 return USB_STOR_TRANSPORT_ERROR;
44 return USB_STOR_TRANSPORT_GOOD;
48 * MS_ReaderReadPage()
50 int MS_ReaderReadPage(struct us_data *us, DWORD PhyBlockAddr,
51 BYTE PageNum, PDWORD PageBuf, MS_LibTypeExtdat *ExtraDat)
53 struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
54 int result;
55 BYTE ExtBuf[4];
56 DWORD bn = PhyBlockAddr * 0x20 + PageNum;
58 /* printk(KERN_INFO "MS --- MS_ReaderReadPage,
59 PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum); */
61 result = ENE_LoadBinCode(us, MS_RW_PATTERN);
62 if (result != USB_STOR_XFER_GOOD)
63 return USB_STOR_TRANSPORT_ERROR;
65 /* Read Page Data */
66 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
67 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
68 bcb->DataTransferLength = 0x200;
69 bcb->Flags = 0x80;
70 bcb->CDB[0] = 0xF1;
71 bcb->CDB[1] = 0x02;
72 bcb->CDB[5] = (BYTE)(bn);
73 bcb->CDB[4] = (BYTE)(bn>>8);
74 bcb->CDB[3] = (BYTE)(bn>>16);
75 bcb->CDB[2] = (BYTE)(bn>>24);
77 result = ENE_SendScsiCmd(us, FDIR_READ, PageBuf, 0);
78 if (result != USB_STOR_XFER_GOOD)
79 return USB_STOR_TRANSPORT_ERROR;
81 /* Read Extra Data */
82 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
83 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
84 bcb->DataTransferLength = 0x4;
85 bcb->Flags = 0x80;
86 bcb->CDB[0] = 0xF1;
87 bcb->CDB[1] = 0x03;
88 bcb->CDB[5] = (BYTE)(PageNum);
89 bcb->CDB[4] = (BYTE)(PhyBlockAddr);
90 bcb->CDB[3] = (BYTE)(PhyBlockAddr>>8);
91 bcb->CDB[2] = (BYTE)(PhyBlockAddr>>16);
92 bcb->CDB[6] = 0x01;
94 result = ENE_SendScsiCmd(us, FDIR_READ, &ExtBuf, 0);
95 if (result != USB_STOR_XFER_GOOD)
96 return USB_STOR_TRANSPORT_ERROR;
98 ExtraDat->reserved = 0;
99 ExtraDat->intr = 0x80; /* Not yet,fireware support */
100 ExtraDat->status0 = 0x10; /* Not yet,fireware support */
101 ExtraDat->status1 = 0x00; /* Not yet,fireware support */
102 ExtraDat->ovrflg = ExtBuf[0];
103 ExtraDat->mngflg = ExtBuf[1];
104 ExtraDat->logadr = MemStickLogAddr(ExtBuf[2], ExtBuf[3]);
106 return USB_STOR_TRANSPORT_GOOD;
110 * MS_ReaderEraseBlock()
112 int MS_ReaderEraseBlock(struct us_data *us, DWORD PhyBlockAddr)
114 struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
115 int result;
116 DWORD bn = PhyBlockAddr;
118 /* printk(KERN_INFO "MS --- MS_ReaderEraseBlock,
119 PhyBlockAddr = %x\n", PhyBlockAddr); */
120 result = ENE_LoadBinCode(us, MS_RW_PATTERN);
121 if (result != USB_STOR_XFER_GOOD)
122 return USB_STOR_TRANSPORT_ERROR;
124 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
125 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
126 bcb->DataTransferLength = 0x200;
127 bcb->Flags = 0x80;
128 bcb->CDB[0] = 0xF2;
129 bcb->CDB[1] = 0x06;
130 bcb->CDB[4] = (BYTE)(bn);
131 bcb->CDB[3] = (BYTE)(bn>>8);
132 bcb->CDB[2] = (BYTE)(bn>>16);
134 result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
135 if (result != USB_STOR_XFER_GOOD)
136 return USB_STOR_TRANSPORT_ERROR;
138 return USB_STOR_TRANSPORT_GOOD;
142 * MS_CardInit()
144 int MS_CardInit(struct us_data *us)
146 DWORD result = 0;
147 WORD TmpBlock;
148 PBYTE PageBuffer0 = NULL, PageBuffer1 = NULL;
149 MS_LibTypeExtdat extdat;
150 WORD btBlk1st, btBlk2nd;
151 DWORD btBlk1stErred;
153 printk(KERN_INFO "MS_CardInit start\n");
155 MS_LibFreeAllocatedArea(us);
157 PageBuffer0 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
158 PageBuffer1 = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
159 if ((PageBuffer0 == NULL) || (PageBuffer1 == NULL)) {
160 result = MS_NO_MEMORY_ERROR;
161 goto exit;
164 btBlk1st = btBlk2nd = MS_LB_NOT_USED;
165 btBlk1stErred = 0;
167 for (TmpBlock = 0; TmpBlock < MS_MAX_INITIAL_ERROR_BLOCKS+2;
168 TmpBlock++) {
169 switch (MS_ReaderReadPage(us, TmpBlock, 0,
170 (DWORD *)PageBuffer0, &extdat)) {
171 case MS_STATUS_SUCCESS:
172 break;
173 case MS_STATUS_INT_ERROR:
174 break;
175 case MS_STATUS_ERROR:
176 default:
177 continue;
180 if ((extdat.ovrflg & MS_REG_OVR_BKST) == MS_REG_OVR_BKST_NG)
181 continue;
183 if (((extdat.mngflg & MS_REG_MNG_SYSFLG) == MS_REG_MNG_SYSFLG_USER) ||
184 (be16_to_cpu(((MemStickBootBlockPage0 *)PageBuffer0)->header.wBlockID) != MS_BOOT_BLOCK_ID) ||
185 (be16_to_cpu(((MemStickBootBlockPage0 *)PageBuffer0)->header.wFormatVersion) != MS_BOOT_BLOCK_FORMAT_VERSION) ||
186 (((MemStickBootBlockPage0 *)PageBuffer0)->header.bNumberOfDataEntry != MS_BOOT_BLOCK_DATA_ENTRIES))
187 continue;
189 if (btBlk1st != MS_LB_NOT_USED) {
190 btBlk2nd = TmpBlock;
191 break;
194 btBlk1st = TmpBlock;
195 memcpy(PageBuffer1, PageBuffer0, MS_BYTES_PER_PAGE);
196 if (extdat.status1 &
197 (MS_REG_ST1_DTER | MS_REG_ST1_EXER | MS_REG_ST1_FGER))
198 btBlk1stErred = 1;
201 if (btBlk1st == MS_LB_NOT_USED) {
202 result = MS_STATUS_ERROR;
203 goto exit;
206 /* write protect */
207 if ((extdat.status0 & MS_REG_ST0_WP) == MS_REG_ST0_WP_ON)
208 MS_LibCtrlSet(us, MS_LIB_CTRL_WRPROTECT);
210 result = MS_STATUS_ERROR;
211 /* 1st Boot Block */
212 if (btBlk1stErred == 0)
213 result = MS_LibProcessBootBlock(us, btBlk1st, PageBuffer1);
214 /* 1st */
215 /* 2nd Boot Block */
216 if (result && (btBlk2nd != MS_LB_NOT_USED))
217 result = MS_LibProcessBootBlock(us, btBlk2nd, PageBuffer0);
219 if (result) {
220 result = MS_STATUS_ERROR;
221 goto exit;
224 for (TmpBlock = 0; TmpBlock < btBlk1st; TmpBlock++)
225 us->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR;
227 us->MS_Lib.Phy2LogMap[btBlk1st] = MS_LB_BOOT_BLOCK;
229 if (btBlk2nd != MS_LB_NOT_USED) {
230 for (TmpBlock = btBlk1st + 1; TmpBlock < btBlk2nd; TmpBlock++)
231 us->MS_Lib.Phy2LogMap[TmpBlock] = MS_LB_INITIAL_ERROR;
232 us->MS_Lib.Phy2LogMap[btBlk2nd] = MS_LB_BOOT_BLOCK;
235 result = MS_LibScanLogicalBlockNumber(us, btBlk1st);
236 if (result)
237 goto exit;
239 for (TmpBlock = MS_PHYSICAL_BLOCKS_PER_SEGMENT;
240 TmpBlock < us->MS_Lib.NumberOfPhyBlock;
241 TmpBlock += MS_PHYSICAL_BLOCKS_PER_SEGMENT) {
242 if (MS_CountFreeBlock(us, TmpBlock) == 0) {
243 MS_LibCtrlSet(us, MS_LIB_CTRL_WRPROTECT);
244 break;
248 /* write */
249 if (MS_LibAllocWriteBuf(us)) {
250 result = MS_NO_MEMORY_ERROR;
251 goto exit;
254 result = MS_STATUS_SUCCESS;
256 exit:
257 kfree(PageBuffer1);
258 kfree(PageBuffer0);
260 printk(KERN_INFO "MS_CardInit end\n");
261 return result;
265 * MS_LibCheckDisableBlock()
267 int MS_LibCheckDisableBlock(struct us_data *us, WORD PhyBlock)
269 PWORD PageBuf = NULL;
270 DWORD result = MS_STATUS_SUCCESS;
271 DWORD blk, index = 0;
272 MS_LibTypeExtdat extdat;
274 PageBuf = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
275 if (PageBuf == NULL) {
276 result = MS_NO_MEMORY_ERROR;
277 goto exit;
280 MS_ReaderReadPage(us, PhyBlock, 1, (DWORD *)PageBuf, &extdat);
281 do {
282 blk = be16_to_cpu(PageBuf[index]);
283 if (blk == MS_LB_NOT_USED)
284 break;
285 if (blk == us->MS_Lib.Log2PhyMap[0]) {
286 result = MS_ERROR_FLASH_READ;
287 break;
289 index++;
290 } while (1);
292 exit:
293 kfree(PageBuf);
294 return result;
298 * MS_LibFreeAllocatedArea()
300 void MS_LibFreeAllocatedArea(struct us_data *us)
302 MS_LibFreeWriteBuf(us);
303 MS_LibFreeLogicalMap(us);
305 us->MS_Lib.flags = 0;
306 us->MS_Lib.BytesPerSector = 0;
307 us->MS_Lib.SectorsPerCylinder = 0;
309 us->MS_Lib.cardType = 0;
310 us->MS_Lib.blockSize = 0;
311 us->MS_Lib.PagesPerBlock = 0;
313 us->MS_Lib.NumberOfPhyBlock = 0;
314 us->MS_Lib.NumberOfLogBlock = 0;
318 * MS_LibFreeWriteBuf()
320 void MS_LibFreeWriteBuf(struct us_data *us)
322 us->MS_Lib.wrtblk = (WORD)-1; /* set to -1 */
324 /* memset((fdoExt)->MS_Lib.pagemap, 0,
325 sizeof((fdoExt)->MS_Lib.pagemap)) */
326 MS_LibClearPageMap(us);
328 if (us->MS_Lib.blkpag) {
329 kfree((BYTE *)(us->MS_Lib.blkpag)); /* Arnold test ... */
330 us->MS_Lib.blkpag = NULL;
333 if (us->MS_Lib.blkext) {
334 kfree((BYTE *)(us->MS_Lib.blkext)); /* Arnold test ... */
335 us->MS_Lib.blkext = NULL;
340 * MS_LibFreeLogicalMap()
342 int MS_LibFreeLogicalMap(struct us_data *us)
344 kfree(us->MS_Lib.Phy2LogMap);
345 us->MS_Lib.Phy2LogMap = NULL;
347 kfree(us->MS_Lib.Log2PhyMap);
348 us->MS_Lib.Log2PhyMap = NULL;
350 return 0;
354 * MS_LibProcessBootBlock()
356 int MS_LibProcessBootBlock(struct us_data *us, WORD PhyBlock, BYTE *PageData)
358 MemStickBootBlockSysEnt *SysEntry;
359 MemStickBootBlockSysInf *SysInfo;
360 DWORD i, result;
361 BYTE PageNumber;
362 BYTE *PageBuffer;
363 MS_LibTypeExtdat ExtraData;
366 PageBuffer = kmalloc(MS_BYTES_PER_PAGE, GFP_KERNEL);
367 if (PageBuffer == NULL)
368 return (DWORD)-1;
370 result = (DWORD)-1;
372 SysInfo = &(((MemStickBootBlockPage0 *)PageData)->sysinf);
374 if ((SysInfo->bMsClass != MS_SYSINF_MSCLASS_TYPE_1) ||
375 (be16_to_cpu(SysInfo->wPageSize) != MS_SYSINF_PAGE_SIZE) ||
376 ((SysInfo->bSecuritySupport & MS_SYSINF_SECURITY) == MS_SYSINF_SECURITY_SUPPORT) ||
377 (SysInfo->bReserved1 != MS_SYSINF_RESERVED1) ||
378 (SysInfo->bReserved2 != MS_SYSINF_RESERVED2) ||
379 (SysInfo->bFormatType != MS_SYSINF_FORMAT_FAT) ||
380 (SysInfo->bUsage != MS_SYSINF_USAGE_GENERAL))
381 goto exit;
383 switch (us->MS_Lib.cardType = SysInfo->bCardType) {
384 case MS_SYSINF_CARDTYPE_RDONLY:
385 MS_LibCtrlSet(us, MS_LIB_CTRL_RDONLY);
386 break;
387 case MS_SYSINF_CARDTYPE_RDWR:
388 MS_LibCtrlReset(us, MS_LIB_CTRL_RDONLY);
389 break;
390 case MS_SYSINF_CARDTYPE_HYBRID:
391 default:
392 goto exit;
395 us->MS_Lib.blockSize = be16_to_cpu(SysInfo->wBlockSize);
396 us->MS_Lib.NumberOfPhyBlock = be16_to_cpu(SysInfo->wBlockNumber);
397 us->MS_Lib.NumberOfLogBlock = be16_to_cpu(SysInfo->wTotalBlockNumber)
399 us->MS_Lib.PagesPerBlock = us->MS_Lib.blockSize * SIZE_OF_KIRO /
400 MS_BYTES_PER_PAGE;
401 us->MS_Lib.NumberOfSegment = us->MS_Lib.NumberOfPhyBlock /
402 MS_PHYSICAL_BLOCKS_PER_SEGMENT;
403 us->MS_Model = be16_to_cpu(SysInfo->wMemorySize);
405 /*Allocate to all number of logicalblock and physicalblock */
406 if (MS_LibAllocLogicalMap(us))
407 goto exit;
409 /* Mark the book block */
410 MS_LibSetBootBlockMark(us, PhyBlock);
412 SysEntry = &(((MemStickBootBlockPage0 *)PageData)->sysent);
414 for (i = 0; i < MS_NUMBER_OF_SYSTEM_ENTRY; i++) {
415 DWORD EntryOffset, EntrySize;
417 EntryOffset = be32_to_cpu(SysEntry->entry[i].dwStart);
419 if (EntryOffset == 0xffffff)
420 continue;
421 EntrySize = be32_to_cpu(SysEntry->entry[i].dwSize);
423 if (EntrySize == 0)
424 continue;
426 if (EntryOffset + MS_BYTES_PER_PAGE + EntrySize >
427 us->MS_Lib.blockSize * (DWORD)SIZE_OF_KIRO)
428 continue;
430 if (i == 0) {
431 BYTE PrevPageNumber = 0;
432 WORD phyblk;
434 if (SysEntry->entry[i].bType !=
435 MS_SYSENT_TYPE_INVALID_BLOCK)
436 goto exit;
438 while (EntrySize > 0) {
440 PageNumber = (BYTE)(EntryOffset /
441 MS_BYTES_PER_PAGE + 1);
442 if (PageNumber != PrevPageNumber) {
443 switch (MS_ReaderReadPage(us, PhyBlock,
444 PageNumber, (DWORD *)PageBuffer,
445 &ExtraData)) {
446 case MS_STATUS_SUCCESS:
447 break;
448 case MS_STATUS_WRITE_PROTECT:
449 case MS_ERROR_FLASH_READ:
450 case MS_STATUS_ERROR:
451 default:
452 goto exit;
455 PrevPageNumber = PageNumber;
458 phyblk = be16_to_cpu(*(WORD *)(PageBuffer +
459 (EntryOffset % MS_BYTES_PER_PAGE)));
460 if (phyblk < 0x0fff)
461 MS_LibSetInitialErrorBlock(us, phyblk);
463 EntryOffset += 2;
464 EntrySize -= 2;
466 } else if (i == 1) { /* CIS/IDI */
467 MemStickBootBlockIDI *idi;
469 if (SysEntry->entry[i].bType != MS_SYSENT_TYPE_CIS_IDI)
470 goto exit;
472 switch (MS_ReaderReadPage(us, PhyBlock,
473 (BYTE)(EntryOffset / MS_BYTES_PER_PAGE + 1),
474 (DWORD *)PageBuffer, &ExtraData)) {
475 case MS_STATUS_SUCCESS:
476 break;
477 case MS_STATUS_WRITE_PROTECT:
478 case MS_ERROR_FLASH_READ:
479 case MS_STATUS_ERROR:
480 default:
481 goto exit;
484 idi = &((MemStickBootBlockCIS_IDI *)(PageBuffer +
485 (EntryOffset % MS_BYTES_PER_PAGE)))->idi.idi;
486 if (le16_to_cpu(idi->wIDIgeneralConfiguration) !=
487 MS_IDI_GENERAL_CONF)
488 goto exit;
490 us->MS_Lib.BytesPerSector =
491 le16_to_cpu(idi->wIDIbytesPerSector);
492 if (us->MS_Lib.BytesPerSector != MS_BYTES_PER_PAGE)
493 goto exit;
495 } /* End for .. */
497 result = 0;
499 exit:
500 if (result)
501 MS_LibFreeLogicalMap(us);
503 kfree(PageBuffer);
505 result = 0;
506 return result;
510 * MS_LibAllocLogicalMap()
512 int MS_LibAllocLogicalMap(struct us_data *us)
514 DWORD i;
517 us->MS_Lib.Phy2LogMap = kmalloc(us->MS_Lib.NumberOfPhyBlock *
518 sizeof(WORD), GFP_KERNEL);
519 us->MS_Lib.Log2PhyMap = kmalloc(us->MS_Lib.NumberOfLogBlock *
520 sizeof(WORD), GFP_KERNEL);
522 if ((us->MS_Lib.Phy2LogMap == NULL) ||
523 (us->MS_Lib.Log2PhyMap == NULL)) {
524 MS_LibFreeLogicalMap(us);
525 return (DWORD)-1;
528 for (i = 0; i < us->MS_Lib.NumberOfPhyBlock; i++)
529 us->MS_Lib.Phy2LogMap[i] = MS_LB_NOT_USED;
531 for (i = 0; i < us->MS_Lib.NumberOfLogBlock; i++)
532 us->MS_Lib.Log2PhyMap[i] = MS_LB_NOT_USED;
534 return 0;
538 * MS_LibSetBootBlockMark()
540 int MS_LibSetBootBlockMark(struct us_data *us, WORD phyblk)
542 return MS_LibSetLogicalBlockMark(us, phyblk, MS_LB_BOOT_BLOCK);
546 * MS_LibSetLogicalBlockMark()
548 int MS_LibSetLogicalBlockMark(struct us_data *us, WORD phyblk, WORD mark)
550 if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
551 return (DWORD)-1;
553 us->MS_Lib.Phy2LogMap[phyblk] = mark;
555 return 0;
559 * MS_LibSetInitialErrorBlock()
561 int MS_LibSetInitialErrorBlock(struct us_data *us, WORD phyblk)
563 return MS_LibSetLogicalBlockMark(us, phyblk, MS_LB_INITIAL_ERROR);
567 * MS_LibScanLogicalBlockNumber()
569 int MS_LibScanLogicalBlockNumber(struct us_data *us, WORD btBlk1st)
571 WORD PhyBlock, newblk, i;
572 WORD LogStart, LogEnde;
573 MS_LibTypeExtdat extdat;
574 BYTE buf[0x200];
575 DWORD count = 0, index = 0;
577 for (PhyBlock = 0; PhyBlock < us->MS_Lib.NumberOfPhyBlock;) {
578 MS_LibPhy2LogRange(PhyBlock, &LogStart, &LogEnde);
580 for (i = 0; i < MS_PHYSICAL_BLOCKS_PER_SEGMENT;
581 i++, PhyBlock++) {
582 switch (MS_LibConv2Logical(us, PhyBlock)) {
583 case MS_STATUS_ERROR:
584 continue;
585 default:
586 break;
589 if (count == PhyBlock) {
590 MS_LibReadExtraBlock(us, PhyBlock,
591 0, 0x80, &buf);
592 count += 0x80;
594 index = (PhyBlock % 0x80) * 4;
596 extdat.ovrflg = buf[index];
597 extdat.mngflg = buf[index+1];
598 extdat.logadr = MemStickLogAddr(buf[index+2],
599 buf[index+3]);
601 if ((extdat.ovrflg & MS_REG_OVR_BKST) !=
602 MS_REG_OVR_BKST_OK) {
603 MS_LibSetAcquiredErrorBlock(us, PhyBlock);
604 continue;
607 if ((extdat.mngflg & MS_REG_MNG_ATFLG) ==
608 MS_REG_MNG_ATFLG_ATTBL) {
609 MS_LibErasePhyBlock(us, PhyBlock);
610 continue;
613 if (extdat.logadr != MS_LB_NOT_USED) {
614 if ((extdat.logadr < LogStart) ||
615 (LogEnde <= extdat.logadr)) {
616 MS_LibErasePhyBlock(us, PhyBlock);
617 continue;
620 newblk = MS_LibConv2Physical(us, extdat.logadr);
622 if (newblk != MS_LB_NOT_USED) {
623 if (extdat.logadr == 0) {
624 MS_LibSetLogicalPair(us,
625 extdat.logadr,
626 PhyBlock);
627 if (MS_LibCheckDisableBlock(us,
628 btBlk1st)) {
629 MS_LibSetLogicalPair(us,
630 extdat.logadr, newblk);
631 continue;
635 MS_LibReadExtra(us, newblk, 0, &extdat);
636 if ((extdat.ovrflg & MS_REG_OVR_UDST) ==
637 MS_REG_OVR_UDST_UPDATING) {
638 MS_LibErasePhyBlock(us,
639 PhyBlock);
640 continue;
641 } else {
642 MS_LibErasePhyBlock(us, newblk);
646 MS_LibSetLogicalPair(us, extdat.logadr,
647 PhyBlock);
650 } /* End for ... */
652 return MS_STATUS_SUCCESS;
656 * MS_LibAllocWriteBuf()
658 int MS_LibAllocWriteBuf(struct us_data *us)
660 us->MS_Lib.wrtblk = (WORD)-1;
662 us->MS_Lib.blkpag = kmalloc(us->MS_Lib.PagesPerBlock *
663 us->MS_Lib.BytesPerSector, GFP_KERNEL);
664 us->MS_Lib.blkext = kmalloc(us->MS_Lib.PagesPerBlock *
665 sizeof(MS_LibTypeExtdat), GFP_KERNEL);
667 if ((us->MS_Lib.blkpag == NULL) || (us->MS_Lib.blkext == NULL)) {
668 MS_LibFreeWriteBuf(us);
669 return (DWORD)-1;
672 MS_LibClearWriteBuf(us);
674 return 0;
678 * MS_LibClearWriteBuf()
680 void MS_LibClearWriteBuf(struct us_data *us)
682 int i;
684 us->MS_Lib.wrtblk = (WORD)-1;
685 MS_LibClearPageMap(us);
687 if (us->MS_Lib.blkpag)
688 memset(us->MS_Lib.blkpag, 0xff,
689 us->MS_Lib.PagesPerBlock * us->MS_Lib.BytesPerSector);
691 if (us->MS_Lib.blkext) {
692 for (i = 0; i < us->MS_Lib.PagesPerBlock; i++) {
693 us->MS_Lib.blkext[i].status1 = MS_REG_ST1_DEFAULT;
694 us->MS_Lib.blkext[i].ovrflg = MS_REG_OVR_DEFAULT;
695 us->MS_Lib.blkext[i].mngflg = MS_REG_MNG_DEFAULT;
696 us->MS_Lib.blkext[i].logadr = MS_LB_NOT_USED;
702 * MS_LibPhy2LogRange()
704 void MS_LibPhy2LogRange(WORD PhyBlock, WORD *LogStart, WORD *LogEnde)
706 PhyBlock /= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
708 if (PhyBlock) {
709 *LogStart = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT +
710 (PhyBlock - 1) * MS_LOGICAL_BLOCKS_PER_SEGMENT;/*496*/
711 *LogEnde = *LogStart + MS_LOGICAL_BLOCKS_PER_SEGMENT;/*496*/
712 } else {
713 *LogStart = 0;
714 *LogEnde = MS_LOGICAL_BLOCKS_IN_1ST_SEGMENT;/*494*/
719 * MS_LibReadExtraBlock()
721 int MS_LibReadExtraBlock(struct us_data *us, DWORD PhyBlock,
722 BYTE PageNum, BYTE blen, void *buf)
724 struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
725 int result;
727 /* printk("MS_LibReadExtraBlock --- PhyBlock = %x,
728 PageNum = %x, blen = %x\n", PhyBlock, PageNum, blen); */
730 /* Read Extra Data */
731 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
732 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
733 bcb->DataTransferLength = 0x4 * blen;
734 bcb->Flags = 0x80;
735 bcb->CDB[0] = 0xF1;
736 bcb->CDB[1] = 0x03;
737 bcb->CDB[5] = (BYTE)(PageNum);
738 bcb->CDB[4] = (BYTE)(PhyBlock);
739 bcb->CDB[3] = (BYTE)(PhyBlock>>8);
740 bcb->CDB[2] = (BYTE)(PhyBlock>>16);
741 bcb->CDB[6] = blen;
743 result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
744 if (result != USB_STOR_XFER_GOOD)
745 return USB_STOR_TRANSPORT_ERROR;
747 return USB_STOR_TRANSPORT_GOOD;
751 * MS_LibReadExtra()
753 int MS_LibReadExtra(struct us_data *us, DWORD PhyBlock,
754 BYTE PageNum, MS_LibTypeExtdat *ExtraDat)
756 struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
757 int result;
758 BYTE ExtBuf[4];
760 /* printk("MS_LibReadExtra --- PhyBlock = %x, PageNum = %x\n"
761 , PhyBlock, PageNum); */
762 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
763 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
764 bcb->DataTransferLength = 0x4;
765 bcb->Flags = 0x80;
766 bcb->CDB[0] = 0xF1;
767 bcb->CDB[1] = 0x03;
768 bcb->CDB[5] = (BYTE)(PageNum);
769 bcb->CDB[4] = (BYTE)(PhyBlock);
770 bcb->CDB[3] = (BYTE)(PhyBlock>>8);
771 bcb->CDB[2] = (BYTE)(PhyBlock>>16);
772 bcb->CDB[6] = 0x01;
774 result = ENE_SendScsiCmd(us, FDIR_READ, &ExtBuf, 0);
775 if (result != USB_STOR_XFER_GOOD)
776 return USB_STOR_TRANSPORT_ERROR;
778 ExtraDat->reserved = 0;
779 ExtraDat->intr = 0x80; /* Not yet, waiting for fireware support */
780 ExtraDat->status0 = 0x10; /* Not yet, waiting for fireware support */
781 ExtraDat->status1 = 0x00; /* Not yet, waiting for fireware support */
782 ExtraDat->ovrflg = ExtBuf[0];
783 ExtraDat->mngflg = ExtBuf[1];
784 ExtraDat->logadr = MemStickLogAddr(ExtBuf[2], ExtBuf[3]);
786 return USB_STOR_TRANSPORT_GOOD;
790 * MS_LibSetAcquiredErrorBlock()
792 int MS_LibSetAcquiredErrorBlock(struct us_data *us, WORD phyblk)
794 WORD log;
796 if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
797 return (DWORD)-1;
799 log = us->MS_Lib.Phy2LogMap[phyblk];
801 if (log < us->MS_Lib.NumberOfLogBlock)
802 us->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED;
804 if (us->MS_Lib.Phy2LogMap[phyblk] != MS_LB_INITIAL_ERROR)
805 us->MS_Lib.Phy2LogMap[phyblk] = MS_LB_ACQUIRED_ERROR;
807 return 0;
811 * MS_LibErasePhyBlock()
813 int MS_LibErasePhyBlock(struct us_data *us, WORD phyblk)
815 WORD log;
817 if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
818 return MS_STATUS_ERROR;
820 log = us->MS_Lib.Phy2LogMap[phyblk];
822 if (log < us->MS_Lib.NumberOfLogBlock)
823 us->MS_Lib.Log2PhyMap[log] = MS_LB_NOT_USED;
825 us->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED;
827 if (MS_LibIsWritable(us)) {
828 switch (MS_ReaderEraseBlock(us, phyblk)) {
829 case MS_STATUS_SUCCESS:
830 us->MS_Lib.Phy2LogMap[phyblk] = MS_LB_NOT_USED_ERASED;
831 return MS_STATUS_SUCCESS;
832 case MS_ERROR_FLASH_ERASE:
833 case MS_STATUS_INT_ERROR:
834 MS_LibErrorPhyBlock(us, phyblk);
835 return MS_ERROR_FLASH_ERASE;
836 case MS_STATUS_ERROR:
837 default:
838 MS_LibCtrlSet(us, MS_LIB_CTRL_RDONLY);
839 MS_LibSetAcquiredErrorBlock(us, phyblk);
840 return MS_STATUS_ERROR;
844 MS_LibSetAcquiredErrorBlock(us, phyblk);
846 return MS_STATUS_SUCCESS;
850 * MS_LibErrorPhyBlock()
852 int MS_LibErrorPhyBlock(struct us_data *us, WORD phyblk)
854 if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
855 return MS_STATUS_ERROR;
857 MS_LibSetAcquiredErrorBlock(us, phyblk);
859 if (MS_LibIsWritable(us))
860 return MS_LibOverwriteExtra(us, phyblk, 0,
861 (BYTE)(~MS_REG_OVR_BKST & BYTE_MASK));
864 return MS_STATUS_SUCCESS;
868 * MS_LibOverwriteExtra()
870 int MS_LibOverwriteExtra(struct us_data *us, DWORD PhyBlockAddr,
871 BYTE PageNum, BYTE OverwriteFlag)
873 struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
874 int result;
876 /* printk("MS --- MS_LibOverwriteExtra, \
877 PhyBlockAddr = %x, PageNum = %x\n", PhyBlockAddr, PageNum); */
878 result = ENE_LoadBinCode(us, MS_RW_PATTERN);
879 if (result != USB_STOR_XFER_GOOD)
880 return USB_STOR_TRANSPORT_ERROR;
882 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
883 bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
884 bcb->DataTransferLength = 0x4;
885 bcb->Flags = 0x80;
886 bcb->CDB[0] = 0xF2;
887 bcb->CDB[1] = 0x05;
888 bcb->CDB[5] = (BYTE)(PageNum);
889 bcb->CDB[4] = (BYTE)(PhyBlockAddr);
890 bcb->CDB[3] = (BYTE)(PhyBlockAddr>>8);
891 bcb->CDB[2] = (BYTE)(PhyBlockAddr>>16);
892 bcb->CDB[6] = OverwriteFlag;
893 bcb->CDB[7] = 0xFF;
894 bcb->CDB[8] = 0xFF;
895 bcb->CDB[9] = 0xFF;
897 result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
898 if (result != USB_STOR_XFER_GOOD)
899 return USB_STOR_TRANSPORT_ERROR;
901 return USB_STOR_TRANSPORT_GOOD;
905 * MS_LibForceSetLogicalPair()
907 int MS_LibForceSetLogicalPair(struct us_data *us, WORD logblk, WORD phyblk)
909 if (logblk == MS_LB_NOT_USED)
910 return 0;
912 if ((logblk >= us->MS_Lib.NumberOfLogBlock) ||
913 (phyblk >= us->MS_Lib.NumberOfPhyBlock))
914 return (DWORD)-1;
916 us->MS_Lib.Phy2LogMap[phyblk] = logblk;
917 us->MS_Lib.Log2PhyMap[logblk] = phyblk;
919 return 0;
923 * MS_LibSetLogicalPair()
925 int MS_LibSetLogicalPair(struct us_data *us, WORD logblk, WORD phyblk)
927 if ((logblk >= us->MS_Lib.NumberOfLogBlock) ||
928 (phyblk >= us->MS_Lib.NumberOfPhyBlock))
929 return (DWORD)-1;
931 us->MS_Lib.Phy2LogMap[phyblk] = logblk;
932 us->MS_Lib.Log2PhyMap[logblk] = phyblk;
934 return 0;
938 * MS_CountFreeBlock()
940 int MS_CountFreeBlock(struct us_data *us, WORD PhyBlock)
942 DWORD Ende, Count;
944 Ende = PhyBlock + MS_PHYSICAL_BLOCKS_PER_SEGMENT;
945 for (Count = 0; PhyBlock < Ende; PhyBlock++) {
946 switch (us->MS_Lib.Phy2LogMap[PhyBlock]) {
947 case MS_LB_NOT_USED:
948 case MS_LB_NOT_USED_ERASED:
949 Count++;
950 default:
951 break;
955 return Count;
959 * MS_LibSearchBlockFromPhysical()
961 int MS_LibSearchBlockFromPhysical(struct us_data *us, WORD phyblk)
963 WORD Newblk;
964 WORD blk;
965 MS_LibTypeExtdat extdat;
967 if (phyblk >= us->MS_Lib.NumberOfPhyBlock)
968 return MS_LB_ERROR;
970 for (blk = phyblk + 1; blk != phyblk; blk++) {
971 if ((blk & MS_PHYSICAL_BLOCKS_PER_SEGMENT_MASK) == 0)
972 blk -= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
974 Newblk = us->MS_Lib.Phy2LogMap[blk];
975 if (us->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED_ERASED)
976 return blk;
977 else if (us->MS_Lib.Phy2LogMap[blk] == MS_LB_NOT_USED) {
978 switch (MS_LibReadExtra(us, blk, 0, &extdat)) {
979 case MS_STATUS_SUCCESS:
980 case MS_STATUS_SUCCESS_WITH_ECC:
981 break;
982 case MS_NOCARD_ERROR:
983 return MS_NOCARD_ERROR;
984 case MS_STATUS_INT_ERROR:
985 return MS_LB_ERROR;
986 case MS_ERROR_FLASH_READ:
987 default:
988 MS_LibSetAcquiredErrorBlock(us, blk);
989 /* MS_LibErrorPhyBlock(fdoExt, blk); */
990 continue;
991 } /* End switch */
993 if ((extdat.ovrflg & MS_REG_OVR_BKST) !=
994 MS_REG_OVR_BKST_OK) {
995 MS_LibSetAcquiredErrorBlock(us, blk);
996 continue;
999 switch (MS_LibErasePhyBlock(us, blk)) {
1000 case MS_STATUS_SUCCESS:
1001 return blk;
1002 case MS_STATUS_ERROR:
1003 return MS_LB_ERROR;
1004 case MS_ERROR_FLASH_ERASE:
1005 default:
1006 MS_LibErrorPhyBlock(us, blk);
1007 break;
1010 } /* End for */
1012 return MS_LB_ERROR;
1016 * MS_LibSearchBlockFromLogical()
1018 int MS_LibSearchBlockFromLogical(struct us_data *us, WORD logblk)
1020 WORD phyblk;
1022 phyblk = MS_LibConv2Physical(us, logblk);
1023 if (phyblk >= MS_LB_ERROR) {
1024 if (logblk >= us->MS_Lib.NumberOfLogBlock)
1025 return MS_LB_ERROR;
1027 phyblk = (logblk + MS_NUMBER_OF_BOOT_BLOCK) /
1028 MS_LOGICAL_BLOCKS_PER_SEGMENT;
1029 phyblk *= MS_PHYSICAL_BLOCKS_PER_SEGMENT;
1030 phyblk += MS_PHYSICAL_BLOCKS_PER_SEGMENT - 1;
1033 return MS_LibSearchBlockFromPhysical(us, phyblk);