os/linux-2.6-tag--devboard-R2_10-4/arch/cris/arch-v32/drivers/elphel/cxsdram353.c

Go to the documentation of this file.
00001 /*!***************************************************************************
00002 *! FILE NAME  : cxsdram353.c
00003 *! DESCRIPTION: TBD
00004 *! Copyright (C) 2002-2008 Elphel, Inc
00005 *! -----------------------------------------------------------------------------**
00006 *!
00007 *!  This program is free software: you can redistribute it and/or modify
00008 *!  it under the terms of the GNU General Public License as published by
00009 *!  the Free Software Foundation, either version 3 of the License, or
00010 *!  (at your option) any later version.
00011 *!
00012 *!  This program is distributed in the hope that it will be useful,
00013 *!  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 *!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 *!  GNU General Public License for more details.
00016 *!
00017 *!  You should have received a copy of the GNU General Public License
00018 *!  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 *! -----------------------------------------------------------------------------**
00020 *!  $Log: cxsdram353.c,v $
00021 *!  Revision 1.1.1.1  2008/11/27 20:04:00  elphel
00022 *!
00023 *!
00024 *!  Revision 1.6  2008/10/25 20:01:33  elphel
00025 *!  just put notes about not using file->f_pos in read() and write()
00026 *!
00027 *!  Revision 1.5  2008/10/06 08:31:08  elphel
00028 *!  snapshot, first images
00029 *!
00030 *!  Revision 1.4  2008/09/20 00:29:49  elphel
00031 *!  moved driver major/minor numbers to a single file - include/asm-cris/elphel/driver_numbers.h
00032 *!
00033 *!  Revision 1.3  2008/09/12 00:23:58  elphel
00034 *!  removed cc353.c, cc353.h
00035 *!
00036 *!  Revision 1.3  2008/08/24 16:16:30  elphel
00037 *!  added support for quantizer tuning (zero bin, shift) and enable writing to the /dev/ccam_img to upload test patterns for compression
00038 *!
00039 *!  Revision 1.2  2008/08/18 06:03:47  elphel
00040 *!  Removed disabling video SDRAM channel 0 (that should be done differently)
00041 *!
00042 *!  Revision 1.1.1.1  2007/08/17 10:23:18  elphel
00043 *!  This is a fresh tree based on elphel353-2.10
00044 *!
00045 *!  Revision 1.7  2007/08/17 10:23:18  spectr_rain
00046 *!  switch to GPL3 license
00047 *!
00048 *!  Revision 1.6  2007/07/20 10:17:45  spectr_rain
00049 *!  *** empty log message ***
00050 *!
00051 *!  Revision 1.1.1.1  2007/02/23 10:11:48  elphel
00052 *!  initial import into CVS
00053 *!
00054 *!  Revision 1.8  2006/09/19 16:22:14  spectr_rain
00055 *!  *** empty log message ***
00056 *!
00057 *!  Revision 1.7  2006/09/02 22:04:17  spectr_rain
00058 *!  *** empty log message ***
00059 *!
00060 *!  Revision 1.6  2006/09/02 00:19:49  spectr_rain
00061 *!  lock sensor while readrawimage
00062 *!
00063 *!  Revision 1.5  2006/09/01 21:36:59  spectr_rain
00064 *!  *** empty log message ***
00065 *!
00066 *!  Revision 1.4  2006/09/01 21:16:00  spectr_rain
00067 *!  *** empty log message ***
00068 *!
00069 *!  Revision 1.3  2006/09/01 21:02:00  spectr_rain
00070 *!  *** empty log message ***
00071 *!
00072 *!  Revision 1.2  2006/09/01 18:54:40  spectr_rain
00073 *!  some fixes for /dev/ccam_img (image.raw)
00074 *!
00075 *!  Revision 1.1.1.1  2006/07/11 19:14:59  spectr_rain
00076 *!  unwork with less than 5MPx Micron sensor, initial branch
00077 *!
00078 *!  Revision 1.2  2005/05/10 21:08:49  elphel
00079 *!  *** empty log message ***
00080 *!
00081 
00082 FULL_WIDTH and FULL_HEIGHT increased by 4 each to include 1
00083 */
00084 
00085 /****************** INCLUDE FILES SECTION ***********************************/
00086 #define FULL_WIDTH  ( get_imageParamsThis(P_ACTUAL_WIDTH)+4 )
00087 #define FULL_HEIGHT ( get_imageParamsThis(P_ACTUAL_HEIGHT)+4 )
00088 
00089 #include <linux/module.h>
00090 #include <linux/sched.h>
00091 #include <linux/slab.h>
00092 #include <linux/errno.h>
00093 #include <linux/kernel.h>
00094 #include <linux/fs.h>
00095 #include <linux/string.h>
00096 #include <linux/init.h>
00097 #include <linux/autoconf.h>
00098 
00099 #include <asm/system.h>
00100 //#include <asm/svinto.h>
00101 #include <asm/io.h>
00102 
00103 #include <asm/irq.h>
00104 
00105 #include <asm/delay.h>
00106 #include <asm/uaccess.h>
00107 #include <asm/elphel/driver_numbers.h>
00108 #include <asm/elphel/c313a.h>
00109 
00110 #include "fpgactrl.h"  // defines port_csp0_addr, port_csp4_addr 
00111 #include "framepars.h"  // defines port_csp0_addr, port_csp4_addr 
00112 
00113 #include "x3x3.h"
00114 //#include "cc3x3.h"
00115 #include "cxsdram.h"
00116 
00117 #define D(x)
00118 #if ELPHEL_DEBUG
00119   #define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;}
00120 #else
00121   #define MDF(x)
00122 #endif
00123 
00124 
00125 
00126 
00127 #define IMAGERAW_MODULE_DESCRIPTION "Raw image access driver for Elphel 353  camera"
00128 #define IMAGERAW_DRIVER_NAME        "Raw image access driver"
00129 static const char x353raw_name[] = "elphel_raw353";
00130 
00131 
00132 static int linebuf_fpn[4096];
00133 static int lineinbuf_fpn;               // should be -1 after frame acquisition, etc - program sensor
00134 static int linebufdirty_fpn = 0;
00135 static int linebuf_img[4096];
00136 static int lineinbuf_img;               // should be -1 after frame acquisition, etc - program sensor
00137 static int linebufdirty_img = 0;
00138 
00139 static int minor_lock=0;        
00140 
00141 
00142 int *   x353raw_fpn_readline(int line, int ignore);
00143 int     x353raw_fpn_writeline(void);
00144 ssize_t x353raw_fpn_read(struct file * file, char * buf, size_t count, loff_t *off);
00145 ssize_t x353raw_fpn_write(struct file * file, const char * buf, size_t count, loff_t *off);
00146 int *   x353raw_frame_readline(int line, int ignore);
00147 int     x353raw_frame_writeline(void);
00148 ssize_t x353raw_frame_read(struct file * file, char * buf, size_t count, loff_t *off);
00149 ssize_t x353raw_frame_write(struct file * file, const char * buf, size_t count, loff_t *off);
00150 loff_t  x353raw_frame_lseek(struct file * file, loff_t offset, int orig);
00151 void    x353raw_frame_release(void); // was missing?
00152 int     x353raw_frame_open(struct inode *inode, struct file *filp);
00153 int     x353raw_fpn_open(struct inode *inode, struct file *filp);
00154 loff_t  x353raw_fpn_lseek(struct file * file, loff_t offset, int orig);
00155 void    x353raw_fpn_release(void);
00156 void   x353raw_f_invalidate (void); // to be called when page number is changed. Write should not be in progress
00157 
00158 int     x353raw_open(struct inode *inode, struct file *filp);
00159 int     x353raw_release(struct inode *inode, struct file *filp);
00160 loff_t  x353raw_lseek (struct file * file, loff_t offset, int orig);
00161 ssize_t x353raw_write(struct file * file, const char * buf, size_t count, loff_t *off);
00162 ssize_t x353raw_read(struct file * file, char * buf, size_t count, loff_t *off);
00163 
00164 
00165 
00166 
00167 
00168 int *x353raw_fpn_readline(int line, int ignore) {       // read fpn line to buffer (returns buffer address). ignore - contents does not matter (to write over)
00169         int ntilex, padlen, sa, nw, n, i, li;   //nw - number of 32-bit words to read)
00170 
00171         if(line == lineinbuf_fpn)
00172                 return linebuf_fpn;             // cache hit
00173         if((port_csp0_addr[X313_WA_SD_MODE] & 3) != 3)
00174                 return NULL;                    // SDRAM was not enabled or refresh was not on
00175         if(linebufdirty_fpn) {
00176                 if (x353raw_fpn_writeline() < 0)
00177                         return NULL;            // failed to write buffer
00178         }
00179         lineinbuf_fpn = line;
00180         if(ignore) return linebuf_fpn;
00181         nw = ((FULL_WIDTH + 1) >> 1);
00182         ntilex = ((nw + 3) >> 2);
00183         padlen = ((ntilex + 31) >> 5);
00184         sa = X313_MAP_FPN + ((padlen * line) << 8);
00185         X313_INIT_SDCHAN(3, 0, 0, 0, sa, 0x3ff, 0xfff); // 4096 rows of 32x256 16-bit words each - 64MB > than memory
00186 //      enable channel if it was not already
00187         X313_CHN_EN(3);
00188         li = 0;
00189         while (nw > 0) {
00190                 i = 1000;
00191                 D(printk("wait "));
00192                 while (((i--) > 0) && !X313_SR(PIORDY)) udelay(1);
00193                 D(printk("ready, i=%d\n", (int) i));
00194                 if (i == 0)
00195                         return NULL;            // page not ready
00196                 n = nw;
00197                 if (n > 128)
00198                         n = 128;
00199                 i = RD_SD_PIOWIN;       // will return garbage (because of latency), prepares to the next read, increments address
00200                 for (i = 0; i < n; i++)
00201                         linebuf_fpn[li++] = RD_SD_PIOWIN;
00202                 nw -= n;
00203                 if (nw > 0)
00204                         port_csp0_addr[X313_WA_SDPIO_NEXT] = 0; // next page (all but last)
00205         }
00206         return linebuf_fpn;
00207 }
00208 
00209 int x353raw_fpn_writeline(void) {       // write current line of FPN data to SDRAM, clear "dirty" flag
00210         int ntilex, padlen, sa, nw, n, i, li;
00211 
00212         if(linebufdirty_fpn == 0)
00213                 return 0;
00214         if(lineinbuf_fpn >= 0) {
00215                 if((port_csp0_addr[X313_WA_SD_MODE] & 3) != 3) return -1;
00216                 nw = ((FULL_WIDTH + 1) >> 1);
00217                 ntilex = ((nw + 3) >> 2);
00218                 padlen = ((ntilex + 31) >> 5);
00219                 sa = X313_MAP_FPN + ((padlen * lineinbuf_fpn) << 8);
00220                 X313_INIT_SDCHAN(3, 0, 1, 0, sa, 0x3ff, 0xfff); 
00221 
00222     X313_CHN_EN(3);
00223 
00224                 li = 0;
00225                 while (nw > 0) {
00226                         i = 1000;
00227                         D(printk("wait "));
00228                         while (((i--) > 0) && !X313_SR(PIORDY)) udelay(1);
00229                         D(printk("ready, i=%d\n", (int) i));
00230                         if (i == 0)  return -1;         
00231                         n = nw;
00232                         if (n > 128)
00233                                 n = 128;
00234                         for (i = 0; i < n; i++)
00235                                 port_csp0_addr[X313_WA_SD_PIOWIN] = linebuf_fpn[li++];
00236                         nw -= n;
00237                         port_csp0_addr[X313_WA_SDPIO_NEXT] = 0; // skip 8x32 data (all but last)
00238                 }
00239                 // write the last page if it was partial
00240 //              while(li & 0x3f) {
00241 //                      port_csp0_addr[X313_WA_SDPIO_NEXT] = 0; // skip 8x32 data (all but last)
00242 //                      li += 8;
00243 //              }
00245                 i = 1000;
00246                 while (((i--) > 0) && !X313_SR(PIOWEMPTY)) udelay(1);
00247                 if (i == 0)
00248                         return -EFAULT;         // page not ready
00249         }
00250         linebufdirty_fpn = 0;
00251         return 0;
00252 }
00253 
00254 
00255 ssize_t x353raw_fpn_read(struct file * file, char *buf, size_t count, loff_t * off) {
00256         unsigned long p, fsz, y, xb, xbl, left;
00257         char *bp = buf;
00258         char *mp;
00259 
00260         MDF(printk("count=%x, off=%x\n", (int) count, (int) off));
00262         p = *off;
00263 //      printk("x353raw_fpn_read (%x/%x) ", (int) p, (int) count);
00264         fsz = (FULL_WIDTH * FULL_HEIGHT) << 1;
00265 //      if(p >= fsz)  return -EINVAL; // bigger than SDRAM
00266         if((p + count) > fsz) { // truncate count
00267                 count = fsz - p;
00268         }
00269         left = count;
00270         while(left > 0) {
00271                 // calculate start address, pointed by p;
00272 //              printk(":%x:",(int) p);
00273                 y = (p / FULL_WIDTH) >> 1;
00274 //              printk("+%x+",(int) y);
00275                 xb = p - y * (FULL_WIDTH << 1);
00276                 xbl = (FULL_WIDTH << 1) - xb;
00277                 if(xbl > left)
00278                         xbl = left;                     // xbl - number of bytes left in the same line
00279                 if(!(mp = (char *)x353raw_fpn_readline(y, 0)))
00280                         return -EFAULT;         // read SDRAM error
00281 //              copy data
00282                 mp += xb;
00283 //              D(printk("copytouser, ibp=%x, nb=%x\n", (int) ibp, (int) nb));
00284                 if(copy_to_user(bp, mp, xbl))
00285                         return -EFAULT;
00286                 left -= xbl;
00287                 p += xbl;
00288                 bp += xbl;
00289         }                                                       // while (left >0)
00290 
00291    *off+=count;
00292         return count;
00293 }
00294 
00295 ssize_t x353raw_fpn_write(struct file * file, const char *buf, size_t count, loff_t * off) {
00296         unsigned long p, fsz, y, xb, xbl, left;
00297         const char *bp = buf;
00298         char *mp;
00299 
00300 //  MDF(printk("x353raw_fpn_write, count=%x, off=%x\n", (int) count, (int) off));
00302    p=*off;
00303         fsz = (FULL_WIDTH * FULL_HEIGHT) << 1;
00304         if (p >= fsz)
00305                 return -EINVAL;                 // bigger than SDRAM
00306         if ((p + count) > fsz) {        // truncate count
00307                 count = fsz - p;
00308         }
00309         left = count;
00310         while (left > 0) {
00311                 // calculate start address, pointed by p;
00312                 y = (p / FULL_WIDTH) >> 1;
00313                 xb = p - y * (FULL_WIDTH << 1);
00314                 xbl = (FULL_WIDTH << 1) - xb;
00315                 if (xbl > left)
00316                         xbl = left;                     // xbl - number of bytes left in the same line
00317                 // do we need to overwrite a whole line? ((xb==0) && (xbl==(FULL_WIDTH<<1)))
00318                 if (!(mp = (char *) x353raw_fpn_readline(y, ((xb == 0) && (xbl == (FULL_WIDTH << 1))))))
00319                         return -EFAULT;         // read SDRAM error
00320                 // copy to line buffer
00321                 mp += xb;
00322                 if (copy_from_user(mp, bp, xbl))
00323                         return -EFAULT;
00324                 left -= xbl;
00325                 p += xbl;
00326                 bp += xbl;
00327                 linebufdirty_fpn = 1;   // mark as modified
00328         }                                                       // while (left >0)
00329 
00330        *off+=count;
00331         return count;
00332 }
00333 
00334 
00335 loff_t x353raw_fpn_lseek(struct file * file, loff_t offset, int orig) {
00336 
00337         //  orig 0: position from begining
00338         //  orig 1: relative from current position
00339         //  orig 2: position from last address
00340 
00341 
00342         unsigned long fsz;
00343 
00344         fsz = (FULL_WIDTH * FULL_HEIGHT) << 1;
00345 
00346         MDF(printk("orig= %x, offset=k %x\n",(int) orig, (int) offset));
00347         switch (orig) {
00348         case 0:
00349                 file->f_pos = offset;
00350                 break;
00351         case 1:
00352                 file->f_pos += offset;
00353                 break;
00354         case 2:
00355                 file->f_pos = fsz + offset;
00356                 break;
00357         default:
00358                 return -EINVAL;
00359         }
00360 
00361         // truncate position
00362         if (file->f_pos < 0) {
00363                 file->f_pos = 0;
00364                 return (-EOVERFLOW);
00365         }
00366 
00367         if (file->f_pos > fsz) {
00368                 file->f_pos = fsz;
00369                 return (-EOVERFLOW);
00370         }
00371         return (file->f_pos);
00372 }
00373 
00374 
00375 // ----------------------------------------
00376 int *x353raw_frame_readline(int line, int ignore) {     
00377         int ntilex, padlen, sa, nw, n, i, li;
00378 
00379 //      int line2;
00380 //      int buf128[128];
00381 //      int d;
00382 //      int d, pw;
00383 //      unsigned char *cbuf128 = (unsigned char *) buf128;
00384 //      unsigned char *clinebuf = (unsigned char *) linebuf_img;
00385 //      unsigned short *sbuf128 = (unsigned short *) buf128;
00386 //      unsigned short *slinebuf = (unsigned short *) linebuf_img;
00387 
00388         if(line == lineinbuf_img)
00389                 return linebuf_img;             // cache hit
00390         if((port_csp0_addr[X313_WA_SD_MODE] & 3) != 3)
00391                 return NULL;                    // SDRAM was not enabled or refresh was not on
00392         if(linebufdirty_img) {
00393                 if (x353raw_frame_writeline() < 0)
00394                         return NULL;            // failed to write buffer
00395         }
00396         lineinbuf_img = line;
00397         if(ignore) return linebuf_img;
00398         if((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME))       // n - number of 32-bit words to read 
00399                 nw = ((FULL_WIDTH + 3) >> 2);
00400         else
00401                 nw = ((FULL_WIDTH + 1) >> 1);
00402         ntilex = ((nw + 3) >> 2);
00403         padlen = ((ntilex + 31) >> 5);
00404 
00405 // in external (or virtual) trigger mode always 2 frames acquired (exactly), so there is no need to find the boarder
00406 // just add 2 frames.
00407 // so read line into buffer in any case
00408 
00409         sa = X313_MAP_FRAME + ((padlen * line) << 8);
00410 
00411 //pw = FULL_WIDTH;
00412         X313_INIT_SDCHAN(3, 0, 0, 0, sa, 0x3ff, 0xfff); // 4096 rows of 32x256 16-bit words each - 64MB > than memory
00413 //printk("readline(): line1 == %d, sa == 0x%08X; nw == %d, padlen == %d, FULL_WIDTH == %d\r\n", line, sa, nw, padlen, pw);
00414 
00415         // enable channel if it was not already
00416 //      port_csp0_addr[X313_WA_SD_MODE] |= 0x23;        // channel3 enabled, refresh, sdram
00417     X313_CHN_EN(3);
00418 
00419         li = 0;
00420         while(nw > 0) {
00421                 i = 1000;
00422                 D(printk("wait "));
00423                 while(((i--) > 0) && !X313_SR(PIORDY)) udelay(1);
00424                 D(printk("ready, i = %d\n", (int) i));
00425                 if(i == 0)
00426                         return NULL;            // page not ready
00427                 n = nw;
00429                 if(n > 128) n = 128;
00431                 i = RD_SD_PIOWIN;       // will return garbage (because of latency), prepares to the next read, increments address
00432                 for(i = 0; i < n; i++)
00433 //                      linebuf_img[li++] = 0x13141516;
00434                         linebuf_img[li++] = RD_SD_PIOWIN;
00435                 nw -= n;
00436                 if(nw > 0)
00437                         port_csp0_addr[X313_WA_SDPIO_NEXT] = 0; // next page (all but last)
00438         }
00439 
00440         // now add line from the second frame if external (or virtual) trigger
00441 /*
00442         if(get_imageParamsThis(P_TRIG) > 0) {   //(external)
00443                 line2 = line + FULL_HEIGHT;     // second frame
00444 //              sa = X313_MAP_FRAME + ((padlen * line2) << 7);
00445                 sa = X313_MAP_FRAME + ((padlen * line2) << 8);
00446 //              X313_INIT_SDCHAN(3, 0, 0, 0, sa, 0xff, 0x7ff);   // 2048 rows of 16x128 16-bit words each
00447                 X313_INIT_SDCHAN(3, 0, 0, 0, sa, 0x3ff, 0xfff); // 4096 rows of 32x256 16-bit words each - 64MB > than memory
00448 printk("readline(): line2 == %d, sa == 0x%08X\r\n", line, sa);
00449                 // enable channel if it was not already
00450 //              port_csp0_addr[X313_WA_SD_MODE] |= 0x23;        // channel3 enabled, refresh, sdram
00451     X313_CHN_EN(3);
00452 
00453 
00454                 li = 0;
00455                 while(nw > 0) {
00456                         i = 1000;
00457                         while(((i--) > 0) && !X313_SR(PIORDY)) udelay(1);
00458                         if(i == 0)
00459                                 return NULL;    // page not ready
00460                         n = nw;
00461                         if(n > 128)
00462                                 n = 128;
00463 //                      i = RD_SD_PIOWIN;       // will return garbage (because of latency), prepares to the next read, increments address
00464                         for(i = 0; i < n; i++)
00465                                 buf128[i] = port_csp0_addr[X313_WA_SD_PIOWIN];
00466                         if((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME)) {
00467                                 for(i = 0; i < 512; i++) {
00468                                         d = clinebuf[li];
00469                                         d += cbuf128[i];
00470                                         d -= get_imageParamsThis(P_FATZERO);
00471                                         if (d < 0)
00472                                                 d = 0;
00473                                         else if (d > 255)
00474                                                 d = 255;
00475                                         clinebuf[li++] = d;
00476                                 }
00477                         } else {
00478                                 for(i = 0; i < 256; i++) {
00479                                         d = slinebuf[li];
00480                                         d += sbuf128[i];
00481                                         d -= get_imageParamsThis(P_FATZERO);
00482                                         if(d < 0)
00483                                                 d = 0;
00484                                         else if(d > 65535)
00485                                                 d = 65535;
00486                                         slinebuf[li++] = d;
00487                                 }
00488                         }
00489                         nw -= n;
00490                         if(nw > 0)
00491                                 port_csp0_addr[X313_WA_SDPIO_NEXT] = 0; // next page (all but last)
00492                 }
00493         }
00494 */
00495         return linebuf_img;
00496 }
00497 
00498 int x353raw_frame_writeline(void) {     
00499   int ntilex, padlen, sa, nw, n, i, li;
00500   if(linebufdirty_img == 0) {
00501        MDF(printk("lineinbuf_img=0x%x, linebufdirty_img=0x%x\n", lineinbuf_img, linebufdirty_img));
00502        return 0;
00503   }
00504   if(lineinbuf_img >= 0) {
00505     if((port_csp0_addr[X313_WA_SD_MODE] & 3) != 3) return -1; 
00506     if((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME))  
00507       nw = ((FULL_WIDTH + 3) >> 2);
00508     else
00509       nw = ((FULL_WIDTH + 1) >> 1);
00510     ntilex = ((nw + 3) >> 2);
00511     padlen = ((ntilex + 31) >> 5);
00512     sa = X313_MAP_FRAME + ((padlen * lineinbuf_img) << 8);
00513 
00514     i=1000;
00515     while (((i--)>0) && !X313_SR(PIOWEMPTY)) udelay(1); 
00516     if (i==0) return -EFAULT;  
00517 
00518     X313_INIT_SDCHAN(3, 0, 1, 0, sa, 0x3ff, 0xfff); 
00519     MDF(printk("lineinbuf_img=0x%x, sa=0x%x, nw=0x%x\n", lineinbuf_img, sa, nw));
00520     X313_CHN_EN(3);
00521 
00522     li = 0;
00523     while (nw > 0) {
00524       i = 1000;
00525       MDF(printk("wait, nw=0x%x : ", nw));
00526       while (((i--) > 0) && !X313_SR(PIORDY))  udelay(1);
00527       MDF(printk("ready, i=%d\n", (int) i));
00528       if (i == 0) return -EFAULT;               
00529       n = nw;
00531       if (n > 128)  n = 128;
00532       for (i = 0; i < n; i++) port_csp0_addr[X313_WA_SD_PIOWIN] = linebuf_img[li++];
00533       nw -= n;
00534       port_csp0_addr[X313_WA_SDPIO_NEXT] = 0; 
00535     }
00538     i = 1000;
00539     while (((i--) > 0) && !X313_SR(PIOWEMPTY))  udelay(1);
00540     if (i == 0)
00541     return -EFAULT;             
00542   }
00543   linebufdirty_img = 0;
00544   return 0;
00545 }
00546 
00547 
00548 ssize_t x353raw_frame_read(struct file * file, char *buf, size_t count, loff_t * off) {
00549         unsigned long p, fsz, y, xb, xbl, left;
00550         char *bp = buf;
00551         char *mp;
00552         p=*off;
00553         MDF(printk("count = %x, off = %x, f_pos = %d\r\n", (int)count, (int)off, (int) p));
00554         fsz = (FULL_WIDTH * FULL_HEIGHT) << (((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME)) ? 0 : 1);
00555         MDF(printk("FULL_WIDTH = 0x%x, FULL_HEIGHT = 0x%x, fsz = 0x%x\r\n", (int) FULL_WIDTH, (int)FULL_HEIGHT, (int) fsz));
00556         if((p + count) > fsz) { // truncate count
00557                 count = fsz - p;
00558         }
00559         left = count;
00560         while(left > 0) {
00561                 // calculate start address, pointed by p;
00562                 if((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME)) {
00563                         y = p / FULL_WIDTH;
00564                         xb = p - y * FULL_WIDTH;
00565                         xbl = FULL_WIDTH - xb;
00566                 } else {
00567                         y = (p / FULL_WIDTH) >> 1;
00568                         xb = p - y * (FULL_WIDTH << 1);
00569                         xbl = (FULL_WIDTH << 1) - xb;
00570                 }
00571                 if(xbl > left)
00572                         xbl = left;                     // xbl - number of bytes left in the same line
00573                 if(!(mp = (char *)x353raw_frame_readline(y + FULL_HEIGHT * get_imageParamsThis(P_PAGE_READ), 0))) {
00574 printk("read SDRAM error!\r\n");
00575                         return -EFAULT;         // read SDRAM error
00576                 }
00577 // copy data
00578                 mp += xb;
00579 //    D(printk ("copytouser, ibp=%x, nb=%x\n", (int) ibp, (int) nb));
00580                 if(copy_to_user(bp, mp, xbl)) {
00581 printk("copy_to_user error!\r\n");
00582                         return -EFAULT;
00583                 }
00584                 left -= xbl;
00585                 p += xbl;
00586                 bp += xbl;
00587         }                                                       // while (left >0)
00588 
00589    *off+=count;
00590 //printk("count == %d\r\n", count);
00591         return count;
00592 }
00593 
00594 ssize_t x353raw_frame_write(struct file * file, const char * buf, size_t count, loff_t *off) {
00595    unsigned long p, fsz, y, xb, xbl, left, bytes_in_line;
00596    const char *bp = buf;
00597    char *mp;
00598    p=*off;
00599 //   fsz = (FULL_WIDTH * FULL_HEIGHT) << 1;
00600    fsz = (FULL_WIDTH * FULL_HEIGHT) << (((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME)) ? 0 : 1);
00601 
00602    if (p >= fsz) return -EINVAL; 
00603    if ((p + count) > fsz) {     
00604       count = fsz - p;
00605    }
00606    left = count;
00607    MDF(printk("count == %x, off == %x, f_pos == %d\r\n", (int)count, (int)off, (int) p));
00608    while (left > 0) {
00610       if((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME)) {
00611          y =             p / FULL_WIDTH;
00612          xb =            p - y * FULL_WIDTH;
00613          bytes_in_line = FULL_WIDTH;
00614          xbl =           bytes_in_line - xb;
00615       } else {
00616          y =             (p / FULL_WIDTH) >> 1;
00617          xb =            p - y * (FULL_WIDTH << 1);
00618          bytes_in_line = (FULL_WIDTH <<1);
00619          xbl =           bytes_in_line - xb;
00620       }
00621       if (xbl > left) xbl = left; 
00622 
00624       if (!(mp = (char *) x353raw_frame_readline(y, ((xb == 0) && (xbl == bytes_in_line))))) return -EFAULT; 
00625 
00626       mp += xb;
00627       if (copy_from_user(mp, bp, xbl)) return -EFAULT;
00628       left -= xbl;
00629       p += xbl;
00630       bp += xbl;
00631       linebufdirty_img = 1; 
00632    } 
00633    *off+=count;
00634    return count;
00635 }
00636 
00637 
00638 
00639 
00640 loff_t x353raw_frame_lseek(struct file * file, loff_t offset, int orig) {
00641 /*
00642  *  orig 0: position from begning of eeprom
00643  *  orig 1: relative from current position
00644  *  orig 2: position from last eeprom address
00645  */
00646 
00647         unsigned long fsz;
00648         fsz = (FULL_WIDTH * FULL_HEIGHT) << (((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME)) ? 0 : 1);
00649 
00650 //      MDF(printk("frame_lseek %x\n", (int) offset));
00651 
00652         switch (orig) {
00653         case 0:
00654                 file->f_pos = offset;
00655                 break;
00656         case 1:
00657                 file->f_pos += offset;
00658                 break;
00659         case 2:
00660                 file->f_pos = fsz + offset;
00661                 break;
00662         default:
00663                 return -EINVAL;
00664         }
00665 
00666         /* truncate position */
00667         if (file->f_pos < 0) {
00668                 file->f_pos = 0;
00669                 return (-EOVERFLOW);
00670         }
00671 
00672         if (file->f_pos > fsz) {
00673                 file->f_pos = fsz;
00674                 return (-EOVERFLOW);
00675         }
00676         return (file->f_pos);
00677 }
00678 
00679 int x353raw_frame_open(struct inode *inode, struct file *filp) {        // set filesize
00680         inode->i_size = (FULL_WIDTH * FULL_HEIGHT) << (((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME)) ? 0 : 1);
00681         linebufdirty_fpn = 0;
00682         lineinbuf_img = -1;
00683 //      MDF(printk("frame_open, size = %x\n", (int) inode->i_size));
00684 //      printk("frame_open, size = 0x%08X; %d\n", (int)inode->i_size, (int)inode->i_size);
00685         return 0;
00686 }
00687 
00688 void x353raw_frame_release(void) {
00689   if(linebufdirty_img)  x353raw_frame_writeline();
00690   MDF(printk("\n"));
00691 
00692 }
00693 
00694 int x353raw_fpn_open(struct inode *inode, struct file *filp) {  // set filesize
00695         inode->i_size = (FULL_WIDTH * FULL_HEIGHT) << 1;
00696         linebufdirty_fpn = 0;
00697         lineinbuf_fpn = -1;
00698         MDF(printk("size = %x\n", (int) inode->i_size));
00699         return 0;
00700 }
00701 
00702 void x353raw_fpn_release(void) {
00703         if(linebufdirty_fpn)
00704                 x353raw_fpn_writeline();
00705         MDF(printk("\n"));
00706 
00707 }
00708 
00709 void x353raw_f_invalidate(void) {       // to be called when page number is changed. Write should not be in progress
00710         linebufdirty_fpn = 0;
00711         linebufdirty_img = 0;
00712         lineinbuf_fpn = -1;
00713         lineinbuf_img = -1;
00714 }
00715 
00717 
00718 
00719 static struct file_operations x353raw_fops = {
00720    owner:    THIS_MODULE,
00721    llseek:   x353raw_lseek,
00722    read:     x353raw_read,
00723    write:    x353raw_write,
00724    open:     x353raw_open,
00725    release:  x353raw_release
00726 };
00727 
00728 static int __init x353raw_init(void) {
00729    int res;
00730    res = register_chrdev(IMAGERAW_MAJOR, x353raw_name, &x353raw_fops);
00731    if(res < 0) {
00732      printk(KERN_ERR "x353raw_init: couldn't get a major number %d.\n",IMAGERAW_MAJOR);
00733      return res;
00734    }
00735     printk(IMAGERAW_DRIVER_NAME"- %d\n", IMAGERAW_MAJOR);
00736     return 0;
00737 }
00738 
00739 //#define IMAGERAW_MINOR_FRAME  1
00740 //#define IMAGERAW_MINOR_FPN    2
00741 //#define IMAGERAW_MINOR_UNLOCK 3
00742 //static int minor_lock=0;        /// hardware does not support concurrent accesses, so the driver will be locked for one user
00743 
00744 int x353raw_open(struct inode *inode, struct file *filp) {
00745   int res=0;
00746   int p = MINOR(inode->i_rdev);
00747   switch (p) {
00748     case IMAGERAW_MINOR_UNLOCK:
00749       minor_lock=0;
00750       return 0; 
00751     case IMAGERAW_MINOR_FRAME:
00752       if (minor_lock) return -EACCES;
00753       res=x353raw_frame_open(inode, filp);
00754       break;
00755     case IMAGERAW_MINOR_FPN:
00756       if (minor_lock) return -EACCES;
00757       res=x353raw_fpn_open(inode, filp);
00758       break;
00759     default: return -EINVAL;
00760   }
00761   minor_lock=p; 
00762   return 0;
00763 }
00764 
00765 int x353raw_release(struct inode *inode, struct file *filp) {
00766   int p = MINOR(inode->i_rdev);
00767   switch (p) {
00768     case IMAGERAW_MINOR_UNLOCK:
00769       break; 
00770     case IMAGERAW_MINOR_FRAME:
00771       x353raw_frame_release();
00772       break;
00773     case IMAGERAW_MINOR_FPN:
00774       x353raw_fpn_release();
00775       break;
00776     default: return -EINVAL;
00777   }
00778   minor_lock=0; 
00779   return 0;
00780 }
00781 
00782 loff_t x353raw_lseek (struct file * file, loff_t offset, int orig) {
00783   switch (minor_lock) {
00784     case IMAGERAW_MINOR_FRAME: return x353raw_frame_lseek(file, offset, orig);
00785     case IMAGERAW_MINOR_FPN:   return x353raw_fpn_lseek  (file, offset, orig);
00786     default:                   return -EINVAL;
00787   }
00788 }
00789 
00790 ssize_t x353raw_write(struct file * file, const char * buf, size_t count, loff_t *off) {
00791   switch (minor_lock) {
00792     case IMAGERAW_MINOR_FRAME: return x353raw_frame_write(file, buf, count, off);
00793     case IMAGERAW_MINOR_FPN:   return x353raw_fpn_write  (file, buf, count, off);
00794     default:                   return -EINVAL;
00795   }
00796 }
00797 
00798 ssize_t x353raw_read(struct file * file, char * buf, size_t count, loff_t *off) {
00799   switch (minor_lock) {
00800     case IMAGERAW_MINOR_FRAME: return x353raw_frame_read(file, buf, count, off);
00801     case IMAGERAW_MINOR_FPN:   return x353raw_fpn_read  (file, buf, count, off);
00802     default:                   return -EINVAL;
00803   }
00804 }
00805 
00806 module_init(x353raw_init);
00807 MODULE_LICENSE("GPLv3.0");
00808 MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
00809 MODULE_DESCRIPTION(IMAGERAW_MODULE_DESCRIPTION);
00810 
00811 

Generated on Fri Nov 28 00:06:23 2008 for elphel by  doxygen 1.5.1