diff -urp ivtv-latest/driver/ivtv-api.c ivtv/driver/ivtv-api.c --- ivtv-latest/driver/ivtv-api.c 2003-11-01 09:35:36.000000000 +0100 +++ ivtv/driver/ivtv-api.c 2003-11-05 00:32:32.000000000 +0100 @@ -1481,47 +1481,46 @@ int ivtv_v4l2_open(struct inode *inode, int ivtv_v4l2_read(struct file *filp, char *buf, size_t count, loff_t *pos) { struct ivtv_open_id *id = filp->private_data; - + struct ivtv *itv = id->itv; + struct ivtv_v4l2_stream *stream; int ret=0; - + IVTV_DEBUG(IVTV_DEBUG_INFO,"v4l2 read\n"); - if (down_interruptible(&id->itv->sem_lock)) + if (down_interruptible(&itv->sem_lock)) return -ERESTARTSYS; - //FIXME need to handle non-blocking io - //FIXME needs locking - //FIXME this can be collapsed into 1 var i think - if (!test_bit(IVTV_F_S_CAP, &id->itv->v4l2.streams[id->type].s_flags) && - (id->itv->v4l2.streams[id->type].id == -1)) { - - set_bit(IVTV_F_S_CAP, &id->itv->v4l2.streams[id->type].s_flags); - id->itv->v4l2.streams[id->type].id = id->open_id; + stream = &itv->v4l2.streams[id->type]; - ret = ivtv_start_v4l2_stream(id); - if (ret) - IVTV_DEBUG(IVTV_DEBUG_INFO, - "Error in v4l2 stream init\n"); - id->itv->v4l2.streams[id->type].seq = 0; - id->itv->v4l2.streams[id->type].ubytes= 0; + if (!test_and_set_bit(IVTV_F_S_CAP, &stream->s_flags)) { + stream->id = id->open_id; + + ret = ivtv_start_v4l2_stream(id); + if (ret) { + IVTV_DEBUG(IVTV_DEBUG_INFO, + "Error in v4l2 stream init\n"); + /* bit of a hack... but try to reload firmware + * if capture init fails */ + ret = ivtv_firmware_copy(itv); + if (!ret) + ret = ivtv_start_v4l2_stream(id); + } + stream->seq = 0; + stream->ubytes = 0; } else { - if (id->open_id != id->itv->v4l2.streams[id->type].id) + if (id->open_id != stream->id) ret = -EBUSY; } - up(&id->itv->sem_lock); + up(&itv->sem_lock); if (ret) return ret; - if (filp->f_flags & O_NONBLOCK) { - if(!(ivtv_stream_has_data(id)) ) - return -EAGAIN; - } - - ret = ivtv_read(id,buf,count); + ret = ivtv_read(id, buf, count, !(filp->f_flags & O_NONBLOCK)); - if (ret > 0) *pos += ret; + if (ret > 0) + *pos += ret; return ret; } @@ -1529,6 +1528,8 @@ int ivtv_v4l2_read(struct file *filp, ch ssize_t ivtv_v4l2_write(struct file *filp, const char *buf, size_t count, loff_t *pos) { struct ivtv_open_id *id = filp->private_data; + struct ivtv *itv = id->itv; + struct ivtv_v4l2_stream *stream; int ret=0; if ( (id->type != IVTV_DEC_STREAM_TYPE_MPG) && @@ -1537,20 +1538,21 @@ ssize_t ivtv_v4l2_write(struct file *fil return -EINVAL; } - if (down_interruptible(&id->itv->sem_lock)) + if (down_interruptible(&itv->sem_lock)) return -ERESTARTSYS; // Initialize Decoder /* FIXME we'll need to make this its own stream type */ - if (!test_and_set_bit(IVTV_F_S_CAP, &id->itv->v4l2.streams[id->type].s_flags)) { - id->itv->v4l2.streams[id->type].id = id->open_id; + stream = &itv->v4l2.streams[id->type]; + if (!test_and_set_bit(IVTV_F_S_CAP, &stream->s_flags)) { + stream->id = id->open_id; ret = ivtv_start_v4l2_decode(id); } else { - if (id->open_id != id->itv->v4l2.streams[id->type].id) + if (id->open_id != stream->id) ret = -EBUSY; } - up(&id->itv->sem_lock); + up(&itv->sem_lock); if (ret) return ret; diff -urp ivtv-latest/driver/ivtv-driver.c ivtv/driver/ivtv-driver.c --- ivtv-latest/driver/ivtv-driver.c 2003-11-02 07:27:07.000000000 +0100 +++ ivtv/driver/ivtv-driver.c 2003-11-05 15:07:20.636718368 +0100 @@ -209,6 +209,17 @@ int ivtv_enq_buf(struct ivtv *itv, struc return 0; } +/* called to remove the buffer returned by _peek_ functions */ +void ivtv_del_buf(struct ivtv *itv, struct ivtv_buffer_list *queue, + struct ivtv_buffer *buffer) { + unsigned long flags; + + spin_lock_irqsave(&itv->lock, flags); + list_del_init(&buffer->list); + queue->elements--; + spin_unlock_irqrestore(&itv->lock, flags); +} + /* returns first item in queue, doesn't dequeue */ struct ivtv_buffer *ivtv_deq_peek_head(struct ivtv *itv, struct ivtv_buffer_list *queue) { @@ -367,11 +378,14 @@ int ivtv_init_queue(struct ivtv *itv, st int ivtv_move_queue(struct ivtv *itv, struct ivtv_buffer_list *src, struct ivtv_buffer_list *dst) { struct ivtv_buffer *buf; + unsigned long flags; - while ((buf = ivtv_deq_buf(itv, src))) { - ivtv_enq_buf(itv, dst, buf); - } + spin_lock_irqsave(&itv->lock, flags); + while ((buf = __ivtv_deq_buf(src))) + __ivtv_enq_buf(dst, buf); + + spin_unlock_irqrestore(&itv->lock, flags); return 0; } @@ -1044,18 +1058,43 @@ int ivtv_stop_decode(struct ivtv_open_id return 0; } +struct ivtv_v4l2_stream *ivtv_get_busy_stream(struct ivtv *itv, int start) { + struct ivtv_v4l2_stream *stream; + unsigned long flags; + int i; + + spin_lock_irqsave(&itv->lock, flags); + + for (i = start; i < itv->v4l2.streamcount; i++) { + stream = &itv->v4l2.streams[i]; + if (test_and_clear_bit(IVTV_F_S_DMAP, &stream->s_flags)) { + spin_unlock_irqrestore(&itv->lock, flags); + return stream; + } + } + + spin_unlock_irqrestore(&itv->lock, flags); + return NULL; +} + void ivtv_dec_timeout(unsigned long arg) { struct ivtv *itv = (struct ivtv *)arg; + struct ivtv_v4l2_stream *stream; + + if (!ivtv_claimed(itv)) + IVTV_DEBUG(IVTV_DEBUG_ERR, "timed out, but not busy\n"); /* FIXME mpg only :/ */ - struct ivtv_v4l2_stream *stream = &itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_MPG]; + stream = ivtv_get_busy_stream(itv, IVTV_DEC_STREAM_TYPE_MPG); - if (!test_bit(IVTV_F_S_DMAP, &stream->s_flags)) + if (!stream) { + IVTV_DEBUG(IVTV_DEBUG_ERR, "timed out, but no expecting irq\n"); return; + } IVTV_DEBUG(IVTV_DEBUG_ERR, "ivtv_dec_timeout: lost IRQ; resetting...\n"); + set_bit(IVTV_F_S_DMAP, &stream->s_flags); ivtv_dec_DMA_done(itv); - /* kick it off again! */ set_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); ivtv_dec_sched_DMA(itv); } @@ -1244,20 +1283,13 @@ void ivtv_DMA_done_tasklet(unsigned long IVTV_DEBUG(IVTV_DEBUG_INFO, "DMA Done tasklet\n"); - for (y=0; y < itv->v4l2.streamcount; y++) { - if (test_and_clear_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[y].s_flags)) { - stmtype = y; - break; - } - } + stream = ivtv_get_busy_stream(itv, 0); - if (stmtype < 0) { + if (stream == NULL) { IVTV_DEBUG(IVTV_DEBUG_ERR, "Got DMA-done, but not expecting one\n"); goto debug; } - stream = &itv->v4l2.streams[stmtype]; - #if 0 /* Silently return if we're in an overflow state */ if (test_bit(IVTV_F_S_OVERFLOW, &stream->s_flags)) @@ -1352,7 +1384,6 @@ void ivtv_sched_DMA_tasklet(unsigned lon type = data[0]; - /* FIXME should check for null on the stream element */ if (itv->v4l2.streamcount <= type) { IVTV_DEBUG(IVTV_DEBUG_ERR,"No stream handler for type %d\n", type); ivtv_ignore_DMA_req(itv, type); @@ -1441,6 +1472,9 @@ void ivtv_sched_DMA_tasklet(unsigned lon } /* mark overflow condition, next free will restart dma req */ set_bit(IVTV_F_S_OVERFLOW, &itv->v4l2.streams[type].s_flags); + /* FIXME: must wait a little bit, perhaps use timer to fire + * this tasklet */ + tasklet_schedule(&itv->dma_sched_tq); return; } @@ -1983,7 +2017,7 @@ static int ivtv_YUV_fixup(struct ivtv_v4 #endif -long ivtv_read(struct ivtv_open_id *id, char *ubuf, size_t count) { +long ivtv_read(struct ivtv_open_id *id, char *ubuf, size_t count, int block) { int x, sleepctr, datalen, retval=0; struct ivtv *itv = id->itv; size_t newcount; @@ -2017,6 +2051,11 @@ long ivtv_read(struct ivtv_open_id *id, if (buf) break; + if (!block) { + retval = -EAGAIN; + break; + } + ivtv_sleep_timeout(IVTV_SLEEP_WAIT); if (signal_pending(current)) @@ -2089,11 +2128,8 @@ long ivtv_read(struct ivtv_open_id *id, /* if buffer is empty or we've read the whole frame */ if ((buf->buffer.bytesused == 0)) { - spin_lock_irq(&itv->lock); - - list_del(&buf->list); - __ivtv_enq_buf(&st->free_q, buf); - spin_unlock_irq(&itv->lock); + ivtv_del_buf(itv, &st->full_q, buf); + ivtv_enq_buf(itv, &st->free_q, buf); if (test_and_clear_bit(IVTV_F_S_OVERFLOW, &st->s_flags)) tasklet_schedule(&itv->dma_sched_tq); @@ -2134,28 +2170,25 @@ long ivtv_read(struct ivtv_open_id *id, void ivtv_swap_copy(const char *buf, const char *ubuf, size_t count) { u32 *src,*dst; - //int y; + int y; src=(u32 *)ubuf; dst=(u32 *)buf; - /* FIXME this might break on non X86 */ -// #if __CPU__ > 386 - /* Ultra-efficient swab+copy! */ - while ((u32)src <= (u32)ubuf + count) { /* byteswap while copying */ - __asm__ __volatile__ ("bswap %0" : - "=r" (*dst) : - "0" (*src) ); - src++;dst++; - } -// #else - #if 0 - /* Old slow memcpy then swab */ - memcpy((void *)buf,(void *)ubuf,count); - for (y = 0; y < count; y += 4) { - swab32s( (u32 *)((u32)buf + y)); - } - #endif +#ifdef CONFIG_X86 + while ((u32)src <= (u32)ubuf + count) { /* byteswap while copying */ + __asm__ __volatile__ ("bswap %0" : + "=r" (*dst) : + "0" (*src) ); + src++;dst++; + } +#else + /* Old slow memcpy then swab */ + memcpy((void *)buf,(void *)ubuf,count); + for (y = 0; y < count; y += 4) { + swab32s( (u32 *)((u32)buf + y)); + } +#endif } int ivtv_fill_dec_buffers(struct ivtv_open_id *id, const char *ubuf, size_t count) { @@ -2229,10 +2262,8 @@ int ivtv_fill_dec_buffers(struct ivtv_op /* enq buffer when full */ if (buf->buffer.bytesused == IVTV_DMA_DEC_BUF_SIZE) { - spin_lock_irq(&itv->lock); - list_del(&buf->list); - __ivtv_enq_buf(&stream->full_q, buf); - spin_unlock_irq(&itv->lock); + ivtv_del_buf(itv, &stream->free_q, buf); + ivtv_enq_buf(itv, &stream->full_q, buf); } } @@ -2274,6 +2305,9 @@ void ivtv_dec_sched_DMA(struct ivtv *itv IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_dec_sched_DMA\n"); + /* must have pinned down the device */ + IVTV_ASSERT(ivtv_claimed(itv)); + /* fancy way of saying "if (ivtv->dec_needs_data == 0)" */ if (!test_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags)) { IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: no data needed\n"); @@ -2300,17 +2334,12 @@ void ivtv_dec_sched_DMA(struct ivtv *itv IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: unknown stream type %d\n", data[0]); max = 0; + ivtv_unclaim(itv); return; } stream = &itv->v4l2.streams[type]; - if (test_bit(IVTV_F_I_DMAP, &itv->i_flags)) { - IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: decoder busy, delaying\n"); - set_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); - return; - } - /* If we got this far, we have data to send and it wants it */ clear_bit(IVTV_F_I_NEEDS_DATA, &itv->i_flags); @@ -2319,7 +2348,6 @@ void ivtv_dec_sched_DMA(struct ivtv *itv mem_size = data[2]; buffer_bytes = data[3]; /* # bytes in card's buffer */ - while ((max > x) && (mem_size > bytes_written)) { /* send a maximum of 'max' buffers */ buf = ivtv_deq_peek_head(itv, &stream->full_q); @@ -2362,10 +2390,8 @@ void ivtv_dec_sched_DMA(struct ivtv *itv /* buffer is empty? */ if (buf->buffer.bytesused == 0) { - spin_lock_irqsave(&itv->lock, flags); - list_del(&buf->list); - __ivtv_enq_buf(&stream->dma_q, buf); - spin_unlock_irqrestore(&itv->lock, flags); + ivtv_del_buf(itv, &stream->full_q, buf); + ivtv_enq_buf(itv, &stream->dma_q, buf); } x++; } @@ -2390,7 +2416,6 @@ void ivtv_dec_sched_DMA(struct ivtv *itv /* note that we're DMA'ing */ mod_timer(&itv->dec_timeout, jiffies + DEC_DMA_TIMEOUT); set_bit(IVTV_F_S_DMAP, &stream->s_flags); - set_bit(IVTV_F_I_DMAP, &itv->i_flags); ivtv_api_irqsafe(itv->dec_mbox, IVTV_API_DEC_DMA_FROM_HOST, 3,&data[0]); spin_unlock_irqrestore(&itv->lock, flags); @@ -2403,56 +2428,32 @@ void ivtv_dec_sched_DMA(struct ivtv *itv void ivtv_dec_DMA_done(struct ivtv *itv) { struct ivtv_v4l2_stream *stream=NULL; struct ivtv_buffer *buf; - unsigned long flags; - int y, stmtype=-1; + int y; IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: DMA Done tasklet\n"); - spin_lock_irqsave(&itv->lock, flags); + del_timer(&itv->dec_timeout); - if (!test_and_clear_bit(IVTV_F_I_DMAP, &itv->i_flags)) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "DMAP not set\n"); - spin_unlock_irqrestore(&itv->lock, flags); - goto debug; - } - - mod_timer(&itv->dec_timeout, jiffies + DEC_DMA_TIMEOUT); - - for (y=IVTV_DEC_STREAM_TYPE_MPG; y < itv->v4l2.streamcount; y++) { - if (test_and_clear_bit(IVTV_F_S_DMAP, &itv->v4l2.streams[y].s_flags)) { - stmtype = y; - break; - } - } - - spin_unlock_irqrestore(&itv->lock, flags); + stream = ivtv_get_busy_stream(itv, IVTV_DEC_STREAM_TYPE_MPG); /* Handle OSD DMA */ - if ((itv->user_dma_to_device_state != NULL) && - (itv->user_dma_to_device_state->page_count != 0)) { + if (test_and_clear_bit(IVTV_F_I_OSD_DMA, &itv->i_flags)) { IVTV_DEBUG(IVTV_DEBUG_INFO, "OSD: DMA Done\n"); - itv->user_dma_to_device_state->page_count = 0; - - up(&itv->user_dma_to_device_state->lock); - /* wake all the normal streams, in case they fell asleep */ - for (y=IVTV_DEC_STREAM_TYPE_MPG; y < itv->v4l2.streamcount; y++) { + for (y=IVTV_DEC_STREAM_TYPE_MPG; y < itv->v4l2.streamcount; y++) wake_up(&itv->v4l2.streams[y].waitq); - } - - wake_up(&itv->dec_master_w); + ivtv_unclaim(itv); return; } - if (stmtype < 0) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: Got DMA-done, not expecting one\n"); + if (stream == NULL) { + IVTV_DEBUG(IVTV_DEBUG_ERR, "DMAP not set\n"); goto debug; } IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: Stream %d dma-done\n", y); - stream = &itv->v4l2.streams[y]; while ((buf = ivtv_deq_buf(itv, &stream->dma_q)) != NULL) { IVTV_ASSERT(buf->dma_handle != IVTV_DMA_UNMAPPED); @@ -2471,7 +2472,8 @@ void ivtv_dec_DMA_done(struct ivtv *itv) /* wake up queue filler */ wake_up(&stream->waitq); - wake_up(&itv->dec_master_w); + /* release device */ + ivtv_unclaim(itv); return; debug: ivtv_show_debug_flags(itv); @@ -2510,46 +2512,39 @@ int ivtv_get_timing_info(struct ivtv *it return 0; } +/* claim device by marking it busy for dma */ +void ivtv_claim(struct ivtv *itv) { + DECLARE_WAITQUEUE(wait, current); + int i = 0; + + add_wait_queue(&itv->dec_master_w, &wait); + do { + if (i > 5) + IVTV_DEBUG(IVTV_DEBUG_ERR, "waited %d seconds to claim device\n", i); + set_current_state(TASK_UNINTERRUPTIBLE); + + if (!test_and_set_bit(IVTV_F_I_BUSY, &itv->i_flags)) + break; + + schedule_timeout(HZ); + i++; + } while (test_and_set_bit(IVTV_F_I_BUSY, &itv->i_flags)); + set_current_state(TASK_RUNNING); + remove_wait_queue(&itv->dec_master_w, &wait); +} + +void ivtv_unclaim(struct ivtv *itv) { + clear_bit(IVTV_F_I_BUSY, &itv->i_flags); + wake_up(&itv->dec_master_w); +} + ssize_t ivtv_write(struct ivtv_open_id *id, const char *ubuf, size_t count) { -#if 0 - u32 result, data[IVTV_MBOX_MAX_DATA]; - u32 dec_cnt; struct ivtv *itv=id->itv; -#endif int bytes_written=0, ret; IVTV_DEBUG(IVTV_DEBUG_INFO, "ivtv_write\n"); -#if 0 /* Lots of extra debugging stuff */ - /* Last DMA status? */ - if (ivtv_api(itv->dec_mbox, &itv->sem_lock, - IVTV_API_DEC_DMA_STATUS,&result,0,&data[0])) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: error sending status req\n"); - } - - IVTV_DEBUG(IVTV_DEBUG_INFO, - "DEC: DMA status bitmask 0x%08x, stream type: 0x%08x\n", - data[0], data[1]); - - /* buffer fullness stats */ - if (ivtv_api(itv->dec_mbox, &itv->sem_lock, - IVTV_API_DEC_XFER_INFO,&result,0,&data[0])) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: error sending DMA info\n"); - } - - IVTV_DEBUG(IVTV_DEBUG_INFO, - "DEC: Stream type: 0x%08x, maxbytes 0x%08x, bufferbytes 0x%08x\n", - data[0], data[2], data[3]); - - - /* Timing info. */ - if (ivtv_api(itv->dec_mbox, &itv->sem_lock, - IVTV_API_DEC_TIMING_INFO,&result,0,&data[0])) { - IVTV_DEBUG(IVTV_DEBUG_ERR, "DEC: err sending timing info\n"); - } - - IVTV_DEBUG(IVTV_DEBUG_INFO, "DEC: Frames decoded 0x%08x\n", data[0]); -#endif + ivtv_claim(itv); while (bytes_written < count) { /* completely use up user data * before returning */ diff -urp ivtv-latest/driver/ivtv-fb.c ivtv/driver/ivtv-fb.c --- ivtv-latest/driver/ivtv-fb.c 2003-11-01 09:35:36.000000000 +0100 +++ ivtv/driver/ivtv-fb.c 2003-11-05 14:42:11.202187296 +0100 @@ -137,9 +137,12 @@ console hijacks, and allow you to unload #include #include -#include #include +#ifdef CONFIG_MTRR +#include +#endif + #include