📄 xp_atom_dcr.c
字号:
/*----------------------------------------------------------------------------+| This source code has been made available to you by IBM on an AS-IS| basis. Anyone receiving this source is licensed under IBM| copyrights to use it in any way he or she deems fit, including| copying it, modifying it, compiling it, and redistributing it either| with or without modifications. No license under IBM patents or| patent applications is to be implied by the copyright license.|| Any user of this software should understand that IBM cannot provide| technical support for this software and will not be responsible for| any consequences resulting from the use of this software.|| Any person who transfers this source code or any derivative work| must include the IBM copyright notice, this paragraph, and the| preceding two paragraphs in the transferred software.|| COPYRIGHT I B M CORPORATION 1998| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| Author : Ian Govett| Component : xp| File : xp_dcr.c| Purpose : DCR access to Transport Registers| Changes :|| Date By Comments| --------- --- --------------------------------------------------------| 15-Jan-98 IG Created| 04-May-01 TJC Updated for Pallas| 30-Sep-01 LGH change the file name, ported to linux, Combine codes for| three Devices| 29-Oct-02 LGH Add negative filter support for Vesta|+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| DCR Access To The Transport Registers+-----------------------------------------------------------------------------+|| The following functions provide access methods to the DCR registers.| The transport hardware uses an indirect addressing scheme for access to| it's registers. Read and write operations are a two step process. The| address is first written to the transport DCR address register, and| then the read or write operation is done.|| A critical section is required around the indirect address operation| since an interrupt could occur between the writing of an address and| the read or write operation.|| The xp_atom_dcr_read_interrupt() routine reads and immediately clears the| interrupt vector. This reduces the likelihood of missing any interrupts| delivered by the hardware.|| These low level functions are used by the driver to access the| transport demux registers.|+----------------------------------------------------------------------------*//* The necessary header files */#include <linux/config.h>#include <linux/version.h>#ifdef MODVERSIONS#include <linux/modversions.h>#endif#define __NO_VERSION__#include <linux/module.h>#include <linux/kernel.h>#include <linux/config.h>#include <os/os-types.h>#include <hw/hardware.h>#include "av_dcr.h"#include "xp_atom_dcr.h"#include "xp_atom_reg.h"/*----------------------------------------------------------------------------+| XXXX XX XX XXXXXX XXXXXXX XXXXXX XX XX XX XXXX| XX XXX XX X XX X XX X XX XX XXX XX XXXX XX| XX XXXX XX XX XX X XX XX XXXX XX XX XX XX| XX XX XXXX XX XXXX XXXXX XX XXXX XX XX XX| XX XX XXX XX XX X XX XX XX XXX XXXXXX XX| XX XX XX XX XX X XX XX XX XX XX XX XX XX| XXXX XX XX XXXX XXXXXXX XXX XX XX XX XX XX XXXXXXX+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| XXXXXXX XXX XXX XXXXXX XXXXXXX XXXXXX XX XX XX XXXX| XX X XX XX X XX X XX X XX XX XXX XX XXXX XX| XX X XXX XX XX X XX XX XXXX XX XX XX XX| XXXX X XX XXXX XXXXX XX XXXX XX XX XX| XX X XXX XX XX X XX XX XX XXX XXXXXX XX| XX X XX XX XX XX X XX XX XX XX XX XX XX XX| XXXXXXX XXX XXX XXXX XXXXXXX XXX XX XX XX XX XX XXXXXXX+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| xp0_dcr_init_queue+----------------------------------------------------------------------------*/void xp_atom_dcr_init_queue(UINT uDeviceIndex,SHORT wChannelId,ULONG ulQueueTop,ULONG ulQueueBottom){ ULONG ulAddr; ULONG ulCa; ULONG ulCb; XP_QCONFIGA_REG *pCa; XP_QCONFIGB_REG *pCb; pCa = (XP_QCONFIGA_REG *)(void *) &ulCa; pCb = (XP_QCONFIGB_REG *)(void *) &ulCb; /*------------------------------------------------------------------------+ | Read the current queue values +------------------------------------------------------------------------*/ ulAddr = XP_DCR_ADDR_BASE_QCONFIGAB + (wChannelId * 2); ulCa = xp_atom_dcr_read(uDeviceIndex,ulAddr); ulCb = xp_atom_dcr_read(uDeviceIndex,ulAddr+1); /*------------------------------------------------------------------------+ | if the unload type is for streaming data, then use | the BTI interrupt and set the Boundary Threshold (queueInt) | to interrupt every 512 bytes. +------------------------------------------------------------------------*/ pCa->enda = ulQueueTop; pCa->starta = ulQueueBottom; pCb->rptr = ulQueueTop << 4; pCb->apus = 1; pCb->enbl = 0; /*------------------------------------------------------------------------+ | If the unload type is for streaming data, then use | the BTI interrupt and set the Boundary Threshold (queueInt) | to interrupt every 512 bytes. +------------------------------------------------------------------------*/ if(pCb->dtype < 8) { pCa->bthres = 2; pCb->scpc = 0; } else { pCa->bthres = 0; pCb->scpc = 1; } xp_atom_dcr_write(uDeviceIndex,ulAddr, ulCa); xp_atom_dcr_write(uDeviceIndex,ulAddr+1, ulCb);}/*----------------------------------------------------------------------------+| xp_atom_dcr_read_interrupt+-----------------------------------------------------------------------------+|| DESCRIPTION: read & clear the transport demux interrupt|| PROTOTYPE : unsigned long xp_atom_dcr_read_interrupt(void)|| ARGUMENTS :|| RETURNS : value of the transport demux interrupt vector|| ERRORS :|| COMMENTS : This function reads the current interrupt vector, and| immediately clears the interrupt. This reduces the| likelihood of missing an interrupt while the handler is| executing. A critical section is used to read and clear| the interrupt vector. The interrupt read is returned| to the caller. The caller is responsible for handling| all interrupts returned.|+----------------------------------------------------------------------------*///When using this atom function, you must use is as critical section in the upper layerULONG xp_atom_dcr_read_interrupt(UINT uDeviceIndex) /* read & clear interrupt */{ ULONG ulData = 0; switch (uDeviceIndex) { case 0: ulData = MF_DCR(XPT0_IR); MT_DCR(XPT0_IR,ulData); break;#ifdef __DRV_FOR_PALLAS__ case 1: ulData = MF_DCR(XPT1_IR); MT_DCR(XPT1_IR,ulData); break; case 2: ulData = MF_DCR(XPT2_IR); MT_DCR(XPT2_IR,ulData); break;#endif default: break; } return(ulData);}/*----------------------------------------------------------------------------+| xp_atom_dcr_read_queue_config+----------------------------------------------------------------------------*/void xp_atom_dcr_read_queue_config(UINT uDeviceIndex,SHORT wChannelId,ULONG *ppQueueTop,ULONG *ppQueueBottom){ ULONG ulAddr; ULONG ulCa; XP_QCONFIGA_REG *pCa; ulAddr = XP_DCR_ADDR_BASE_QCONFIGAB + (wChannelId * 2); pCa = (XP_QCONFIGA_REG *)(void *) &ulCa; ulCa = xp_atom_dcr_read(uDeviceIndex,ulAddr); *ppQueueTop = pCa->enda; *ppQueueBottom = pCa->starta;}/*----------------------------------------------------------------------------+| xp0_dcr_reset_queue+----------------------------------------------------------------------------*/void xp_atom_dcr_reset_queue(UINT uDeviceIndex,SHORT wChannelId){ ULONG ulAddr = XP_DCR_ADDR_BASE_QCONFIGAB + (wChannelId * 2); xp_atom_dcr_write(uDeviceIndex,ulAddr, 0); xp_atom_dcr_write(uDeviceIndex,ulAddr+1, 0);}/*----------------------------------------------------------------------------+| xp_atom_dcr_write_dram_filter+----------------------------------------------------------------------------*/void xp_atom_dcr_write_dram_filter(UINT uDeviceIndex,SHORT wFilterId, ULONG ulData,ULONG ulMask,ULONG ulControl, ULONG ulPolarity){ ULONG ulAddr; ulAddr = XP_DCR_ADDR_BASE_FILTER + (wFilterId * 4); xp_atom_dcr_write(uDeviceIndex,ulAddr, ulControl); ulAddr++; xp_atom_dcr_write(uDeviceIndex,ulAddr, ulData); ulAddr++; xp_atom_dcr_write(uDeviceIndex,ulAddr, ulMask);#ifndef __DRV_FOR_VESTA__ // for vulcan and pallas ... ulAddr++; xp_atom_dcr_write(uDeviceIndex,ulAddr, ulPolarity);#else { ULONG value; ulAddr = XP_DCR_ADDR_BASE_FILTER + (wFilterId * 4); value = xp_atom_dcr_read(uDeviceIndex,ulAddr); if((ulPolarity & 0xff) != 0xff) value |= 0x00010000; if((ulPolarity & 0xff00) != 0xff00) value |= 0x00020000; if((ulPolarity & 0xff0000) != 0xff0000) value |= 0x00040000; if((ulPolarity & 0xff000000) != 0xff000000) value |= 0x00080000; xp_atom_dcr_write(uDeviceIndex,ulAddr,value); }#endif}/*----------------------------------------------------------------------------+| xp_atom_dcr_write_filter_link+----------------------------------------------------------------------------*/SHORT xp_atom_dcr_write_filter_link(UINT uDeviceIndex,SHORT wFilterId, ULONG ulNextFilterId,ULONG ulEndOfColumn){ ULONG ulAddr; ULONG ulValue; XP_FILTER_CONTROL_REGP pFilter; ulAddr = XP_DCR_ADDR_BASE_FILTER + (wFilterId * 4); ulValue = xp_atom_dcr_read(uDeviceIndex,ulAddr); pFilter = (XP_FILTER_CONTROL_REGP)(void *) &ulValue; pFilter->nfilt = ulNextFilterId; pFilter->ncol = ulEndOfColumn; xp_atom_dcr_write(uDeviceIndex,ulAddr, ulValue); return(0);}/*----------------------------------------------------------------------------+| xp_atom_dcr_write_register+----------------------------------------------------------------------------*/SHORT xp_atom_dcr_write_register(UINT uDeviceIndex,XP_DCR_REGISTER_TYPE regtype,ULONG ulData){ ULONG ulValue; XP_BUCKET1Q_REGP pBucket; XP_CONFIG1_REGP pConfig1; /*------------------------------------------------------------------------+ | Read the value from hardware +------------------------------------------------------------------------*/ switch(regtype) { case XP_BUCKET1Q_REG_BVALID: ulValue = xp_atom_dcr_read(uDeviceIndex,XP_DCR_ADDR_BUCKET1Q); pBucket = (XP_BUCKET1Q_REGP)(void *) &ulValue; pBucket->bvalid = ulData; xp_atom_dcr_write(uDeviceIndex,XP_DCR_ADDR_BUCKET1Q, ulValue); break; case XP_BUCKET1Q_REG_INDX: ulValue = xp_atom_dcr_read(uDeviceIndex,XP_DCR_ADDR_BUCKET1Q); pBucket = (XP_BUCKET1Q_REGP)(void *) &ulValue; pBucket->indx = ulData; xp_atom_dcr_write(uDeviceIndex,XP_DCR_ADDR_BUCKET1Q, ulValue); break; if(uDeviceIndex == 0) { case XP_CONFIG1_REG_APWMA: ulValue = xp_atom_dcr_read(uDeviceIndex,XP_DCR_ADDR_CONFIG1); pConfig1 = (XP_CONFIG1_REGP)(void *) &ulValue; pConfig1->apwma = ulData; xp_atom_dcr_write(uDeviceIndex,XP_DCR_ADDR_CONFIG1, ulValue); break; } default: return(-1); } return(0);}/*----------------------------------------------------------------------------+| XX XXXXXX XXXXXX XXXXX| XXXX XX XX XX XX XX| XX XX XX XX XX XX| XX XX XXXXX XX XX| XXXXXX XX XX XX| XX XX XX XX XX XX| XX XX XX XXXXXX XXXXX+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| xp_atom_dcr_read+-----------------------------------------------------------------------------+|| DESCRIPTION: Read a transport demux DCR register|| PROTOTYPE : unsigned long xp_atom_dcr_read(| unsigned long address)|| ARGUMENTS : address - demux DCR address to read|| RETURNS : contents of the DCR location|| ERRORS :|| COMMENTS : The transport demux uses indirect DCR addressing. An DCR| register (0x180) is first written with the demux index,| and then a read operation is performed and loaded into| the 'data' register A critical section must surround this| indirect addressing to eliminate any interrupts which| could affect the operation.|+----------------------------------------------------------------------------*/ULONG xp_atom_dcr_read(UINT uDeviceIndex,ULONG ulAddress){ ULONG ulData = 0; switch (uDeviceIndex) { case 0: MT_DCR(XPT0_LR,ulAddress); ulData = MF_DCR(XPT0_DT); break;#ifdef __DRV_FOR_PALLAS__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -