📄 device.c
字号:
/* * device.c - mcc driver: bottom half side * * (C) Copyright 2002 * Gianfranco Morandi, Eurostudio s.r.l., gianfranco.morandi@euro-studio.it * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * * */#ifndef __KERNEL__# define __KERNEL__#endif#ifndef MODULE# define MODULE#endif#include <linux/kernel.h>#include <linux/fs.h>#include <linux/delay.h>#include <linux/param.h>#include <linux/module.h>#include <linux/sched.h>#include <asm/semaphore.h>#include <asm/io.h>#include <asm/system.h>#include <linux/time.h>#include <linux/malloc.h>#include "mcc.h" /* Local header file */ #include "mpc8260.h" /* IMM definitions and declarations */#include "mccIOC.h"/*--------------------------------------------------------------------------------- * Global variables *--------------------------------------------------------------------------------- */volatile t_PQ2IMM *IMM; /* Internal Memory Map base pointer */VUBYTE SI; /* Which SI is in use for this example */VUBYTE MCC; /* Which MCC is in use for this example *//* read & write handshaking (non volevo farlo cosi' !)*/extern int writeNow[BUFFER_SIZE];extern int valid[BUFFER_SIZE];extern int readNow[BUFFER_SIZE];/* buffer descriptors base pointer*/extern BDRINGS *RxTxBD;/* TxRx data buffer */extern unsigned char *BufferPool;/* TxRx interrupt queue*/extern unsigned int *txIntCQ;extern unsigned int *rxIntCQ;/* spin lock variable*/extern spinlock_t lock;/* data stream read and write buffer*/extern FrameBuffer *ReadBuffer;extern FrameBuffer *WriteBuffer;/*--------------------------------------------------------------------------------- * Function prototypes *--------------------------------------------------------------------------------- */void InitBDs(unsigned int,UBYTE);void MCCGlobalInit(void);void MCCChanSpecInit(UHWORD,UBYTE);void MCCExChanSpecInit(unsigned int,UHWORD,UHWORD);void InitTxRxParams(UHWORD);void SIinit(void);void startTxRx(void);void stopTxRx(void);void mainInitMCC(unsigned int );void mcc_ISR(int , void *, struct pt_regs *);void BDsStatus(unsigned char, unsigned char, unsigned short *, unsigned short *, unsigned int *);void SiRamStatus(unsigned char,unsigned char*,unsigned char*,unsigned char*,unsigned short*, unsigned short*,unsigned short*,unsigned char*,unsigned short*,unsigned short*,unsigned short*);void CpmReadRegisters(CPM_STATUS_IOC *);void getFrame(unsigned int, unsigned short);void sendFrame(unsigned int, unsigned short);void restoreBDs(unsigned short);void RestartServiceRoutine(void);void stopCpmMcc(unsigned char mcn);extern void mccFasync(void);/*--------------------------------------------------------------------------------- * Functions *--------------------------------------------------------------------------------- */ /* * Name: * mainInitMCC * Description: * main MCC and SI init */void mainInitMCC(unsigned int BASE_ADDR){ unsigned int chnOffset,chnNum; /* work with MCC1,SI1 and TDMC */ SI = SI1; MCC = MCC1; //TDM = TDMC; /* pointer to MPC8260 internal memory map. */ IMM = (t_PQ2IMM *)(BASE_ADDR); /*Initialize SI RAM : TDM1C and TDM1D routing */ SIinit(); /*Initialize TxRxBDs */ chnOffset = 0; for(chnNum = CHNSTART;chnNum < (CHNSTART+NUMBER_OF_CHANNELS);chnNum++){ InitBDs(chnOffset,TRAN_NOTSUPERCHAN); chnOffset+=NUM_RXBDS; } /*Initialize Global parameters */ MCCGlobalInit(); /*Initialize Extra Channel Specific parameters */ chnOffset = 0; for(chnNum = CHNSTART;chnNum < (CHNSTART+NUMBER_OF_CHANNELS);chnNum++){ MCCExChanSpecInit(chnNum,chnOffset+TxBDSOFFSET,chnOffset); chnOffset+=NUM_RXBDS; } /* Initialize Channel Specific parameters */ for(chnNum = CHNSTART;chnNum < (CHNSTART+NUMBER_OF_CHANNELS);chnNum++){ MCCChanSpecInit(chnNum,TRAN_NOTSUPERCHAN); }} /* mainInitMCC *//* * Name: * startTxRx * Description: * start TDM */void startTxRx(){ /* Issue Init RX & TX Parameters Command for MCC1 */ InitTxRxParams(64); InitTxRxParams(96); /* Enable TDM1C and TDM1D */ IMM->si_regs[SI].sigmr = 0x0c; }/* * Name: * stopTxRx * Description: * stop TDM */void stopTxRx(){ unsigned char mcn; /* Disable TDM1C and TDM1D */ IMM->si_regs[SI].sigmr = 0x00; /* stop CPM */ for(mcn = CHNSTART; mcn<(CHNSTART+NUMBER_OF_CHANNELS);mcn++) stopCpmMcc(mcn);} /* end of stopTxRx *//* * Name: * stopCpmMcc * Description: * stop MCC */void stopCpmMcc(unsigned char mcn){ volatile unsigned int psbc; if (MCC == MCC1) psbc = CPCR_MCC1_PSBC; else psbc = CPCR_MCC2_PSBC; while ((IMM->cpm_cpcr & CPCR_FLG) != READY_TO_RX_CMD); IMM->cpm_cpcr = CPCR_MCC_STOP_TX | psbc | (mcn<<6)| CPCR_FLG; /* ISSUE COMMAND */ while ((IMM->cpm_cpcr & CPCR_FLG) != READY_TO_RX_CMD); while ((IMM->cpm_cpcr & CPCR_FLG) != READY_TO_RX_CMD); IMM->cpm_cpcr = CPCR_MCC_STOP_RX | psbc | (mcn<<6)| CPCR_FLG; /* ISSUE COMMAND */ while ((IMM->cpm_cpcr & CPCR_FLG) != READY_TO_RX_CMD);}/* * Name: * SIinit * Description: * SI ram entries configuration */void SIinit(){ unsigned short chnNum; unsigned int count; chnNum = CHNSTART; /*chnannel 64 */ /* SI1 entries for TDM1C */ for(count=0;count < 32;count++){ IMM->si_ram[SI].tx_siram[count] = 0x8002 | (chnNum << 5); /* see page 14-13*/ IMM->si_ram[SI].rx_siram[count] = 0x8002 | (chnNum << 5); if(count == 31){ IMM->si_ram[SI].tx_siram[count] = 0x8003 | (chnNum << 5); /* see page 14-13*/ IMM->si_ram[SI].rx_siram[count] = 0x8003 | (chnNum << 5); } chnNum++; } /* SI1 entries for TDM1D */ for(count=0;count < 32;count++){ IMM->si_ram[SI].tx_siram[count+64] = 0x8002 | (chnNum << 5); /* see page 14-13*/ IMM->si_ram[SI].rx_siram[count+64] = 0x8002 | (chnNum << 5); if(count == 31){ IMM->si_ram[SI].tx_siram[count+64] = 0x8003 | (chnNum << 5); /* see page 14-13*/ IMM->si_ram[SI].rx_siram[count+64] = 0x8003 | (chnNum << 5); } chnNum++; } IMM->si_regs[SI].sixmr[TDMC] = 0x0040; /* 0 offset for SIRAM 1cond bank 1st 32 entries, CRT */ IMM->si_regs[SI].sixmr[TDMD] = 0x2040; /* 64 offset for SIRAM 2cond bank 1st 32 entries, CRT */} /* SIinit *//* * Name: * InitBDs * Description: * Init Tx and Rx BDs */void InitBDs(unsigned int offset, UBYTE mode){ unsigned int index;unsigned int addr; /* Initialize RxBDs */ for (index = 0; index < NUM_RXBDS; index++){ if( index != (NUM_RXBDS-1) ){/* If not the last RxBD for this channel */ RxTxBD->RxBD[index+offset].bd_cstatus = 0x9000; /* Empty, Interrupt */ /* old 0x9000 */ } else {/* if last RxBD for this channel */ RxTxBD->RxBD[index+offset].bd_cstatus = 0xB000; /* Empty, Interrupt,Wrap */ } RxTxBD->RxBD[index+offset].bd_length = 0;/* clear the buffer length */ /*address of receive area */ addr = (unsigned int )BufferPool + BUFFER_SIZE*NUMBER_OF_CHANNELS*NUM_TXBDS + (offset+index)*BUFFER_SIZE; RxTxBD->RxBD[index+offset].bd_addr =(unsigned int )( addr - (unsigned int )PAGE_OFFSET ); }/* end for loop initializing RxBDs */ /* Initialize TxBDs */ for (index=0; index < NUM_TXBDS; index++){ if( index != (NUM_TXBDS-1) ) { /* If not the last TxBD for this channel */ RxTxBD->TxBD[index+offset].bd_cstatus = 0x8000; /* Set Ready bit */ /*----------------------------------------------------*/ /* If this channel is HDLC, also set Last and TC bits */ /*----------------------------------------------------*/ /*if ( (mode == HDLC_NOTSUPERCHAN) || (mode == HDLC_SUPERCHAN) ) RxTxBD->TxBD[index+offset].bd_cstatus |= 0x0C00; */ } else { /* if last TxBD for this channel */ RxTxBD->TxBD[index+offset].bd_cstatus = 0xA000;/* Set Ready, Wrap bits */ /*----------------------------------------------------*/ /* If this channel is HDLC, also set Last and TC bits */ /*----------------------------------------------------*/ /*if ( (mode == HDLC_NOTSUPERCHAN) || (mode == HDLC_SUPERCHAN) ) RxTxBD->TxBD[index+offset].bd_cstatus |= 0x0C00;*/ } /* load the buffer length */ //if ( (mode == HDLC_NOTSUPERCHAN) || (mode == HDLC_SUPERCHAN) ) /* if this channel is HDLC */ //{ // RxTxBD->TxBD[index+offset].bd_length = (BUFFER_SIZE-4); //} // else /* Transparent */ RxTxBD->TxBD[index+offset].bd_length = (BUFFER_SIZE);/* set buffer length */ addr = ( (unsigned int ) BufferPool+(offset+index)*BUFFER_SIZE); RxTxBD->TxBD[index+offset].bd_addr = (unsigned int )( addr - (unsigned int )PAGE_OFFSET);/* set address to point tx area */ }} /* end InitBDs *//* * Name: * MCCGlobalInit * Description: * configure MCC global parameter */void MCCGlobalInit(){ unsigned int addr;/* set up abbreviated pointer */t_Mcc_Pram* MCCglobal; MCCglobal = (t_Mcc_Pram * ) &(IMM->pram.serials.mcc_pram[MCC]); addr = (unsigned int ) RxTxBD; MCCglobal->mccbase = addr - PAGE_OFFSET;/* base of BDs used by this MCC */ MCCglobal->mccstate = ALL_ZEROS; MCCglobal->mrblr = MCC_MRBLR; /* max Rx buffer length */ MCCglobal->grfthr = NUMBER_OF_CHANNELS*NUM_RXBDS; MCCglobal->grfcnt = MCCglobal->grfthr; /* grfthr decrementer */ MCCglobal->rinttmp = ALL_ZEROS; MCCglobal->data0 = ALL_ZEROS; MCCglobal->data1 = ALL_ZEROS; addr = (unsigned int) txIntCQ; MCCglobal->tintbase = addr - PAGE_OFFSET; /* base of Tx int. circular queue */ MCCglobal->tintptr = MCCglobal->tintbase; /* temp ptr for tx interrupts*/ MCCglobal->tinttmp = ALL_ZEROS; /* must be cleared by user */ MCCglobal->sctpbase = (unsigned int )NULL; /*base of superchannel table*/ MCCglobal->c_mask32 = CRC32; /* 32 bit crc constant */ MCCglobal->xtrabase = MCCXTRABASE; /*base of chan-specific xtra params */ MCCglobal->c_mask16 = CRC16; /* 16 bit crc constant */ /* Note that we are using only 1 one of the four possible Rx int. queues */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -