blob: 346c5702f41116ad549dcf5bf3c9caf7fb5920e8 [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
Johannes Schilling8be88042013-06-06 18:10:45 +020036struct keucr_media_info Ssfdc;
37struct keucr_media_address Media;
38struct keucr_media_area CisArea;
Al Cho126bb032010-09-08 00:42:32 -070039
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
Amarjargal Gundjalamb9594b82013-05-17 01:06:49 -0700106 addr1 = (WORD)*(redundant + REDT_ADDR1H)*0x0100 +
107 (WORD)*(redundant + REDT_ADDR1L);
108 addr2 = (WORD)*(redundant + REDT_ADDR2H)*0x0100 +
109 (WORD)*(redundant + REDT_ADDR2L);
Al Cho126bb032010-09-08 00:42:32 -0700110
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300111 if (addr1 == addr2)
112 if ((addr1 & 0xF000) == 0x1000) {
113 Media.LogBlock = (addr1 & 0x0FFF) / 2;
114 return SMSUCCESS;
115 }
Al Cho126bb032010-09-08 00:42:32 -0700116
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300117 if (hweight16((WORD)(addr1^addr2)) != 0x01)
118 return ERROR;
Al Cho126bb032010-09-08 00:42:32 -0700119
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300120 if ((addr1 & 0xF000) == 0x1000)
121 if (!(hweight16(addr1) & 0x01)) {
122 Media.LogBlock = (addr1 & 0x0FFF) / 2;
123 return SMSUCCESS;
124 }
Al Cho126bb032010-09-08 00:42:32 -0700125
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300126 if ((addr2 & 0xF000) == 0x1000)
127 if (!(hweight16(addr2) & 0x01)) {
128 Media.LogBlock = (addr2 & 0x0FFF) / 2;
129 return SMSUCCESS;
130 }
Al Cho126bb032010-09-08 00:42:32 -0700131
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300132 return ERROR;
Al Cho126bb032010-09-08 00:42:32 -0700133}
134
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300135/* ----- Clr_D_RedundantData() ------------------------------------------ */
Al Cho126bb032010-09-08 00:42:32 -0700136void Clr_D_RedundantData(BYTE *redundant)
137{
138 char i;
139
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300140 for (i = 0; i < REDTSIZE; i++)
141 *(redundant + i) = 0xFF;
Al Cho126bb032010-09-08 00:42:32 -0700142}
143
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300144/* ----- Set_D_LogBlockAddr() ------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700145void Set_D_LogBlockAddr(BYTE *redundant)
146{
147 WORD addr;
148
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300149 *(redundant + REDT_BLOCK) = 0xFF;
150 *(redundant + REDT_DATA) = 0xFF;
151 addr = Media.LogBlock*2 + 0x1000;
Al Cho126bb032010-09-08 00:42:32 -0700152
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300153 if ((hweight16(addr) % 2))
Al Cho126bb032010-09-08 00:42:32 -0700154 addr++;
155
Amarjargal Gundjalamb9594b82013-05-17 01:06:49 -0700156 *(redundant + REDT_ADDR1H) = *(redundant + REDT_ADDR2H) =
157 (BYTE)(addr / 0x0100);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300158 *(redundant + REDT_ADDR1L) = *(redundant + REDT_ADDR2L) = (BYTE)addr;
Al Cho126bb032010-09-08 00:42:32 -0700159}
160
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300161/*----- Set_D_FailBlock() ---------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700162void Set_D_FailBlock(BYTE *redundant)
163{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300164 char i;
165 for (i = 0; i < REDTSIZE; i++)
166 *redundant++ = (BYTE)((i == REDT_BLOCK) ? 0xF0 : 0xFF);
Al Cho126bb032010-09-08 00:42:32 -0700167}
168
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300169/* ----- Set_D_DataStaus() ---------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700170void Set_D_DataStaus(BYTE *redundant)
171{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300172 redundant += REDT_DATA;
173 *redundant = 0x00;
Al Cho126bb032010-09-08 00:42:32 -0700174}
175
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300176/* SmartMedia Function Command Subroutine
177 * 6250 CMD 6
178 */
179/* ----- Ssfdc_D_Reset() ------------------------------------------------ */
Al Cho126bb032010-09-08 00:42:32 -0700180void Ssfdc_D_Reset(struct us_data *us)
181{
Al Cho126bb032010-09-08 00:42:32 -0700182 return;
Al Cho126bb032010-09-08 00:42:32 -0700183}
184
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300185/* ----- Ssfdc_D_ReadCisSect() ------------------------------------------ */
186int Ssfdc_D_ReadCisSect(struct us_data *us, BYTE *buf, BYTE *redundant)
Al Cho126bb032010-09-08 00:42:32 -0700187{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300188 BYTE zone, sector;
Al Cho126bb032010-09-08 00:42:32 -0700189 WORD block;
Al Cho126bb032010-09-08 00:42:32 -0700190
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300191 zone = Media.Zone; block = Media.PhyBlock; sector = Media.Sector;
192 Media.Zone = 0;
193 Media.PhyBlock = CisArea.PhyBlock;
194 Media.Sector = CisArea.Sector;
Al Cho126bb032010-09-08 00:42:32 -0700195
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300196 if (Ssfdc_D_ReadSect(us, buf, redundant)) {
Amarjargal Gundjalamb9594b82013-05-17 01:06:49 -0700197 Media.Zone = zone;
198 Media.PhyBlock = block;
199 Media.Sector = sector;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300200 return ERROR;
Al Cho126bb032010-09-08 00:42:32 -0700201 }
202
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300203 Media.Zone = zone; Media.PhyBlock = block; Media.Sector = sector;
204 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -0700205}
Ruslan Pisarev74a5e012011-07-22 14:17:04 +0300206
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300207/* 6250 CMD 1 */
208/* ----- Ssfdc_D_ReadSect() --------------------------------------------- */
209int Ssfdc_D_ReadSect(struct us_data *us, BYTE *buf, BYTE *redundant)
Al Cho126bb032010-09-08 00:42:32 -0700210{
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);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300216 if (result != USB_STOR_XFER_GOOD) {
Laura Lawniczak6fbb90b2013-06-06 18:10:48 +0200217 dev_err(&us->pusb_dev->dev,
218 "Failed to load SmartMedia read/write code\n");
Al Cho126bb032010-09-08 00:42:32 -0700219 return USB_STOR_TRANSPORT_ERROR;
220 }
221
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300222 addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
223 addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
Al Cho126bb032010-09-08 00:42:32 -0700224
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300225 /* Read sect data */
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100226 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700227 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300233 bcb->CDB[3] = (BYTE)(addr / 0x0100);
234 bcb->CDB[2] = Media.Zone / 2;
Al Cho126bb032010-09-08 00:42:32 -0700235
236 result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
237 if (result != USB_STOR_XFER_GOOD)
238 return USB_STOR_TRANSPORT_ERROR;
239
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300240 /* Read redundant */
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100241 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700242 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300248 bcb->CDB[3] = (BYTE)(addr / 0x0100);
249 bcb->CDB[2] = Media.Zone / 2;
Al Cho126bb032010-09-08 00:42:32 -0700250 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
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300260/* ----- Ssfdc_D_ReadBlock() --------------------------------------------- */
Amarjargal Gundjalamb9594b82013-05-17 01:06:49 -0700261int Ssfdc_D_ReadBlock(struct us_data *us, WORD count, BYTE *buf,
262 BYTE *redundant)
Al Cho126bb032010-09-08 00:42:32 -0700263{
264 struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
265 int result;
266 WORD addr;
267
Al Cho126bb032010-09-08 00:42:32 -0700268 result = ENE_LoadBinCode(us, SM_RW_PATTERN);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300269 if (result != USB_STOR_XFER_GOOD) {
Laura Lawniczak6fbb90b2013-06-06 18:10:48 +0200270 dev_err(&us->pusb_dev->dev,
271 "Failed to load SmartMedia read/write code\n");
Al Cho126bb032010-09-08 00:42:32 -0700272 return USB_STOR_TRANSPORT_ERROR;
273 }
274
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300275 addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
276 addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
Al Cho126bb032010-09-08 00:42:32 -0700277
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300278 /* Read sect data */
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100279 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700280 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300286 bcb->CDB[3] = (BYTE)(addr / 0x0100);
287 bcb->CDB[2] = Media.Zone / 2;
Al Cho126bb032010-09-08 00:42:32 -0700288
289 result = ENE_SendScsiCmd(us, FDIR_READ, buf, 0);
290 if (result != USB_STOR_XFER_GOOD)
291 return USB_STOR_TRANSPORT_ERROR;
292
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300293 /* Read redundant */
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100294 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700295 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300301 bcb->CDB[3] = (BYTE)(addr / 0x0100);
302 bcb->CDB[2] = Media.Zone / 2;
Al Cho126bb032010-09-08 00:42:32 -0700303 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}
Al Cho126bb032010-09-08 00:42:32 -0700312
Al Cho126bb032010-09-08 00:42:32 -0700313
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300314/* ----- Ssfdc_D_CopyBlock() -------------------------------------------- */
Amarjargal Gundjalamb9594b82013-05-17 01:06:49 -0700315int Ssfdc_D_CopyBlock(struct us_data *us, WORD count, BYTE *buf,
316 BYTE *redundant)
Al Cho126bb032010-09-08 00:42:32 -0700317{
318 struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
319 int result;
Al Cho126bb032010-09-08 00:42:32 -0700320 WORD ReadAddr, WriteAddr;
321
Al Cho126bb032010-09-08 00:42:32 -0700322 result = ENE_LoadBinCode(us, SM_RW_PATTERN);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300323 if (result != USB_STOR_XFER_GOOD) {
Laura Lawniczak6fbb90b2013-06-06 18:10:48 +0200324 dev_err(&us->pusb_dev->dev,
325 "Failed to load SmartMedia read/write code\n");
Al Cho126bb032010-09-08 00:42:32 -0700326 return USB_STOR_TRANSPORT_ERROR;
327 }
328
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300329 ReadAddr = (WORD)Media.Zone*Ssfdc.MaxBlocks + ReadBlock;
Al Cho126bb032010-09-08 00:42:32 -0700330 ReadAddr = ReadAddr*(WORD)Ssfdc.MaxSectors;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300331 WriteAddr = (WORD)Media.Zone*Ssfdc.MaxBlocks + WriteBlock;
Al Cho126bb032010-09-08 00:42:32 -0700332 WriteAddr = WriteAddr*(WORD)Ssfdc.MaxSectors;
333
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300334 /* Write sect data */
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100335 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700336 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300342 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);
Al Cho126bb032010-09-08 00:42:32 -0700346 bcb->CDB[10] = Media.Sector;
347
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300348 if (ReadBlock != NO_ASSIGN) {
Al Cho126bb032010-09-08 00:42:32 -0700349 bcb->CDB[4] = (BYTE)ReadAddr;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300350 bcb->CDB[3] = (BYTE)(ReadAddr / 0x0100);
351 bcb->CDB[2] = Media.Zone / 2;
352 } else
Al Cho126bb032010-09-08 00:42:32 -0700353 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}
Al Cho126bb032010-09-08 00:42:32 -0700361
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300362/* ----- Ssfdc_D_WriteSectForCopy() ------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700363int 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300367 WORD addr;
Al Cho126bb032010-09-08 00:42:32 -0700368
Al Cho126bb032010-09-08 00:42:32 -0700369 result = ENE_LoadBinCode(us, SM_RW_PATTERN);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300370 if (result != USB_STOR_XFER_GOOD) {
Laura Lawniczak6fbb90b2013-06-06 18:10:48 +0200371 dev_err(&us->pusb_dev->dev,
372 "Failed to load SmartMedia read/write code\n");
Al Cho126bb032010-09-08 00:42:32 -0700373 return USB_STOR_TRANSPORT_ERROR;
374 }
375
376
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300377 addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
378 addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
Al Cho126bb032010-09-08 00:42:32 -0700379
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300380 /* Write sect data */
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100381 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700382 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300388 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);
Al Cho126bb032010-09-08 00:42:32 -0700392
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
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300400/* 6250 CMD 5 */
401/* ----- Ssfdc_D_EraseBlock() ------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700402int 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);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300409 if (result != USB_STOR_XFER_GOOD) {
Laura Lawniczak6fbb90b2013-06-06 18:10:48 +0200410 dev_err(&us->pusb_dev->dev,
411 "Failed to load SmartMedia read/write code\n");
Al Cho126bb032010-09-08 00:42:32 -0700412 return USB_STOR_TRANSPORT_ERROR;
413 }
414
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300415 addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
416 addr = addr*(WORD)Ssfdc.MaxSectors;
Al Cho126bb032010-09-08 00:42:32 -0700417
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100418 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700419 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300425 bcb->CDB[6] = (BYTE)(addr / 0x0100);
426 bcb->CDB[5] = Media.Zone / 2;
Al Cho126bb032010-09-08 00:42:32 -0700427
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
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300435/* 6250 CMD 2 */
436/*----- Ssfdc_D_ReadRedtData() ----------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700437int 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300442 BYTE *buf;
Al Cho126bb032010-09-08 00:42:32 -0700443
444 result = ENE_LoadBinCode(us, SM_RW_PATTERN);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300445 if (result != USB_STOR_XFER_GOOD) {
Laura Lawniczak6fbb90b2013-06-06 18:10:48 +0200446 dev_err(&us->pusb_dev->dev,
447 "Failed to load SmartMedia read/write code\n");
Al Cho126bb032010-09-08 00:42:32 -0700448 return USB_STOR_TRANSPORT_ERROR;
449 }
450
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300451 addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
452 addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
Al Cho126bb032010-09-08 00:42:32 -0700453
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100454 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700455 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300461 bcb->CDB[3] = (BYTE)(addr / 0x0100);
462 bcb->CDB[2] = Media.Zone / 2;
Al Cho126bb032010-09-08 00:42:32 -0700463 bcb->CDB[8] = 0;
464 bcb->CDB[9] = 1;
465
466 buf = kmalloc(0x10, GFP_KERNEL);
Al Cho126bb032010-09-08 00:42:32 -0700467 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
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300476/* 6250 CMD 4 */
477/* ----- Ssfdc_D_WriteRedtData() ---------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700478int 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;
Al Cho126bb032010-09-08 00:42:32 -0700482 WORD addr;
483
484 result = ENE_LoadBinCode(us, SM_RW_PATTERN);
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300485 if (result != USB_STOR_XFER_GOOD) {
Laura Lawniczak6fbb90b2013-06-06 18:10:48 +0200486 dev_err(&us->pusb_dev->dev,
487 "Failed to load SmartMedia read/write code\n");
Al Cho126bb032010-09-08 00:42:32 -0700488 return USB_STOR_TRANSPORT_ERROR;
489 }
490
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300491 addr = (WORD)Media.Zone*Ssfdc.MaxBlocks + Media.PhyBlock;
492 addr = addr*(WORD)Ssfdc.MaxSectors + Media.Sector;
Al Cho126bb032010-09-08 00:42:32 -0700493
Konstantin Katuev307ae1d2010-10-29 12:18:18 +1100494 memset(bcb, 0, sizeof(struct bulk_cb_wrap));
Al Cho126bb032010-09-08 00:42:32 -0700495 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;
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300501 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);
Al Cho126bb032010-09-08 00:42:32 -0700505
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
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300513/* ----- Ssfdc_D_CheckStatus() ------------------------------------------ */
Al Cho126bb032010-09-08 00:42:32 -0700514int Ssfdc_D_CheckStatus(void)
515{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300516 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -0700517}
Ruslan Pisarev74a5e012011-07-22 14:17:04 +0300518
519
520
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300521/* SmartMedia ID Code Check & Mode Set Subroutine
522 * ----- Set_D_SsfdcModel() ---------------------------------------------
523 */
Al Cho126bb032010-09-08 00:42:32 -0700524int Set_D_SsfdcModel(BYTE dcode)
525{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300526 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 }
Al Cho126bb032010-09-08 00:42:32 -0700627
Amarjargal Gundjalam5a5097a2013-05-17 01:06:19 -0700628 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -0700629}
630
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300631/* ----- _Check_D_DevCode() --------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700632BYTE _Check_D_DevCode(BYTE dcode)
633{
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300634 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 }
Al Cho126bb032010-09-08 00:42:32 -0700654}
Ruslan Pisarev74a5e012011-07-22 14:17:04 +0300655
656
657
658
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300659/* SmartMedia ECC Control Subroutine
660 * ----- Check_D_ReadError() ----------------------------------------------
661 */
Al Cho126bb032010-09-08 00:42:32 -0700662int Check_D_ReadError(BYTE *redundant)
663{
Randy Dunlapfb03d4f2011-05-09 10:47:51 -0700664 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -0700665}
666
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300667/* ----- Check_D_Correct() ---------------------------------------------- */
668int Check_D_Correct(BYTE *buf, BYTE *redundant)
Al Cho126bb032010-09-08 00:42:32 -0700669{
Randy Dunlapfb03d4f2011-05-09 10:47:51 -0700670 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -0700671}
672
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300673/* ----- Check_D_CISdata() ---------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700674int Check_D_CISdata(BYTE *buf, BYTE *redundant)
675{
Javier Martinez Canillas1b5b4e12011-01-02 23:14:26 +0100676 BYTE cis[] = {0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02,
677 0xDF, 0x01, 0x20};
Al Cho126bb032010-09-08 00:42:32 -0700678
Javier Martinez Canillas1b5b4e12011-01-02 23:14:26 +0100679 int cis_len = sizeof(cis);
Al Cho126bb032010-09-08 00:42:32 -0700680
Javier Martinez Canillas1b5b4e12011-01-02 23:14:26 +0100681 if (!IsSSFDCCompliance && !IsXDCompliance)
Randy Dunlapfb03d4f2011-05-09 10:47:51 -0700682 return SMSUCCESS;
Al Cho126bb032010-09-08 00:42:32 -0700683
Javier Martinez Canillas1b5b4e12011-01-02 23:14:26 +0100684 if (!memcmp(redundant + 0x0D, EccBuf, 3))
685 return memcmp(buf, cis, cis_len);
Al Cho126bb032010-09-08 00:42:32 -0700686
Javier Martinez Canillas1b5b4e12011-01-02 23:14:26 +0100687 if (!_Correct_D_SwECC(buf, redundant + 0x0D, EccBuf))
688 return memcmp(buf, cis, cis_len);
Al Cho126bb032010-09-08 00:42:32 -0700689
Javier Martinez Canillas1b5b4e12011-01-02 23:14:26 +0100690 buf += 0x100;
691 if (!memcmp(redundant + 0x08, EccBuf + 0x03, 3))
692 return memcmp(buf, cis, cis_len);
Al Cho126bb032010-09-08 00:42:32 -0700693
Javier Martinez Canillas1b5b4e12011-01-02 23:14:26 +0100694 if (!_Correct_D_SwECC(buf, redundant + 0x08, EccBuf + 0x03))
695 return memcmp(buf, cis, cis_len);
696
697 return ERROR;
Al Cho126bb032010-09-08 00:42:32 -0700698}
699
Ruslan Pisarev50d487e32011-07-22 14:17:23 +0300700/* ----- Set_D_RightECC() ---------------------------------------------- */
Al Cho126bb032010-09-08 00:42:32 -0700701void Set_D_RightECC(BYTE *redundant)
702{
Amarjargal Gundjalam5a5097a2013-05-17 01:06:19 -0700703 /* Driver ECC Check */
704 return;
Al Cho126bb032010-09-08 00:42:32 -0700705}
Al Cho126bb032010-09-08 00:42:32 -0700706
Al Cho126bb032010-09-08 00:42:32 -0700707