00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 #include <linux/module.h>
00076 #include <linux/mm.h>
00077 #include <linux/sched.h>
00078 #include <linux/slab.h>
00079 #include <linux/errno.h>
00080 #include <linux/kernel.h>
00081 #include <linux/fs.h>
00082 #include <linux/string.h>
00083 #include <linux/init.h>
00084 #include <linux/autoconf.h>
00085 #include <linux/time.h>
00086
00087 #include <asm/system.h>
00088 #include <asm/arch/memmap.h>
00089
00090 #include <asm/io.h>
00091
00092 #include <asm/arch/dma.h>
00093 #include <asm/arch/hwregs/dma_defs.h>
00094 #include <asm/arch/hwregs/dma.h>
00095 #include <asm/arch/hwregs/reg_map.h>
00096 #include <asm/arch/hwregs/bif_dma_defs.h>
00097
00098
00099 #include <asm/irq.h>
00100 #include <asm/atomic.h>
00101
00102
00103 #include <asm/delay.h>
00104 #include <asm/uaccess.h>
00105 #include <asm/elphel/c313a.h>
00106
00107 #include "fpgactrl.h"
00108
00109 #include "x3x3.h"
00110 #include "cc3x3.h"
00111 #include "cxdma.h"
00112 #include "circbuf.h"
00113 #include "exif.h"
00114
00115 #define MD12(x)
00116 #define D(x)
00117 #define D1(x)
00118
00119 #define MD1(x)
00120
00121 #define MD2(x)
00122
00123
00124 #define MD5(x)
00125
00126 #define MD6(x)
00127
00128 #define MD7(x)
00129
00130
00131 #define D0(x)
00132
00133
00134 #define MD8(x)
00135
00136 #define MD9(x)
00137
00138 #define MD10(x)
00139
00140 #define MD11(x)
00141
00142
00143 #define JPEG_HEADER_SIZE 0x26f
00144 #if 0
00145 #define TRAILER_SIZE 0x02
00146 #define HEADER_YQTABLE 0x19
00147 #define HEADER_CQTABLE 0x5e
00148
00149 #define HEADER_HEIGHT 0xa3
00150 #define HEADER_WIDTH 0xa5
00151 #endif
00152
00153
00154
00155 static unsigned long ccam_dma_buf[CCAM_DMA_SIZE + (PAGE_SIZE>>2)] __attribute__ ((aligned (PAGE_SIZE)));
00157 unsigned long * ccam_dma_buf_ptr = NULL;
00158 unsigned long * ccam_dma = NULL;
00159 void init_ccam_dma_buf_ptr(void) {
00160 ccam_dma_buf_ptr = ccam_dma_buf;
00161 ccam_dma = ccam_dma_buf;
00162 }
00163 extern struct frame_params_t frame_params;
00167 wait_queue_head_t circbuf_wait_queue;
00178 #define CIRCBUF_MAJOR 135
00179 #define CIRCBUF_DRIVER_NAME "Elphel (R) Model 353 video buffer device driver"
00180 static struct file_operations circbuf_fops = {
00181 owner: THIS_MODULE,
00182 llseek: circbuf_all_lseek,
00183 read: circbuf_all_read,
00184 write: circbuf_all_write,
00185 ioctl: circbuf_all_ioctl,
00186 open: circbuf_all_open,
00187 mmap: circbuf_all_mmap,
00188 poll: circbuf_all_poll,
00189 release: circbuf_all_release
00190 };
00191
00192
00193
00194
00195
00196 struct circbuf_pd {
00197 int minor;
00198 struct wait_queue *circbuf_wait_queue;
00199
00200 };
00201
00202 int circbuf_all_open(struct inode *inode, struct file *filp) {
00203 int res;
00204 struct circbuf_pd * privData;
00205 privData= (struct circbuf_pd *) kmalloc(sizeof(struct circbuf_pd),GFP_KERNEL);
00206 if (!privData) return -ENOMEM;
00207 filp->private_data = privData;
00208 privData-> minor=MINOR(inode->i_rdev);
00209 MD10(printk("circbuf_all_open, minor=0x%x\n",privData-> minor));
00210 switch (privData-> minor) {
00211 case CMOSCAM_MINOR_CIRCBUF :
00212 res=circbuf_open(inode,filp);
00213 break;
00214 case CMOSCAM_MINOR_JPEAGHEAD :
00215 res=jpeghead_open(inode,filp);
00216 break;
00217 default:
00218 kfree(filp->private_data);
00219 return -EINVAL;
00220 }
00221 return res;
00222 }
00223 int circbuf_all_release(struct inode *inode, struct file *filp) {
00224 int res=0;
00225 int p = MINOR(inode->i_rdev);
00226 MD10(printk("circbuf_all_release, minor=0x%x\n",p));
00227 switch ( p ) {
00228 case CMOSCAM_MINOR_CIRCBUF :
00229
00230 break;
00231 case CMOSCAM_MINOR_JPEAGHEAD :
00232
00233 break;
00234 default:
00235 return -EINVAL;
00236 }
00237 kfree(filp->private_data);
00238 return res;
00239 }
00240
00241 loff_t circbuf_all_lseek(struct file * file, loff_t offset, int orig) {
00242 struct circbuf_pd * privData;
00243 privData = (struct circbuf_pd *) file->private_data;
00244 MD10(printk("circbuf_all_lseek, minor=0x%x\n",privData-> minor));
00245 switch (privData->minor) {
00246 case CMOSCAM_MINOR_CIRCBUF : return circbuf_lseek (file, offset, orig);
00247 case CMOSCAM_MINOR_JPEAGHEAD : return jpeghead_lseek (file, offset, orig);
00248 default: return -EINVAL;
00249 }
00250 }
00251
00252 ssize_t circbuf_all_read(struct file * file, char * buf, size_t count, loff_t *off) {
00253 struct circbuf_pd * privData;
00254 privData = (struct circbuf_pd *) file->private_data;
00255 MD10(printk("circbuf_all_read, minor=0x%x\n",privData-> minor));
00256 switch (privData->minor) {
00257 case CMOSCAM_MINOR_CIRCBUF : return circbuf_read (file, buf, count, off);
00258 case CMOSCAM_MINOR_JPEAGHEAD : return jpeghead_read (file, buf, count, off);
00259 default: return -EINVAL;
00260 }
00261 }
00262 ssize_t circbuf_all_write(struct file * file, const char * buf, size_t count, loff_t *off) {
00263 struct circbuf_pd * privData;
00264 privData = (struct circbuf_pd *) file->private_data;
00265 MD10(printk("circbuf_all_write, minor=0x%x, count=%d, off=%d\n",privData-> minor, (int) count,(int)*off));
00266 switch (privData->minor) {
00267 case CMOSCAM_MINOR_CIRCBUF : return circbuf_write (file, buf, count, off);
00268 case CMOSCAM_MINOR_JPEAGHEAD : return jpeghead_write (file, buf, count, off);
00269 default: return -EINVAL;
00270 }
00271 }
00272
00273
00274 int circbuf_all_mmap (struct file *file, struct vm_area_struct *vma) {
00275 struct circbuf_pd * privData;
00276 privData = (struct circbuf_pd *) file->private_data;
00277 MD10(printk("circbuf_all_mmap, minor=0x%x\n",privData-> minor));
00278 switch (privData->minor) {
00279 case CMOSCAM_MINOR_CIRCBUF : return circbuf_mmap (file, vma);
00280 default: return -EINVAL;
00281 }
00282 }
00283
00284 unsigned int circbuf_all_poll (struct file *file, poll_table *wait) {
00285 struct circbuf_pd * privData;
00286 privData = (struct circbuf_pd *) file->private_data;
00287 MD10(printk("circbuf_all_poll, minor=0x%x\n",privData-> minor));
00288 switch (privData->minor) {
00289 case CMOSCAM_MINOR_CIRCBUF :
00290 return circbuf_poll (file, wait);
00291 default: return -EINVAL;
00292 }
00293 }
00294
00295 int circbuf_all_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) {
00296 struct circbuf_pd * privData;
00297 privData = (struct circbuf_pd *) filp->private_data;
00298 printk("\n========== IOCTL is not implemented in circbuf_all_ioctl, minor=0x%x, cmd=0x%x, _IOC_NR(cmd)=0x%x, arg=0x%x\n",privData-> minor, (int) cmd, _IOC_NR(cmd), (int) arg);
00299 return -EINVAL;
00300 }
00301
00302
00303
00304
00305 int circbuf_open(struct inode *inode, struct file *filp) {
00306 inode->i_size = ((CCAM_DMA_SIZE) << 2);
00307 MD10(printk("circbuf_open, inode->i_size=0x%x\n", (int)inode->i_size));
00308 circbuf_lseek(filp, CIRCLSEEK_LAST, SEEK_END);
00309
00310 return 0;
00311 }
00312
00313
00314
00354
00355
00356
00357
00358
00359
00360 int circbufValidPointer(int rp, struct frame_params_t ** fpp) {
00361 if (rp & 0x1f) {
00362 MD10(printk("circbufValidPointer: misaligned pointer\n"));
00363 return -2;
00364 }
00365 int wp=camSeqGetJPEG_wp();
00366 int p= rp >> 2;
00367 struct frame_params_t * fp;
00368 fp = (struct frame_params_t *) &ccam_dma_buf[X313_BUFFSUB(p, 8)];
00369
00370 MD10(printk("rp=0x%x (0x%x), offset=0x%x\n",rp,p,(int)&ccam_dma_buf[p]-(int)fp); dumpFrameParams(fp, "in circbufValidPointer:"));
00371
00372 *fpp=fp;
00373 MD11(printk("p=0x%x , wp==0x%x\n",p,wp));
00374 if (p == wp) {
00375 return 0;
00376 }
00377 if (fp->signffff != 0xffff) {
00378 MD10(printk("circbufValidPointer: signanure overwritten\n"));
00379 return -1;
00380 }
00381 if ((fp->timestamp_sec) & X313_LENGTH_MASK) return 0;
00382 return 1;
00383
00384 }
00385
00386 loff_t circbuf_lseek(struct file * file, loff_t offset, int orig) {
00387
00388
00389
00390 int l = (CCAM_DMA_SIZE << 2);
00391 int fl=0;
00392 struct frame_params_t * fp;
00393 int fvld=-1;
00394 int rp, bp, prev_p, preprev_p;
00395 int nf;
00396 int nz=1;
00397 MD12(int dbg_i);
00398
00399 MD11(printk("circbuf_lseek, offset=0x%x, orig=0x%x\n",(int) offset, (int) orig));
00400 switch(orig) {
00401 case SEEK_SET:
00402 file->f_pos = offset;
00403 break;
00404 case SEEK_CUR:
00405 if (offset) file->f_pos += offset;
00406 else if (circbufValidPointer(file->f_pos, &fp) <0 ) return -EINVAL;
00407 break;
00408 case SEEK_END:
00409 if (offset <= 0) {
00410 file->f_pos = l + offset;
00411 } else {
00412
00413 switch (offset) {
00414 case CIRCLSEEK_TORP:
00415 file->f_pos=camSeqGetJPEG_rp()<<2;
00416 case CIRCLSEEK_PREV:
00417 case CIRCLSEEK_NEXT:
00418 case CIRCLSEEK_SETP:
00419 case CIRCLSEEK_VALID:
00420 case CIRCLSEEK_READY:
00421 case CIRCLSEEK_FREE:
00422 case CIRCLSEEK_USED:
00423 if (((fvld=circbufValidPointer(file->f_pos, &fp))) <0 )
00424 return -EINVAL;
00425 }
00426 switch (offset) {
00427 case CIRCLSEEK_FREE:
00428 bp=(file->f_pos - (camSeqGetJPEG_wp()<<2));
00429
00430 return (file->f_pos=(bp>0)?bp:(bp+l));
00431 case CIRCLSEEK_USED:
00432 bp=((camSeqGetJPEG_wp()<<2) - file->f_pos);
00433
00434 return (file->f_pos=(bp>0)?bp:(bp+l));
00435 case CIRCLSEEK_TORP:
00436 break;
00437 case CIRCLSEEK_TOWP:
00438 file->f_pos=camSeqGetJPEG_wp()<<2;
00439 break;
00440 case CIRCLSEEK_LAST:
00441 file->f_pos=camSeqGetJPEG_wp()<<2;
00442 fvld=circbufValidPointer(file->f_pos, &fp);
00443 case CIRCLSEEK_PREV:
00444 rp= file->f_pos >> 2;
00445 fl=ccam_dma_buf[X313_BUFFSUB(rp, 9)] ^ X313_LENGTH_MASK;
00446 MD11(printk("CIRCLSEEK_PREV: rp=0x%x, fvld=%d, fl=0x%x\n", rp, fvld,fl));
00447 if (fl & X313_LENGTH_MASK) {
00448 if (offset==CIRCLSEEK_LAST) break;
00449 return -EOVERFLOW;
00450 }
00451 bp = (X313_BUFFSUB(rp, X313_PADDED_FRAME(fl))<<2);
00452 MD11(printk("CIRCLSEEK_PREV: bp=0x%x (0x%x), circbufValidPointer=%d\n", bp, bp>>2,circbufValidPointer(rp>>2, &fp)));
00453 if (circbufValidPointer(bp, &fp) < 0 ) {
00454 if (offset==CIRCLSEEK_LAST) break;
00455 return -EOVERFLOW;
00456 }
00458 file->f_pos=bp;
00459 break;
00460 case CIRCLSEEK_NEXT:
00461 MD11(printk("CIRCLSEEK_NEXT: rp=0x%x, fvld=%d, fp->timestamp_sec=0x%x\n", file->f_pos >> 2, fvld, fp->timestamp_sec));
00462 if (fvld <=0)
00463 return -EOVERFLOW;
00464 file->f_pos = X313_BUFFADD(file->f_pos >> 2, X313_PADDED_FRAME(fp->timestamp_sec)) <<2 ;
00465 break;
00466 case CIRCLSEEK_FIRST:
00467 case CIRCLSEEK_SCND:
00469 rp=camSeqGetJPEG_wp();
00470 prev_p=rp;
00471 preprev_p=prev_p;
00472 nf=0;
00473 nz=1;
00474 file->f_pos=rp<<2;
00475 while ((((fvld=circbufValidPointer(rp<<2, &fp))) >= 0) & (nz>=0)) {
00476 nf++;
00477
00478 preprev_p=prev_p;
00479 prev_p=rp;
00480 fl=ccam_dma_buf[X313_BUFFSUB(rp, 9)] ^ X313_LENGTH_MASK;
00481 MD11(printk("\nf=%d, rp=0x%x, fvld=%d, fl=0x%x\n",nf, rp, fvld, fl));
00482 if (fl & X313_LENGTH_MASK) break;
00483
00484 rp= X313_BUFFSUB(rp, X313_PADDED_FRAME(fl));
00485 if (rp > prev_p) nz-- ;
00486 }
00487
00488 MD11(printk("after while{}: nf=%d, rp=0x%x, fvld=%d, fl=0x%x\n",nf, rp, fvld, fl));
00489 file->f_pos=((offset==CIRCLSEEK_SCND)?preprev_p:prev_p) << 2;
00490 break;
00491 case CIRCLSEEK_SETP:
00492 camSeqSetJPEG_rp(file->f_pos>>2);
00493 break;
00494 case CIRCLSEEK_VALID:
00495 break;
00496 case CIRCLSEEK_READY:
00497 if (fvld <=0) return -EINVAL;
00498 break;
00499 case CIRCLSEEK_WAIT:
00500 #if 0
00501 fvld=circbufValidPointer(file->f_pos, &fp);
00502 if (fvld < 0) return -ESPIPE;
00503 if (fvld > 0) return file->f_pos ;
00504
00505 MD12(printk ("\n%s:%d: before wait_event_interruptible: WP= 0x%x, file->f_pos=0x%x\n",__FILE__,__LINE__,(int)camSeqGetJPEG_wp(),(int)file->f_pos));
00506 MD12(for (dbg_i= 8; dbg_i>0 ;dbg_i--) printk("%08x ",(int) ccam_dma_buf[X313_BUFFSUB(file->f_pos>>2, dbg_i)]));
00507 wait_event_interruptible (circbuf_wait_queue,(camSeqGetJPEG_wp()<<2)!=file->f_pos);
00508 MD12(printk ("\n\nafter wait_event_interruptible: WP= 0x%x, file->f_pos=0x%x\n",(int)camSeqGetJPEG_wp(),(int)file->f_pos));
00509 MD12(for (dbg_i= 8; dbg_i>0 ;dbg_i--) printk("%08x ",(int) ccam_dma_buf[X313_BUFFSUB(file->f_pos>>2, dbg_i)]));
00510
00511 return file->f_pos ;
00512 #endif
00513
00514 while (((fvld=circbufValidPointer(file->f_pos, &fp)))==0) {
00515 wait_event_interruptible (circbuf_wait_queue,(camSeqGetJPEG_wp()<<2)!=file->f_pos);
00516 }
00517 if (fvld < 0) return -ESPIPE;
00518 return file->f_pos ;
00519 }
00520
00521
00522
00523 return ( file->f_pos );
00524 }
00525 break;
00526 default:
00527 return -EINVAL;
00528 }
00529
00530 while (file->f_pos < 0) file->f_pos+=l;
00531 while (file->f_pos > l) file->f_pos-=l;
00532 if ((orig !=SEEK_END) && (file->f_pos == l)) file->f_pos=0;
00533 return file->f_pos ;
00534 }
00535
00536 ssize_t circbuf_write(struct file * file, const char * buf, size_t count, loff_t *off) {
00537 unsigned long p;
00538 char *char_pb = (char *)ccam_dma_buf;
00539 D(printk("circbuf_write\n"));
00540
00541 p = *off;
00542 if(p >= (CCAM_DMA_SIZE << 2))
00543 p = (CCAM_DMA_SIZE << 2);
00544 if((p + count) > (CCAM_DMA_SIZE << 2)) {
00545 count = (CCAM_DMA_SIZE << 2) - p;
00546 }
00547 if(count) {
00548 if(copy_from_user(&char_pb[p], buf, count))
00549 return -EFAULT;
00550
00551 *off += count;
00552 }
00553 return count;
00554 }
00555
00556 ssize_t circbuf_read(struct file * file, char * buf, size_t count, loff_t *off) {
00557 unsigned long p;
00558 char * char_pb = (char *) ccam_dma_buf;
00559
00560 p = *off;
00561 D(printk("circbuf_read pos=%d,count=%d, off=%d\r\n",p,count,off ));
00562 if (p >= (CCAM_DMA_SIZE<<2)) p = (CCAM_DMA_SIZE<<2);
00563 if( (p + count) > (CCAM_DMA_SIZE<<2)) {
00564 count = (CCAM_DMA_SIZE<<2) - p;
00565 }
00566 if (count) {
00567 if (copy_to_user(buf, &char_pb[p], count)) return -EFAULT;
00568
00569 *off+=count;
00570 }
00571 return count;
00572 }
00573 int circbuf_mmap (struct file *file, struct vm_area_struct *vma) {
00574
00575 int rslt;
00576
00577 MD7(printk("vm_start=%lx\r\n",vma->vm_start));
00578 MD7(printk("vm_end=%lx\r\n",vma->vm_end));
00579 MD7(printk("vm_pgoff=%lx\r\n",vma->vm_pgoff));
00580 MD7(printk("vm_file=%lx\r\n",(unsigned long) (vma->vm_file)));
00581 MD7(printk("ccam_dma_buf=%lx\r\n",(unsigned long) (virt_to_phys (&ccam_dma_buf[0]))));
00582
00583 rslt=remap_pfn_range(vma,
00584 vma->vm_start,
00585
00586 ((unsigned long) virt_to_phys(&ccam_dma_buf[0])) >> PAGE_SHIFT,
00587 vma->vm_end-vma->vm_start,
00588 vma->vm_page_prot);
00589
00590 MD7(printk("remap_pfn_range returned=%x\r\n",rslt));
00591 if (rslt) return -EAGAIN;
00592
00593
00594 return 0;
00595 }
00602 unsigned int circbuf_poll (struct file *file, poll_table *wait) {
00603 struct frame_params_t * fp;
00604 struct circbuf_pd * privData;
00605 privData = (struct circbuf_pd *) file->private_data;
00606 int rslt;
00607 MD10(printk("circbuf_poll\n"));
00608 rslt= circbufValidPointer(file->f_pos, &fp);
00609 if (rslt < 0) {
00610 MD10(printk("circbuf_poll:invalid pointer\n"));
00611 return POLLHUP ;
00612 } else if (rslt > 0) {
00613 return POLLIN | POLLRDNORM;
00614 } else {
00615 poll_wait(file, &circbuf_wait_queue, wait);
00618 if ((camSeqGetJPEG_wp()<<2)!=file->f_pos) return POLLIN | POLLRDNORM;
00619 }
00620 return 0;
00621 }
00622
00627
00628
00629 int jpeghead_open(struct inode *inode, struct file *filp) {
00630 inode->i_size=JPEG_HEADER_SIZE;
00631
00632 return 0;
00633 }
00634
00650 loff_t jpeghead_lseek(struct file * file, loff_t offset, int orig){
00651
00652
00653
00654
00655 int rp;
00656 struct frame_params_t * fp;
00657
00658 switch (orig)
00659 {
00660 case SEEK_SET:
00661 file->f_pos = offset;
00662 break;
00663 case SEEK_CUR:
00664 file->f_pos += offset;
00665 break;
00666 case SEEK_END:
00667 if (offset <= 0) {
00668 file->f_pos = JPEG_HEADER_SIZE + offset;
00669 } else {
00670 file->f_pos=0;
00671 rp= (offset >>2) & (~7);
00672 fp = (struct frame_params_t *) &ccam_dma_buf[X313_BUFFSUB(rp, 8)];
00673 if ((fp->signffff != 0xffff) ||
00674 ((fp->timestamp_sec) & X313_LENGTH_MASK)) return -EINVAL;
00675 setJPEGHeader ((int) fp->quality, (int) fp->width, (int) fp->height);
00676 return ( file->f_pos );
00677 }
00678 break;
00679 default:
00680 return -EINVAL;
00681 }
00682
00683
00684 if (file->f_pos < 0) {
00685 file->f_pos = 0;
00686 return(-EOVERFLOW);
00687 }
00688
00689 if (file->f_pos > JPEG_HEADER_SIZE) {
00690 file->f_pos = JPEG_HEADER_SIZE;
00691 }
00692 return ( file->f_pos );
00693 }
00694
00695
00696
00697 ssize_t jpeghead_read(struct file * file, char * buf, size_t count, loff_t *off) {
00698 unsigned long p;
00699
00700 D(printk("jpeghead_read\n"));
00701
00702 p = *off;
00703 if(p >= JPEG_HEADER_SIZE)
00704 p = JPEG_HEADER_SIZE;
00705 if((p + count) > JPEG_HEADER_SIZE) {
00706 count = JPEG_HEADER_SIZE - p;
00707 }
00708 if(count) {
00709 if(copy_to_user(buf, &jpeg_header_sbuffer_ptr[p], count))
00710 return -EFAULT;
00711
00712 *off += count;
00713 }
00714 return count;
00715 }
00716
00717 ssize_t jpeghead_write(struct file * file, const char * buf, size_t count, loff_t *off) {
00718 unsigned long p;
00719
00720 D(printk("jpeghead_write\n"));
00721
00722 p = *off;
00723 if (p >= JPEG_HEADER_SIZE) p = JPEG_HEADER_SIZE;
00724 if( (p + count) > JPEG_HEADER_SIZE) {
00725 count = JPEG_HEADER_SIZE - p;
00726 }
00727 if (count) {
00728 if (copy_from_user(&jpeg_header_sbuffer_ptr[p],buf, count)) return -EFAULT;
00729
00730 *off+=count;
00731 }
00732 return count;
00733 }
00734
00735 static int __init circbuf_all_init(void) {
00736 int res;
00737 res = register_chrdev(CIRCBUF_MAJOR, "circbuf_operations", &circbuf_fops);
00738 if(res < 0) {
00739 printk(KERN_ERR "circbuf_all_init: couldn't get a major number %d.\n",CIRCBUF_MAJOR);
00740 return res;
00741 }
00742 init_waitqueue_head(&circbuf_wait_queue);
00743 printk(CIRCBUF_DRIVER_NAME"\r\n");
00744 return 0;
00745 }
00746
00747
00748 module_init(circbuf_all_init);
00749 MODULE_LICENSE("GPLv3.0");
00750 MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
00751 MODULE_DESCRIPTION(CIRCBUF_DRIVER_NAME);
00752