Merge branch 'next' of git://git.monstr.eu/linux-2.6-microblaze
[pandora-kernel.git] / drivers / staging / keucr / smilsub.c
1 #include <linux/slab.h>
2 #include "usb.h"
3 #include "scsiglue.h"
4 #include "transport.h"
5
6 #include "smcommon.h"
7 #include "smil.h"
8
9 void   _Set_D_SsfdcRdCmd(BYTE);
10 void   _Set_D_SsfdcRdAddr(BYTE);
11 void   _Set_D_SsfdcRdChip(void);
12 void   _Set_D_SsfdcRdStandby(void);
13 void   _Start_D_SsfdcRdHwECC(void);
14 void   _Stop_D_SsfdcRdHwECC(void);
15 void   _Load_D_SsfdcRdHwECC(BYTE);
16 void   _Set_D_SsfdcWrCmd(BYTE);
17 void   _Set_D_SsfdcWrAddr(BYTE);
18 void   _Set_D_SsfdcWrBlock(void);
19 void   _Set_D_SsfdcWrStandby(void);
20 void   _Start_D_SsfdcWrHwECC(void);
21 void   _Load_D_SsfdcWrHwECC(BYTE);
22 int    _Check_D_SsfdcBusy(WORD);
23 int    _Check_D_SsfdcStatus(void);
24 void   _Reset_D_SsfdcErr(void);
25 void   _Read_D_SsfdcBuf(BYTE *);
26 void   _Write_D_SsfdcBuf(BYTE *);
27 void   _Read_D_SsfdcByte(BYTE *);
28 void   _ReadRedt_D_SsfdcBuf(BYTE *);
29 void   _WriteRedt_D_SsfdcBuf(BYTE *);
30 BYTE   _Check_D_DevCode(BYTE);
31
32 void   _Set_D_ECCdata(BYTE, BYTE *);
33 void   _Calc_D_ECCdata(BYTE *);
34
35
36 struct SSFDCTYPE                Ssfdc;
37 struct ADDRESS                  Media;
38 struct CIS_AREA                 CisArea;
39
40 static BYTE                            EccBuf[6];
41 extern PBYTE                    SMHostAddr;
42 extern DWORD                    ErrXDCode;
43
44 extern WORD  ReadBlock;
45 extern WORD  WriteBlock;
46
47
48
49 #define EVEN                    0             /* Even Page for 256byte/page */
50 #define ODD                     1             /* Odd Page for 256byte/page */
51
52
53 /* SmartMedia Redundant buffer data Control Subroutine
54  *----- Check_D_DataBlank() --------------------------------------------
55  */
56 int Check_D_DataBlank(BYTE *redundant)
57 {
58         char i;
59
60         for (i = 0; i < REDTSIZE; i++)
61                 if (*redundant++ != 0xFF)
62                         return  ERROR;
63
64         return SMSUCCESS;
65 }
66
67 /* ----- Check_D_FailBlock() -------------------------------------------- */
68 int Check_D_FailBlock(BYTE *redundant)
69 {
70         redundant += REDT_BLOCK;
71
72         if (*redundant == 0xFF)
73                 return SMSUCCESS;
74         if (!*redundant)
75                 return ERROR;
76         if (hweight8(*redundant) < 7)
77                 return ERROR;
78
79         return SMSUCCESS;
80 }
81
82 /* ----- Check_D_DataStatus() ------------------------------------------- */
83 int Check_D_DataStatus(BYTE *redundant)
84 {
85         redundant += REDT_DATA;
86
87         if (*redundant == 0xFF)
88                 return SMSUCCESS;
89         if (!*redundant) {
90                 ErrXDCode = ERR_DataStatus;
91                 return ERROR;
92         } else
93                 ErrXDCode = NO_ERROR;
94
95         if (hweight8(*redundant) < 5)
96                 return ERROR;
97
98         return SMSUCCESS;
99 }
100
101 /* ----- Load_D_LogBlockAddr() ------------------------------------------ */
102 int Load_D_LogBlockAddr(BYTE *redundant)
103 {
104         WORD addr1, addr2;
105
106         addr1 = (WORD)*(redundant + REDT_ADDR1H)*0x0100 + (WORD)*(redundant + REDT_ADDR1L);
107         addr2 = (WORD)*(redundant + REDT_ADDR2H)*0x0100 + (WORD)*(redundant + REDT_ADDR2L);
108
109         if (addr1 == addr2)
110                 if ((addr1 & 0xF000) == 0x1000) {
111                         Media.LogBlock = (addr1 & 0x0FFF) / 2;
112                         return SMSUCCESS;
113                 }
114
115         if (hweight16((WORD)(addr1^addr2)) != 0x01)
116                 return ERROR;
117
118         if ((addr1 & 0xF000) == 0x1000)
119                 if (!(hweight16(addr1) & 0x01)) {
120                         Media.LogBlock = (addr1 & 0x0FFF) / 2;
121                         return SMSUCCESS;
122                 }
123
124         if ((addr2 & 0xF000) == 0x1000)
125                 if (!(hweight16(addr2) & 0x01)) {
126                         Media.LogBlock = (addr2 & 0x0FFF) / 2;
127                         return SMSUCCESS;
128                 }
129
130         return ERROR;
131 }
132
133 /* ----- Clr_D_RedundantData() ------------------------------------------ */
134 void Clr_D_RedundantData(BYTE *redundant)
135 {
136         char i;
137
138         for (i = 0; i < REDTSIZE; i++)
139                 *(redundant + i) = 0xFF;
140 }
141
142 /* ----- Set_D_LogBlockAddr() ------------------------------------------- */
143 void Set_D_LogBlockAddr(BYTE *redundant)
144 {
145         WORD addr;
146
147         *(redundant + REDT_BLOCK) = 0xFF;
148         *(redundant + REDT_DATA) = 0xFF;
149         addr = Media.LogBlock*2 + 0x1000;
150
151         if ((hweight16(addr) % 2))
152                 addr++;
153
154         *(redundant + REDT_ADDR1H) = *(redundant + REDT_ADDR2H) = (BYTE)(addr / 0x0100);
155         *(redundant + REDT_ADDR1L) = *(redundant + REDT_ADDR2L) = (BYTE)addr;
156 }
157
158 /*----- Set_D_FailBlock() ---------------------------------------------- */
159 void Set_D_FailBlock(BYTE *redundant)
160 {
161         char i;
162         for (i = 0; i < REDTSIZE; i++)
163                 *redundant++ = (BYTE)((i == REDT_BLOCK) ? 0xF0 : 0xFF);
164 }
165
166 /* ----- Set_D_DataStaus() ---------------------------------------------- */
167 void Set_D_DataStaus(BYTE *redundant)
168 {
169         redundant += REDT_DATA;
170         *redundant = 0x00;
171 }
172
173 /* SmartMedia Function Command Subroutine
174  * 6250 CMD 6
175  */
176 /* ----- Ssfdc_D_Reset() ------------------------------------------------ */
177 void Ssfdc_D_Reset(struct us_data *us)
178 {
179         return;
180 }
181
182 /* ----- Ssfdc_D_ReadCisSect() ------------------------------------------ */
183 int Ssfdc_D_ReadCisSect(struct us_data *us, BYTE *buf, BYTE *redundant)
184 {
185         BYTE zone, sector;
186         WORD block;
187
188         zone = Media.Zone; block = Media.PhyBlock; sector = Media.Sector;
189         Media.Zone = 0;
190         Media.PhyBlock = CisArea.PhyBlock;
191         Media.Sector = CisArea.Sector;
192
193         if (Ssfdc_D_ReadSect(us, buf, redundant)) {
194                 Media.Zone = zone; Media.PhyBlock = block; Media.Sector = sector;
195                 return ERROR;
196         }
197
198         Media.Zone = zone; Media.PhyBlock = block; Media.Sector = sector;
199         return SMSUCCESS;
200 }
201
202 /* 6250 CMD 1 */
203 /* ----- Ssfdc_D_ReadSect() --------------------------------------------- */
204 int Ssfdc_D_ReadSect(struct us_data *us, BYTE *buf, BYTE *redundant)
205 {
206         struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
207         int     result;
208         WORD    addr;
209
210         result = ENE_LoadBinCode(us, SM_RW_PATTERN);
211         if (result != USB_STOR_XFER_GOOD) {
212                 printk("Load SM RW Code Fail !!\n");
213                 return USB_STOR_TRANSPORT_ERROR;
214         }
215
216         addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
217         addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
218
219         /* Read sect data */
220         memset(bcb, 0, sizeof(struct bulk_cb_wrap));
221         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
222         bcb->DataTransferLength = 0x200;
223         bcb->Flags                      = 0x80;
224         bcb->CDB[0]                     = 0xF1;
225         bcb->CDB[1]                     = 0x02;
226         bcb->CDB[4]                     = (BYTE)addr;
227         bcb->CDB[3]                     = (BYTE)(addr / 0x0100);
228         bcb->CDB[2]                     = Media.Zone / 2;
229
230         result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
231         if (result != USB_STOR_XFER_GOOD)
232                 return USB_STOR_TRANSPORT_ERROR;
233
234         /* Read redundant */
235         memset(bcb, 0, sizeof(struct bulk_cb_wrap));
236         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
237         bcb->DataTransferLength = 0x10;
238         bcb->Flags                      = 0x80;
239         bcb->CDB[0]                     = 0xF1;
240         bcb->CDB[1]                     = 0x03;
241         bcb->CDB[4]                     = (BYTE)addr;
242         bcb->CDB[3]                     = (BYTE)(addr / 0x0100);
243         bcb->CDB[2]                     = Media.Zone / 2;
244         bcb->CDB[8]                     = 0;
245         bcb->CDB[9]                     = 1;
246
247         result = ENE_SendScsiCmd(us, FDIR_READ, redundant, 0);
248         if (result != USB_STOR_XFER_GOOD)
249                 return USB_STOR_TRANSPORT_ERROR;
250
251         return USB_STOR_TRANSPORT_GOOD;
252 }
253
254 /* ----- Ssfdc_D_ReadBlock() --------------------------------------------- */
255 int Ssfdc_D_ReadBlock(struct us_data *us, WORD count, BYTE *buf, BYTE *redundant)
256 {
257         struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
258         int     result;
259         WORD    addr;
260
261         result = ENE_LoadBinCode(us, SM_RW_PATTERN);
262         if (result != USB_STOR_XFER_GOOD) {
263                 printk("Load SM RW Code Fail !!\n");
264                 return USB_STOR_TRANSPORT_ERROR;
265         }
266
267         addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
268         addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
269
270         /* Read sect data */
271         memset(bcb, 0, sizeof(struct bulk_cb_wrap));
272         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
273         bcb->DataTransferLength = 0x200*count;
274         bcb->Flags                      = 0x80;
275         bcb->CDB[0]                     = 0xF1;
276         bcb->CDB[1]                     = 0x02;
277         bcb->CDB[4]                     = (BYTE)addr;
278         bcb->CDB[3]                     = (BYTE)(addr / 0x0100);
279         bcb->CDB[2]                     = Media.Zone / 2;
280
281         result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
282         if (result != USB_STOR_XFER_GOOD)
283                 return USB_STOR_TRANSPORT_ERROR;
284
285         /* Read redundant */
286         memset(bcb, 0, sizeof(struct bulk_cb_wrap));
287         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
288         bcb->DataTransferLength = 0x10;
289         bcb->Flags                      = 0x80;
290         bcb->CDB[0]                     = 0xF1;
291         bcb->CDB[1]                     = 0x03;
292         bcb->CDB[4]                     = (BYTE)addr;
293         bcb->CDB[3]                     = (BYTE)(addr / 0x0100);
294         bcb->CDB[2]                     = Media.Zone / 2;
295         bcb->CDB[8]                     = 0;
296         bcb->CDB[9]                     = 1;
297
298         result = ENE_SendScsiCmd(us, FDIR_READ, redundant, 0);
299         if (result != USB_STOR_XFER_GOOD)
300                 return USB_STOR_TRANSPORT_ERROR;
301
302         return USB_STOR_TRANSPORT_GOOD;
303 }
304
305
306 /* ----- Ssfdc_D_CopyBlock() -------------------------------------------- */
307 int Ssfdc_D_CopyBlock(struct us_data *us, WORD count, BYTE *buf, BYTE *redundant)
308 {
309         struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
310         int     result;
311         WORD    ReadAddr, WriteAddr;
312
313         result = ENE_LoadBinCode(us, SM_RW_PATTERN);
314         if (result != USB_STOR_XFER_GOOD) {
315                 printk("Load SM RW Code Fail !!\n");
316                 return USB_STOR_TRANSPORT_ERROR;
317         }
318
319         ReadAddr = (WORD)Media.Zone*Ssfdc.MaxBlocks + ReadBlock;
320         ReadAddr = ReadAddr*(WORD)Ssfdc.MaxSectors;
321         WriteAddr = (WORD)Media.Zone*Ssfdc.MaxBlocks + WriteBlock;
322         WriteAddr = WriteAddr*(WORD)Ssfdc.MaxSectors;
323
324         /* Write sect data */
325         memset(bcb, 0, sizeof(struct bulk_cb_wrap));
326         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
327         bcb->DataTransferLength = 0x200*count;
328         bcb->Flags                      = 0x00;
329         bcb->CDB[0]                     = 0xF0;
330         bcb->CDB[1]                     = 0x08;
331         bcb->CDB[7]                     = (BYTE)WriteAddr;
332         bcb->CDB[6]                     = (BYTE)(WriteAddr / 0x0100);
333         bcb->CDB[5]                     = Media.Zone / 2;
334         bcb->CDB[8]                     = *(redundant + REDT_ADDR1H);
335         bcb->CDB[9]                     = *(redundant + REDT_ADDR1L);
336         bcb->CDB[10]            = Media.Sector;
337
338         if (ReadBlock != NO_ASSIGN) {
339                 bcb->CDB[4]             = (BYTE)ReadAddr;
340                 bcb->CDB[3]             = (BYTE)(ReadAddr / 0x0100);
341                 bcb->CDB[2]             = Media.Zone / 2;
342         } else
343                 bcb->CDB[11]    = 1;
344
345         result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
346         if (result != USB_STOR_XFER_GOOD)
347                 return USB_STOR_TRANSPORT_ERROR;
348
349         return USB_STOR_TRANSPORT_GOOD;
350 }
351
352 /* ----- Ssfdc_D_WriteSectForCopy() ------------------------------------- */
353 int Ssfdc_D_WriteSectForCopy(struct us_data *us, BYTE *buf, BYTE *redundant)
354 {
355         struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
356         int     result;
357         WORD    addr;
358
359         result = ENE_LoadBinCode(us, SM_RW_PATTERN);
360         if (result != USB_STOR_XFER_GOOD) {
361                 printk("Load SM RW Code Fail !!\n");
362                 return USB_STOR_TRANSPORT_ERROR;
363         }
364
365
366         addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
367         addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
368
369         /* Write sect data */
370         memset(bcb, 0, sizeof(struct bulk_cb_wrap));
371         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
372         bcb->DataTransferLength = 0x200;
373         bcb->Flags                      = 0x00;
374         bcb->CDB[0]                     = 0xF0;
375         bcb->CDB[1]                     = 0x04;
376         bcb->CDB[7]                     = (BYTE)addr;
377         bcb->CDB[6]                     = (BYTE)(addr / 0x0100);
378         bcb->CDB[5]                     = Media.Zone / 2;
379         bcb->CDB[8]                     = *(redundant + REDT_ADDR1H);
380         bcb->CDB[9]                     = *(redundant + REDT_ADDR1L);
381
382         result = ENE_SendScsiCmd(us, FDIR_WRITE, buf, 0);
383         if (result != USB_STOR_XFER_GOOD)
384                 return USB_STOR_TRANSPORT_ERROR;
385
386         return USB_STOR_TRANSPORT_GOOD;
387 }
388
389 /* 6250 CMD 5 */
390 /* ----- Ssfdc_D_EraseBlock() ------------------------------------------- */
391 int Ssfdc_D_EraseBlock(struct us_data *us)
392 {
393         struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
394         int     result;
395         WORD    addr;
396
397         result = ENE_LoadBinCode(us, SM_RW_PATTERN);
398         if (result != USB_STOR_XFER_GOOD) {
399                 printk("Load SM RW Code Fail !!\n");
400                 return USB_STOR_TRANSPORT_ERROR;
401         }
402
403         addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
404         addr = addr*(WORD)Ssfdc.MaxSectors;
405
406         memset(bcb, 0, sizeof(struct bulk_cb_wrap));
407         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
408         bcb->DataTransferLength = 0x200;
409         bcb->Flags                      = 0x80;
410         bcb->CDB[0]                     = 0xF2;
411         bcb->CDB[1]                     = 0x06;
412         bcb->CDB[7]                     = (BYTE)addr;
413         bcb->CDB[6]                     = (BYTE)(addr / 0x0100);
414         bcb->CDB[5]                     = Media.Zone / 2;
415
416         result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
417         if (result != USB_STOR_XFER_GOOD)
418                 return USB_STOR_TRANSPORT_ERROR;
419
420         return USB_STOR_TRANSPORT_GOOD;
421 }
422
423 /* 6250 CMD 2 */
424 /*----- Ssfdc_D_ReadRedtData() ----------------------------------------- */
425 int Ssfdc_D_ReadRedtData(struct us_data *us, BYTE *redundant)
426 {
427         struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
428         int     result;
429         WORD    addr;
430         BYTE    *buf;
431
432         result = ENE_LoadBinCode(us, SM_RW_PATTERN);
433         if (result != USB_STOR_XFER_GOOD) {
434                 printk("Load SM RW Code Fail !!\n");
435                 return USB_STOR_TRANSPORT_ERROR;
436         }
437
438         addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
439         addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
440
441         memset(bcb, 0, sizeof(struct bulk_cb_wrap));
442         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
443         bcb->DataTransferLength = 0x10;
444         bcb->Flags                      = 0x80;
445         bcb->CDB[0]                     = 0xF1;
446         bcb->CDB[1]                     = 0x03;
447         bcb->CDB[4]                     = (BYTE)addr;
448         bcb->CDB[3]                     = (BYTE)(addr / 0x0100);
449         bcb->CDB[2]                     = Media.Zone / 2;
450         bcb->CDB[8]                     = 0;
451         bcb->CDB[9]                     = 1;
452
453         buf = kmalloc(0x10, GFP_KERNEL);
454         result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
455         memcpy(redundant, buf, 0x10);
456         kfree(buf);
457         if (result != USB_STOR_XFER_GOOD)
458                 return USB_STOR_TRANSPORT_ERROR;
459
460         return USB_STOR_TRANSPORT_GOOD;
461 }
462
463 /* 6250 CMD 4 */
464 /* ----- Ssfdc_D_WriteRedtData() ---------------------------------------- */
465 int Ssfdc_D_WriteRedtData(struct us_data *us, BYTE *redundant)
466 {
467         struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
468         int     result;
469         WORD                    addr;
470
471         result = ENE_LoadBinCode(us, SM_RW_PATTERN);
472         if (result != USB_STOR_XFER_GOOD) {
473                 printk("Load SM RW Code Fail !!\n");
474                 return USB_STOR_TRANSPORT_ERROR;
475         }
476
477         addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
478         addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
479
480         memset(bcb, 0, sizeof(struct bulk_cb_wrap));
481         bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
482         bcb->DataTransferLength = 0x10;
483         bcb->Flags                      = 0x80;
484         bcb->CDB[0]                     = 0xF2;
485         bcb->CDB[1]                     = 0x05;
486         bcb->CDB[7]                     = (BYTE)addr;
487         bcb->CDB[6]                     = (BYTE)(addr / 0x0100);
488         bcb->CDB[5]                     = Media.Zone / 2;
489         bcb->CDB[8]                     = *(redundant + REDT_ADDR1H);
490         bcb->CDB[9]                     = *(redundant + REDT_ADDR1L);
491
492         result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
493         if (result != USB_STOR_XFER_GOOD)
494                 return USB_STOR_TRANSPORT_ERROR;
495
496         return USB_STOR_TRANSPORT_GOOD;
497 }
498
499 /* ----- Ssfdc_D_CheckStatus() ------------------------------------------ */
500 int Ssfdc_D_CheckStatus(void)
501 {
502         return SMSUCCESS;
503 }
504
505
506
507 /* SmartMedia ID Code Check & Mode Set Subroutine
508  * ----- Set_D_SsfdcModel() ---------------------------------------------
509  */
510 int Set_D_SsfdcModel(BYTE dcode)
511 {
512         switch (_Check_D_DevCode(dcode)) {
513         case SSFDC1MB:
514                 Ssfdc.Model        = SSFDC1MB;
515                 Ssfdc.Attribute    = FLASH | AD3CYC | BS16 | PS256;
516                 Ssfdc.MaxZones     = 1;
517                 Ssfdc.MaxBlocks    = 256;
518                 Ssfdc.MaxLogBlocks = 250;
519                 Ssfdc.MaxSectors   = 8;
520                 break;
521         case SSFDC2MB:
522                 Ssfdc.Model        = SSFDC2MB;
523                 Ssfdc.Attribute    = FLASH | AD3CYC | BS16 | PS256;
524                 Ssfdc.MaxZones     = 1;
525                 Ssfdc.MaxBlocks    = 512;
526                 Ssfdc.MaxLogBlocks = 500;
527                 Ssfdc.MaxSectors   = 8;
528                 break;
529         case SSFDC4MB:
530                 Ssfdc.Model        = SSFDC4MB;
531                 Ssfdc.Attribute    = FLASH | AD3CYC | BS16 | PS512;
532                 Ssfdc.MaxZones     = 1;
533                 Ssfdc.MaxBlocks    = 512;
534                 Ssfdc.MaxLogBlocks = 500;
535                 Ssfdc.MaxSectors   = 16;
536                 break;
537         case SSFDC8MB:
538                 Ssfdc.Model        = SSFDC8MB;
539                 Ssfdc.Attribute    = FLASH | AD3CYC | BS16 | PS512;
540                 Ssfdc.MaxZones     = 1;
541                 Ssfdc.MaxBlocks    = 1024;
542                 Ssfdc.MaxLogBlocks = 1000;
543                 Ssfdc.MaxSectors   = 16;
544                 break;
545         case SSFDC16MB:
546                 Ssfdc.Model        = SSFDC16MB;
547                 Ssfdc.Attribute    = FLASH | AD3CYC | BS32 | PS512;
548                 Ssfdc.MaxZones     = 1;
549                 Ssfdc.MaxBlocks    = 1024;
550                 Ssfdc.MaxLogBlocks = 1000;
551                 Ssfdc.MaxSectors   = 32;
552                 break;
553         case SSFDC32MB:
554                 Ssfdc.Model        = SSFDC32MB;
555                 Ssfdc.Attribute    = FLASH | AD3CYC | BS32 | PS512;
556                 Ssfdc.MaxZones     = 2;
557                 Ssfdc.MaxBlocks    = 1024;
558                 Ssfdc.MaxLogBlocks = 1000;
559                 Ssfdc.MaxSectors   = 32;
560                 break;
561         case SSFDC64MB:
562                 Ssfdc.Model        = SSFDC64MB;
563                 Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
564                 Ssfdc.MaxZones     = 4;
565                 Ssfdc.MaxBlocks    = 1024;
566                 Ssfdc.MaxLogBlocks = 1000;
567                 Ssfdc.MaxSectors   = 32;
568                 break;
569         case SSFDC128MB:
570                 Ssfdc.Model        = SSFDC128MB;
571                 Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
572                 Ssfdc.MaxZones     = 8;
573                 Ssfdc.MaxBlocks    = 1024;
574                 Ssfdc.MaxLogBlocks = 1000;
575                 Ssfdc.MaxSectors   = 32;
576                 break;
577         case SSFDC256MB:
578                 Ssfdc.Model        = SSFDC256MB;
579                 Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
580                 Ssfdc.MaxZones     = 16;
581                 Ssfdc.MaxBlocks    = 1024;
582                 Ssfdc.MaxLogBlocks = 1000;
583                 Ssfdc.MaxSectors   = 32;
584                 break;
585         case SSFDC512MB:
586                 Ssfdc.Model        = SSFDC512MB;
587                 Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
588                 Ssfdc.MaxZones     = 32;
589                 Ssfdc.MaxBlocks    = 1024;
590                 Ssfdc.MaxLogBlocks = 1000;
591                 Ssfdc.MaxSectors   = 32;
592                 break;
593         case SSFDC1GB:
594                 Ssfdc.Model        = SSFDC1GB;
595                 Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
596                 Ssfdc.MaxZones     = 64;
597                 Ssfdc.MaxBlocks    = 1024;
598                 Ssfdc.MaxLogBlocks = 1000;
599                 Ssfdc.MaxSectors   = 32;
600                 break;
601         case SSFDC2GB:
602                 Ssfdc.Model        = SSFDC2GB;
603                 Ssfdc.Attribute    = FLASH | AD4CYC | BS32 | PS512;
604                 Ssfdc.MaxZones     = 128;
605                 Ssfdc.MaxBlocks    = 1024;
606                 Ssfdc.MaxLogBlocks = 1000;
607                 Ssfdc.MaxSectors   = 32;
608                 break;
609         default:
610                 Ssfdc.Model = NOSSFDC;
611                 return ERROR;
612         }
613
614     return SMSUCCESS;
615 }
616
617 /* ----- _Check_D_DevCode() --------------------------------------------- */
618 BYTE _Check_D_DevCode(BYTE dcode)
619 {
620         switch (dcode) {
621         case 0x6E:
622         case 0xE8:
623         case 0xEC: return SSFDC1MB;   /* 8Mbit (1M) NAND */
624         case 0x64:
625         case 0xEA: return SSFDC2MB;   /* 16Mbit (2M) NAND */
626         case 0x6B:
627         case 0xE3:
628         case 0xE5: return SSFDC4MB;   /* 32Mbit (4M) NAND */
629         case 0xE6: return SSFDC8MB;   /* 64Mbit (8M) NAND */
630         case 0x73: return SSFDC16MB;  /* 128Mbit (16M)NAND */
631         case 0x75: return SSFDC32MB;  /* 256Mbit (32M)NAND */
632         case 0x76: return SSFDC64MB;  /* 512Mbit (64M)NAND */
633         case 0x79: return SSFDC128MB; /* 1Gbit(128M)NAND */
634         case 0x71: return SSFDC256MB;
635         case 0xDC: return SSFDC512MB;
636         case 0xD3: return SSFDC1GB;
637         case 0xD5: return SSFDC2GB;
638         default: return NOSSFDC;
639         }
640 }
641
642
643
644
645 /* SmartMedia ECC Control Subroutine
646  * ----- Check_D_ReadError() ----------------------------------------------
647  */
648 int Check_D_ReadError(BYTE *redundant)
649 {
650         return SMSUCCESS;
651 }
652
653 /* ----- Check_D_Correct() ---------------------------------------------- */
654 int Check_D_Correct(BYTE *buf, BYTE *redundant)
655 {
656         return SMSUCCESS;
657 }
658
659 /* ----- Check_D_CISdata() ---------------------------------------------- */
660 int Check_D_CISdata(BYTE *buf, BYTE *redundant)
661 {
662         BYTE cis[] = {0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02,
663                       0xDF, 0x01, 0x20};
664
665         int cis_len = sizeof(cis);
666
667         if (!IsSSFDCCompliance && !IsXDCompliance)
668                 return SMSUCCESS;
669
670         if (!memcmp(redundant + 0x0D, EccBuf, 3))
671                 return memcmp(buf, cis, cis_len);
672
673         if (!_Correct_D_SwECC(buf, redundant + 0x0D, EccBuf))
674                 return memcmp(buf, cis, cis_len);
675
676         buf += 0x100;
677         if (!memcmp(redundant + 0x08, EccBuf + 0x03, 3))
678                 return memcmp(buf, cis, cis_len);
679
680         if (!_Correct_D_SwECC(buf, redundant + 0x08, EccBuf + 0x03))
681                 return memcmp(buf, cis, cis_len);
682
683         return ERROR;
684 }
685
686 /* ----- Set_D_RightECC() ---------------------------------------------- */
687 void Set_D_RightECC(BYTE *redundant)
688 {
689     /* Driver ECC Check */
690     return;
691 }
692
693