blob: d4dd5ed516ce80ebd8de093759bb700161bd7ac1 [file] [log] [blame]
Al Cho126bb032010-09-08 00:42:32 -07001#include <linux/slab.h>
2#include "usb.h"
3#include "scsiglue.h"
4#include "transport.h"
Al Cho126bb032010-09-08 00:42:32 -07005
Al Cho126bb032010-09-08 00:42:32 -07006#include "smcommon.h"
7#include "smil.h"
8
Ruslan Pisarev50d487e32011-07-22 14:17:23 +03009void _Set_D_SsfdcRdCmd(BYTE);
10void _Set_D_SsfdcRdAddr(BYTE);
11void _Set_D_SsfdcRdChip(void);
12void _Set_D_SsfdcRdStandby(void);
13void _Start_D_SsfdcRdHwECC(void);
14void _Stop_D_SsfdcRdHwECC(void);
15void _Load_D_SsfdcRdHwECC(BYTE);
16void _Set_D_SsfdcWrCmd(BYTE);
17void _Set_D_SsfdcWrAddr(BYTE);
18void _Set_D_SsfdcWrBlock(void);
19void _Set_D_SsfdcWrStandby(void);
20void _Start_D_SsfdcWrHwECC(void);
21void _Load_D_SsfdcWrHwECC(BYTE);
22int _Check_D_SsfdcBusy(WORD);
23int _Check_D_SsfdcStatus(void);
24void _Reset_D_SsfdcErr(void);
25void _Read_D_SsfdcBuf(BYTE *);
26void _Write_D_SsfdcBuf(BYTE *);
27void _Read_D_SsfdcByte(BYTE *);
28void _ReadRedt_D_SsfdcBuf(BYTE *);
29void _WriteRedt_D_SsfdcBuf(BYTE *);
30BYTE _Check_D_DevCode(BYTE);
Al Cho126bb032010-09-08 00:42:32 -070031
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030032void _Set_D_ECCdata(BYTE, BYTE *);
33void _Calc_D_ECCdata(BYTE *);
Al Cho126bb032010-09-08 00:42:32 -070034
Ruslan Pisarev74a5e012011-07-22 14:17:04 +030035
Al Cho126bb032010-09-08 00:42:32 -070036struct SSFDCTYPE Ssfdc;
37struct ADDRESS Media;
38struct CIS_AREA CisArea;
39
Randy Dunlapd8aba9d2011-05-09 10:46:24 -070040static BYTE EccBuf[6];
Al Cho126bb032010-09-08 00:42:32 -070041extern PBYTE SMHostAddr;
Al Cho126bb032010-09-08 00:42:32 -070042extern DWORD ErrXDCode;
43
44extern WORD ReadBlock;
45extern WORD WriteBlock;
46
Ruslan Pisarev74a5e012011-07-22 14:17:04 +030047
Al Cho126bb032010-09-08 00:42:32 -070048
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030049#define EVEN 0 /* Even Page for 256byte/page */
50#define ODD 1 /* Odd Page for 256byte/page */
Al Cho126bb032010-09-08 00:42:32 -070051
52
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030053/* SmartMedia Redundant buffer data Control Subroutine
54 *----- Check_D_DataBlank() --------------------------------------------
55 */
Al Cho126bb032010-09-08 00:42:32 -070056int Check_D_DataBlank(BYTE *redundant)
57{
58 char i;
59
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030060 for (i = 0; i < REDTSIZE; i++)
61 if (*redundant++ != 0xFF)
62 return ERROR;
Al Cho126bb032010-09-08 00:42:32 -070063
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030064 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -070065}
66
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030067/* ----- Check_D_FailBlock() -------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -070068int Check_D_FailBlock(BYTE *redundant)
69{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030070 redundant += REDT_BLOCK;
Al Cho126bb032010-09-08 00:42:32 -070071
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030072 if (*redundant == 0xFF)
73 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -070074 if (!*redundant)
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030075 return ERROR;
76 if (hweight8(*redundant) < 7)
77 return ERROR;
Al Cho126bb032010-09-08 00:42:32 -070078
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030079 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -070080}
81
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030082/* ----- Check_D_DataStatus() ------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -070083int Check_D_DataStatus(BYTE *redundant)
84{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030085 redundant += REDT_DATA;
Al Cho126bb032010-09-08 00:42:32 -070086
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030087 if (*redundant == 0xFF)
88 return SMSUCCESS;
89 if (!*redundant) {
Al Cho126bb032010-09-08 00:42:32 -070090 ErrXDCode = ERR_DataStatus;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030091 return ERROR;
92 } else
Al Cho126bb032010-09-08 00:42:32 -070093 ErrXDCode = NO_ERROR;
94
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030095 if (hweight8(*redundant) < 5)
96 return ERROR;
Al Cho126bb032010-09-08 00:42:32 -070097
Ruslan Pisarev50d487e32011-07-22 14:17:23 +030098 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -070099}
100
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300101/* ----- Load_D_LogBlockAddr() ------------------------------------------ */
Al Cho126bb032010-09-08 00:42:32 -0700102int Load_D_LogBlockAddr(BYTE *redundant)
103{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300104 WORD addr1, addr2;
Al Cho126bb032010-09-08 00:42:32 -0700105
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300106 addr1 = (WORD)*(redundant + REDT_ADDR1H)*0x0100 + (WORD)*(redundant + REDT_ADDR1L);
107 addr2 = (WORD)*(redundant + REDT_ADDR2H)*0x0100 + (WORD)*(redundant + REDT_ADDR2L);
Al Cho126bb032010-09-08 00:42:32 -0700108
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300109 if (addr1 == addr2)
110 if ((addr1 & 0xF000) == 0x1000) {
111 Media.LogBlock = (addr1 & 0x0FFF) / 2;
112 return SMSUCCESS;
113 }
Al Cho126bb032010-09-08 00:42:32 -0700114
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300115 if (hweight16((WORD)(addr1^addr2)) != 0x01)
116 return ERROR;
Al Cho126bb032010-09-08 00:42:32 -0700117
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300118 if ((addr1 & 0xF000) == 0x1000)
119 if (!(hweight16(addr1) & 0x01)) {
120 Media.LogBlock = (addr1 & 0x0FFF) / 2;
121 return SMSUCCESS;
122 }
Al Cho126bb032010-09-08 00:42:32 -0700123
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300124 if ((addr2 & 0xF000) == 0x1000)
125 if (!(hweight16(addr2) & 0x01)) {
126 Media.LogBlock = (addr2 & 0x0FFF) / 2;
127 return SMSUCCESS;
128 }
Al Cho126bb032010-09-08 00:42:32 -0700129
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300130 return ERROR;
Al Cho126bb032010-09-08 00:42:32 -0700131}
132
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300133/* ----- Clr_D_RedundantData() ------------------------------------------ */
Al Cho126bb032010-09-08 00:42:32 -0700134void Clr_D_RedundantData(BYTE *redundant)
135{
136 char i;
137
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300138 for (i = 0; i < REDTSIZE; i++)
139 *(redundant + i) = 0xFF;
Al Cho126bb032010-09-08 00:42:32 -0700140}
141
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300142/* ----- Set_D_LogBlockAddr() ------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700143void Set_D_LogBlockAddr(BYTE *redundant)
144{
145 WORD addr;
146
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300147 *(redundant + REDT_BLOCK) = 0xFF;
148 *(redundant + REDT_DATA) = 0xFF;
149 addr = Media.LogBlock*2 + 0x1000;
Al Cho126bb032010-09-08 00:42:32 -0700150
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300151 if ((hweight16(addr) % 2))
Al Cho126bb032010-09-08 00:42:32 -0700152 addr++;
153
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300154 *(redundant + REDT_ADDR1H) = *(redundant + REDT_ADDR2H) = (BYTE)(addr / 0x0100);
155 *(redundant + REDT_ADDR1L) = *(redundant + REDT_ADDR2L) = (BYTE)addr;
Al Cho126bb032010-09-08 00:42:32 -0700156}
157
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300158/*----- Set_D_FailBlock() ---------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700159void Set_D_FailBlock(BYTE *redundant)
160{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300161 char i;
162 for (i = 0; i < REDTSIZE; i++)
163 *redundant++ = (BYTE)((i == REDT_BLOCK) ? 0xF0 : 0xFF);
Al Cho126bb032010-09-08 00:42:32 -0700164}
165
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300166/* ----- Set_D_DataStaus() ---------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700167void Set_D_DataStaus(BYTE *redundant)
168{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300169 redundant += REDT_DATA;
170 *redundant = 0x00;
Al Cho126bb032010-09-08 00:42:32 -0700171}
172
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300173/* SmartMedia Function Command Subroutine
174 * 6250 CMD 6
175 */
176/* ----- Ssfdc_D_Reset() ------------------------------------------------ */
Al Cho126bb032010-09-08 00:42:32 -0700177void Ssfdc_D_Reset(struct us_data *us)
178{
Al Cho126bb032010-09-08 00:42:32 -0700179 return;
Al Cho126bb032010-09-08 00:42:32 -0700180}
181
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300182/* ----- Ssfdc_D_ReadCisSect() ------------------------------------------ */
183int Ssfdc_D_ReadCisSect(struct us_data *us, BYTE *buf, BYTE *redundant)
Al Cho126bb032010-09-08 00:42:32 -0700184{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300185 BYTE zone, sector;
Al Cho126bb032010-09-08 00:42:32 -0700186 WORD block;
Al Cho126bb032010-09-08 00:42:32 -0700187
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300188 zone = Media.Zone; block = Media.PhyBlock; sector = Media.Sector;
189 Media.Zone = 0;
190 Media.PhyBlock = CisArea.PhyBlock;
191 Media.Sector = CisArea.Sector;
Al Cho126bb032010-09-08 00:42:32 -0700192
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300193 if (Ssfdc_D_ReadSect(us, buf, redundant)) {
194 Media.Zone = zone; Media.PhyBlock = block; Media.Sector = sector;
195 return ERROR;
Al Cho126bb032010-09-08 00:42:32 -0700196 }
197
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300198 Media.Zone = zone; Media.PhyBlock = block; Media.Sector = sector;
199 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -0700200}
Ruslan Pisarev74a5e012011-07-22 14:17:04 +0300201
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300202/* 6250 CMD 1 */
203/* ----- Ssfdc_D_ReadSect() --------------------------------------------- */
204int Ssfdc_D_ReadSect(struct us_data *us, BYTE *buf, BYTE *redundant)
Al Cho126bb032010-09-08 00:42:32 -0700205{
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);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300211 if (result != USB_STOR_XFER_GOOD) {
Al Cho126bb032010-09-08 00:42:32 -0700212 printk("Load SM RW Code Fail !!\n");
213 return USB_STOR_TRANSPORT_ERROR;
214 }
215
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300216 addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
217 addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
Al Cho126bb032010-09-08 00:42:32 -0700218
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300219 /* Read sect data */
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100220 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700221 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300227 bcb->CDB[3] = (BYTE)(addr / 0x0100);
228 bcb->CDB[2] = Media.Zone / 2;
Al Cho126bb032010-09-08 00:42:32 -0700229
230 result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
231 if (result != USB_STOR_XFER_GOOD)
232 return USB_STOR_TRANSPORT_ERROR;
233
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300234 /* Read redundant */
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100235 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700236 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300242 bcb->CDB[3] = (BYTE)(addr / 0x0100);
243 bcb->CDB[2] = Media.Zone / 2;
Al Cho126bb032010-09-08 00:42:32 -0700244 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
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300254/* ----- Ssfdc_D_ReadBlock() --------------------------------------------- */
255int Ssfdc_D_ReadBlock(struct us_data *us, WORD count, BYTE *buf, BYTE *redundant)
Al Cho126bb032010-09-08 00:42:32 -0700256{
257 struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
258 int result;
259 WORD addr;
260
Al Cho126bb032010-09-08 00:42:32 -0700261 result = ENE_LoadBinCode(us, SM_RW_PATTERN);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300262 if (result != USB_STOR_XFER_GOOD) {
Al Cho126bb032010-09-08 00:42:32 -0700263 printk("Load SM RW Code Fail !!\n");
264 return USB_STOR_TRANSPORT_ERROR;
265 }
266
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300267 addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
268 addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
Al Cho126bb032010-09-08 00:42:32 -0700269
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300270 /* Read sect data */
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100271 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700272 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300278 bcb->CDB[3] = (BYTE)(addr / 0x0100);
279 bcb->CDB[2] = Media.Zone / 2;
Al Cho126bb032010-09-08 00:42:32 -0700280
281 result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
282 if (result != USB_STOR_XFER_GOOD)
283 return USB_STOR_TRANSPORT_ERROR;
284
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300285 /* Read redundant */
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100286 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700287 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300293 bcb->CDB[3] = (BYTE)(addr / 0x0100);
294 bcb->CDB[2] = Media.Zone / 2;
Al Cho126bb032010-09-08 00:42:32 -0700295 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}
Al Cho126bb032010-09-08 00:42:32 -0700304
Al Cho126bb032010-09-08 00:42:32 -0700305
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300306/* ----- Ssfdc_D_CopyBlock() -------------------------------------------- */
307int Ssfdc_D_CopyBlock(struct us_data *us, WORD count, BYTE *buf, BYTE *redundant)
Al Cho126bb032010-09-08 00:42:32 -0700308{
309 struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
310 int result;
Al Cho126bb032010-09-08 00:42:32 -0700311 WORD ReadAddr, WriteAddr;
312
Al Cho126bb032010-09-08 00:42:32 -0700313 result = ENE_LoadBinCode(us, SM_RW_PATTERN);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300314 if (result != USB_STOR_XFER_GOOD) {
Al Cho126bb032010-09-08 00:42:32 -0700315 printk("Load SM RW Code Fail !!\n");
316 return USB_STOR_TRANSPORT_ERROR;
317 }
318
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300319 ReadAddr = (WORD)Media.Zone*Ssfdc.MaxBlocks + ReadBlock;
Al Cho126bb032010-09-08 00:42:32 -0700320 ReadAddr = ReadAddr*(WORD)Ssfdc.MaxSectors;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300321 WriteAddr = (WORD)Media.Zone*Ssfdc.MaxBlocks + WriteBlock;
Al Cho126bb032010-09-08 00:42:32 -0700322 WriteAddr = WriteAddr*(WORD)Ssfdc.MaxSectors;
323
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300324 /* Write sect data */
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100325 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700326 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300332 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);
Al Cho126bb032010-09-08 00:42:32 -0700336 bcb->CDB[10] = Media.Sector;
337
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300338 if (ReadBlock != NO_ASSIGN) {
Al Cho126bb032010-09-08 00:42:32 -0700339 bcb->CDB[4] = (BYTE)ReadAddr;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300340 bcb->CDB[3] = (BYTE)(ReadAddr / 0x0100);
341 bcb->CDB[2] = Media.Zone / 2;
342 } else
Al Cho126bb032010-09-08 00:42:32 -0700343 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}
Al Cho126bb032010-09-08 00:42:32 -0700351
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300352/* ----- Ssfdc_D_WriteSectForCopy() ------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700353int 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300357 WORD addr;
Al Cho126bb032010-09-08 00:42:32 -0700358
Al Cho126bb032010-09-08 00:42:32 -0700359 result = ENE_LoadBinCode(us, SM_RW_PATTERN);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300360 if (result != USB_STOR_XFER_GOOD) {
Al Cho126bb032010-09-08 00:42:32 -0700361 printk("Load SM RW Code Fail !!\n");
362 return USB_STOR_TRANSPORT_ERROR;
363 }
364
365
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300366 addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
367 addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
Al Cho126bb032010-09-08 00:42:32 -0700368
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300369 /* Write sect data */
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100370 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700371 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300377 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);
Al Cho126bb032010-09-08 00:42:32 -0700381
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
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300389/* 6250 CMD 5 */
390/* ----- Ssfdc_D_EraseBlock() ------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700391int 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);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300398 if (result != USB_STOR_XFER_GOOD) {
Al Cho126bb032010-09-08 00:42:32 -0700399 printk("Load SM RW Code Fail !!\n");
400 return USB_STOR_TRANSPORT_ERROR;
401 }
402
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300403 addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
404 addr = addr*(WORD)Ssfdc.MaxSectors;
Al Cho126bb032010-09-08 00:42:32 -0700405
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100406 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700407 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300413 bcb->CDB[6] = (BYTE)(addr / 0x0100);
414 bcb->CDB[5] = Media.Zone / 2;
Al Cho126bb032010-09-08 00:42:32 -0700415
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
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300423/* 6250 CMD 2 */
424/*----- Ssfdc_D_ReadRedtData() ----------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700425int 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300430 BYTE *buf;
Al Cho126bb032010-09-08 00:42:32 -0700431
432 result = ENE_LoadBinCode(us, SM_RW_PATTERN);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300433 if (result != USB_STOR_XFER_GOOD) {
Al Cho126bb032010-09-08 00:42:32 -0700434 printk("Load SM RW Code Fail !!\n");
435 return USB_STOR_TRANSPORT_ERROR;
436 }
437
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300438 addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
439 addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
Al Cho126bb032010-09-08 00:42:32 -0700440
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100441 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700442 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300448 bcb->CDB[3] = (BYTE)(addr / 0x0100);
449 bcb->CDB[2] = Media.Zone / 2;
Al Cho126bb032010-09-08 00:42:32 -0700450 bcb->CDB[8] = 0;
451 bcb->CDB[9] = 1;
452
453 buf = kmalloc(0x10, GFP_KERNEL);
Al Cho126bb032010-09-08 00:42:32 -0700454 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
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300463/* 6250 CMD 4 */
464/* ----- Ssfdc_D_WriteRedtData() ---------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700465int 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;
Al Cho126bb032010-09-08 00:42:32 -0700469 WORD addr;
470
471 result = ENE_LoadBinCode(us, SM_RW_PATTERN);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300472 if (result != USB_STOR_XFER_GOOD) {
Al Cho126bb032010-09-08 00:42:32 -0700473 printk("Load SM RW Code Fail !!\n");
474 return USB_STOR_TRANSPORT_ERROR;
475 }
476
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300477 addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
478 addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
Al Cho126bb032010-09-08 00:42:32 -0700479
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100480 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700481 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300487 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);
Al Cho126bb032010-09-08 00:42:32 -0700491
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
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300499/* ----- Ssfdc_D_CheckStatus() ------------------------------------------ */
Al Cho126bb032010-09-08 00:42:32 -0700500int Ssfdc_D_CheckStatus(void)
501{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300502 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -0700503}
Ruslan Pisarev74a5e012011-07-22 14:17:04 +0300504
505
506
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300507/* SmartMedia ID Code Check & Mode Set Subroutine
508 * ----- Set_D_SsfdcModel() ---------------------------------------------
509 */
Al Cho126bb032010-09-08 00:42:32 -0700510int Set_D_SsfdcModel(BYTE dcode)
511{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300512 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 }
Al Cho126bb032010-09-08 00:42:32 -0700613
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300614 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -0700615}
616
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300617/* ----- _Check_D_DevCode() --------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700618BYTE _Check_D_DevCode(BYTE dcode)
619{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300620 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 }
Al Cho126bb032010-09-08 00:42:32 -0700640}
Ruslan Pisarev74a5e012011-07-22 14:17:04 +0300641
642
643
644
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300645/* SmartMedia ECC Control Subroutine
646 * ----- Check_D_ReadError() ----------------------------------------------
647 */
Al Cho126bb032010-09-08 00:42:32 -0700648int Check_D_ReadError(BYTE *redundant)
649{
Randy Dunlapfb03d4f2011-05-09 10:47:51 -0700650 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -0700651}
652
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300653/* ----- Check_D_Correct() ---------------------------------------------- */
654int Check_D_Correct(BYTE *buf, BYTE *redundant)
Al Cho126bb032010-09-08 00:42:32 -0700655{
Randy Dunlapfb03d4f2011-05-09 10:47:51 -0700656 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -0700657}
658
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300659/* ----- Check_D_CISdata() ---------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700660int Check_D_CISdata(BYTE *buf, BYTE *redundant)
661{
Javier Martinez Canillas1b5b4e12011-01-02 23:14:26 +0100662 BYTE cis[] = {0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02,
663 0xDF, 0x01, 0x20};
Al Cho126bb032010-09-08 00:42:32 -0700664
Javier Martinez Canillas1b5b4e12011-01-02 23:14:26 +0100665 int cis_len = sizeof(cis);
Al Cho126bb032010-09-08 00:42:32 -0700666
Javier Martinez Canillas1b5b4e12011-01-02 23:14:26 +0100667 if (!IsSSFDCCompliance && !IsXDCompliance)
Randy Dunlapfb03d4f2011-05-09 10:47:51 -0700668 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -0700669
Javier Martinez Canillas1b5b4e12011-01-02 23:14:26 +0100670 if (!memcmp(redundant + 0x0D, EccBuf, 3))
671 return memcmp(buf, cis, cis_len);
Al Cho126bb032010-09-08 00:42:32 -0700672
Javier Martinez Canillas1b5b4e12011-01-02 23:14:26 +0100673 if (!_Correct_D_SwECC(buf, redundant + 0x0D, EccBuf))
674 return memcmp(buf, cis, cis_len);
Al Cho126bb032010-09-08 00:42:32 -0700675
Javier Martinez Canillas1b5b4e12011-01-02 23:14:26 +0100676 buf += 0x100;
677 if (!memcmp(redundant + 0x08, EccBuf + 0x03, 3))
678 return memcmp(buf, cis, cis_len);
Al Cho126bb032010-09-08 00:42:32 -0700679
Javier Martinez Canillas1b5b4e12011-01-02 23:14:26 +0100680 if (!_Correct_D_SwECC(buf, redundant + 0x08, EccBuf + 0x03))
681 return memcmp(buf, cis, cis_len);
682
683 return ERROR;
Al Cho126bb032010-09-08 00:42:32 -0700684}
685
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300686/* ----- Set_D_RightECC() ---------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700687void Set_D_RightECC(BYTE *redundant)
688{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300689 /* Driver ECC Check */
Al Cho126bb032010-09-08 00:42:32 -0700690 return;
Al Cho126bb032010-09-08 00:42:32 -0700691}
Al Cho126bb032010-09-08 00:42:32 -0700692
Al Cho126bb032010-09-08 00:42:32 -0700693