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