/************************************************** * $Id: epic1.c,v 1.18 2000/06/13 21:21:50 tpeters Exp $ * * copyright @ motorola, 1999 * *************************************************/ /* For debug put -DEPICDBG in the DEBUG line in the makefile for no debug comment -DEPICDBG out of the make file */ #include "../../dink.h" #include "epic.h" #include "../../errors.h" #include "../../spr_loc.h" #include "epic_dma.h" extern void decrementer_write(unsigned int); //in except2.s extern void I2O_ISR_host(); extern void I2O_ISR_agent(); extern int pmcIntLine; extern int dink_printf(char *, ... ); #define printf dink_printf #define LONGSWAP(x) ((((x) & 0x000000ff) << 24) | (((x) & 0x0000ff00) << 8)|\ (((x) & 0x00ff0000) >> 8) | (((x) & 0xff000000) >> 24) ) struct SrcVecTable SrcVecTable[MAXVEC] = /* Addr/Vector/ISR Addr cross-reference tbl */ { { EPIC_EX_INT0_VEC_REG, "External Direct/Serial Source 0", 0x0}, { EPIC_EX_INT1_VEC_REG, "External Direct/Serial Source 1", 0x0}, { EPIC_EX_INT2_VEC_REG, "External Direct/Serial Source 2", 0x0}, { EPIC_EX_INT3_VEC_REG, "External Direct/Serial Source 3", 0x0}, { EPIC_EX_INT4_VEC_REG, "External Direct/Serial Source 4", 0x0}, { EPIC_SR_INT5_VEC_REG, "External Serial Source 5", 0x0}, { EPIC_SR_INT6_VEC_REG, "External Serial Source 6", 0x0}, { EPIC_SR_INT7_VEC_REG, "External Serial Source 7", 0x0}, { EPIC_SR_INT8_VEC_REG, "External Serial Source 8", 0x0}, { EPIC_SR_INT9_VEC_REG, "External Serial Source 9", 0x0}, { EPIC_SR_INT10_VEC_REG, "External Serial Source 10", 0x0}, { EPIC_SR_INT11_VEC_REG, "External Serial Source 11", 0x0}, { EPIC_SR_INT12_VEC_REG, "External Serial Source 12", 0x0}, { EPIC_SR_INT13_VEC_REG, "External Serial Source 13", 0x0}, { EPIC_SR_INT14_VEC_REG, "External Serial Source 14", 0x0}, { EPIC_SR_INT15_VEC_REG, "External Serial Source 15", 0x0}, { EPIC_TM0_VEC_REG, "Global Timer Source 0", 0x0}, { EPIC_TM1_VEC_REG, "Global Timer Source 1", 0x0}, { EPIC_TM2_VEC_REG, "Global Timer Source 2", 0x0}, { EPIC_TM3_VEC_REG, "Global Timer Source 3", 0x0}, { EPIC_I2C_INT_VEC_REG, "Internal I2C Source", 0x0}, { EPIC_DMA0_INT_VEC_REG, "Internal DMA0 Source", 0x0}, { EPIC_DMA1_INT_VEC_REG, "Internal DMA1 Source", 0x0}, { EPIC_MSG_INT_VEC_REG, "Internal Message Source", 0x0}, }; /* Ray's DMA0 Interrupt Service Routine */ void DMA0ISR() { DMA_SR stat; unsigned int xTime; DMA_Get_Stat_Epic( LOCAL, get_eumbbar(), 0, &stat ) ; /* Check the DMA status register to see if the DMA transaction was OK, if not * status register PE bit 4 was set. If so, print an appropriate message and * clear the bit. Write a 1 to stat.pe to clear it. * Leave everything else in the register unchanged. * Subsequent DMA transactions do not work until the stat.pe bit is cleared. * We might want to do the same thing for the Local Memory Error bit as well. */ if (stat.pe == 1) { union { DMA_SR stat; unsigned int temp; } s; PRINT("PCI Error on DMA transfer.\n"); s.stat = stat; s.temp &= 0xffffff6c; /* leave rest of status register unchanged */ s.stat.pe = 1; /* clear the pe bit by writing 1 to it */ store_runtime_reg( get_eumbbar(),0x1104, s.temp ); } if ( stat.eocai == 1 ) { PRINT("Direct Mode Interupt ......"); PRINT("Clearing Interupt\n"); store_runtime_reg( get_eumbbar(),0x1104, 1 ); } xTime = decrementer_value; /* Pick up the global value which was saved quickly */ xTime = xTime | 0x80000000; /* Prepend leading bit for next operation */ xTime = ~xTime; /* Determine actual clock counts */ xTime = (4 * xTime) / (memSpeed); PRINT("Transferred %d bytes in %d microseconds >>> %d MB/s transfer rate\n",dma_length, xTime, dma_length/xTime); /* PRINT("Execution Time= %d\n", xTime); PRINT("memSpeed = %d \n",memSpeed); PRINT("Transfer Rate = %d MB/s\n", 10000/xTime); */ } /* Dummy Interrupt Service Routines for DINK's default EPIC state The default state on the Sandpoint Platform is: - IRQ1 and IRQ2 are enabled and can be triggered using the S5 and S6 slide switches on the mother board (direct mode) - IRQ0, IRQ5, IRQ10, IRQ15 are enabled and can be triggered by manipulating pin A6 of PCI Slot0. Note: this is for in-house testing of serial interrupts on Sandpoint only. - Interrupt Service routines set up for timers 0-3, timers are not configured or enabled.*/ void IRQ0ISR() { printf("EPIC: Interrupt Service Routine for interrupt 0\n"); } void IRQ1ISR() { printf("EPIC: Interrupt Service Routine for interrupt 1\n"); } void IRQ2ISR() { printf("EPIC: Interrupt Service Routine for interrupt 2\n"); } void IRQ5ISR() { printf("EPIC: Interrupt Service Routine for interrupt 5\n"); } void IRQ10ISR() { printf("EPIC: Interrupt Service Routine for interrupt 10\n"); } void IRQ15ISR() { printf("EPIC: Interrupt Service Routine for interrupt 15\n"); } void Timer0ISR() { printf("EPIC: Interrupt Service Routine for Timer 0\n"); } void Timer1ISR() { printf("EPIC: Interrupt Service Routine for Timer 1\n"); } void Timer2ISR() { printf("EPIC: Interrupt Service Routine for Timer 2\n"); } void Timer3ISR() { printf("EPIC: Interrupt Service Routine for Timer 3\n"); } /**************************************************************************** * * epicInit - Initializes the EPIC unit by: * * 1) Setting the reset bit in the Global Configuration Register which will: * - Disables all interrupts * - Clears all pending and in-service interrupts * - Sets epic timers to base count * - Sets the value of the Processor Current Task Priority to the * highest priority (0xF) * - Reset spurious vector to 0xFF * - Default to pass-through mode * 2) Sets the EPIC operation mode to Mixed Mode (vs. Pass * Through or 8259 compatible mode). * 3) If IRQType (input) is Direct IRQs: * - IRQType is written to the SIE bit of the EPIC Interrupt * Configuration register (ICR). * - clkRatio is ignored. * If IRQType is Serial IRQs: (Note: not supported yet) * - both IRQType and clkRatio will be written to the ICR register * 4) - Enable IRQ1 and IRQ2 * - Set up ISRs for IRQ1, IRQ2, Timers 0-3 * - If an agent is detected, set up Message Unit Interrupt * - Set up DMA0 Interrupt and Ray's DMA ISR **************************************************************************/ void epicInit ( unsigned int IRQType, /* Direct or Serial */ unsigned int clkRatio /* Clk Ratio for Serial IRQs */ ) { ULONG tmp; /* to hold tmp register values */ unsigned int counter; /* to hold tmp register values */ unsigned int noIRQs; /* to hold # IRQs */ unsigned int noCPUs; /* to hold # CPUs */ unsigned int verID; /* to hold Version ID */ /* Disable External Interrupts */ printf("\nEPIC: Disable External Interrupts\n"); CoreExtIntDisable(); /* Set the Global Conf. register to reset EPIC */ tmp = sysEUMBBARRead(EPIC_GLOBAL_REG); tmp |= 0x80000000; sysEUMBBARWrite(EPIC_GLOBAL_REG, tmp); printf("EPIC: Reseting... "); /* added by Ted Peters 7/20/99 */ /* wait untill reset sequence completes */ while (sysEUMBBARRead(EPIC_GLOBAL_REG) & 0x80000000); /* set to mixed mode */ sysEUMBBARWrite(EPIC_GLOBAL_REG, 0x20000000); printf("Mixed Mode... "); /* Read interrupt conf. reg */ tmp = sysEUMBBARRead(EPIC_INT_CONF_REG); if (IRQType == EPIC_DIRECT_IRQ) /* direct mode */ sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp & 0xf7ffffff); else /* Serial mode */ { tmp = (clkRatio << 28) | 0x08000000; /* Set clock ratio */ sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp); } printf("%s Mode\n",IRQType?"Serial":"Direct"); if ((IRQType == EPIC_SERIAL_IRQ) && (pmcIntLine == AGENT_DETECTED)) { printf("\nNote: Serial Mode is not recommended if in Agent Mode\n"); printf(" in a PCI Slot on Sandpoint\n"); } /* get number of IRQs for false interrupt handling out of reset */ epicFeatures(&noIRQs, &noCPUs, &verID); #ifdef EPICDBG printf("noIRQs: %d noCPUs: %x verID: %x\n", noIRQs, noCPUs, verID); printf("EPIC: Lower Current Task Priority\n"); #endif /* EPICDBG */ epicCurTaskPrioSet(0); #ifdef EPICDBG printf("EPIC: Enable: "); #endif /* EPICDBG */ for (counter = 0; counter <= noIRQs; counter++) { epicIntEnable(counter); #ifdef EPICDBG printf("%d ",counter); #endif /* EPICDBG */ } #ifdef EPICDBG printf("\n"); #endif /* EPICDBG */ for (counter = 0; counter <= noIRQs; counter++) { tmp = epicIntAck(); epicEOI(); #ifdef EPICDBG printf("PASS: %d IACK: %x and EOI\n", counter, tmp); #endif /* EPICDBG */ } #ifdef EPICDBG printf("EPIC: Disable: "); #endif /* EPICDBG */ for (counter = 0; counter <= noIRQs; counter++) { epicIntDisable(counter); #ifdef EPICDBG printf("%d ",counter); #endif /* EPICDBG */ } #ifdef EPICDBG printf("\n"); #endif /* EPICDBG */ epicDefault(IRQType); /* set EPIC unit to default set up */ } /**************************************************************************** * * epicDefault - sets up EPIC unit into a default mode for the * Sandpoint Reference Platform. * * The following code enables interrupts specific for the Sandpoint System. * * Direct Mode Setup: * - Global Timers 0-3 (ISRs only), user can alter Timers to count down. * - DMA0 interrupt is setup with Ray's ISR. * If DINK is running on a Host: * - It enables interrupts and ISRs for IRQ1-2 * unless an Agent is on one of those lines. * These interrupts can be triggered using the * S5 and S6 slide switches on the Sandpoint Motherboard. * If DINK is running on a Host in a host/agent setup: * - the IRQ line and ISR for the Agent is setup. * If DINK is running on an Agent: * - the Message Unit interrupt and ISR is enabled. * * - Lastly, it enables external interrupts. * * Serial Mode Setup: * Note: this mode is for in-house testing of serial interrupts on the EPIC * unit. The EPIC serial interrupt input line is S_INT/IRQ0 which tied to * Slot 1 (2nd from PPMC) on the Sandpoint System. The serial interrupt * can be triggered by manipulating the INTA pin of Slot 1. The INTA * pin of Slot 1 is pin A6. * - Global Timers 0-3 (ISRs only), user can alter Timers to count down. * - DMA0 interrupt is setup with Ray's ISR. * - Enable interrupt and ISR for IRQ0 * * - Lastly, it enables external interrupts. * * RETURNS: None * ***************************************************************************/ void epicDefault(int IRQType) { int status; printf("\n"); printf("EPIC: Configuring EPIC to default mode...\n"); if (IRQType == EPIC_DIRECT_IRQ) /* direct mode specific setup */ { /* If DINK is running on a Host: Set up IRQ1 and IRQ2 for Sandpoint slide switches S5 and S6 unless an Agent was detected on either line. If DINK is running on an Agent: Do not setup IRQ lines. */ if (pmcIntLine != AGENT_DETECTED) /* Not an Agent */ { if (pmcIntLine != 1) /* No Agent on IRQ1 */ { /* set int 1 to active low, edge-sensitive, priority 10 */ printf("EPIC: IRQ1 Configure... "); status = epicIntSourceConfig(1,0,0,10); printf("Connect ISR... "); epicISRConnect(1,IRQ1ISR); /* enable interrupt vector 1 */ printf("Enable\n"); epicIntEnable(1); } if (pmcIntLine != 2) /* No Agent on IRQ2 */ { /* set int 2 to active low, edge-sensitive, priority 10 */ printf("EPIC: IRQ2 Configure... "); status = epicIntSourceConfig(2,0,0,10); printf("Connect ISR... "); epicISRConnect(2,IRQ2ISR); /* enable interrupt vector 2 */ printf("Enable\n"); epicIntEnable(2); } } /* If DINK is running on an Agent in a host/agent setup, we'll enable the use of the Message Unit. The Message Unit can be exercised using the "dev i2o" command in DINK. If DINK is running on the Host, we'll set up the IRQ interrupt vector for whatever IRQ line the Agent was detected on. */ if (pmcIntLine == AGENT_DETECTED) { printf("\n"); printf("EPIC: Host/Agent setup detected\n"); printf("EPIC: Message Unit Interrupt Configure... "); status = epicIntSourceConfig(pmcIntLine,0,0,10); printf("Connect ISR... "); epicISRConnect(pmcIntLine, I2O_ISR_agent); printf("Enable\n"); epicIntEnable(pmcIntLine); /* enable interrupt vector 23 */ } else if (pmcIntLine != 0xff) { printf("\n"); printf("EPIC: Agent detected on IRQ %d\n",pmcIntLine); printf("EPIC: IRQ%d Configure... ",pmcIntLine); status = epicIntSourceConfig(pmcIntLine,0,0,10); printf("Connect ISR... "); epicISRConnect(pmcIntLine, I2O_ISR_host); printf("Enable\n"); printf("\n"); epicIntEnable(pmcIntLine); } } //end of Direct Mode specific setup /* Serial Mode specific setup: if host in serial mode and no PMC in slot 0 */ if ((IRQType == EPIC_SERIAL_IRQ) && (pmcIntLine != AGENT_DETECTED)) { if(pmcIntLine != 0) { /* set int 0 to active low, level-sensitive, priority 10 */ printf("EPIC: IRQ0 Configure... "); status = epicIntSourceConfig(0,0,1,10); printf("Connect ISR... "); epicISRConnect(0,IRQ0ISR); /* enable interrupt vector 0 */ printf("Enable\n"); epicIntEnable(0); /* set int 5 to active low, level-sensitive, priority 10 */ printf("EPIC: IRQ5 Configure... "); status = epicIntSourceConfig(5,0,1,10); printf("Connect ISR... "); epicISRConnect(5,IRQ5ISR); /* enable interrupt vector 5 */ printf("Enable\n"); epicIntEnable(5); /* set int 10 to active low, level-sensitive, priority 10 */ printf("EPIC: IRQ10 Configure... "); status = epicIntSourceConfig(10,0,1,10); printf("Connect ISR... "); epicISRConnect(10,IRQ10ISR); /* enable interrupt vector 10 */ printf("Enable\n"); epicIntEnable(10); /* set int 15 to active low, level-sensitive, priority 10 */ printf("EPIC: IRQ15 Configure... "); status = epicIntSourceConfig(15,0,1,10); printf("Connect ISR... "); epicISRConnect(15,IRQ15ISR); /* enable interrupt vector 15 */ printf("Enable\n"); epicIntEnable(15); } } //end of Serial Mode specific setup /* Set up ISR for global timers 0-3. The timers will not be configured or enable so they are not continually interrupting. Set up will be left for the user to do from the command line */ printf("EPIC: Timer0 Connect ISR...\n"); epicISRConnect(16,Timer0ISR); printf("EPIC: Timer1 Connect ISR...\n"); epicISRConnect(17,Timer1ISR); printf("EPIC: Timer2 Connect ISR...\n"); epicISRConnect(18,Timer2ISR); printf("EPIC: Timer3 Connect ISR...\n"); epicISRConnect(19,Timer3ISR); /* Set up DMA0 interrupt */ printf("EPIC: DMA0 Configure... "); status = epicIntSourceConfig(21,0,0,10); printf("Connect ISR... "); epicISRConnect(21,DMA0ISR); printf("Enable\n"); epicIntEnable(21); /* Lower Current Task Priority */ printf("\n"); printf("EPIC: Lower Current Task Priority\n"); epicCurTaskPrioSet(5); /* Enable External Interrupts */ printf("EPIC: Enable External Interrupts in MSR\n\n"); CoreExtIntEnable(); } /**************************************************************************** * * epicIntEnable - Enable an interrupt source * * This routine clears the mask bit of an external, an internal or * a Timer interrupt vector priority register to enable the interrupt. * * RETURNS: None * ***************************************************************************/ void epicIntEnable ( int intVec /* Interrupt Vector Number */ ) { ULONG tmp; ULONG srAddr; srAddr = SrcVecTable[intVec].srcAddr; /* Retrieve src Vec/Prio register */ tmp = sysEUMBBARRead(srAddr); tmp &= 0x7fffffff; /* Clear the mask bit */ sysEUMBBARWrite(srAddr, tmp); return; } /**************************************************************************** * * epicIntDisable - Disable an interrupt source * * This routine sets the mask bit of an external, an internal or * a Timer interrupt vector priority register to disable the interrupt. * * RETURNS: None * ****************************************************************************/ void epicIntDisable ( int intVec /* Interrupt vector number */ ) { ULONG tmp, srAddr; srAddr = SrcVecTable[intVec].srcAddr; tmp = sysEUMBBARRead(srAddr); tmp |= 0x80000000; /* Set the mask bit */ sysEUMBBARWrite(srAddr, tmp); return; } /**************************************************************************** * epicIntSourceConfig - Set properties of an interrupt source * * This function sets interrupt properites (Polarity, Sense, Interrupt * Prority, and Interrupt Vector) of an Interrupt Source. The properties * can be set when the current source is not in-request or in-service, * which is determined by the Activity bit. This routine return ERROR * if the the Activity bit is 1 (in-request or in-service). * * This function assumes that the Source Vector/Priority register (input) * is a valid address. * * RETURNS: OK or ERROR **************************************************************************/ int epicIntSourceConfig ( int Vect, /* interrupt source vector number */ int Polarity, /* interrupt source polarity */ int Sense, /* interrupt source Sense */ int Prio /* interrupt source priority */ ) { ULONG tmp, newVal; ULONG actBit, srAddr; srAddr = SrcVecTable[Vect].srcAddr; tmp = sysEUMBBARRead(srAddr); actBit = (tmp & 40000000) >> 30; /* retrieve activity bit - bit 30 */ if (actBit == 1) return ERROR; tmp &= 0xff30ff00; /* Erase previously set P,S,Prio,Vector bits */ newVal = (Polarity << 23) | (Sense << 22) | (Prio << 16) | Vect; sysEUMBBARWrite(srAddr, tmp | newVal ); return (OK); } /**************************************************************************** * epicIntAck - acknowledge an interrupt * * This function reads the Interrupt acknowldge register and return * the vector number of the highest pending interrupt. * * RETURNS: Interrupt Vector number. */ unsigned int epicIntAck() { return(sysEUMBBARRead( EPIC_PROC_INT_ACK_REG )); } /**************************************************************************** * epicEOI - signal an end of interrupt * * This function writes 0x0 to the EOI register to signal end of interrupt. * It is usually called after an interrupt routine is served. * * RETURNS: None */ void extern epicEOI() { sysEUMBBARWrite(EPIC_PROC_EOI_REG, 0x0); } /**************************************************************************** * epicCurTaskPrioSet - sets the priority of the Processor Current Task * * This function should be called after epicInit() to lower the priority * of the processor current task. * * RETURNS: OK or ERROR */ int epicCurTaskPrioSet ( int prioNum /* New priority value */ ) { if ( (prioNum < 0) || (prioNum > 0xF)) return ERROR; sysEUMBBARWrite(EPIC_PROC_CTASK_PRI_REG, prioNum); return OK; } /************************************************************************ * function: epicIntTaskGet * * description: Get value of processor current interrupt task priority register * * note: ***********************************************************************/ unsigned char epicIntTaskGet() { /* get the interrupt task priority register */ ULONG reg; unsigned char rec; reg = sysEUMBBARRead( EPIC_PROC_CTASK_PRI_REG ); rec = ( reg & 0x0F ); return rec; } /************************************************************** * function: epicISR * * description: EPIC service routine called by the core exception * at 0x500 * * note: added body to routine. tpeters 7/30/99 **************************************************************/ void epicISR() { VOIDFUNCPTR intISRAddr; unsigned int vector; /* read the IACK register to get interrupt vector number and look up ISR address in SrcVecTable using vector number. we should check for a spurios vector, if it is we should print something and return (no EOI). */ vector = epicIntAck(); /* Check if we got a spurious vector */ /* Modify this later to look up actual spurious vector value set by user in the SVR */ if (vector == 0xff) { #ifdef EPICDBG printf("EPIC: In epicISR() for a Spurious Vector\n"); #endif /* EPICDBG */ return; } intISRAddr = SrcVecTable[vector].isrAddr; #ifdef EPICDBG printf("EPIC: In epicISR() for vector#: %d\n", vector); #endif /* EPICDBG */ /* tpeters 03/29/00 set up dink transfer table so that DINK's dynamic functions are available to the ISR. This is necessary if the user manually downloaded an ISR and connected to epic using "dev epic ISRCnt" and wishes to do things like printf */ epicSetupTransferTable(); /* Now branch to service routine */ intISRAddr(); #ifdef EPICDBG printf("EPIC: Back from ISR\n"); #endif /* EPICDBG */ /* returned from ISR now write to EOI register to end cycle */ epicEOI(); } /************************************************************** * function: epicISRConnect * * description: EPIC routine called to register an ISR with EPIC * for a particular interrupt vector. * * note: added routine. tpeters 7/30/99 **************************************************************/ void epicISRConnect(int vector, VOIDFUNCPTR srcISRAddr) { /* add ISR address to lookup table for given Vector */ SrcVecTable[vector].isrAddr = srcISRAddr; #ifdef EPICDBG printf("EPIC: In epicISRConnect(): Vector: %d -> ISRAddr: %x\n",\ vector, srcISRAddr); #endif /* EPICDBG */ } /************************************************************ * function: epicModeGet * * description: query EPIC mode, return 0 if pass through mode * return 1 if mixed mode * * note: *************************************************************/ unsigned int epicModeGet() { ULONG val; val = sysEUMBBARRead( EPIC_GLOBAL_REG ); return (( val & 0x20000000 ) >> 29); } /********************************************* * function: epicConfigGet * * description: Get the EPIC interrupt Configuration * return 0 if not error, otherwise return 1 * * note: ********************************************/ void epicConfigGet( unsigned int *clkRatio, unsigned int *serEnable) { ULONG val; val = sysEUMBBARRead( EPIC_INT_CONF_REG ); *clkRatio = ( val & 0x70000000 ) >> 28; *serEnable = ( val & 0x8000000 ) >> 27; } /******************************************************************* * sysEUMBBARRead - Read a 32-bit EUMBBAR register * * This routine reads the content of a register in the Embedded * Utilities Memory Block, and swaps to big endian before returning * the value. * * RETURNS: The content of the specified EUMBBAR register. */ ULONG sysEUMBBARRead ( ULONG regNum ) { ULONG temp; temp = *(ULONG *) (EUMBBAR + regNum); return ( LONGSWAP(temp)); } /******************************************************************* * sysEUMBBARWrite - Write a 32-bit EUMBBAR register * * This routine swaps the value to little endian then writes it to * a register in the Embedded Utilities Memory Block address space. * * RETURNS: N/A */ void sysEUMBBARWrite ( ULONG regNum, /* EUMBBAR register address */ ULONG regVal /* Value to be written */ ) { *(ULONG *) (EUMBBAR + regNum) = LONGSWAP(regVal); return ; } /******************************************************** * function: epicVendorId * * description: return the EPIC Vendor Identification * register: * * siliccon version, device id, and vendor id * * note: ********************************************************/ void epicVendorId ( unsigned int *step, unsigned int *devId, unsigned int *venId ) { ULONG val; val = sysEUMBBARRead( EPIC_VENDOR_ID_REG ); *step = ( val & 0x00FF0000 ) >> 16; *devId = ( val & 0x0000FF00 ) >> 8; *venId = ( val & 0x000000FF ); } /************************************************** * function: epicFeatures * * description: return the number of IRQ supported, * number of CPU, and the version of the * OpenEPIC * * note: *************************************************/ void epicFeatures ( unsigned int *noIRQs, unsigned int *noCPUs, unsigned int *verId ) { ULONG val; val = sysEUMBBARRead( EPIC_FEATURES_REG ); *noIRQs = ( val & 0x07FF0000 ) >> 16; *noCPUs = ( val & 0x00001F00 ) >> 8; *verId = ( val & 0x000000FF ); } /********************************************************* * function: epciTmFrequncySet * * description: Set the timer frequency reporting register ********************************************************/ void epicTmFrequencySet( unsigned int frq ) { sysEUMBBARWrite(EPIC_TM_FREQ_REG, frq); } /******************************************************* * function: epicTmFrequncyGet * * description: Get the current value of the Timer Frequency * Reporting register * ******************************************************/ unsigned int epicTmFrequencyGet() { return( sysEUMBBARRead(EPIC_TM_FREQ_REG)) ; } /**************************************************** * function: epicTmBaseSet * * description: Set the #n global timer base count register * return 0 if no error, otherwise return 1. * * note: ****************************************************/ unsigned int epicTmBaseSet ( ULONG srcAddr, /* Address of the Timer Base register */ unsigned int cnt, /* Base count */ unsigned int inhibit /* 1 - count inhibit */ ) { unsigned int val = 0x80000000; /* First inhibit counting the timer */ sysEUMBBARWrite(srcAddr, val) ; /* set the new value */ val = (cnt & 0x7fffffff) | ((inhibit & 0x1) << 31); sysEUMBBARWrite(srcAddr, val) ; return 0; } /*********************************************************************** * function: epicTmBaseGet * * description: Get the current value of the global timer base count register * including the CI bit. return 0 if no error, else return 1. * * note: ***********************************************************************/ unsigned int epicTmBaseGet( ULONG srcAddr, unsigned int *val ) { *val = sysEUMBBARRead( srcAddr ); return 0; } /*********************************************************** * function: epicTmCountGet * * description: Get the value of a given global timer * current count register and toggle bit. * return 0 if no error, otherwise return 1 * note: **********************************************************/ unsigned int epicTmCountGet( ULONG srcAddr, unsigned int *val ) { *val = sysEUMBBARRead( srcAddr ); return 0; } /*********************************************************** * function: epicTmInhibit * * description: Stop counting of a given global timer * return 0 if no error, otherwise return 1 * * note: ***********************************************************/ unsigned int epicTmInhibit( ULONG srcAddr ) { ULONG val; val = sysEUMBBARRead( srcAddr ); val |= 0x80000000; sysEUMBBARWrite( srcAddr, val ); return 0; } /****************************************************************** * function: epicTmEnable * * description: Enable counting of a given global timer * return 0 if no error, otherwise return 1 * * note: *****************************************************************/ unsigned int epicTmEnable( ULONG srcAddr ) { ULONG val; val = sysEUMBBARRead( srcAddr ); val &= 0x7fffffff; sysEUMBBARWrite( srcAddr, val ); return 0; } /****************************************************************** * function: epicErrorHandler * * description: Print error statements using error code * given in r3. * * note: *****************************************************************/ void epicErrorHandler(unsigned int error_code) { printf("\nEPIC Error Handler:\n\n"); switch (error_code) { case epicModeError: printf("An External Interrupt exception 0x500\n"); printf("has occurred. The EPIC unit is currently\n"); printf("in Pass-through mode. Make sure you have\n"); printf("an Interrupt Handler set up at 0x500.\n"); printf("Disabling External Interrupts...\n"); break; default: printf("Unknown error code\n"); break; } } /****************************************************************** * function: epicSourcePrint * * description: * * note: *****************************************************************/ void epicSourcePrint(int Vect) { ULONG srcVal; srcVal = sysEUMBBARRead(SrcVecTable[Vect].srcAddr); printf("%s\n", SrcVecTable[Vect].srcName); printf("Address = 0x%lx\n", SrcVecTable[Vect].srcAddr); printf("Vector = %d\n", (srcVal & 0x000000FF) ); printf("Mask = %d\n", srcVal >> 31); printf("Activitiy = %d\n", (srcVal & 0x40000000) >> 30); printf("Polarity = %d\n", (srcVal & 0x00800000) >> 23); printf("Sense = %d\n", (srcVal & 0x00400000) >> 22); printf("Priority = %d\n", (srcVal & 0x000F0000) >> 16); } /******************************************************* * function: epicStatPrint * ******************************************************/ void epicStatPrint() { unsigned int tmp1, tmp2; unsigned int tmp; /* report the EPIC mode */ tmp = epicModeGet(); PRINT("EPIC mode %s\n", tmp ? "Mixed" : "Pass Though"); /* report the epic interrupt configuration */ epicConfigGet( &tmp1, &tmp2 ); PRINT("EPIC Operation %s\n", tmp2 ? "Serial":"Direct"); if (tmp2 == 1) PRINT("Clock Ratio 0x%x\n", tmp1); /* report the processor task priority */ PRINT("Current task Pri. 0x%x\n\n", epicIntTaskGet() ); /* report the vector number, source address and description */ PRINT("Vector Source Address ISR Address Source Interrupt\n"); for (tmp = 0; tmp < MAXVEC-1; tmp++) PRINT(" %2d %lx %8lx %s\n" , tmp, SrcVecTable[tmp].srcAddr, SrcVecTable[tmp].isrAddr, SrcVecTable[tmp].srcName); } /************************************************************** * function: DMA_Get_Stat_Epic * * description: return the content of status register of * the given DMA channel * * if error, reserved0 field all 1s. **************************************************************/ static DMAStatus DMA_Get_Stat_Epic( LOCATION host, unsigned int eumbbar, unsigned int channel, DMA_SR *stat ) { union { unsigned int tmp; DMA_SR status; } s; if ( channel != 0 && channel != 1 || stat == 0 ) { return DMAINVALID; } s.tmp = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG] ); #ifdef DMADBG0 PRINT( "%s(%d): %s DMA %d (0x%08x) stat = 0x%08x\n", __FILE__, __LINE__, ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG], s.tmp ); #endif *stat = s.status; return DMASUCCESS; }