📄 meteor.c
字号:
else mtr->flags &= ~METEOR_ONLY_EVEN_FIELDS; /* can't change parameters while capturing */ if (mtr->flags & METEOR_CAP_MASK) return(EBUSY); if ((geo->columns & 0x3fe) != geo->columns) { printf( "meteor%d: ioctl: %d: columns too large or not even.\n", unit, geo->columns); error = EINVAL; } if (((geo->rows & 0x7fe) != geo->rows) || ((geo->oformat & METEOR_GEO_FIELD_MASK) && ((geo->rows & 0x3fe) != geo->rows)) ) { printf( "meteor%d: ioctl: %d: rows too large or not even.\n", unit, geo->rows); error = EINVAL; } if (geo->frames > 32) { printf("meteor%d: ioctl: too many frames.\n", unit); error = EINVAL; } if(error) return error; if (temp=geo->rows * geo->columns * geo->frames * 2) { if (geo->oformat & METEOR_GEO_RGB24) temp = temp * 2; /* meteor_mem structure for SYNC Capture */ if (geo->frames > 1) temp += PAGE_SIZE; temp = btoc(temp); if (temp > mtr->alloc_pages#ifdef METEOR_TEST_VIDEO && mtr->video.addr == 0#endif ) { buf = get_meteor_mem(unit, temp*PAGE_SIZE); if(buf != 0) { kmem_free(kernel_map, mtr->bigbuf, (mtr->alloc_pages * PAGE_SIZE)); mtr->bigbuf = buf; mtr->alloc_pages = temp; if(bootverbose) printf( "meteor%d: ioctl: Allocating %d bytes\n", unit, temp*PAGE_SIZE); } else { error = ENOMEM; } } } if(error) return error; mtr->rows = geo->rows; mtr->cols = geo->columns; mtr->frames = geo->frames;#ifdef METEOR_TEST_VIDEO if(mtr->video.addr) buf = vtophys(mtr->video.addr); else#endif buf = vtophys(mtr->bigbuf); /* set defaults and end of buffer locations */ base->dma1e = buf; base->dma2e = buf; base->dma3e = buf; base->dma1o = buf; base->dma2o = buf; base->dma3o = buf; base->stride1e = 0; base->stride2e = 0; base->stride3e = 0; base->stride1o = 0; base->stride2o = 0; base->stride3o = 0; /* set end of DMA location, even/odd */ base->dma_end_e = base->dma_end_o = buf + mtr->alloc_pages * PAGE_SIZE; /* * Determine if we can use the hardware range detect. */ if(mtr->alloc_pages * PAGE_SIZE < RANGE_BOUNDARY && ((buf & 0xff000000) | base->dma_end_e) == (buf + mtr->alloc_pages * PAGE_SIZE) ) mtr->range_enable = 0x8000; else { mtr->range_enable = 0x0; base->dma_end_e = base->dma_end_o = 0xffffffff; } switch (geo->oformat & METEOR_GEO_OUTPUT_MASK) { case 0: /* default */ case METEOR_GEO_RGB16: mtr->depth = 2; mtr->frame_size = mtr->rows * mtr->cols * mtr->depth; mtr->flags &= ~METEOR_OUTPUT_FMT_MASK; mtr->flags |= METEOR_RGB16; temp = mtr->cols * mtr->depth; /* recal stride and starting point */ switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) { case METEOR_ONLY_ODD_FIELDS: base->dma1o = buf;#ifdef METEOR_TEST_VIDEO if(mtr->video.addr && mtr->video.width) base->stride1o = mtr->video.width-temp;#endif SAA7196_WRITE(mtr, 0x20, 0xd0); break; case METEOR_ONLY_EVEN_FIELDS: base->dma1e = buf;#ifdef METEOR_TEST_VIDEO if(mtr->video.addr && mtr->video.width) base->stride1e = mtr->video.width-temp;#endif SAA7196_WRITE(mtr, 0x20, 0xf0); break; default: /* interlaced even/odd */ base->dma1e = buf; base->dma1o = buf + temp; base->stride1e = base->stride1o = temp;#ifdef METEOR_TEST_VIDEO if(mtr->video.addr && mtr->video.width) { base->dma1o = buf + mtr->video.width; base->stride1e = base->stride1o = mtr->video.width - temp + mtr->video.width; }#endif SAA7196_WRITE(mtr, 0x20, 0x90); break; } base->routee = base->routeo = 0xeeeeee01; break; case METEOR_GEO_RGB24: mtr->depth = 4; mtr->frame_size = mtr->rows * mtr->cols * mtr->depth; mtr->flags &= ~METEOR_OUTPUT_FMT_MASK; mtr->flags |= METEOR_RGB24; temp = mtr->cols * mtr->depth; /* recal stride and starting point */ switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) { case METEOR_ONLY_ODD_FIELDS: base->dma1o = buf;#ifdef METEOR_TEST_VIDEO if(mtr->video.addr && mtr->video.width) base->stride1o = mtr->video.width-temp;#endif SAA7196_WRITE(mtr, 0x20, 0xd2); break; case METEOR_ONLY_EVEN_FIELDS: base->dma1e = buf;#ifdef METEOR_TEST_VIDEO if(mtr->video.addr && mtr->video.width) base->stride1e = mtr->video.width-temp;#endif SAA7196_WRITE(mtr, 0x20, 0xf2); break; default: /* interlaced even/odd */ base->dma1e = buf; base->dma1o = buf + mtr->cols * mtr->depth; base->stride1e = base->stride1o = mtr->cols * mtr->depth;#ifdef METEOR_TEST_VIDEO if(mtr->video.addr && mtr->video.width) { base->dma1o = buf + mtr->video.width; base->stride1e = base->stride1o = mtr->video.width - temp + mtr->video.width; }#endif SAA7196_WRITE(mtr, 0x20, 0x92); break; } base->routee= base->routeo= 0x39393900; break; case METEOR_GEO_YUV_PLANAR: mtr->depth = 2; temp = mtr->rows * mtr->cols; /* compute frame size */ mtr->frame_size = temp * mtr->depth; mtr->flags &= ~METEOR_OUTPUT_FMT_MASK; mtr->flags |= METEOR_YUV_PLANAR; /* recal stride and starting point */ switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) { case METEOR_ONLY_ODD_FIELDS: base->dma1o = buf; /* Y Odd */ base->dma2o = buf + temp; /* U Odd */ temp >>= 1; base->dma3o = base->dma2o + temp; /* V Odd */ SAA7196_WRITE(mtr, 0x20, 0xd1); break; case METEOR_ONLY_EVEN_FIELDS: base->dma1e = buf; /* Y Even */ base->dma2e = buf + temp; /* U Even */ temp >>= 1; base->dma2e= base->dma2e + temp; /* V Even */ SAA7196_WRITE(mtr, 0x20, 0xf1); break; default: /* interlaced even/odd */ base->dma1e = buf; /* Y Even */ base->dma2e = buf + temp; /* U Even */ temp >>= 2; base->dma3e = base->dma2e + temp; /* V Even */ base->dma1o = base->dma1e+mtr->cols;/* Y Odd */ base->dma2o = base->dma3e + temp; /* U Odd */ base->dma3o = base->dma2o + temp; /* V Odd */ base->stride1e = base->stride1o = mtr->cols; SAA7196_WRITE(mtr, 0x20, 0x91); break; } switch (geo->oformat & (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) { case METEOR_GEO_YUV_9: base->routee=base->routeo = 0xaaaaffc3; break; case METEOR_GEO_YUV_12: base->routee=base->routeo = 0xaaaaffc2; break; default: base->routee=base->routeo = 0xaaaaffc1; break; } break; case METEOR_GEO_YUV_422:/* same as planer, different uv order */ mtr->depth = 2; temp = mtr->rows * mtr->cols; /* compute frame size */ mtr->frame_size = temp * mtr->depth; mtr->flags &= ~METEOR_OUTPUT_FMT_MASK; mtr->flags |= METEOR_YUV_422; switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) { case METEOR_ONLY_ODD_FIELDS: base->dma1o = buf; base->dma2o = buf + temp; base->dma3o = base->dma2o + (temp >> 1); SAA7196_WRITE(mtr, 0x20, 0xd1); break; case METEOR_ONLY_EVEN_FIELDS: base->dma1e = buf; base->dma2e = buf + temp; base->dma3e = base->dma2e + (temp >> 1); SAA7196_WRITE(mtr, 0x20, 0xf1); break; default: /* interlaced even/odd */ base->dma1e = buf; /* Y even */ base->dma2e = buf + temp; /* U even */ base->dma3e = base->dma2e + (temp >> 1);/* V even */ base->dma1o = base->dma1e+mtr->cols;/* Y odd */ temp = mtr->cols >> 1; base->dma2o = base->dma2e+temp; /* U odd */ base->dma3o = base->dma3e+temp; /* V odd */ base->stride1e = base->stride1o = mtr->cols; /* Y stride */ base->stride2e = base->stride2o = temp; /* U stride */ base->stride3e = base->stride3o = temp; /* V stride */ SAA7196_WRITE(mtr, 0x20, 0x91); break; } switch (geo->oformat & (METEOR_GEO_YUV_12 | METEOR_GEO_YUV_9)) { case METEOR_GEO_YUV_9: base->routee=base->routeo = 0xaaaaffc3; break; case METEOR_GEO_YUV_12: base->routee=base->routeo = 0xaaaaffc2; break; default: base->routee=base->routeo = 0xaaaaffc1; break; } break; case METEOR_GEO_YUV_PACKED: mtr->depth = 2; mtr->frame_size = mtr->rows * mtr->cols * mtr->depth; mtr->flags &= ~METEOR_OUTPUT_FMT_MASK; mtr->flags |= METEOR_YUV_PACKED; /* recal stride and odd starting point */ switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) { case METEOR_ONLY_ODD_FIELDS: base->dma1o = buf; SAA7196_WRITE(mtr, 0x20, 0xd1); break; case METEOR_ONLY_EVEN_FIELDS: base->dma1e = buf; SAA7196_WRITE(mtr, 0x20, 0xf1); break; default: /* interlaced even/odd */ base->dma1e = buf; base->dma1o = buf + mtr->cols * mtr->depth; base->stride1e = base->stride1o = mtr->cols * mtr->depth; SAA7196_WRITE(mtr, 0x20, 0x91); break; } base->routee = base->routeo = 0xeeeeee41; break; default: error = EINVAL; /* invalid argument */ printf("meteor%d: ioctl: invalid output format\n",unit); break; } /* set cols */ SAA7196_WRITE(mtr, 0x21, mtr->cols & 0xff); SAA7196_WRITE(mtr, 0x24, ((SAA7196_REG(mtr, 0x24) & ~0x03) | ((mtr->cols >> 8) & 0x03))); /* set rows */ if(mtr->flags & METEOR_ONLY_FIELDS_MASK) { SAA7196_WRITE(mtr, 0x25, ((mtr->rows) & 0xff)); SAA7196_WRITE(mtr, 0x28, ((SAA7196_REG(mtr, 0x28) & ~0x03) | ((mtr->rows >> 8) & 0x03))); } else { /* Interlaced */ SAA7196_WRITE(mtr, 0x25, ((mtr->rows >> 1) & 0xff)); SAA7196_WRITE(mtr, 0x28, ((SAA7196_REG(mtr, 0x28) & ~0x03) | ((mtr->rows >> 9) & 0x03))); } /* set signed/unsigned chrominance */ SAA7196_WRITE(mtr, 0x30, (SAA7196_REG(mtr, 0x30) & ~0x10) | ((geo->oformat&METEOR_GEO_UNSIGNED)?0:0x10)); break; case METEORGETGEO: geo = (struct meteor_geomet *) arg; geo->rows = mtr->rows; geo->columns = mtr->cols; geo->frames = mtr->frames; geo->oformat = (mtr->flags & METEOR_OUTPUT_FMT_MASK) | (mtr->flags & METEOR_ONLY_FIELDS_MASK) | (SAA7196_REG(mtr, 0x30) & 0x10 ? 0:METEOR_GEO_UNSIGNED); switch(base->routee & 0xff) { case 0xc3: geo->oformat |= METEOR_GEO_YUV_9; break; case 0xc2: geo->oformat |= METEOR_GEO_YUV_12; break; default: break; } break; case METEORSCOUNT: /* (re)set error counts */ cnt = (struct meteor_counts *) arg; mtr->fifo_errors = cnt->fifo_errors; mtr->dma_errors = cnt->dma_errors; mtr->frames_captured = cnt->frames_captured; mtr->even_fields_captured = cnt->even_fields_captured; mtr->odd_fields_captured = cnt->odd_fields_captured; break; case METEORGCOUNT: /* get error counts */ cnt = (struct meteor_counts *) arg; cnt->fifo_errors = mtr->fifo_errors; cnt->dma_errors = mtr->dma_errors; cnt->frames_captured = mtr->frames_captured; cnt->even_fields_captured = mtr->even_fields_captured; cnt->odd_fields_captured = mtr->odd_fields_captured; break; default: printf("meteor%d: ioctl: invalid ioctl request\n", unit); error = ENOTTY; break; } return(error);}intmeteor_mmap(dev_t dev, vm_offset_t offset, int nprot){ int unit; meteor_reg_t *mtr; unit = UNIT(minor(dev)); if (unit >= NMETEOR) /* at this point could this happen? */ return(-1); mtr = &(meteor[unit]); if(nprot & PROT_EXEC) return -1; if(offset >= mtr->alloc_pages * PAGE_SIZE) return -1; return i386_btop(vtophys(mtr->bigbuf) + offset);}#if !defined(METEOR_FreeBSD_210) /* XXX */static meteor_devsw_installed = 0;static void meteor_drvinit(void *unused){ dev_t dev; if( ! meteor_devsw_installed ) { dev = makedev(CDEV_MAJOR, 0); cdevsw_add(&dev,&meteor_cdevsw, NULL); meteor_devsw_installed = 1; }}SYSINIT(meteordev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,meteor_drvinit,NULL)#endif#endif /* NMETEOR > 0 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -