block/spectra: use do_div() for 64bit divs
[pandora-kernel.git] / drivers / block / spectra / lld_emu.c
1 /*
2  * NAND Flash Controller Device Driver
3  * Copyright (c) 2009, Intel Corporation and its suppliers.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  */
19
20 #include <linux/fs.h>
21 #include <linux/slab.h>
22 #include "flash.h"
23 #include "ffsdefs.h"
24 #include "lld_emu.h"
25 #include "lld.h"
26 #if CMD_DMA
27 #include "lld_cdma.h"
28 #endif
29
30 #define GLOB_LLD_PAGES           64
31 #define GLOB_LLD_PAGE_SIZE       (512+16)
32 #define GLOB_LLD_PAGE_DATA_SIZE  512
33 #define GLOB_LLD_BLOCKS          2048
34
35 #if (CMD_DMA  && FLASH_EMU)
36 #include "lld_cdma.h"
37 u32 totalUsedBanks;
38 u32 valid_banks[MAX_CHANS];
39 #endif
40
41 #if FLASH_EMU                   /* This is for entire module */
42
43 static u8 *flash_memory[GLOB_LLD_BLOCKS * GLOB_LLD_PAGES];
44
45 /* Read nand emu file and then fill it's content to flash_memory */
46 int emu_load_file_to_mem(void)
47 {
48         mm_segment_t fs;
49         struct file *nef_filp = NULL;
50         struct inode *inode = NULL;
51         loff_t nef_size = 0;
52         loff_t tmp_file_offset, file_offset;
53         ssize_t nread;
54         int i, rc = -EINVAL;
55
56         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
57                        __FILE__, __LINE__, __func__);
58
59         fs = get_fs();
60         set_fs(get_ds());
61
62         nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0);
63         if (IS_ERR(nef_filp)) {
64                 printk(KERN_ERR "filp_open error: "
65                        "Unable to open nand emu file!\n");
66                 return PTR_ERR(nef_filp);
67         }
68
69         if (nef_filp->f_path.dentry) {
70                 inode = nef_filp->f_path.dentry->d_inode;
71         } else {
72                 printk(KERN_ERR "Can not get valid inode!\n");
73                 goto out;
74         }
75
76         nef_size = i_size_read(inode->i_mapping->host);
77         if (nef_size <= 0) {
78                 printk(KERN_ERR "Invalid nand emu file size: "
79                        "0x%llx\n", nef_size);
80                 goto out;
81         } else {
82                 nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: %lld\n",
83                                nef_size);
84         }
85
86         file_offset = 0;
87         for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) {
88                 tmp_file_offset = file_offset;
89                 nread = vfs_read(nef_filp,
90                                  (char __user *)flash_memory[i],
91                                  GLOB_LLD_PAGE_SIZE, &tmp_file_offset);
92                 if (nread < GLOB_LLD_PAGE_SIZE) {
93                         printk(KERN_ERR "%s, Line %d - "
94                                "nand emu file partial read: "
95                                "%d bytes\n", __FILE__, __LINE__, (int)nread);
96                         goto out;
97                 }
98                 file_offset += GLOB_LLD_PAGE_SIZE;
99         }
100         rc = 0;
101
102 out:
103         filp_close(nef_filp, current->files);
104         set_fs(fs);
105         return rc;
106 }
107
108 /* Write contents of flash_memory to nand emu file */
109 int emu_write_mem_to_file(void)
110 {
111         mm_segment_t fs;
112         struct file *nef_filp = NULL;
113         struct inode *inode = NULL;
114         loff_t nef_size = 0;
115         loff_t tmp_file_offset, file_offset;
116         ssize_t nwritten;
117         int i, rc = -EINVAL;
118
119         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
120                        __FILE__, __LINE__, __func__);
121
122         fs = get_fs();
123         set_fs(get_ds());
124
125         nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0);
126         if (IS_ERR(nef_filp)) {
127                 printk(KERN_ERR "filp_open error: "
128                        "Unable to open nand emu file!\n");
129                 return PTR_ERR(nef_filp);
130         }
131
132         if (nef_filp->f_path.dentry) {
133                 inode = nef_filp->f_path.dentry->d_inode;
134         } else {
135                 printk(KERN_ERR "Invalid " "nef_filp->f_path.dentry value!\n");
136                 goto out;
137         }
138
139         nef_size = i_size_read(inode->i_mapping->host);
140         if (nef_size <= 0) {
141                 printk(KERN_ERR "Invalid "
142                        "nand emu file size: 0x%llx\n", nef_size);
143                 goto out;
144         } else {
145                 nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: "
146                                "%lld\n", nef_size);
147         }
148
149         file_offset = 0;
150         for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) {
151                 tmp_file_offset = file_offset;
152                 nwritten = vfs_write(nef_filp,
153                                      (char __user *)flash_memory[i],
154                                      GLOB_LLD_PAGE_SIZE, &tmp_file_offset);
155                 if (nwritten < GLOB_LLD_PAGE_SIZE) {
156                         printk(KERN_ERR "%s, Line %d - "
157                                "nand emu file partial write: "
158                                "%d bytes\n", __FILE__, __LINE__, (int)nwritten);
159                         goto out;
160                 }
161                 file_offset += GLOB_LLD_PAGE_SIZE;
162         }
163         rc = 0;
164
165 out:
166         filp_close(nef_filp, current->files);
167         set_fs(fs);
168         return rc;
169 }
170
171 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
172 * Function:     emu_Flash_Init
173 * Inputs:       none
174 * Outputs:      PASS=0 (notice 0=ok here)
175 * Description:  Creates & initializes the flash RAM array.
176 *
177 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
178 u16 emu_Flash_Init(void)
179 {
180         int i;
181
182         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
183                        __FILE__, __LINE__, __func__);
184
185         flash_memory[0] = (u8 *)vmalloc(GLOB_LLD_PAGE_SIZE *
186                                                    GLOB_LLD_BLOCKS *
187                                                    GLOB_LLD_PAGES *
188                                                    sizeof(u8));
189         if (!flash_memory[0]) {
190                 printk(KERN_ERR "Fail to allocate memory "
191                        "for nand emulator!\n");
192                 return ERR;
193         }
194
195         memset((char *)(flash_memory[0]), 0xFF,
196                GLOB_LLD_PAGE_SIZE * GLOB_LLD_BLOCKS * GLOB_LLD_PAGES *
197                sizeof(u8));
198
199         for (i = 1; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++)
200                 flash_memory[i] = flash_memory[i - 1] + GLOB_LLD_PAGE_SIZE;
201
202         emu_load_file_to_mem(); /* Load nand emu file to mem */
203
204         return PASS;
205 }
206
207 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
208 * Function:     emu_Flash_Release
209 * Inputs:       none
210 * Outputs:      PASS=0 (notice 0=ok here)
211 * Description:          Releases the flash.
212 *
213 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
214 int emu_Flash_Release(void)
215 {
216         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
217                        __FILE__, __LINE__, __func__);
218
219         emu_write_mem_to_file();  /* Write back mem to nand emu file */
220
221         vfree(flash_memory[0]);
222         return PASS;
223 }
224
225 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
226 * Function:     emu_Read_Device_ID
227 * Inputs:       none
228 * Outputs:      PASS=1 FAIL=0
229 * Description:  Reads the info from the controller registers.
230 *               Sets up DeviceInfo structure with device parameters
231 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
232
233 u16 emu_Read_Device_ID(void)
234 {
235         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
236                        __FILE__, __LINE__, __func__);
237
238         DeviceInfo.wDeviceMaker = 0;
239         DeviceInfo.wDeviceType = 8;
240         DeviceInfo.wSpectraStartBlock = 36;
241         DeviceInfo.wSpectraEndBlock = GLOB_LLD_BLOCKS - 1;
242         DeviceInfo.wTotalBlocks = GLOB_LLD_BLOCKS;
243         DeviceInfo.wPagesPerBlock = GLOB_LLD_PAGES;
244         DeviceInfo.wPageSize = GLOB_LLD_PAGE_SIZE;
245         DeviceInfo.wPageDataSize = GLOB_LLD_PAGE_DATA_SIZE;
246         DeviceInfo.wPageSpareSize = GLOB_LLD_PAGE_SIZE -
247             GLOB_LLD_PAGE_DATA_SIZE;
248         DeviceInfo.wBlockSize = DeviceInfo.wPageSize * GLOB_LLD_PAGES;
249         DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * GLOB_LLD_PAGES;
250         DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock -
251                                                 DeviceInfo.wSpectraStartBlock
252                                                 + 1);
253         DeviceInfo.MLCDevice = 1; /* Emulate MLC device */
254         DeviceInfo.nBitsInPageNumber =
255                 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock);
256         DeviceInfo.nBitsInPageDataSize =
257                 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize);
258         DeviceInfo.nBitsInBlockDataSize =
259                 (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize);
260
261 #if CMD_DMA
262         totalUsedBanks = 4;
263         valid_banks[0] = 1;
264         valid_banks[1] = 1;
265         valid_banks[2] = 1;
266         valid_banks[3] = 1;
267 #endif
268
269         return PASS;
270 }
271
272 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
273 * Function:     emu_Flash_Reset
274 * Inputs:       none
275 * Outputs:      PASS=0 (notice 0=ok here)
276 * Description:          Reset the flash
277 *
278 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
279 u16 emu_Flash_Reset(void)
280 {
281         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
282                        __FILE__, __LINE__, __func__);
283
284         return PASS;
285 }
286
287 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
288 * Function:     emu_Erase_Block
289 * Inputs:       Address
290 * Outputs:      PASS=0 (notice 0=ok here)
291 * Description:          Erase a block
292 *
293 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
294 u16 emu_Erase_Block(u32 block_add)
295 {
296         int i;
297
298         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
299                        __FILE__, __LINE__, __func__);
300
301         if (block_add >= DeviceInfo.wTotalBlocks) {
302                 printk(KERN_ERR "emu_Erase_Block error! "
303                        "Too big block address: %d\n", block_add);
304                 return FAIL;
305         }
306
307         nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n",
308                 (int)block_add);
309
310         for (i = block_add * GLOB_LLD_PAGES;
311              i < ((block_add + 1) * GLOB_LLD_PAGES); i++) {
312                 if (flash_memory[i]) {
313                         memset((u8 *)(flash_memory[i]), 0xFF,
314                                DeviceInfo.wPageSize * sizeof(u8));
315                 }
316         }
317
318         return PASS;
319 }
320
321 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
322 * Function:     emu_Write_Page_Main
323 * Inputs:       Write buffer address pointer
324 *               Block number
325 *               Page  number
326 *               Number of pages to process
327 * Outputs:      PASS=0 (notice 0=ok here)
328 * Description:  Write the data in the buffer to main area of flash
329 *
330 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
331 u16 emu_Write_Page_Main(u8 *write_data, u32 Block,
332                            u16 Page, u16 PageCount)
333 {
334         int i;
335
336         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
337                        __FILE__, __LINE__, __func__);
338
339         if (Block >= DeviceInfo.wTotalBlocks)
340                 return FAIL;
341
342         if (Page + PageCount > DeviceInfo.wPagesPerBlock)
343                 return FAIL;
344
345         nand_dbg_print(NAND_DBG_DEBUG, "emu_Write_Page_Main: "
346                        "lba %u Page %u PageCount %u\n",
347                        (unsigned int)Block,
348                        (unsigned int)Page, (unsigned int)PageCount);
349
350         for (i = 0; i < PageCount; i++) {
351                 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
352                         printk(KERN_ERR "Run out of memory\n");
353                         return FAIL;
354                 }
355                 memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]),
356                        write_data, DeviceInfo.wPageDataSize);
357                 write_data += DeviceInfo.wPageDataSize;
358                 Page++;
359         }
360
361         return PASS;
362 }
363
364 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
365 * Function:     emu_Read_Page_Main
366 * Inputs:       Read buffer address pointer
367 *               Block number
368 *               Page  number
369 *               Number of pages to process
370 * Outputs:      PASS=0 (notice 0=ok here)
371 * Description:  Read the data from the flash main area to the buffer
372 *
373 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
374 u16 emu_Read_Page_Main(u8 *read_data, u32 Block,
375                           u16 Page, u16 PageCount)
376 {
377         int i;
378
379         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
380                        __FILE__, __LINE__, __func__);
381
382         if (Block >= DeviceInfo.wTotalBlocks)
383                 return FAIL;
384
385         if (Page + PageCount > DeviceInfo.wPagesPerBlock)
386                 return FAIL;
387
388         nand_dbg_print(NAND_DBG_DEBUG, "emu_Read_Page_Main: "
389                        "lba %u Page %u PageCount %u\n",
390                        (unsigned int)Block,
391                        (unsigned int)Page, (unsigned int)PageCount);
392
393         for (i = 0; i < PageCount; i++) {
394                 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
395                         memset(read_data, 0xFF, DeviceInfo.wPageDataSize);
396                 } else {
397                         memcpy(read_data,
398                                (u8 *) (flash_memory[Block * GLOB_LLD_PAGES
399                                                       + Page]),
400                                DeviceInfo.wPageDataSize);
401                 }
402                 read_data += DeviceInfo.wPageDataSize;
403                 Page++;
404         }
405
406         return PASS;
407 }
408
409 #ifndef ELDORA
410 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
411 * Function:     emu_Read_Page_Main_Spare
412 * Inputs:       Write Buffer
413 *                       Address
414 *                       Buffer size
415 * Outputs:      PASS=0 (notice 0=ok here)
416 * Description:          Read from flash main+spare area
417 *
418 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
419 u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block,
420                                 u16 Page, u16 PageCount)
421 {
422         int i;
423
424         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
425                        __FILE__, __LINE__, __func__);
426
427         if (Block >= DeviceInfo.wTotalBlocks) {
428                 printk(KERN_ERR "Read Page Main+Spare "
429                        "Error: Block Address too big\n");
430                 return FAIL;
431         }
432
433         if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
434                 printk(KERN_ERR "Read Page Main+Spare "
435                        "Error: Page number too big\n");
436                 return FAIL;
437         }
438
439         nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - "
440                        "No. of pages %u block %u start page %u\n",
441                        (unsigned int)PageCount,
442                        (unsigned int)Block, (unsigned int)Page);
443
444         for (i = 0; i < PageCount; i++) {
445                 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
446                         memset(read_data, 0xFF, DeviceInfo.wPageSize);
447                 } else {
448                         memcpy(read_data, (u8 *) (flash_memory[Block *
449                                                                  GLOB_LLD_PAGES
450                                                                  + Page]),
451                                DeviceInfo.wPageSize);
452                 }
453
454                 read_data += DeviceInfo.wPageSize;
455                 Page++;
456         }
457
458         return PASS;
459 }
460
461 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
462 * Function:     emu_Write_Page_Main_Spare
463 * Inputs:       Write buffer
464 *                       address
465 *                       buffer length
466 * Outputs:      PASS=0 (notice 0=ok here)
467 * Description:          Write the buffer to main+spare area of flash
468 *
469 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
470 u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block,
471                                  u16 Page, u16 page_count)
472 {
473         u16 i;
474
475         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
476                        __FILE__, __LINE__, __func__);
477
478         if (Block >= DeviceInfo.wTotalBlocks) {
479                 printk(KERN_ERR "Write Page Main + Spare "
480                        "Error: Block Address too big\n");
481                 return FAIL;
482         }
483
484         if (Page + page_count > DeviceInfo.wPagesPerBlock) {
485                 printk(KERN_ERR "Write Page Main + Spare "
486                        "Error: Page number too big\n");
487                 return FAIL;
488         }
489
490         nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - "
491                        "No. of pages %u block %u start page %u\n",
492                        (unsigned int)page_count,
493                        (unsigned int)Block, (unsigned int)Page);
494
495         for (i = 0; i < page_count; i++) {
496                 if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
497                         printk(KERN_ERR "Run out of memory!\n");
498                         return FAIL;
499                 }
500                 memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]),
501                        write_data, DeviceInfo.wPageSize);
502                 write_data += DeviceInfo.wPageSize;
503                 Page++;
504         }
505
506         return PASS;
507 }
508
509 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
510 * Function:     emu_Write_Page_Spare
511 * Inputs:       Write buffer
512 *                       Address
513 *                       buffer size
514 * Outputs:      PASS=0 (notice 0=ok here)
515 * Description:          Write the buffer in the spare area
516 *
517 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
518 u16 emu_Write_Page_Spare(u8 *write_data, u32 Block,
519                             u16 Page, u16 PageCount)
520 {
521         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
522                        __FILE__, __LINE__, __func__);
523
524         if (Block >= DeviceInfo.wTotalBlocks) {
525                 printk(KERN_ERR "Read Page Spare Error: "
526                        "Block Address too big\n");
527                 return FAIL;
528         }
529
530         if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
531                 printk(KERN_ERR "Read Page Spare Error: "
532                        "Page number too big\n");
533                 return FAIL;
534         }
535
536         nand_dbg_print(NAND_DBG_DEBUG, "Write Page Spare- "
537                        "block %u page %u\n",
538                        (unsigned int)Block, (unsigned int)Page);
539
540         if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
541                 printk(KERN_ERR "Run out of memory!\n");
542                 return FAIL;
543         }
544
545         memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page] +
546                          DeviceInfo.wPageDataSize), write_data,
547                (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
548
549         return PASS;
550 }
551
552 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
553 * Function:     emu_Read_Page_Spare
554 * Inputs:       Write Buffer
555 *                       Address
556 *                       Buffer size
557 * Outputs:      PASS=0 (notice 0=ok here)
558 * Description:          Read data from the spare area
559 *
560 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
561 u16 emu_Read_Page_Spare(u8 *write_data, u32 Block,
562                            u16 Page, u16 PageCount)
563 {
564         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
565                        __FILE__, __LINE__, __func__);
566
567         if (Block >= DeviceInfo.wTotalBlocks) {
568                 printk(KERN_ERR "Read Page Spare "
569                        "Error: Block Address too big\n");
570                 return FAIL;
571         }
572
573         if (Page + PageCount > DeviceInfo.wPagesPerBlock) {
574                 printk(KERN_ERR "Read Page Spare "
575                        "Error: Page number too big\n");
576                 return FAIL;
577         }
578
579         nand_dbg_print(NAND_DBG_DEBUG, "Read Page Spare- "
580                        "block %u page %u\n",
581                        (unsigned int)Block, (unsigned int)Page);
582
583         if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) {
584                 memset(write_data, 0xFF,
585                        (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
586         } else {
587                 memcpy(write_data,
588                        (u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]
589                                  + DeviceInfo.wPageDataSize),
590                        (DeviceInfo.wPageSize - DeviceInfo.wPageDataSize));
591         }
592
593         return PASS;
594 }
595
596 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
597 * Function:     emu_Enable_Disable_Interrupts
598 * Inputs:       enable or disable
599 * Outputs:      none
600 * Description:  NOP
601 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
602 void emu_Enable_Disable_Interrupts(u16 INT_ENABLE)
603 {
604         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
605                        __FILE__, __LINE__, __func__);
606 }
607
608 u16 emu_Get_Bad_Block(u32 block)
609 {
610         return 0;
611 }
612
613 #if CMD_DMA
614 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
615 * Support for CDMA functions
616 ************************************
617 *       emu_CDMA_Flash_Init
618 *           CDMA_process_data command   (use LLD_CDMA)
619 *           CDMA_MemCopy_CMD            (use LLD_CDMA)
620 *       emu_CDMA_execute all commands
621 *       emu_CDMA_Event_Status
622 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
623 u16 emu_CDMA_Flash_Init(void)
624 {
625         u16 i;
626
627         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
628                        __FILE__, __LINE__, __func__);
629
630         for (i = 0; i < MAX_DESCS + MAX_CHANS; i++) {
631                 PendingCMD[i].CMD = 0;
632                 PendingCMD[i].Tag = 0;
633                 PendingCMD[i].DataAddr = 0;
634                 PendingCMD[i].Block = 0;
635                 PendingCMD[i].Page = 0;
636                 PendingCMD[i].PageCount = 0;
637                 PendingCMD[i].DataDestAddr = 0;
638                 PendingCMD[i].DataSrcAddr = 0;
639                 PendingCMD[i].MemCopyByteCnt = 0;
640                 PendingCMD[i].ChanSync[0] = 0;
641                 PendingCMD[i].ChanSync[1] = 0;
642                 PendingCMD[i].ChanSync[2] = 0;
643                 PendingCMD[i].ChanSync[3] = 0;
644                 PendingCMD[i].ChanSync[4] = 0;
645                 PendingCMD[i].Status = 3;
646         }
647
648         return PASS;
649 }
650
651 static void emu_isr(int irq, void *dev_id)
652 {
653         /* TODO:  ... */
654 }
655
656 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
657 * Function:     CDMA_Execute_CMDs
658 * Inputs:       tag_count:  the number of pending cmds to do
659 * Outputs:      PASS/FAIL
660 * Description:  execute each command in the pending CMD array
661 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
662 u16 emu_CDMA_Execute_CMDs(u16 tag_count)
663 {
664         u16 i, j;
665         u8 CMD;         /* cmd parameter */
666         u8 *data;
667         u32 block;
668         u16 page;
669         u16 count;
670         u16 status = PASS;
671
672         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
673                        __FILE__, __LINE__, __func__);
674
675         nand_dbg_print(NAND_DBG_TRACE, "At start of Execute CMDs: "
676                        "Tag Count %u\n", tag_count);
677
678         for (i = 0; i < totalUsedBanks; i++) {
679                 PendingCMD[i].CMD = DUMMY_CMD;
680                 PendingCMD[i].Tag = 0xFF;
681                 PendingCMD[i].Block =
682                     (DeviceInfo.wTotalBlocks / totalUsedBanks) * i;
683
684                 for (j = 0; j <= MAX_CHANS; j++)
685                         PendingCMD[i].ChanSync[j] = 0;
686         }
687
688         CDMA_Execute_CMDs(tag_count);
689
690         print_pending_cmds(tag_count);
691
692 #if DEBUG_SYNC
693         }
694         debug_sync_cnt++;
695 #endif
696
697         for (i = MAX_CHANS;
698              i < tag_count + MAX_CHANS; i++) {
699                 CMD = PendingCMD[i].CMD;
700                 data = PendingCMD[i].DataAddr;
701                 block = PendingCMD[i].Block;
702                 page = PendingCMD[i].Page;
703                 count = PendingCMD[i].PageCount;
704
705                 switch (CMD) {
706                 case ERASE_CMD:
707                         emu_Erase_Block(block);
708                         PendingCMD[i].Status = PASS;
709                         break;
710                 case WRITE_MAIN_CMD:
711                         emu_Write_Page_Main(data, block, page, count);
712                         PendingCMD[i].Status = PASS;
713                         break;
714                 case WRITE_MAIN_SPARE_CMD:
715                         emu_Write_Page_Main_Spare(data, block, page, count);
716                         PendingCMD[i].Status = PASS;
717                         break;
718                 case READ_MAIN_CMD:
719                         emu_Read_Page_Main(data, block, page, count);
720                         PendingCMD[i].Status = PASS;
721                         break;
722                 case MEMCOPY_CMD:
723                         memcpy(PendingCMD[i].DataDestAddr,
724                                PendingCMD[i].DataSrcAddr,
725                                PendingCMD[i].MemCopyByteCnt);
726                 case DUMMY_CMD:
727                         PendingCMD[i].Status = PASS;
728                         break;
729                 default:
730                         PendingCMD[i].Status = FAIL;
731                         break;
732                 }
733         }
734
735         /*
736          * Temperory adding code to reset PendingCMD array for basic testing.
737          * It should be done at the end of  event status function.
738          */
739         for (i = tag_count + MAX_CHANS; i < MAX_DESCS; i++) {
740                 PendingCMD[i].CMD = 0;
741                 PendingCMD[i].Tag = 0;
742                 PendingCMD[i].DataAddr = 0;
743                 PendingCMD[i].Block = 0;
744                 PendingCMD[i].Page = 0;
745                 PendingCMD[i].PageCount = 0;
746                 PendingCMD[i].DataDestAddr = 0;
747                 PendingCMD[i].DataSrcAddr = 0;
748                 PendingCMD[i].MemCopyByteCnt = 0;
749                 PendingCMD[i].ChanSync[0] = 0;
750                 PendingCMD[i].ChanSync[1] = 0;
751                 PendingCMD[i].ChanSync[2] = 0;
752                 PendingCMD[i].ChanSync[3] = 0;
753                 PendingCMD[i].ChanSync[4] = 0;
754                 PendingCMD[i].Status = CMD_NOT_DONE;
755         }
756
757         nand_dbg_print(NAND_DBG_TRACE, "At end of Execute CMDs.\n");
758
759         emu_isr(0, 0); /* This is a null isr now. Need fill it in future */
760
761         return status;
762 }
763
764 /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
765 * Function:     emu_Event_Status
766 * Inputs:       none
767 * Outputs:      Event_Status code
768 * Description:  This function can also be used to force errors
769 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
770 u16 emu_CDMA_Event_Status(void)
771 {
772         nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
773                        __FILE__, __LINE__, __func__);
774
775         return EVENT_PASS;
776 }
777
778 #endif /* CMD_DMA */
779 #endif /* !ELDORA */
780 #endif /* FLASH_EMU */