1 #include <linux/slab.h>
7 static int Conv_D_MediaAddr(struct us_data
*, DWORD
);
8 static int Inc_D_MediaAddr(struct us_data
*);
9 static int Media_D_ReadOneSect(struct us_data
*, WORD
, BYTE
*);
11 static int Copy_D_BlockAll(struct us_data
*, DWORD
);
13 static int Assign_D_WriteBlock(void);
14 static int Release_D_ReadBlock(struct us_data
*);
15 static int Release_D_WriteBlock(struct us_data
*);
16 static int Release_D_CopySector(struct us_data
*);
18 static int Copy_D_PhyOneSect(struct us_data
*);
19 static int Read_D_PhyOneSect(struct us_data
*, WORD
, BYTE
*);
20 static int Erase_D_PhyOneBlock(struct us_data
*);
22 static int Set_D_PhyFmtValue(struct us_data
*);
23 static int Search_D_CIS(struct us_data
*);
24 static int Make_D_LogTable(struct us_data
*);
26 static int MarkFail_D_PhyOneBlock(struct us_data
*);
29 static BYTE WorkBuf
[SECTSIZE
];
30 static BYTE Redundant
[REDTSIZE
];
31 static BYTE WorkRedund
[REDTSIZE
];
32 /* 128 x 1000, Log2Phy[MAX_ZONENUM][MAX_LOGBLOCK]; */
33 static WORD
*Log2Phy
[MAX_ZONENUM
];
34 static BYTE Assign
[MAX_ZONENUM
][MAX_BLOCKNUM
/ 8];
35 static WORD AssignStart
[MAX_ZONENUM
];
39 static DWORD SectCopyMode
;
41 /* BIT Control Macro */
42 static BYTE BitData
[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
43 #define Set_D_Bit(a, b) (a[(BYTE)((b) / 8)] |= BitData[(b) % 8])
44 #define Clr_D_Bit(a, b) (a[(BYTE)((b) / 8)] &= ~BitData[(b) % 8])
45 #define Chk_D_Bit(a, b) (a[(BYTE)((b) / 8)] & BitData[(b) % 8])
47 /* ----- SM_FreeMem() ------------------------------------------------- */
52 pr_info("SM_FreeMem start\n");
53 for (i
= 0; i
< MAX_ZONENUM
; i
++) {
54 if (Log2Phy
[i
] != NULL
) {
55 pr_info("Free Zone = %x, Addr = %p\n", i
, Log2Phy
[i
]);
63 /* SmartMedia Read/Write/Erase Function */
64 /* ----- Media_D_ReadSector() ------------------------------------------- */
65 int Media_D_ReadSector(struct us_data
*us
, DWORD start
, WORD count
, BYTE
*buf
)
69 if (Conv_D_MediaAddr(us
, start
))
73 len
= Ssfdc
.MaxSectors
- Media
.Sector
;
79 if (Media_D_ReadOneSect(us
, bn
, buf
)) {
80 ErrCode
= ERR_EccReadErr
;
92 if (Inc_D_MediaAddr(us
))
99 /* ----- Media_D_CopySector() ------------------------------------------ */
100 int Media_D_CopySector(struct us_data
*us
, DWORD start
, WORD count
, BYTE
*buf
)
104 /* pr_info("Media_D_CopySector !!!\n"); */
105 if (Conv_D_MediaAddr(us
, start
))
109 if (Assign_D_WriteBlock())
112 len
= Ssfdc
.MaxSectors
- Media
.Sector
;
118 if (Ssfdc_D_CopyBlock(us
, bn
, buf
, Redundant
)) {
119 ErrCode
= ERR_WriteFault
;
124 if (Release_D_CopySector(us
)) {
125 if (ErrCode
== ERR_HwError
) {
126 ErrCode
= ERR_WriteFault
;
135 buf
+= bn
* SECTSIZE
;
137 if (Inc_D_MediaAddr(us
))
144 /* ----- Release_D_CopySector() ------------------------------------------ */
145 static int Release_D_CopySector(struct us_data
*us
)
147 Log2Phy
[Media
.Zone
][Media
.LogBlock
] = WriteBlock
;
148 Media
.PhyBlock
= ReadBlock
;
150 if (Media
.PhyBlock
== NO_ASSIGN
) {
151 Media
.PhyBlock
= WriteBlock
;
155 Clr_D_Bit(Assign
[Media
.Zone
], Media
.PhyBlock
);
156 Media
.PhyBlock
= WriteBlock
;
161 /* SmartMedia Physical Format Test Subroutine */
162 /* ----- Check_D_MediaFmt() --------------------------------------------- */
163 int Check_D_MediaFmt(struct us_data
*us
)
165 pr_info("Check_D_MediaFmt\n");
171 SectCopyMode
= COMPLETED
;
173 if (Set_D_PhyFmtValue(us
)) {
174 ErrCode
= ERR_UnknownMedia
;
178 if (Search_D_CIS(us
)) {
179 ErrCode
= ERR_IllegalFmt
;
183 MediaChange
= SMSUCCESS
;
187 /* SmartMedia Physical Address Control Subroutine */
188 /* ----- Conv_D_MediaAddr() --------------------------------------------- */
189 static int Conv_D_MediaAddr(struct us_data
*us
, DWORD addr
)
193 temp
= addr
/ Ssfdc
.MaxSectors
;
194 Media
.Zone
= (BYTE
) (temp
/ Ssfdc
.MaxLogBlocks
);
196 if (Log2Phy
[Media
.Zone
] == NULL
) {
197 if (Make_D_LogTable(us
)) {
198 ErrCode
= ERR_IllegalFmt
;
203 Media
.Sector
= (BYTE
) (addr
% Ssfdc
.MaxSectors
);
204 Media
.LogBlock
= (WORD
) (temp
% Ssfdc
.MaxLogBlocks
);
206 if (Media
.Zone
< Ssfdc
.MaxZones
) {
207 Clr_D_RedundantData(Redundant
);
208 Set_D_LogBlockAddr(Redundant
);
209 Media
.PhyBlock
= Log2Phy
[Media
.Zone
][Media
.LogBlock
];
213 ErrCode
= ERR_OutOfLBA
;
217 /* ----- Inc_D_MediaAddr() ---------------------------------------------- */
218 static int Inc_D_MediaAddr(struct us_data
*us
)
220 WORD LogBlock
= Media
.LogBlock
;
222 if (++Media
.Sector
< Ssfdc
.MaxSectors
)
225 if (Log2Phy
[Media
.Zone
] == NULL
) {
226 if (Make_D_LogTable(us
)) {
227 ErrCode
= ERR_IllegalFmt
;
233 Media
.LogBlock
= LogBlock
;
235 if (++Media
.LogBlock
< Ssfdc
.MaxLogBlocks
) {
236 Clr_D_RedundantData(Redundant
);
237 Set_D_LogBlockAddr(Redundant
);
238 Media
.PhyBlock
= Log2Phy
[Media
.Zone
][Media
.LogBlock
];
244 if (++Media
.Zone
< Ssfdc
.MaxZones
) {
245 if (Log2Phy
[Media
.Zone
] == NULL
) {
246 if (Make_D_LogTable(us
)) {
247 ErrCode
= ERR_IllegalFmt
;
254 Clr_D_RedundantData(Redundant
);
255 Set_D_LogBlockAddr(Redundant
);
256 Media
.PhyBlock
= Log2Phy
[Media
.Zone
][Media
.LogBlock
];
261 ErrCode
= ERR_OutOfLBA
;
266 /* SmartMedia Read/Write Subroutine with Retry */
267 /* ----- Media_D_ReadOneSect() ------------------------------------------ */
268 static int Media_D_ReadOneSect(struct us_data
*us
, WORD count
, BYTE
*buf
)
272 if (!Read_D_PhyOneSect(us
, count
, buf
))
274 if (ErrCode
== ERR_HwError
)
276 if (ErrCode
== ERR_DataStatus
)
279 #ifdef RDERR_REASSIGN
280 if (Ssfdc
.Attribute
& MWP
) {
281 if (ErrCode
== ERR_CorReadErr
)
287 for (retry
= 0; retry
< 2; retry
++) {
288 if (Copy_D_BlockAll(us
,
289 (err
== ERR_EccReadErr
) ? REQ_FAIL
: REQ_ERASE
)) {
290 if (ErrCode
== ERR_HwError
)
296 if (ErrCode
== ERR_CorReadErr
)
303 if (ErrCode
== ERR_CorReadErr
)
310 /* SmartMedia Physical Sector Data Copy Subroutine */
311 /* ----- Copy_D_BlockAll() ---------------------------------------------- */
312 static int Copy_D_BlockAll(struct us_data
*us
, DWORD mode
)
318 if (Assign_D_WriteBlock())
320 if (mode
== REQ_FAIL
)
321 SectCopyMode
= REQ_FAIL
;
323 for (Media
.Sector
= 0; Media
.Sector
< Ssfdc
.MaxSectors
;
325 if (Copy_D_PhyOneSect(us
)) {
326 if (ErrCode
== ERR_HwError
)
328 if (Release_D_WriteBlock(us
))
331 ErrCode
= ERR_WriteFault
;
332 Media
.PhyBlock
= ReadBlock
;
339 if (Release_D_ReadBlock(us
))
342 Media
.PhyBlock
= WriteBlock
;
347 /* SmartMedia Physical Block Assign/Release Subroutine */
348 /* ----- Assign_D_WriteBlock() ------------------------------------------ */
349 static int Assign_D_WriteBlock(void)
351 ReadBlock
= Media
.PhyBlock
;
353 for (WriteBlock
= AssignStart
[Media
.Zone
];
354 WriteBlock
< Ssfdc
.MaxBlocks
; WriteBlock
++) {
355 if (!Chk_D_Bit(Assign
[Media
.Zone
], WriteBlock
)) {
356 Set_D_Bit(Assign
[Media
.Zone
], WriteBlock
);
357 AssignStart
[Media
.Zone
] = WriteBlock
+ 1;
358 Media
.PhyBlock
= WriteBlock
;
359 SectCopyMode
= REQ_ERASE
;
365 WriteBlock
< AssignStart
[Media
.Zone
]; WriteBlock
++) {
366 if (!Chk_D_Bit(Assign
[Media
.Zone
], WriteBlock
)) {
367 Set_D_Bit(Assign
[Media
.Zone
], WriteBlock
);
368 AssignStart
[Media
.Zone
] = WriteBlock
+ 1;
369 Media
.PhyBlock
= WriteBlock
;
370 SectCopyMode
= REQ_ERASE
;
375 WriteBlock
= NO_ASSIGN
;
376 ErrCode
= ERR_WriteFault
;
381 /* ----- Release_D_ReadBlock() ------------------------------------------ */
382 static int Release_D_ReadBlock(struct us_data
*us
)
387 SectCopyMode
= COMPLETED
;
389 if (mode
== COMPLETED
)
392 Log2Phy
[Media
.Zone
][Media
.LogBlock
] = WriteBlock
;
393 Media
.PhyBlock
= ReadBlock
;
395 if (Media
.PhyBlock
== NO_ASSIGN
) {
396 Media
.PhyBlock
= WriteBlock
;
400 if (mode
== REQ_ERASE
) {
401 if (Erase_D_PhyOneBlock(us
)) {
402 if (ErrCode
== ERR_HwError
)
404 if (MarkFail_D_PhyOneBlock(us
))
407 Clr_D_Bit(Assign
[Media
.Zone
], Media
.PhyBlock
);
408 } else if (MarkFail_D_PhyOneBlock(us
))
411 Media
.PhyBlock
= WriteBlock
;
415 /* ----- Release_D_WriteBlock() ----------------------------------------- */
416 static int Release_D_WriteBlock(struct us_data
*us
)
418 SectCopyMode
= COMPLETED
;
419 Media
.PhyBlock
= WriteBlock
;
421 if (MarkFail_D_PhyOneBlock(us
))
424 Media
.PhyBlock
= ReadBlock
;
428 /* SmartMedia Physical Sector Data Copy Subroutine */
429 /* ----- Copy_D_PhyOneSect() -------------------------------------------- */
430 static int Copy_D_PhyOneSect(struct us_data
*us
)
435 /* pr_info("Copy_D_PhyOneSect --- Sector = %x\n", Media.Sector); */
436 if (ReadBlock
!= NO_ASSIGN
) {
437 Media
.PhyBlock
= ReadBlock
;
438 for (retry
= 0; retry
< 2; retry
++) {
441 if (Ssfdc_D_ReadCisSect(us
, WorkBuf
,
443 ErrCode
= ERR_HwError
;
448 if (Check_D_CISdata(WorkBuf
, WorkRedund
)) {
449 ErrCode
= ERR_HwError
;
455 if (Ssfdc_D_ReadSect(us
, WorkBuf
, WorkRedund
)) {
456 ErrCode
= ERR_HwError
;
460 if (Check_D_DataStatus(WorkRedund
)) {
464 if (!Check_D_ReadError(WorkRedund
)) {
468 if (!Check_D_Correct(WorkBuf
, WorkRedund
)) {
474 SectCopyMode
= REQ_FAIL
;
478 for (i
= 0; i
< SECTSIZE
; i
++)
479 WorkBuf
[i
] = DUMMY_DATA
;
480 Clr_D_RedundantData(WorkRedund
);
483 Set_D_LogBlockAddr(WorkRedund
);
485 Set_D_RightECC(WorkRedund
);
486 Set_D_DataStaus(WorkRedund
);
489 Media
.PhyBlock
= WriteBlock
;
491 if (Ssfdc_D_WriteSectForCopy(us
, WorkBuf
, WorkRedund
)) {
492 ErrCode
= ERR_HwError
;
496 if (Ssfdc_D_CheckStatus()) {
497 ErrCode
= ERR_WriteFault
;
501 Media
.PhyBlock
= ReadBlock
;
505 /* SmartMedia Physical Sector Read/Write/Erase Subroutine */
506 /* ----- Read_D_PhyOneSect() -------------------------------------------- */
507 static int Read_D_PhyOneSect(struct us_data
*us
, WORD count
, BYTE
*buf
)
512 if (Media
.PhyBlock
== NO_ASSIGN
) {
513 for (i
= 0; i
< SECTSIZE
; i
++)
518 for (retry
= 0; retry
< 2; retry
++) {
522 if (Ssfdc_D_ReadCisSect(us
, WorkBuf
, WorkRedund
)) {
523 ErrCode
= ERR_HwError
;
527 if (Check_D_CISdata(WorkBuf
, WorkRedund
)) {
528 ErrCode
= ERR_HwError
;
534 if (Ssfdc_D_ReadBlock(us
, count
, buf
, Redundant
)) {
535 ErrCode
= ERR_HwError
;
539 if (Check_D_DataStatus(Redundant
)) {
540 ErrCode
= ERR_DataStatus
;
544 if (!Check_D_ReadError(Redundant
))
547 if (!Check_D_Correct(buf
, Redundant
)) {
548 ErrCode
= ERR_CorReadErr
;
553 ErrCode
= ERR_EccReadErr
;
557 /* ----- Erase_D_PhyOneBlock() ------------------------------------------ */
558 static int Erase_D_PhyOneBlock(struct us_data
*us
)
560 if (Ssfdc_D_EraseBlock(us
)) {
561 ErrCode
= ERR_HwError
;
565 if (Ssfdc_D_CheckStatus()) {
566 ErrCode
= ERR_WriteFault
;
573 /* SmartMedia Physical Format Check Local Subroutine */
574 /* ----- Set_D_PhyFmtValue() -------------------------------------------- */
575 static int Set_D_PhyFmtValue(struct us_data
*us
)
577 if (Set_D_SsfdcModel(us
->SM_DeviceID
))
583 /* ----- Search_D_CIS() ------------------------------------------------- */
584 static int Search_D_CIS(struct us_data
*us
)
589 for (Media
.PhyBlock
= 0;
590 Media
.PhyBlock
< (Ssfdc
.MaxBlocks
- Ssfdc
.MaxLogBlocks
- 1);
592 if (Ssfdc_D_ReadRedtData(us
, Redundant
)) {
597 if (!Check_D_FailBlock(Redundant
))
601 if (Media
.PhyBlock
== (Ssfdc
.MaxBlocks
- Ssfdc
.MaxLogBlocks
- 1)) {
606 while (Media
.Sector
< CIS_SEARCH_SECT
) {
608 if (Ssfdc_D_ReadRedtData(us
, Redundant
)) {
613 if (!Check_D_DataStatus(Redundant
)) {
614 if (Ssfdc_D_ReadSect(us
, WorkBuf
, Redundant
)) {
619 if (Check_D_CISdata(WorkBuf
, Redundant
)) {
624 CisArea
.PhyBlock
= Media
.PhyBlock
;
625 CisArea
.Sector
= Media
.Sector
;
637 /* ----- Make_D_LogTable() ---------------------------------------------- */
638 static int Make_D_LogTable(struct us_data
*us
)
640 WORD phyblock
, logblock
;
642 if (Log2Phy
[Media
.Zone
] == NULL
) {
643 Log2Phy
[Media
.Zone
] = kmalloc(MAX_LOGBLOCK
* sizeof(WORD
),
645 /* pr_info("ExAllocatePool Zone = %x, Addr = %x\n",
646 Media.Zone, Log2Phy[Media.Zone]); */
647 if (Log2Phy
[Media
.Zone
] == NULL
)
653 /* pr_info("Make_D_LogTable --- MediaZone = 0x%x\n",
655 for (Media
.LogBlock
= 0; Media
.LogBlock
< Ssfdc
.MaxLogBlocks
;
657 Log2Phy
[Media
.Zone
][Media
.LogBlock
] = NO_ASSIGN
;
659 for (Media
.PhyBlock
= 0; Media
.PhyBlock
< (MAX_BLOCKNUM
/ 8);
661 Assign
[Media
.Zone
][Media
.PhyBlock
] = 0x00;
663 for (Media
.PhyBlock
= 0; Media
.PhyBlock
< Ssfdc
.MaxBlocks
;
665 if ((!Media
.Zone
) && (Media
.PhyBlock
<= CisArea
.PhyBlock
)) {
666 Set_D_Bit(Assign
[Media
.Zone
], Media
.PhyBlock
);
670 if (Ssfdc_D_ReadRedtData(us
, Redundant
)) {
675 if (!Check_D_DataBlank(Redundant
))
678 Set_D_Bit(Assign
[Media
.Zone
], Media
.PhyBlock
);
680 if (Check_D_FailBlock(Redundant
))
683 if (Load_D_LogBlockAddr(Redundant
))
686 if (Media
.LogBlock
>= Ssfdc
.MaxLogBlocks
)
689 if (Log2Phy
[Media
.Zone
][Media
.LogBlock
] == NO_ASSIGN
) {
690 Log2Phy
[Media
.Zone
][Media
.LogBlock
] = Media
.PhyBlock
;
694 phyblock
= Media
.PhyBlock
;
695 logblock
= Media
.LogBlock
;
696 Media
.Sector
= (BYTE
)(Ssfdc
.MaxSectors
- 1);
698 if (Ssfdc_D_ReadRedtData(us
, Redundant
)) {
703 if (!Load_D_LogBlockAddr(Redundant
) &&
704 (Media
.LogBlock
== logblock
)) {
705 Media
.PhyBlock
= Log2Phy
[Media
.Zone
][logblock
];
707 if (Ssfdc_D_ReadRedtData(us
, Redundant
)) {
712 Media
.PhyBlock
= phyblock
;
714 if (!Load_D_LogBlockAddr(Redundant
)) {
715 if (Media
.LogBlock
!= logblock
) {
717 Log2Phy
[Media
.Zone
][logblock
];
718 Log2Phy
[Media
.Zone
][logblock
] =
722 Media
.PhyBlock
= Log2Phy
[Media
.Zone
][logblock
];
723 Log2Phy
[Media
.Zone
][logblock
] = phyblock
;
728 Media
.PhyBlock
= phyblock
;
730 AssignStart
[Media
.Zone
] = 0;
732 } /* End for (Media.Zone<MAX_ZONENUM) */
738 /* ----- MarkFail_D_PhyOneBlock() --------------------------------------- */
739 static int MarkFail_D_PhyOneBlock(struct us_data
*us
)
744 Set_D_FailBlock(WorkRedund
);
746 for (Media
.Sector
= 0; Media
.Sector
< Ssfdc
.MaxSectors
;
748 if (Ssfdc_D_WriteRedtData(us
, WorkRedund
)) {
751 ErrCode
= ERR_HwError
;
754 } /* NO Status Check */