📄 btvid3.c
字号:
/****************************************************************** MODULE: Bt878 Decoder Interace** DESCRITPION: Connexant Bt878 NTSC Video Decoder VxWorks* 5.4 PCI Driver and Video Processing Utilities** ORIGINAL AUTHOR: Sam Siewert, University of Colorado, Boulder* UPDATED BY: Zach Pfeffer, University of Colorado, Boulder* Dan Walkes, University of Colorado, Boulder* * CREATED: May 7, 2000* MODIFIED: June 17, 2004* Feb 22, 2005* * NOTES:** This code is intended to be used as driver bottom-half functions* rather than an exported top-half video driver interface.** Note that this was coded for VxWorks 5.4 for x86/PCI architecture* and assumes the pcPentium BSP PCI API.** As of Feb 22, the Pentium 3 BSP and Tornado 2.2 development tool is also* supported.** CODE USAGE:** To test the bottom half functions, start video acquisition with:* ---------------------------------------------------------------------** 1) call to start_video_report(void (*pNewFrameReportFn) (unsigned char *pNewBuffer))* with a pointer to the function to call when a new frame is received * (or to simply call start_video() to test functionality)** 2) call to activate(1) for 320x240 RGB 32 bit 30 fps decoding** 3) call to set_mux(3) for external NTSC camera S-video input* Note: the mux value depends on which card you are using and which video* input you are using. See btvid.h #defines for more information.** 4) call to reset_status() to ensure proper sync of code and hardware** 5) repeated calls to report() to ensure frame acauisition is working* and that errors in decoding are being handled properly.** The frame_acq_cnt (value returned by GetFrameAcqCount()) * should increase and that the DMA PC should advance as well as the decoder count.** Finally try dumping a frame to the host with* the write_save_buffer(0) function call.*** 6) call to full_reset() to shut the bottom-half down completely.*** REVISION HISTORY AND NOTES:** Date Update* ---------------------------------------------------------------------* May 7, 2000 Created.* March 23, 2001 Updated for VxWorks 5.4 - changed PCI interrupt* vector registration code.** July 2004 Built a struct array to store info about each PCI* card of interest.** July 2004 Wrote:* decodePIRQxRouteControlRegister* findAndDecodePCIInterruptRoutingTable* dumpPCIFunctionsConfigurationHeader* dumpPCIStatusAndCommand** July 2004 Changed the way the Interrupt is specified. * Instead of statically setting it in a global* define it is now read from the BT878's interrupt * line register in start_video().** July 2004 Expanded btvid_controller_config to output more* debug information about the base address registers* in the BT878.** July 2004 Due to incompatibilities in versions of* Northbridge and Southbridge Intel chips* the current code looks for and explicit * vendor,device value in intel_pci_config. * If it fails to find such a value it * defaults to the old settings.* * Feb 2005 Split files into debug and .h files for readability* Added #defines for typical SET_MUX values.* Made some modifications to PCI_DEV operation and* added functionality specific to P3 targets.* Added start_video_report(void (*pNewFrameReportFn) (unsigned char *pNewBuffer))* to decrease coupling between btvid file and application file.* Moved intel_pci_config(),btvid_controller_config(),test_status() to start_video* from btvid_drvr so that errors do not occur when driver functions are spawned at* shell priority (so activate() does not occur until after these functions have run.)** WARNINGS:** The only mode(s) fully supported and test to date are:* ---------------------------------------------------------------------* NTSC_320_X_240** Other modes have not been tested and may not work without modification.*** REFERENCES:** 1) Bt878 chipset documentation - available on the class WWW site: * http://www-sgc.colorado.edu/~siewerts/ecen/hardware/pdf/** 2) Ph.D. dissertation on RT Video pipelines - available on the CU* research WWW site: * http://www-sgc.colorado.edu/~siewerts/research/rt.html** 3) PCI vendor and device IDs - available on class WWW site:* http://www.datashopper.dk/~finth/pci.html*****************************************************************//* VxWorks API includes */#include "vxWorks.h"#include "stdio.h"#include "stdlib.h"#include "ioLib.h"#include "semLib.h"#include "intLib.h"#include "vmLib.h" /* added to support */#include "iv.h"/* VxWorks 5.4 PCI driver interface includes */#include "drv/pci/pciConfigLib.h"#include "drv/pci/pciConfigShow.h"#include "drv/pci/pciHeaderDefs.h"#include "drv/pci/pciLocalBus.h"#include "drv/pci/pciIntLib.h"/* pcPentium BSP includes */#include "sysLib.h"#include "btvid.h"STATUS pciLibInitStatus = NONE; /* initialization done */int pciConfigMech = NONE; /* 1=mechanism-1, 2=mechanism-2 */int pciMaxBus = PCI_MAX_BUS; /* Max number of sub-busses *//* Bottom-half status variables */UINT last_dstatus = 0x0;UINT last_isr_status = 0x0;UINT total_dma_disabled_errs = 0x0;UINT total_sync_errs = 0x0;UINT total_abort_errs = 0x0;UINT total_dma_errs = 0x0;UINT total_parity_errs = 0x0;UINT total_bus_parity_errs = 0x0;UINT total_fifo_overrun_errs = 0x0;UINT total_fifo_resync_errs = 0x0;UINT total_bus_latency_errs = 0x0;UINT total_risc_ints = 0x0;UINT total_ints = 0x0;UINT total_write_tags = 0x0;UINT total_skip_tags = 0x0;UINT total_jump_tags = 0x0;UINT total_sync_tags = 0x0;/* Bottom-half control-monitor variables */int BT878INT; /* this will be set with the IRQ of the BT878 */UINT sysVectorIRQ0 = INT_NUM_IRQ0;UINT ir_table_addr = NULL;UINT frame_rdy_cnt = 0;int replace_write_with_skip = FALSE;int acq_type = NTSC_320_X_240;UINT int_errors_to_check = ( SCERR_INT | OCERR_INT | PABORT_INT | RIPERR_INT | PPERR_INT | FDSR_INT | FTRGT_INT | FBUS_INT | MYSTERY_INT);int btvid_tid;int frame_acq_cnt = 0;int current_frame = 1;SEM_ID frameRdy;/* a global pointer to the frame received function */void (*pglobFnNewFrameRcvd) (unsigned char *pNewFrameBuffer);PCI_DEV_BUS_NAME PCI_DEV[NUMDEVICES];#define MAX_DEVICE_TYPES 11 const DEVTYPE_S asDefDevtype[MAX_DEVICE_TYPES] = { { NORTH_BRIDGE, INTEL_VENDOR_ID, PCI_DEVICE_ID_INTEL_82441FX, "Northbridge: Intel 82441FX", FALSE }, { NORTH_BRIDGE, INTEL_VENDOR_ID, PCI_DEVICE_ID_INTEL_82439TX, "Northbridge: Intel 82439TX", FALSE }, { NORTH_BRIDGE, INTEL_VENDOR_ID, PCI_DEVICE_ID_INTEL_820820, "Northbridge: Intel 820820", FALSE }, { NORTH_BRIDGE, INTEL_VENDOR_ID, PCI_DEVICE_ID_INTEL_MY_NB, "Northbridge: Intel Host-Hub Interface Bridge", FALSE },//Added by chen { SOUTH_BRIDGE, INTEL_VENDOR_ID, PCI_DEVICE_ID_INTEL_82371SB_0, "Southbridge: Intel 82371SB", FALSE }, { SOUTH_BRIDGE, INTEL_VENDOR_ID, PCI_DEVICE_ID_INTEL_82371AB_0, "Southbridge: Intel 82371AB", FALSE }, { SOUTH_BRIDGE, INTEL_VENDOR_ID, PCI_DEVICE_ID_INTEL_82801AA, "Southbridge: Intel 82801AA", FALSE }, { SOUTH_BRIDGE, INTEL_VENDOR_ID, PCI_DEVICE_ID_INTEL_MY_SB, "Southbridge: Intel Hub Interface to PCI Bridge", FALSE },//Added by chen { CAPTURE_VIDEO_CARD1, PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878, "Capture Card 1: BT878", FALSE}, { CAPTURE_VIDEO_CARD2, PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878, "Capture Card 2: BT878", FALSE}, { 0,0,0,0}, /* null terminate list*/};DEVTYPE_S asDevtype[MAX_DEVICE_TYPES]; /* a RAM copy of the same list *//* Returns the first instance of the specified device in the device list * Returns a pointer to the device type entry if success, 0 if fail */DEVTYPE_S *FindNextDevTypeInList(unsigned int uiVendorID, unsigned int uiDeviceID){ DEVTYPE_S *psDevType; psDevType = &asDevtype[0]; while(psDevType->enDevType || psDevType->uiVenId || psDevType->uiDevId || psDevType->pDevDescString) { if( psDevType->uiVenId == uiVendorID && psDevType->uiDevId == uiDeviceID && !psDevType->bFound ) { psDevType->bFound = TRUE; printf("Found Device Type: %s\n",psDevType->pDevDescString); return psDevType; } psDevType++; }; return FALSE; }STATUS findBusDevFunNo(void) { int i = 0; STATUS temp; for(i = 0; i < NUMDEVICES; i++) PCI_DEV[i].Found = pciFindDevice( PCI_DEV[i].venId, PCI_DEV[i].devId, PCI_DEV[i].index, &(PCI_DEV[i].busNo), &(PCI_DEV[i].deviceNo), &(PCI_DEV[i].funcNo) ); return temp;}/* ----------------------------------------------------------- Input: none Return: STATUS OK if all specified devices were found ERROR if any device was not found This function prints any errors that occured during PCI_DEV structure init. */STATUS reportDevFoundStatus(void){ STATUS stReturn = OK; if(PCI_DEV[NORTH_BRIDGE].Found != OK) { printf("Warning: Northbridge not found!!!\n"); stReturn = ERROR; } if(PCI_DEV[SOUTH_BRIDGE].Found != OK) { printf("Warning: Southbridge not found!!!\n"); stReturn = ERROR; } if(PCI_DEV[CAPTURE_VIDEO_CARD1].Found != OK) { printf("Error: Capture card not found!!!\n"); stReturn = ERROR; } if(PCI_DEV[CAPTURE_VIDEO_CARD2].Found != OK && stReturn != ERROR) { printf("Note: Only one capture card found\n"); } return stReturn;} /* Fills in the PCI dev structure with the vendor ID, bus number, and device number for * All devices found. * */ unsigned char FillPCIDev(void){ int deviceNo; int devices; int busNo=0; ushort_t vendorId; ushort_t deviceId; DEVTYPE_S *psDevType; if (pciLibInitStatus != OK) /* sanity check */ { if (pciConfigLibInit (PCI_MECHANISM_1, 0xCF8, 0xCFC, 0) != OK) { printf("PCI lib config error\n"); return (ERROR); } } if (pciConfigMech == PCI_MECHANISM_1) devices = 0x1f; else devices = 0x1f; memcpy(asDevtype,asDefDevtype,sizeof(asDefDevtype)); /* copy the default device type list */ for(busNo = 0; busNo < 10; busNo++) { for (deviceNo=0; deviceNo <= devices; deviceNo++) { pciConfigInWord (busNo, deviceNo, 0, PCI_CFG_VENDOR_ID, &vendorId); pciConfigInWord (busNo, deviceNo, 0, PCI_CFG_DEVICE_ID, &deviceId); if (vendorId != 0xffff) { psDevType = FindNextDevTypeInList(vendorId,deviceId); /* is this device found in the list? */ if(psDevType) /* the device was found */ { /* init respective portion of PCIDEV structure */ PCI_DEV[psDevType->enDevType].venId = vendorId; PCI_DEV[psDevType->enDevType].devId = deviceId; PCI_DEV[psDevType->enDevType].busNo = busNo; PCI_DEV[psDevType->enDevType].deviceNo = deviceNo; } } } } return (OK); }/* ----------------------------------------------------------- Input: none Return: STATUS OK if all specified devices were found ERROR if any device was not found This function is used to initialize PCI devices. Set the vendor ID and device ID for each of the respective devices you assume you will find on the PCI bus for your particular target.*/STATUS initializePCI_DEV(void) { int i = 0; BT878INT = 11; /* as a default in ECEN5623, BT878 cards will use IRQ11 */ for(i = 0; i < NUMDEVICES; i++) { PCI_DEV[i].venId = 0; PCI_DEV[i].devId = 0; PCI_DEV[i].index = 0; PCI_DEV[i].busNo = 0; PCI_DEV[i].deviceNo = 0; PCI_DEV[i].funcNo = 0; } FillPCIDev(); /* fill in the PCIDEV structure with all device info */ findBusDevFunNo(); return reportDevFoundStatus();}/* For Base Address Register Checks */#define BAR_IS_IMPLEMENTED(readback) readback & 0xFFFFFFFF#define BAR_IS_MEM_ADDRESS_DECODER(readback) !(readback & 0x1)#define BAR_IS_IO_ADDRESS_DECODER(readback) (readback & 0x0)#define BAR_IS_32_BIT_DECODER(readback) ((readback & 0x6) >> 1) == 0x0#define BAR_IS_64_BIT_DECODER(readback) ((readback & 0x6) >> 1) == 0x2#define BAR_IS_PREFETCHABLE(readback) (readback & 0x8)#define PCI_ROUTING_TABLE_SIGNATURE 0x52495024#define PCI_ROUTING_TABLE_SIG_BYTE0 0x24#define PCI_ROUTING_TABLE_SIG_BYTE1 0x50#define PCI_ROUTING_TABLE_SIG_BYTE2 0x49#define PCI_ROUTING_TABLE_SIG_BYTE3 0x52/* Design Notes on Microcode PACKED RGB32 320x240 NTSC MODE MICROCODE ---------------------------------------- BYTE3 BYTE2 BYTE1 BYTE0 alpha RED GREEN BLUE ODD LINES first (120 x 320) 00320 ... 00639 00960 ... 01179 01500 ... 01819 ... 70480 ... 70799 EVEN LINES second (120 x 320) 00000 ... 00319 00640 ... 00959 01180 ... 01499 ... 70160 ... 70479 ---- GENERATES FRAME INTA 490 microcode instructions per frame X NUMFRAMES ----------- 490 * NUMFRAMES microcode instructions 2 ------------------------------------------------------- FIELD SYNC 001 DMA_MC_SYNC_FM1_WORD_0, 002 DMA_MC_SYNC_WORD_1, 120 x 2 = 240 ------------------------------------------------------- BEG ODD LINE FIELD 001 DMA_MC_WRITE_1280_LINE, 002 &(frame_buffer[0][320]), ------------------------------------------------------- END ODD LINE FIELD 4 ------------------------------------------------------- VRE & FIELD SYNC 001 DMA_MC_SYNC_VRE_WORD_0, 002 DMA_MC_SYNC_WORD_1, 003 DMA_MC_SYNC_FM1_WORD_0, 004 DMA_MC_SYNC_WORD_1, 120 x 2 = 240 ----------------------------/--------------------------- BEG EVEN LINE FIELD 001 DMA_MC_WRITE_1280_LINE, 002 &(frame_buffer[0][0]), ------------------------------------------------------- END EVEN LINE FIELD 2 ------------------------------------------------------- VRO SYNC 001 DMA_MC_SYNC_VRO_WORD_0, 002 DMA_MC_SYNC_WORD_1, 001 JUMP 002 ADDRESS*//******************************** BEG DMA MC ****************//**** MC TAGS FOR DEBUGGING ****/#define DMA_MC_SYNC 0x00080000 #define DMA_MC_WRITE 0x00010000#define DMA_MC_SKIP 0x00020000#define DMA_MC_JUMP 0x00B40000 /* Clears all for next frame */#define DMA_MC_SYNC_FM1_WORD_0 (0x80008006 | DMA_MC_SYNC)#define DMA_MC_SYNC_FM1_WORD_0_IRQ (0x81008006 | DMA_MC_SYNC)#define DMA_MC_SYNC_WORD_1 (0x00000000)#define DMA_MC_SKIP_1280_LINE (0x2C000500 | DMA_MC_SKIP)#define DMA_MC_SKIP_640_SOL (0x28000280 | DMA_MC_SKIP)#define DMA_MC_SKIP_640_EOL (0x24000280 | DMA_MC_SKIP)#define DMA_MC_SKIP_320_SOL (0x28000140 | DMA_MC_SKIP)#define DMA_MC_SKIP_320 (0x20000140 | DMA_MC_SKIP)#define DMA_MC_SKIP_320_EOL (0x24000140 | DMA_MC_SKIP)#define DMA_MC_SKIP_1280_LINE_IRQ (0x2D000500 | DMA_MC_SKIP)#define DMA_MC_SKIP_40_SOL (0x28000028 | DMA_MC_SKIP)#define DMA_MC_SKIP_40_EOL (0x24000028 | DMA_MC_SKIP)#define DMA_MC_SKIP_2560_LINE (0x2C000A00 | DMA_MC_SKIP)#define DMA_MC_SKIP_1280_SOL (0x28000500 | DMA_MC_SKIP)#define DMA_MC_SKIP_1280_EOL (0x24000500 | DMA_MC_SKIP)#define DMA_MC_SKIP_2560_LINE_IRQ (0x2D000A00 | DMA_MC_SKIP)#define DMA_MC_WRITE_2560_LINE (0x1C000A00 | DMA_MC_WRITE)#define DMA_MC_WRITE_1280_SOL (0x18000500 | DMA_MC_WRITE)#define DMA_MC_WRITE_1280_EOL (0x14000500 | DMA_MC_WRITE)#define DMA_MC_WRITE_2560_LINE_IRQ (0x1D000A00 | DMA_MC_WRITE)#define DMA_MC_WRITE_1280_LINE (0x1C000500 | DMA_MC_WRITE)#define DMA_MC_WRITE_80_LINE (0x1C000050 | DMA_MC_WRITE)#define DMA_MC_WRITE_640_SOL (0x18000280 | DMA_MC_WRITE)#define DMA_MC_WRITE_640_EOL (0x14000280 | DMA_MC_WRITE)#define DMA_MC_WRITE_320_SOL (0x18000140 | DMA_MC_WRITE)#define DMA_MC_WRITE_320 (0x10000140 | DMA_MC_WRITE)#define DMA_MC_WRITE_320_EOL (0x14000140 | DMA_MC_WRITE)#define DMA_MC_WRITE_1280_LINE_IRQ (0x1D000500 | DMA_MC_WRITE)#define DMA_MC_SYNC_VRE_WORD_0 (0x80008004 | DMA_MC_SYNC)#define DMA_MC_SYNC_VRE_WORD_0_IRQ (0x81008004)#define DMA_MC_SYNC_VRO_WORD_0 (0x8000800C | DMA_MC_SYNC)#define DMA_MC_SYNC_VRO_WORD_0_IRQ (0x8100800C)#define DMA_MC_JUMP_TO_BEG (0x70000000 | DMA_MC_JUMP)#define DMA_MC_JUMP_TO_BEG_IRQ (0x71000000 | DMA_MC_JUMP)#define DMA_MC_HALT (0xFFFFFFFF)/**** TEST SCANLINE BUFFER ****/unsigned int test_buffer[320];/**** TEST MICROCODE 1 ****//* For one 640 pixel by 480 line NTSC frame 2 --------------------- DMA_MC_SYNC_FM1_WORD_0, DMA_MC_SYNC_WORD_1, 240 x 1 = 240 ------------- DMA_MC_SKIP_1280_LINE, 4 --------------------- DMA_MC_SYNC_VRE_WORD_0, DMA_MC_SYNC_WORD_1, DMA_MC_SYNC_FM1_WORD_0, DMA_MC_SYNC_WORD_1, 240 x 1 = 240 ------------- DMA_MC_SKIP_1280_LINE, 4 --------------------- DMA_MC_SYNC_VRO_WORD_0, DMA_MC_SYNC_WORD_1, DMA_MC_JUMP_TO_BEG, (unsigned int)&(dma_test_microcode[0])*/unsigned int dma_test_microcode[970];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -