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