📄 dv1394.c
字号:
#endif return 0;}static int dv1394_release(struct inode *inode, struct file *file){ struct video_card *video = file_to_video_card(file); /* OK to free the DMA buffer, no more mappings can exist */ do_dv1394_shutdown(video, 1); /* clean up async I/O users */ dv1394_fasync(-1, file, 0); /* give someone else a turn */ clear_bit(0, &video->open); return 0;}/*** PROC_FS INTERFACE ******************************************************/#ifdef CONFIG_PROC_FSstatic LIST_HEAD(dv1394_procfs);struct dv1394_procfs_entry { struct list_head list; struct proc_dir_entry *procfs; char name[32]; struct dv1394_procfs_entry *parent;};static spinlock_t dv1394_procfs_lock = SPIN_LOCK_UNLOCKED;static int dv1394_procfs_read( char *page, char **start, off_t off, int count, int *eof, void *data){ struct video_card *video = (struct video_card*) data; snprintf( page, count, "\format=%s\n\channel=%d\n\cip_n=%lu\n\cip_d=%lu\n\syt_offset=%u\n", (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"), video->channel, video->cip_n, video->cip_d, video->syt_offset ); return strlen(page);}/* lifted from the stallion.c driver */#undef TOLOWER#define TOLOWER(x) ((((x) >= 'A') && ((x) <= 'Z')) ? ((x) + 0x20) : (x))static unsigned long atol(char *str){ unsigned long val; int base, c; char *sp; val = 0; sp = str; if ((*sp == '0') && (*(sp+1) == 'x')) { base = 16; sp += 2; } else if (*sp == '0') { base = 8; sp++; } else { base = 10; } for (; (*sp != 0); sp++) { c = (*sp > '9') ? (TOLOWER(*sp) - 'a' + 10) : (*sp - '0'); if ((c < 0) || (c >= base)) { printk(KERN_ERR "dv1394: atol() invalid argument %s\n", str); val = 0; break; } val = (val * base) + c; } return(val);}static int dv1394_procfs_write( struct file *file, const char *buffer, unsigned long count, void *data){ int len = 0; char new_value[65]; char *pos; struct video_card *video = (struct video_card*) data; if (count > 64) len = 64; else len = count; if (copy_from_user( new_value, buffer, len)) return -EFAULT; new_value[len] = 0; pos = strchr(new_value, '='); if (pos != NULL) { int val_len = len - (pos-new_value) - 1; char buf[65]; memset(buf, 0, 65); strncpy(buf, pos+1, val_len); if (buf[val_len-1] == '\n') buf[val_len-1] = 0; if (strnicmp( new_value, "format", (pos-new_value)) == 0) { if (strnicmp( buf, "NTSC", val_len) == 0) video->pal_or_ntsc = DV1394_NTSC; else if (strnicmp( buf, "PAL", val_len) == 0) video->pal_or_ntsc = DV1394_PAL; } else if (strnicmp( new_value, "cip_n", (pos-new_value)) == 0) { video->cip_n = atol(buf); } else if (strnicmp( new_value, "cip_d", (pos-new_value)) == 0) { video->cip_d = atol(buf); } else if (strnicmp( new_value, "syt_offset", (pos-new_value)) == 0) { video->syt_offset = atol(buf); } else if (strnicmp( new_value, "channel", (pos-new_value)) == 0) { video->channel = atol(buf); } } return len;}struct dv1394_procfs_entry *dv1394_procfs_find( char *name){ struct list_head *lh; struct dv1394_procfs_entry *p; spin_lock( &dv1394_procfs_lock); if (!list_empty(&dv1394_procfs)) { list_for_each(lh, &dv1394_procfs) { p = list_entry(lh, struct dv1394_procfs_entry, list); if (!strncmp(p->name, name, sizeof(p->name))) { spin_unlock( &dv1394_procfs_lock); return p; } } } spin_unlock( &dv1394_procfs_lock); return NULL;}static int dv1394_procfs_add_entry(struct video_card *video){ char buf[32]; struct dv1394_procfs_entry *p; struct dv1394_procfs_entry *parent; p = kmalloc(sizeof(struct dv1394_procfs_entry), GFP_KERNEL); if (!p) { printk(KERN_ERR "dv1394: cannot allocate dv1394_procfs_entry\n"); goto err; } memset(p, 0, sizeof(struct dv1394_procfs_entry)); snprintf(buf, sizeof(buf), "dv/host%d/%s", (video->id>>2), (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL")); parent = dv1394_procfs_find(buf); if (parent == NULL) { printk(KERN_ERR "dv1394: unable to locate parent procfs of %s\n", buf); goto err_free; } p->procfs = create_proc_entry( (video->mode == MODE_RECEIVE ? "in" : "out"), 0666, parent->procfs); if (p->procfs == NULL) { printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/%s/%s\n", parent->name, (video->mode == MODE_RECEIVE ? "in" : "out")); goto err_free; } p->procfs->owner = THIS_MODULE; p->procfs->data = video; p->procfs->read_proc = dv1394_procfs_read; p->procfs->write_proc = dv1394_procfs_write; spin_lock( &dv1394_procfs_lock); INIT_LIST_HEAD(&p->list); list_add_tail(&p->list, &dv1394_procfs); spin_unlock( &dv1394_procfs_lock); return 0; err_free: kfree(p); err: return -ENOMEM;}static intdv1394_procfs_add_dir( char *name, struct dv1394_procfs_entry *parent, struct dv1394_procfs_entry **out){ struct dv1394_procfs_entry *p; p = kmalloc(sizeof(struct dv1394_procfs_entry), GFP_KERNEL); if (!p) { printk(KERN_ERR "dv1394: cannot allocate dv1394_procfs_entry\n"); goto err; } memset(p, 0, sizeof(struct dv1394_procfs_entry)); if (parent == NULL) { snprintf(p->name, sizeof(p->name), "%s", name); p->procfs = proc_mkdir( name, ieee1394_procfs_entry); } else { snprintf(p->name, sizeof(p->name), "%s/%s", parent->name, name); p->procfs = proc_mkdir( name, parent->procfs); } if (p->procfs == NULL) { printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/%s\n", p->name); goto err_free; } p->procfs->owner = THIS_MODULE; p->parent = parent; if (out != NULL) *out = p; spin_lock( &dv1394_procfs_lock); INIT_LIST_HEAD(&p->list); list_add_tail(&p->list, &dv1394_procfs); spin_unlock( &dv1394_procfs_lock); return 0; err_free: kfree(p); err: return -ENOMEM;}void dv1394_procfs_del( char *name){ struct dv1394_procfs_entry *p = dv1394_procfs_find(name); if (p != NULL) { if (p->parent == NULL) remove_proc_entry(p->name, ieee1394_procfs_entry); else remove_proc_entry(p->name, p->parent->procfs); spin_lock( &dv1394_procfs_lock); list_del(&p->list); spin_unlock( &dv1394_procfs_lock); kfree(p); }}#endif /* CONFIG_PROC_FS *//*** DEVICE DRIVER HANDLERS ************************************************/static void it_tasklet_func(unsigned long data){ int wake = 0; struct video_card *video = (struct video_card*) data; spin_lock(&video->spinlock); if (!video->dma_running) goto out; irq_printk("ContextControl = %08x, CommandPtr = %08x\n", reg_read(video->ohci, video->ohci_IsoXmitContextControlSet), reg_read(video->ohci, video->ohci_IsoXmitCommandPtr) ); if ( (video->ohci_it_ctx != -1) && (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) ) { struct frame *f; unsigned int frame, i; if (video->active_frame == -1) frame = 0; else frame = video->active_frame; /* check all the DMA-able frames */ for (i = 0; i < video->n_frames; i++, frame = (frame+1) % video->n_frames) { irq_printk("IRQ checking frame %d...", frame); f = video->frames[frame]; if (f->state != FRAME_READY) { irq_printk("clear, skipping\n"); /* we don't own this frame */ continue; } irq_printk("DMA\n"); /* check the frame begin semaphore to see if we can free the previous frame */ if ( *(f->frame_begin_timestamp) ) { int prev_frame; struct frame *prev_f; /* don't reset, need this later *(f->frame_begin_timestamp) = 0; */ irq_printk(" BEGIN\n"); prev_frame = frame - 1; if (prev_frame == -1) prev_frame += video->n_frames; prev_f = video->frames[prev_frame]; /* make sure we can actually garbage collect this frame */ if ( (prev_f->state == FRAME_READY) && prev_f->done && (!f->done) ) { frame_reset(prev_f); video->n_clear_frames++; wake = 1; video->active_frame = frame; irq_printk(" BEGIN - freeing previous frame %d, new active frame is %d\n", prev_frame, frame); } else { irq_printk(" BEGIN - can't free yet\n"); } f->done = 1; } /* see if we need to set the timestamp for the next frame */ if ( *(f->mid_frame_timestamp) ) { struct frame *next_frame; u32 begin_ts, ts_cyc, ts_off; *(f->mid_frame_timestamp) = 0; begin_ts = le32_to_cpu(*(f->frame_begin_timestamp)); irq_printk(" MIDDLE - first packet was sent at cycle %4u (%2u), assigned timestamp was (%2u) %4u\n", begin_ts & 0x1FFF, begin_ts & 0xF, f->assigned_timestamp >> 12, f->assigned_timestamp & 0xFFF); /* prepare next frame and assign timestamp */ next_frame = video->frames[ (frame+1) % video->n_frames ]; if (next_frame->state == FRAME_READY) { irq_printk(" MIDDLE - next frame is ready, good\n"); } else { debug_printk("dv1394: Underflow! At least one frame has been dropped.\n"); next_frame = f; } /* set the timestamp to the timestamp of the last frame sent, plus the length of the last frame sent, plus the syt latency */ ts_cyc = begin_ts & 0xF; /* advance one frame, plus syt latency (typically 2-3) */ ts_cyc += f->n_packets + video->syt_offset ; ts_off = 0; ts_cyc += ts_off/3072; ts_off %= 3072; next_frame->assigned_timestamp = ((ts_cyc&0xF) << 12) + ts_off; if (next_frame->cip_syt1) { next_frame->cip_syt1->b[6] = next_frame->assigned_timestamp >> 8; next_frame->cip_syt1->b[7] = next_frame->assigned_timestamp & 0xFF; } if (next_frame->cip_syt2) { next_frame->cip_syt2->b[6] = next_frame->assigned_timestamp >> 8; next_frame->cip_syt2->b[7] = next_frame->assigned_timestamp & 0xFF; } } /* see if the frame looped */ if ( *(f->frame_end_timestamp) ) { *(f->frame_end_timestamp) = 0; debug_printk(" END - the frame looped at least once\n"); video->dropped_frames++; } } /* for (each frame) */ } if (wake) { kill_fasync(&video->fasync, SIGIO, POLL_OUT); /* wake readers/writers/ioctl'ers */ wake_up_interruptible(&video->waitq); }out: spin_unlock(&video->spinlock);}static void ir_tasklet_func(unsigned long data){ int wake = 0; struct video_card *video = (struct video_card*) data; spin_lock(&video->spinlock); if (!video->dma_running) goto out; if ( (video->ohci_ir_ctx != -1) && (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) ) { int sof=0; /* start-of-frame flag */ struct frame *f; u16 packet_length, packet_time; int i, dbc=0; struct DMA_descriptor_block *block = NULL; u16 xferstatus; int next_i, prev_i; struct DMA_descriptor_block *next = NULL; dma_addr_t next_dma = 0; struct DMA_descriptor_block *prev = NULL; /* loop over all descriptors in all frames */ for (i = 0; i < video->n_frames*MAX_PACKETS; i++) { struct packet *p = dma_region_i(&video->packet_buf, struct packet, video->current_packet); /* make sure we are seeing the latest changes to p */ dma_region_sync(&video->packet_buf, (unsigned long) p - (unsigned long) video->packet_buf.kvirt, sizeof(struct packet)); packet_length = le16_to_cpu(p->data_length); packet_time = le16_to_cpu(p->timestamp); irq_printk("received packet %02d, timestamp=%04x, length=%04x, sof=%02x%02x\n", video->current_packet, packet_time, packet_length, p->data[0], p->data[1]); /* get the descriptor based on packet_buffer cursor */ f = video->frames[video->current_packet / MAX_PACKETS]; block = &(f->descriptor_pool[video->current_packet % MAX_PACKETS]); xfe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -