?? meteor.c
字號:
}/* * There is also a problem with range checking on the 7116. * It seems to only work for 22 bits, so the max size we can allocate * is 22 bits long or 4194304 bytes assuming that we put the beginning * of the buffer on a 2^24 bit boundary. The range registers will use * the top 8 bits of the dma start registers along with the bottom 22 * bits of the range register to determine if we go out of range. * This makes getting memory a real kludge. * */#define RANGE_BOUNDARY (1<<22)static vm_offset_tget_meteor_mem(int unit, unsigned size){vm_offset_t addr = 0; addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, 1<<24); if(addr == 0) addr = vm_page_alloc_contig(size, 0x100000, 0xffffffff, PAGE_SIZE); if(addr == 0) { printf("meteor%d: Unable to allocate %d bytes of memory.\n", unit, size); } return addr;}static voidbt254_write(meteor_reg_t *mtr, u_char addr, u_char data){ addr &= 0x7; /* sanity? */ mtr->bt254_reg[addr] = data; PCF8574_DATA_WRITE(mtr, data); /* set data */ PCF8574_CTRL_WRITE(mtr, (PCF8574_CTRL_REG(mtr) & ~0x7) | addr); PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x10); /* WR/ to 0 */ PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x10); /* WR to 1 */ PCF8574_DATA_WRITE(mtr, 0xff); /* clr data */}static voidbt254_init(meteor_reg_t *mtr){int i; PCF8574_CTRL_WRITE(mtr, 0x7f); PCF8574_DATA_WRITE(mtr, 0xff); /* data port must be 0xff */ PCF8574_CTRL_WRITE(mtr, 0x7f); /* init RGB module for 24bpp, composite input */ for(i=0; i<NUM_BT254_REGS; i++) bt254_write(mtr, i, bt254_default[i]); bt254_write(mtr, BT254_COMMAND, 0x00); /* 24 bpp */}static voidbt254_ntsc(meteor_reg_t *mtr, int arg){ if (arg){ /* Set NTSC bit */ PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x20); } else { /* reset NTSC bit */ PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) &= ~0x20); }}static voidselect_bt254(meteor_reg_t *mtr){ /* disable saa7196, saaen = 1 */ PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x80); /* enable Bt254, bten = 0 */ PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x40);}static voidselect_saa7196(meteor_reg_t *mtr){ /* disable Bt254, bten = 1 */ PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) | 0x40); /* enable saa7196, saaen = 0 */ PCF8574_CTRL_WRITE(mtr, PCF8574_CTRL_REG(mtr) & ~0x80);}/* * Initialize the 7116, 7196 and the RGB module. */static voidmeteor_init ( meteor_reg_t *mtr ){ mreg_t *vbase_addr; int i; /* * Initialize the Philips SAA7116 */ mtr->base->cap_cntl = 0x00000040L; vbase_addr = &mtr->base->dma1e; for (i = 0 ; i < (sizeof(struct saa7116_regs)/sizeof(mreg_t)); i++) *vbase_addr++ = saa7116_pci_default[i]; /* * Check for the Philips SAA7196 */ i2c_print_err = 0; if(i2c_write(mtr, SAA7196_I2C_ADDR, SAA7116_I2C_WRITE, 0, 0xff) == 0) { i2c_print_err = 1; /* * Initialize 7196 */ for (i = 0; i < NUM_SAA7196_I2C_REGS; i++) SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]); /* * Get version number. */ SAA7196_WRITE(mtr, SAA7196_STDC, SAA7196_REG(mtr, SAA7196_STDC) & ~0x02); SAA7196_READ(mtr); printf("meteor%d: <Philips SAA 7196> rev 0x%x\n", METEOR_NUM(mtr), (unsigned)((mtr->base->i2c_read & 0xff000000L) >> 28)); } else { i2c_print_err = 1; printf("meteor%d: <Philips SAA 7196 NOT FOUND>\n", METEOR_NUM(mtr)); } /* * Check for RGB module, initialized if found. */ i2c_print_err = 0; if(i2c_write(mtr,PCF8574_DATA_I2C_ADDR,SAA7116_I2C_WRITE,0,0xff) == 0) { i2c_print_err = 1; printf("meteor%d: <Booktree 254 (RGB module)>\n", METEOR_NUM(mtr)); /* does this have a rev #? */ bt254_init(mtr); /* Set up RGB module */ mtr->flags = METEOR_RGB; } else { i2c_print_err = 1; mtr->flags = 0; } set_fps(mtr, 30);}static voidmet_attach(pcici_t tag, int unit){#ifdef METEOR_IRQ u_long old_irq, new_irq;#endif METEOR_IRQ meteor_reg_t *mtr; vm_offset_t buf; u_long latency; if (unit >= NMETEOR) { printf("meteor%d: attach: only %d units configured.\n", unit, NMETEOR); printf("meteor%d: attach: invalid unit number.\n", unit); return ; } mtr = &meteor[unit]; mtr->tag = tag; pci_map_mem(tag, PCI_MAP_REG_START, (vm_offset_t *)&mtr->base, &mtr->phys_base);#ifdef METEOR_IRQ /* from the configuration file */ old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); pci_conf_write(tag, PCI_INTERRUPT_REG, METEOR_IRQ); new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); printf("meteor%d: attach: irq changed from %d to %d\n", unit, (old_irq & 0xff), (new_irq & 0xff));#endif METEOR_IRQ /* setup the interrupt handling routine */ pci_map_int(tag, meteor_intr, (void*) mtr, &net_imask); /* * PCI latency timer. 32 is a good value for 4 bus mastering slots, if * you have more than for, then 16 would probably be a better value. * */#ifndef METEOR_DEF_LATENCY_VALUE#define METEOR_DEF_LATENCY_VALUE 32 #endif latency = pci_conf_read(tag, PCI_LATENCY_TIMER); latency = (latency >> 8) & 0xff; if(bootverbose) { if(latency) printf("meteor%d: PCI bus latency is", unit); else printf("meteor%d: PCI bus latency was 0 changing to", unit); } if(!latency) { latency = METEOR_DEF_LATENCY_VALUE; pci_conf_write(tag, PCI_LATENCY_TIMER, latency<<8); } if(bootverbose) { printf(" %lu.\n", latency); } meteor_init(mtr); /* set up saa7116, saa7196, and rgb module */ if(METEOR_ALLOC) buf = get_meteor_mem(unit, METEOR_ALLOC); else buf = 0; if(bootverbose) { printf("meteor%d: buffer size %d, addr 0x%x\n", unit, METEOR_ALLOC, vtophys(buf)); } mtr->bigbuf = buf; mtr->alloc_pages = METEOR_ALLOC_PAGES; if(buf != 0) { bzero((caddr_t) buf, METEOR_ALLOC); buf = vtophys(buf); /* 640x480 RGB 16 */ mtr->base->dma1e = buf; mtr->base->dma1o = buf + 0x500; mtr->base->dma_end_e = mtr->base->dma_end_o = buf + METEOR_ALLOC; } /* 1 frame of 640x480 RGB 16 */ mtr->cols = 640; mtr->rows = 480; mtr->depth = 2; /* two bytes per pixel */ mtr->frames = 1; /* one frame */ mtr->flags |= METEOR_INITALIZED | METEOR_AUTOMODE | METEOR_DEV0 | METEOR_RGB16;#ifdef DEVFS mtr->devfs_token = devfs_add_devswf(&meteor_cdevsw, unit, DV_CHR, 0, 0, 0644, "meteor");#endif}#define UNIT(x) ((x) & 0x07)#ifdef unusedstatic intmeteor_reset(dev_t dev){int unit = UNIT(minor(dev));struct saa7116_regs *m; if(unit >= NMETEOR) return ENXIO; m = meteor[unit].base; m->cap_cntl = 0x0; tsleep((caddr_t)m, METPRI, "Mreset", hz/50); m->cap_cntl = 0x8ff0; m->cap_cntl = 0x80c0; m->cap_cntl = 0x8040; tsleep((caddr_t)m, METPRI, "Mreset", hz/10); m->cap_cntl = 0x80c0; return 0;}#endif/*---------------------------------------------------------**** Meteor character device driver routines****---------------------------------------------------------*/intmeteor_open(dev_t dev, int flags, int fmt, struct proc *p){ meteor_reg_t *mtr; int unit; int i; unit = UNIT(minor(dev)); if (unit >= NMETEOR) /* unit out of range */ return(ENXIO); mtr = &(meteor[unit]); if (!(mtr->flags & METEOR_INITALIZED)) /* device not found */ return(ENXIO); if (mtr->flags & METEOR_OPEN) /* device is busy */ return(EBUSY); mtr->flags |= METEOR_OPEN; /* * Make sure that the i2c regs are set the same for each open. */ for(i=0; i< NUM_SAA7196_I2C_REGS; i++) { SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]); } mtr->fifo_errors = 0; mtr->dma_errors = 0; mtr->frames_captured = 0; mtr->even_fields_captured = 0; mtr->odd_fields_captured = 0; mtr->proc = (struct proc *)0; set_fps(mtr, 30);#ifdef METEOR_TEST_VIDEO mtr->video.addr = 0; mtr->video.width = 0; mtr->video.banksize = 0; mtr->video.ramsize = 0;#endif return(0);}intmeteor_close(dev_t dev, int flags, int fmt, struct proc *p){ meteor_reg_t *mtr; int unit; #ifdef METEOR_DEALLOC_ABOVE int temp;#endif unit = UNIT(minor(dev)); if (unit >= NMETEOR) /* unit out of range */ return(ENXIO); mtr = &(meteor[unit]); mtr->flags &= ~METEOR_OPEN; if(mtr->flags & METEOR_SINGLE) /* this should not happen, the read capture should have completed or in the very least recieved a signal before close is called. */ wakeup((caddr_t)mtr); /* continue read */ /* * Turn off capture mode. */ mtr->base->cap_cntl = 0x8ff0; mtr->flags &= ~(METEOR_CAP_MASK|METEOR_WANT_MASK);#ifdef METEOR_DEALLOC_PAGES if (mtr->bigbuf != NULL) { kmem_free(kernel_map,mtr->bigbuf,(mtr->alloc_pages*PAGE_SIZE)); mtr->bigbuf = NULL; mtr->alloc_pages = 0; }#else#ifdef METEOR_DEALLOC_ABOVE if (mtr->bigbuf != NULL && mtr->alloc_pages > METEOR_DEALLOC_ABOVE) { temp = METEOR_DEALLOC_ABOVE - mtr->alloc_pages; kmem_free(kernel_map, mtr->bigbuf+((mtr->alloc_pages - temp) * PAGE_SIZE), (temp * PAGE_SIZE)); mtr->alloc_pages = METEOR_DEALLOC_ABOVE; }#endif#endif return(0);}static voidstart_capture(meteor_reg_t *mtr, unsigned type){mreg_t *cap = &mtr->base->cap_cntl; mtr->flags |= type; switch(mtr->flags & METEOR_ONLY_FIELDS_MASK) { case METEOR_ONLY_EVEN_FIELDS: mtr->flags |= METEOR_WANT_EVEN; if(type == METEOR_SINGLE) *cap = 0x0ff4 | mtr->range_enable; else *cap = 0x0ff1 | mtr->range_enable; break; case METEOR_ONLY_ODD_FIELDS: mtr->flags |= METEOR_WANT_ODD; if(type == METEOR_SINGLE) *cap = 0x0ff8 | mtr->range_enable; else *cap = 0x0ff2 | mtr->range_enable; break; default: mtr->flags |= METEOR_WANT_MASK; if(type == METEOR_SINGLE) *cap = 0x0ffc | mtr->range_enable; else *cap = 0x0ff3 | mtr->range_enable; break; }}intmeteor_read(dev_t dev, struct uio *uio, int ioflag){ meteor_reg_t *mtr; int unit; int status; int count; unit = UNIT(minor(dev)); if (unit >= NMETEOR) /* unit out of range */ return(ENXIO); mtr = &(meteor[unit]); if (mtr->bigbuf == 0)/* no frame buffer allocated (ioctl failed) */ return(ENOMEM); if (mtr->flags & METEOR_CAP_MASK)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -