w32113
驱动牛犊
驱动牛犊
  • 注册日期2003-07-14
  • 最后登录2006-04-19
  • 粉丝0
  • 关注0
  • 积分30分
  • 威望3点
  • 贡献值0点
  • 好评度3点
  • 原创分0分
  • 专家分0分
阅读:1606回复:0

请教pci卡中断处理问题

楼主#
更多 发布于:2004-01-14 09:46
我用windriver开发一块基于AMCC 的S5920  PCI卡的驱动程序,因为PCI中断是电平触发,驱动响应PCI中断需要在驱动内核立即给与中断应答,使中断无效,而在中断服务线程里达不到应答效果。否则可能将一次中断信号当做多次中断,可能造成死机或挂起。
下面是中断使能用户级delphi接口函数()
function S1160_IntEnable (hS1160 : S1160_HANDLE; funcIntHandler : S1160_INT_HANDLER) : BOOLEAN;
var
    dwStatus : DWORD;
     addrSpace : S1160_ADDR;

begin
        if hS1160^.Int.hThread<>0        { check if interrupt is already enabled }
        then
            S1160_IntEnable := False
        else
        begin
            FillChar(hS1160^.Int.Trans[0], SizeOf(hS1160^.Int.Trans), 0);
             { One transfer command is issued to CANCEL the source of the interrupt,     }
             { otherwise, the PC will hang when an interrupt occurs!                     }

            addrSpace := S1160_INTCSR_SPACE;
 
            if hS1160^.addrDesc[addrSpace].fIsMemory
            then
            begin
                hS1160^.Int.Trans[0].dwPort := hS1160^.cardReg.Card.Item[hS1160^.addrDesc[addrSpace].index].Memory.dwTransAddr;
                hS1160^.Int.Trans[0].cmdTrans := RM_DWORD;
            end
            else
            begin
                hS1160^.Int.Trans[0].dwPort := hS1160^.cardReg.Card.Item[hS1160^.addrDesc[addrSpace].index].IO.dwAddr;
                hS1160^.Int.Trans[0].cmdTrans := RP_DWORD;
            end;
            hS1160^.Int.Trans[0].dwPort := hS1160^.Int.Trans[0].dwPort + S1160_INTCSR_OFFSET;

            FillChar(hS1160^.Int.Trans[1], SizeOf(hS1160^.Int.Trans), 0);
             { One transfer command is issued to CANCEL the source of the interrupt,     }
             { otherwise, the PC will hang when an interrupt occurs!                     }

            addrSpace := S1160_INTCSR_SPACE;
 
            if hS1160^.addrDesc[addrSpace].fIsMemory
            then
            begin
                hS1160^.Int.Trans[1].dwPort := hS1160^.cardReg.Card.Item[hS1160^.addrDesc[addrSpace].index].Memory.dwTransAddr;
                hS1160^.Int.Trans[1].cmdTrans := WM_DWORD;
            end
            else
            begin
                hS1160^.Int.Trans[1].dwPort := hS1160^.cardReg.Card.Item[hS1160^.addrDesc[addrSpace].index].IO.dwAddr;
                hS1160^.Int.Trans[1].cmdTrans := WP_DWORD;
            end;
            hS1160^.Int.Trans[1].dwPort := hS1160^.Int.Trans[1].dwPort + S1160_INTCSR_OFFSET;
            hS1160^.Int.Trans[1].ADword := $0;

            hS1160^.Int.Int.dwCmds := 2;
            hS1160^.Int.Int.Cmd := @hS1160^.Int.Trans[0];
            hS1160^.Int.Int.dwOptions := hS1160^.Int.Int.dwOptions or INTERRUPT_CMD_COPY;

            { this calls WD_IntEnable() and creates an interrupt handler thread }
            hS1160^.Int.funcIntHandler := funcIntHandler;
            dwStatus := InterruptEnable(@hS1160^.Int.hThread, hS1160^.hWD, @hS1160^.Int.Int, S1160_IntHandler, POINTER(hS1160));
            if dwStatus>0
            then
            begin
                FmtStr(S1160_ErrorString, \'InterruptEnable failed with status ($%x) - %s\', [dwStatus, Stat2Str(dwStatus)]);
                S1160_IntEnable := False;
            end
            else
                S1160_IntEnable := True;
        end;
end;
上面的函数作用是响应中断时向S5920芯片中断控制寄存器BAR0的S1160_INTCSR_OFFSET=0X38,写0使中断无效。不知是否正确。测试时好像控制字没有写进去,造成中断不停的触发。请各位大虾赐教,先谢了
游客

返回顶部