1 #include <linux/slab.h>
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);
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 *);
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 *);
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 *);
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);
46 int MarkFail_D_PhyOneBlock(struct us_data *);
50 static BYTE WorkBuf[SECTSIZE];
51 static BYTE Redundant[REDTSIZE];
52 static BYTE WorkRedund[REDTSIZE];
53 /* 128 x 1000, Log2Phy[MAX_ZONENUM][MAX_LOGBLOCK]; */
54 static WORD *Log2Phy[MAX_ZONENUM];
55 static BYTE Assign[MAX_ZONENUM][MAX_BLOCKNUM / 8];
56 static WORD AssignStart[MAX_ZONENUM];
60 static DWORD SectCopyMode;
62 /* BIT Control Macro */
63 static BYTE BitData[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
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])
68 BYTE IsSSFDCCompliance;
72 /* ----- SM_FreeMem() ------------------------------------------------- */
77 pr_info("SM_FreeMem start\n");
78 for (i = 0; i < MAX_ZONENUM; i++) {
79 if (Log2Phy[i] != NULL) {
80 pr_info("Free Zone = %x, Addr = %p\n", i, Log2Phy[i]);
88 /* SmartMedia Read/Write/Erase Function */
89 /* ----- Media_D_ReadSector() ------------------------------------------- */
90 int Media_D_ReadSector(struct us_data *us, DWORD start, WORD count, BYTE *buf)
94 if (Conv_D_MediaAddr(us, start))
98 len = Ssfdc.MaxSectors - Media.Sector;
104 if (Media_D_ReadOneSect(us, bn, buf)) {
105 ErrCode = ERR_EccReadErr;
115 buf += bn * SECTSIZE;
117 if (Inc_D_MediaAddr(us))
124 /* ----- Media_D_CopySector() ------------------------------------------ */
125 int Media_D_CopySector(struct us_data *us, DWORD start, WORD count, BYTE *buf)
129 /* pr_info("Media_D_CopySector !!!\n"); */
130 if (Conv_D_MediaAddr(us, start))
134 if (Assign_D_WriteBlock())
137 len = Ssfdc.MaxSectors - Media.Sector;
143 if (Ssfdc_D_CopyBlock(us, bn, buf, Redundant)) {
144 ErrCode = ERR_WriteFault;
149 if (Release_D_CopySector(us)) {
150 if (ErrCode == ERR_HwError) {
151 ErrCode = ERR_WriteFault;
160 buf += bn * SECTSIZE;
162 if (Inc_D_MediaAddr(us))
169 /* ----- Release_D_CopySector() ------------------------------------------ */
170 int Release_D_CopySector(struct us_data *us)
172 Log2Phy[Media.Zone][Media.LogBlock] = WriteBlock;
173 Media.PhyBlock = ReadBlock;
175 if (Media.PhyBlock == NO_ASSIGN) {
176 Media.PhyBlock = WriteBlock;
180 Clr_D_Bit(Assign[Media.Zone], Media.PhyBlock);
181 Media.PhyBlock = WriteBlock;
186 /* SmartMedia Physical Format Test Subroutine */
187 /* ----- Check_D_MediaFmt() --------------------------------------------- */
188 int Check_D_MediaFmt(struct us_data *us)
190 pr_info("Check_D_MediaFmt\n");
196 SectCopyMode = COMPLETED;
198 if (Set_D_PhyFmtValue(us)) {
199 ErrCode = ERR_UnknownMedia;
203 if (Search_D_CIS(us)) {
204 ErrCode = ERR_IllegalFmt;
208 MediaChange = SMSUCCESS;
212 /* SmartMedia Physical Address Control Subroutine */
213 /* ----- Conv_D_MediaAddr() --------------------------------------------- */
214 int Conv_D_MediaAddr(struct us_data *us, DWORD addr)
218 temp = addr / Ssfdc.MaxSectors;
219 Media.Zone = (BYTE) (temp / Ssfdc.MaxLogBlocks);
221 if (Log2Phy[Media.Zone] == NULL) {
222 if (Make_D_LogTable(us)) {
223 ErrCode = ERR_IllegalFmt;
228 Media.Sector = (BYTE) (addr % Ssfdc.MaxSectors);
229 Media.LogBlock = (WORD) (temp % Ssfdc.MaxLogBlocks);
231 if (Media.Zone < Ssfdc.MaxZones) {
232 Clr_D_RedundantData(Redundant);
233 Set_D_LogBlockAddr(Redundant);
234 Media.PhyBlock = Log2Phy[Media.Zone][Media.LogBlock];
238 ErrCode = ERR_OutOfLBA;
242 /* ----- Inc_D_MediaAddr() ---------------------------------------------- */
243 int Inc_D_MediaAddr(struct us_data *us)
245 WORD LogBlock = Media.LogBlock;
247 if (++Media.Sector < Ssfdc.MaxSectors)
250 if (Log2Phy[Media.Zone] == NULL) {
251 if (Make_D_LogTable(us)) {
252 ErrCode = ERR_IllegalFmt;
258 Media.LogBlock = LogBlock;
260 if (++Media.LogBlock < Ssfdc.MaxLogBlocks) {
261 Clr_D_RedundantData(Redundant);
262 Set_D_LogBlockAddr(Redundant);
263 Media.PhyBlock = Log2Phy[Media.Zone][Media.LogBlock];
269 if (++Media.Zone < Ssfdc.MaxZones) {
270 if (Log2Phy[Media.Zone] == NULL) {
271 if (Make_D_LogTable(us)) {
272 ErrCode = ERR_IllegalFmt;
279 Clr_D_RedundantData(Redundant);
280 Set_D_LogBlockAddr(Redundant);
281 Media.PhyBlock = Log2Phy[Media.Zone][Media.LogBlock];
286 ErrCode = ERR_OutOfLBA;
291 /* SmartMedia Read/Write Subroutine with Retry */
292 /* ----- Media_D_ReadOneSect() ------------------------------------------ */
293 int Media_D_ReadOneSect(struct us_data *us, WORD count, BYTE *buf)
297 if (!Read_D_PhyOneSect(us, count, buf))
299 if (ErrCode == ERR_HwError)
301 if (ErrCode == ERR_DataStatus)
304 #ifdef RDERR_REASSIGN
305 if (Ssfdc.Attribute & MWP) {
306 if (ErrCode == ERR_CorReadErr)
312 for (retry = 0; retry < 2; retry++) {
313 if (Copy_D_BlockAll(us,
314 (err == ERR_EccReadErr) ? REQ_FAIL : REQ_ERASE)) {
315 if (ErrCode == ERR_HwError)
321 if (ErrCode == ERR_CorReadErr)
328 if (ErrCode == ERR_CorReadErr)
335 /* SmartMedia Physical Sector Data Copy Subroutine */
336 /* ----- Copy_D_BlockAll() ---------------------------------------------- */
337 int Copy_D_BlockAll(struct us_data *us, DWORD mode)
343 if (Assign_D_WriteBlock())
345 if (mode == REQ_FAIL)
346 SectCopyMode = REQ_FAIL;
348 for (Media.Sector = 0; Media.Sector < Ssfdc.MaxSectors;
350 if (Copy_D_PhyOneSect(us)) {
351 if (ErrCode == ERR_HwError)
353 if (Release_D_WriteBlock(us))
356 ErrCode = ERR_WriteFault;
357 Media.PhyBlock = ReadBlock;
364 if (Release_D_ReadBlock(us))
367 Media.PhyBlock = WriteBlock;
372 /* SmartMedia Physical Block Assign/Release Subroutine */
373 /* ----- Assign_D_WriteBlock() ------------------------------------------ */
374 int Assign_D_WriteBlock(void)
376 ReadBlock = Media.PhyBlock;
378 for (WriteBlock = AssignStart[Media.Zone];
379 WriteBlock < Ssfdc.MaxBlocks; WriteBlock++) {
380 if (!Chk_D_Bit(Assign[Media.Zone], WriteBlock)) {
381 Set_D_Bit(Assign[Media.Zone], WriteBlock);
382 AssignStart[Media.Zone] = WriteBlock + 1;
383 Media.PhyBlock = WriteBlock;
384 SectCopyMode = REQ_ERASE;
390 WriteBlock < AssignStart[Media.Zone]; WriteBlock++) {
391 if (!Chk_D_Bit(Assign[Media.Zone], WriteBlock)) {
392 Set_D_Bit(Assign[Media.Zone], WriteBlock);
393 AssignStart[Media.Zone] = WriteBlock + 1;
394 Media.PhyBlock = WriteBlock;
395 SectCopyMode = REQ_ERASE;
400 WriteBlock = NO_ASSIGN;
401 ErrCode = ERR_WriteFault;
406 /* ----- Release_D_ReadBlock() ------------------------------------------ */
407 int Release_D_ReadBlock(struct us_data *us)
412 SectCopyMode = COMPLETED;
414 if (mode == COMPLETED)
417 Log2Phy[Media.Zone][Media.LogBlock] = WriteBlock;
418 Media.PhyBlock = ReadBlock;
420 if (Media.PhyBlock == NO_ASSIGN) {
421 Media.PhyBlock = WriteBlock;
425 if (mode == REQ_ERASE) {
426 if (Erase_D_PhyOneBlock(us)) {
427 if (ErrCode == ERR_HwError)
429 if (MarkFail_D_PhyOneBlock(us))
432 Clr_D_Bit(Assign[Media.Zone], Media.PhyBlock);
433 } else if (MarkFail_D_PhyOneBlock(us))
436 Media.PhyBlock = WriteBlock;
440 /* ----- Release_D_WriteBlock() ----------------------------------------- */
441 int Release_D_WriteBlock(struct us_data *us)
443 SectCopyMode = COMPLETED;
444 Media.PhyBlock = WriteBlock;
446 if (MarkFail_D_PhyOneBlock(us))
449 Media.PhyBlock = ReadBlock;
453 /* SmartMedia Physical Sector Data Copy Subroutine */
454 /* ----- Copy_D_PhyOneSect() -------------------------------------------- */
455 int Copy_D_PhyOneSect(struct us_data *us)
460 /* pr_info("Copy_D_PhyOneSect --- Secotr = %x\n", Media.Sector); */
461 if (ReadBlock != NO_ASSIGN) {
462 Media.PhyBlock = ReadBlock;
463 for (retry = 0; retry < 2; retry++) {
466 if (Ssfdc_D_ReadCisSect(us, WorkBuf,
468 ErrCode = ERR_HwError;
473 if (Check_D_CISdata(WorkBuf, WorkRedund)) {
474 ErrCode = ERR_HwError;
480 if (Ssfdc_D_ReadSect(us, WorkBuf, WorkRedund)) {
481 ErrCode = ERR_HwError;
485 if (Check_D_DataStatus(WorkRedund)) {
489 if (!Check_D_ReadError(WorkRedund)) {
493 if (!Check_D_Correct(WorkBuf, WorkRedund)) {
499 SectCopyMode = REQ_FAIL;
503 for (i = 0; i < SECTSIZE; i++)
504 WorkBuf[i] = DUMMY_DATA;
505 Clr_D_RedundantData(WorkRedund);
508 Set_D_LogBlockAddr(WorkRedund);
510 Set_D_RightECC(WorkRedund);
511 Set_D_DataStaus(WorkRedund);
514 Media.PhyBlock = WriteBlock;
516 if (Ssfdc_D_WriteSectForCopy(us, WorkBuf, WorkRedund)) {
517 ErrCode = ERR_HwError;
521 if (Ssfdc_D_CheckStatus()) {
522 ErrCode = ERR_WriteFault;
526 Media.PhyBlock = ReadBlock;
530 /* SmartMedia Physical Sector Read/Write/Erase Subroutine */
531 /* ----- Read_D_PhyOneSect() -------------------------------------------- */
532 int Read_D_PhyOneSect(struct us_data *us, WORD count, BYTE *buf)
537 if (Media.PhyBlock == NO_ASSIGN) {
538 for (i = 0; i < SECTSIZE; i++)
543 for (retry = 0; retry < 2; retry++) {
547 if (Ssfdc_D_ReadCisSect(us, WorkBuf, WorkRedund)) {
548 ErrCode = ERR_HwError;
552 if (Check_D_CISdata(WorkBuf, WorkRedund)) {
553 ErrCode = ERR_HwError;
559 if (Ssfdc_D_ReadBlock(us, count, buf, Redundant)) {
560 ErrCode = ERR_HwError;
564 if (Check_D_DataStatus(Redundant)) {
565 ErrCode = ERR_DataStatus;
569 if (!Check_D_ReadError(Redundant))
572 if (!Check_D_Correct(buf, Redundant)) {
573 ErrCode = ERR_CorReadErr;
578 ErrCode = ERR_EccReadErr;
582 /* ----- Erase_D_PhyOneBlock() ------------------------------------------ */
583 int Erase_D_PhyOneBlock(struct us_data *us)
585 if (Ssfdc_D_EraseBlock(us)) {
586 ErrCode = ERR_HwError;
590 if (Ssfdc_D_CheckStatus()) {
591 ErrCode = ERR_WriteFault;
598 /* SmartMedia Physical Format Check Local Subroutine */
599 /* ----- Set_D_PhyFmtValue() -------------------------------------------- */
600 int Set_D_PhyFmtValue(struct us_data *us)
602 if (Set_D_SsfdcModel(us->SM_DeviceID))
608 /* ----- Search_D_CIS() ------------------------------------------------- */
609 int Search_D_CIS(struct us_data *us)
614 for (Media.PhyBlock = 0;
615 Media.PhyBlock < (Ssfdc.MaxBlocks - Ssfdc.MaxLogBlocks - 1);
617 if (Ssfdc_D_ReadRedtData(us, Redundant)) {
622 if (!Check_D_FailBlock(Redundant))
626 if (Media.PhyBlock == (Ssfdc.MaxBlocks - Ssfdc.MaxLogBlocks - 1)) {
631 while (Media.Sector < CIS_SEARCH_SECT) {
633 if (Ssfdc_D_ReadRedtData(us, Redundant)) {
638 if (!Check_D_DataStatus(Redundant)) {
639 if (Ssfdc_D_ReadSect(us, WorkBuf, Redundant)) {
644 if (Check_D_CISdata(WorkBuf, Redundant)) {
649 CisArea.PhyBlock = Media.PhyBlock;
650 CisArea.Sector = Media.Sector;
662 /* ----- Make_D_LogTable() ---------------------------------------------- */
663 int Make_D_LogTable(struct us_data *us)
665 WORD phyblock, logblock;
667 if (Log2Phy[Media.Zone] == NULL) {
668 Log2Phy[Media.Zone] = kmalloc(MAX_LOGBLOCK * sizeof(WORD),
670 /* pr_info("ExAllocatePool Zone = %x, Addr = %x\n",
671 Media.Zone, Log2Phy[Media.Zone]); */
672 if (Log2Phy[Media.Zone] == NULL)
678 /* pr_info("Make_D_LogTable --- MediaZone = 0x%x\n",
680 for (Media.LogBlock = 0; Media.LogBlock < Ssfdc.MaxLogBlocks;
682 Log2Phy[Media.Zone][Media.LogBlock] = NO_ASSIGN;
684 for (Media.PhyBlock = 0; Media.PhyBlock < (MAX_BLOCKNUM / 8);
686 Assign[Media.Zone][Media.PhyBlock] = 0x00;
688 for (Media.PhyBlock = 0; Media.PhyBlock < Ssfdc.MaxBlocks;
690 if ((!Media.Zone) && (Media.PhyBlock <= CisArea.PhyBlock)) {
691 Set_D_Bit(Assign[Media.Zone], Media.PhyBlock);
695 if (Ssfdc_D_ReadRedtData(us, Redundant)) {
700 if (!Check_D_DataBlank(Redundant))
703 Set_D_Bit(Assign[Media.Zone], Media.PhyBlock);
705 if (Check_D_FailBlock(Redundant))
708 if (Load_D_LogBlockAddr(Redundant))
711 if (Media.LogBlock >= Ssfdc.MaxLogBlocks)
714 if (Log2Phy[Media.Zone][Media.LogBlock] == NO_ASSIGN) {
715 Log2Phy[Media.Zone][Media.LogBlock] = Media.PhyBlock;
719 phyblock = Media.PhyBlock;
720 logblock = Media.LogBlock;
721 Media.Sector = (BYTE)(Ssfdc.MaxSectors - 1);
723 if (Ssfdc_D_ReadRedtData(us, Redundant)) {
728 if (!Load_D_LogBlockAddr(Redundant) &&
729 (Media.LogBlock == logblock)) {
730 Media.PhyBlock = Log2Phy[Media.Zone][logblock];
732 if (Ssfdc_D_ReadRedtData(us, Redundant)) {
737 Media.PhyBlock = phyblock;
739 if (!Load_D_LogBlockAddr(Redundant)) {
740 if (Media.LogBlock != logblock) {
742 Log2Phy[Media.Zone][logblock];
743 Log2Phy[Media.Zone][logblock] =
747 Media.PhyBlock = Log2Phy[Media.Zone][logblock];
748 Log2Phy[Media.Zone][logblock] = phyblock;
753 Media.PhyBlock = phyblock;
755 AssignStart[Media.Zone] = 0;
757 } /* End for (Media.Zone<MAX_ZONENUM) */
763 /* ----- MarkFail_D_PhyOneBlock() --------------------------------------- */
764 int MarkFail_D_PhyOneBlock(struct us_data *us)
769 Set_D_FailBlock(WorkRedund);
771 for (Media.Sector = 0; Media.Sector < Ssfdc.MaxSectors;
773 if (Ssfdc_D_WriteRedtData(us, WorkRedund)) {
776 ErrCode = ERR_HwError;
779 } /* NO Status Check */