⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os-interrupt.c

📁 IBM source for pallas/vulcan/vesta
💻 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+----------------------------------------------------------------------------*/#ifdef LINUX#define __NO_VERSION__#include <linux/kernel.h>#include <linux/config.h>#include <linux/sched.h>#include <linux/interrupt.h>#include <linux/string.h>       /* for memset */#include <asm/irq.h>#endif  // LINUX#include <os/os-sync.h>#include <os/os-interrupt.h>#include <os/os-io.h>#undef __DRV_DEBUG#include <os/drv_debug.h>#include "os-interrupt-local.h"#ifndef NULL    // My local NULL definition    #define NULL ((void *)0)#endifstatic UINT _mask_tab[MAX_IRQ] = {    0x80000000, 0x40000000, 0x20000000, 0x10000000,    0x08000000, 0x04000000, 0x02000000, 0x01000000,    0x00800000, 0x00400000, 0x00200000, 0x00100000,    0x00080000, 0x00040000, 0x00020000, 0x00010000,    0x00008000, 0x00004000, 0x00002000, 0x00001000,    0x00000800, 0x00000400, 0x00000200, 0x00000100,    0x00000080, 0x00000040, 0x00000020, 0x00000010,    0x00000008, 0x00000004, 0x00000002, 0x00000001};static IRQ     _irq_tab[MAX_IRQ];static UINT    _irq_tab_init = 0;void inline os_irq_clear(IRQ *pIrq){    pIrq->uIrq = 0;    pIrq->uAttr = 0;    pIrq->handler = NULL;    pIrq->nCount = 0;    pIrq->uTaskFlag = 0;    pIrq->pData = NULL;    pIrq->mutex = NULL;}INT    os_irq_init(void){    int i;    if(_irq_tab_init != 0)        return -1;    for(i =0; i < MAX_IRQ; i++)    {        os_irq_clear(&(_irq_tab[i]));    }    _irq_tab_init = 1;    return 0;}//As an interrupt handler, current interrupt is disabledvoid os_irq_standard_handler(int irq, void* dev_id, struct pt_regs *regs){    IRQ *pIrq;    pIrq = (IRQ*)dev_id;//printk("<0>@"); // YYD    PDEBUG("IRQ: irq handler = %d\n", irq);    if(pIrq->uIrq == 0)        return;    if(pIrq->handler)    {        pIrq->nCount++;        pIrq->handler(pIrq->uIrq, pIrq->pData);    }}//install new interrupt handlerINT    os_install_irq(UINT uIrq, UINT uAttr,                       void (*handler)(UINT uIrq, void *pData),                        void *pData){    UINT uReg;    UINT uRet;    MUTEX_T mutex;    UINT uFlags;    PDEBUG("IRQ: install new IRQ = %d", uIrq);    // Check validity of new interrupt    if(uIrq == 0 || uIrq > MAX_IRQ)    {        PDEBUG("IRQ: irq number is out of range\n");        return -1;    }        if((uAttr & (IRQ_LEVEL_TRIG | IRQ_EDGE_TRIG)) == 0 )    {        PDEBUG("IRQ: haven't specified level/edge trigger\n");        return -1;    }    if((uAttr & (IRQ_POSITIVE_TRIG | IRQ_NEGATIVE_TRIG)) == 0)    {        PDEBUG("IRQ: haven't specified positive/negative trigger\n");        return -1;    }    // check if interrupt handler exists    if (handler == NULL)    {        PDEBUG("IRQ: No irq_handler\n");        return -1;    }    if (_irq_tab[uIrq].uIrq != 0)    {        PDEBUG("IRQ: irq %d exists\n", uIrq);        return -1;    }    //create mutex for futher task operation    if((mutex = os_create_mutex()) == NULL)    {        PDEBUG("TASK: can not create mutex\n");        return -1;    }    //enter critical section    uFlags = os_enter_critical_section();    // set level/edge bit in UIC    uReg = MF_DCR(UICTR) & (~_mask_tab[uIrq]);    if( (uAttr & IRQ_EDGE_TRIG) != 0)    {        MT_DCR(UICTR, (uReg | _mask_tab[uIrq]));    }    else    {        MT_DCR(UICTR, uReg);    }    // set polarity bit in UIC    uReg = MF_DCR(UICPR) & (~_mask_tab[uIrq]);    if( (uAttr & IRQ_POSITIVE_TRIG) != 0)    {        MT_DCR(UICPR, (uReg | _mask_tab[uIrq]));    }    else    {        MT_DCR(UICPR, uReg);    }    _irq_tab[uIrq].uIrq = uIrq;    _irq_tab[uIrq].nCount = 0;    _irq_tab[uIrq].uAttr = uAttr;    _irq_tab[uIrq].uTaskFlag = 0;    _irq_tab[uIrq].pData = pData;    _irq_tab[uIrq].handler = handler;    _irq_tab[uIrq].mutex = mutex;#ifdef LINUX    // install hardware interrupt handler    uRet = request_irq(uIrq,        os_irq_standard_handler, SA_SHIRQ, NULL, &(_irq_tab[uIrq]));#endif // LINUX    if (uRet != 0)    {        os_irq_clear(&(_irq_tab[uIrq]));        os_leave_critical_section(uFlags);        os_delete_mutex(mutex);        return -1;    }    os_leave_critical_section(uFlags);    return 0;}INT    os_uninstall_irq(UINT uIrq){    MUTEX_T mutex;    UINT uFlags;    PDEBUG("IRQ: uninstall IRQ = %d", uIrq);    // Check validity of new interrupt    if(uIrq == 0 || uIrq > MAX_IRQ)    {        PDEBUG("IRQ: irq number is out of range\n");        return -1;    }    if(_irq_tab[uIrq].uIrq == 0)    {        PDEBUG("IRQ: this interrupt not installed\n");        return -1;    }    if(_irq_tab[uIrq].uTaskFlag != 0)    {        PDEBUG("IRQ: attached task is activing, remove first\n");        return -1;    }    mutex = _irq_tab[uIrq].mutex;    //enter critical section    uFlags = os_enter_critical_section();    {#ifdef LINUX        // uninstall hardware interrupt handler        free_irq(uIrq, &(_irq_tab[uIrq]));     #endif // LINUX    }        os_irq_clear(&(_irq_tab[uIrq]));    os_leave_critical_section(uFlags);    //delete mutex    if(mutex)        os_delete_mutex(mutex);    return 0;}INT    os_enable_irq(UINT uIrq){#ifdef LINUX//printk("<0>["); // YYD    enable_irq(uIrq);    return 0;#endif}INT    os_disable_irq(UINT uIrq){#ifdef LINUX//printk("<0>]"); // YYD    disable_irq(uIrq);    return 0;#endif}INT    os_get_irq_count(UINT uIrq){    if(uIrq == 0 || uIrq > MAX_IRQ)    {        PDEBUG("IRQ: irq number is out of range\n");        return -1;    }    if(_irq_tab[uIrq].uIrq == 0)    {        PDEBUG("IRQ: this interrupt not installed\n");        return -1;    }    return _irq_tab[uIrq].nCount;}INT    os_reset_irq_count(UINT uIrq){    UINT uFlags;    if(uIrq == 0 || uIrq > MAX_IRQ)    {        PDEBUG("IRQ: irq number is out of range\n");        return -1;    }    if(_irq_tab[uIrq].uIrq == 0)    {        PDEBUG("IRQ: this interrupt not installed\n");        return -1;    }    uFlags = os_enter_critical_section();    {        _irq_tab[uIrq].nCount = 0;    }    os_leave_critical_section(uFlags);    return 0;}INT    os_dump_irq(UINT uIrq){    if(uIrq == 0 || uIrq > MAX_IRQ)    {        PDEBUG("IRQ: irq number is out of range\n");        return -1;    }    PDEBUG("IRQ: irq number = %u \n", _irq_tab[uIrq].uIrq);    PDEBUG("IRQ: irq attribute = 0x%8.8x\n", _irq_tab[uIrq].uAttr);    PDEBUG("IRQ: irq count = %u\n", _irq_tab[uIrq].nCount);    PDEBUG("IRQ: irq handler = 0x%8.8x\n", (UINT)_irq_tab[uIrq].handler);    PDEBUG("IRQ: irq task = 0x%8.8x\n", _irq_tab[uIrq].uTaskFlag);    if(_irq_tab[uIrq].uTaskFlag == 1)    {        PDEBUG("IRQ: task function = 0x%8.8x\n", (UINT)_irq_tab[uIrq].task.irq_task);        PDEBUG("IRQ: task msg size = %u\n", _irq_tab[uIrq].task.uMsgSize);        PDEBUG("IRQ: task active number = %u\n", _irq_tab[uIrq].task.nActiveNum);    }    return 0;}INT    os_add_irq_task(UINT uIrq, void (*irq_task)(QUEUE_T *pQueue),                         UINT uMsgSize,                         UINT uQueueSize){    TASK *pTask;    PDEBUG("IRQ: add irq task = %d", uIrq);    // Check validity of new interrupt    if(uIrq == 0 || uIrq > MAX_IRQ)    {        PDEBUG("TASK: irq number is out of range\n");        return -1;    }    if(irq_task == NULL)    {        PDEBUG("TASK: no task function\n");        return -1;    }    if(_irq_tab[uIrq].uIrq == 0)    {        PDEBUG("IRQ: this interrupt not installed\n");        return -1;    }    //synchronize to access uTaskFlag    os_get_mutex(_irq_tab[uIrq].mutex);    if(_irq_tab[uIrq].uTaskFlag != 0)    {        PDEBUG("TASK: attached task is activing, remove first\n");        os_release_mutex(_irq_tab[uIrq].mutex);        return -1;    }    pTask = &(_irq_tab[uIrq].task);    //clear task    memset((void*)pTask, 0, sizeof(TASK));    //create message queue    if(uQueueSize != 0 && uMsgSize != 0)    {        if( os_create_queue(&(pTask->Queue), NULL, uQueueSize, uMsgSize) != 0)        {            PDEBUG("IRQ.TASK: create msg queue error\n");            return -1;        }        pTask->uQueueFlag = 1;    }    else        pTask->uQueueFlag = 0;    pTask->task.routine = os_standard_task;    pTask->task.data = (void*)pTask;    pTask->uIrq = uIrq;    pTask->uMsgSize = uMsgSize;    pTask->irq_task = irq_task;    pTask->nActiveNum = 0;    _irq_tab[uIrq].uTaskFlag = 1;    os_release_mutex(_irq_tab[uIrq].mutex);    return 0;}//count the number of active taskvoid os_standard_task(void *pData){    UINT uFlags;    TASK* pTask = pData;    uFlags = os_enter_critical_section();    {        if(pTask->irq_task)        {            void (*irq_task)(QUEUE_T *pQueue);            irq_task = pTask->irq_task;            os_leave_critical_section(uFlags);            //call user's task function            if(pTask->uQueueFlag)                irq_task(&(pTask->Queue));            else                irq_task(NULL);        }        else        {            os_leave_critical_section(uFlags);            PDEBUG("TASK: active task without handler!\n");        }    }}/*This function must be called from interrupt handler and we  assume interrupt is disabled here*/INT    os_call_irq_task(UINT uIrq, void *pMsg){    /*we do not check parameter here because this function is usually called       by interrupt handler*/    TASK *pTask;    PDEBUG("TASK: call irq task %d\n", uIrq);    if(_irq_tab[uIrq].uTaskFlag == 0)        return -1;    pTask = &(_irq_tab[uIrq].task);    //enqueue new message    if(pTask->uQueueFlag)        if( os_enqueue(&(pTask->Queue), pMsg) < 0 )            return -1;    //install task function to system task queue#ifdef LINUX    queue_task(&(pTask->task), &tq_immediate);    mark_bh(IMMEDIATE_BH);#endif    return 0;}INT    os_delete_irq_task(UINT uIrq){    TASK *pTask;    UINT uFlags;    PDEBUG("TASK: try to delete irq task = %d", uIrq);    // Check validity of new interrupt    if(uIrq == 0 || uIrq > MAX_IRQ)    {        PDEBUG("IRQ.TASK: irq number is out of range\n");        return -1;    }    //keep synchronize with os_add_irq_task    os_get_mutex(_irq_tab[uIrq].mutex);    if(_irq_tab[uIrq].uTaskFlag == 0)    {        os_release_mutex(_irq_tab[uIrq].mutex);        return 0;    }    pTask = &(_irq_tab[uIrq].task);    //check if all activated tasks have been executed    uFlags = os_enter_critical_section();    if(os_get_queue_status(&(pTask->Queue)) > 0)    {        PDEBUG("TASK: activated task exist, please try again!\n");        os_leave_critical_section(uFlags);        os_release_mutex(_irq_tab[uIrq].mutex);        return -1;    }        // stop all futher calling tasks now    _irq_tab[uIrq].uTaskFlag = 0;    os_leave_critical_section(uFlags);    if(pTask->uQueueFlag)        os_delete_queue(&(pTask->Queue));    pTask->uIrq = 0;    pTask->irq_task = NULL;    os_release_mutex(_irq_tab[uIrq].mutex);    return 0;}    INT    os_irq_task_get_msg(QUEUE_T *pQueue, void *pMsg)    {    return os_dequeue(pQueue, pMsg);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -