source: drsdaq/VME/struck/sis1100/V2.02/dev/pci/sis1100_irq.c@ 23

Last change on this file since 23 was 22, checked in by ogrimm, 16 years ago
First commit of drsdaq program
File size: 7.0 KB
Line 
1/* $ZEL: sis1100_irq.c,v 1.7 2004/05/27 23:10:23 wuestner Exp $ */
2
3/*
4 * Copyright (c) 2001-2004
5 * Matthias Drochner, Peter Wuestner. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include "sis1100_sc.h"
30
31int
32sis1100_enable_irq(struct sis1100_softc* sc,
33 u_int32_t plx_mask, u_int32_t sis_mask)
34{
35 DECLARE_SPINLOCKFLAGS(flags)
36 if (plx_mask) {
37 SPIN_LOCK_IRQSAVE(sc->lock_intcsr, flags);
38 plxwritereg(sc, INTCSR, plxreadreg(sc, INTCSR)|plx_mask);
39 SPIN_UNLOCK_IRQRESTORE(sc->lock_intcsr, flags);
40 }
41
42 if (sis_mask) {
43 sis_mask&=sis1100_all_irq;
44 sis1100writereg(sc, sr, sis_mask); /* clear pending irqs */
45 sis1100writereg(sc, cr, sis_mask); /* enable irqs */
46 }
47 return 0;
48}
49
50int
51sis1100_disable_irq(struct sis1100_softc* sc,
52 u_int32_t plx_mask, u_int32_t sis_mask)
53{
54 DECLARE_SPINLOCKFLAGS(flags)
55 if (plx_mask) {
56 SPIN_LOCK_IRQSAVE(sc->lock_intcsr, flags);
57 plxwritereg(sc, INTCSR, plxreadreg(sc, INTCSR)&~plx_mask);
58 SPIN_UNLOCK_IRQRESTORE(sc->lock_intcsr, flags);
59 }
60
61 if (sis_mask) sis1100writereg(sc, cr, (sis_mask&sis1100_all_irq)<<16);
62 return 0;
63}
64
65/* Doorbell | Local | DMA0 | DMA1 */
66#define HANDLED_IRQS (plxirq_doorbell_active|plxirq_local_active|\
67 plxirq_dma0_active|plxirq_dma1_active)
68
69#ifdef __NetBSD__
70int
71sis1100_intr(void* vsc)
72#elif __linux__
73irqreturn_t
74sis1100_intr(int irq, void *vsc, struct pt_regs *regs)
75#endif
76{
77 DECLARE_SPINLOCKFLAGS(flags)
78 struct sis1100_softc* sc=(struct sis1100_softc*)vsc;
79 u_int32_t intcsr;
80 int local, handler_command, wakeup_handler, wakeup_local;
81
82 intcsr=plxreadreg(sc, INTCSR);
83 if (!(intcsr & HANDLED_IRQS)) return IRQ_NONE;
84
85 local=0;
86 handler_command=0;
87 wakeup_handler=0;
88 wakeup_local=0;
89
90 if (intcsr&plxirq_doorbell_active) { /* == VME/CAMAC IRQ */
91 u_int32_t help=plxreadreg(sc, L2PDBELL);
92 pINFO(sc, "doorbell irq: doorbell=0x%x", help);
93 SPIN_LOCK_IRQSAVE(sc->lock_doorbell, flags);
94 sc->doorbell|=help;
95 SPIN_UNLOCK_IRQRESTORE(sc->lock_doorbell, flags);
96 plxwritereg(sc, L2PDBELL, help);
97 handler_command|=handlercomm_doorbell;
98 wakeup_handler=1;
99 }
100 if (intcsr&plxirq_local_active) { /* local Interrupt */
101 local=1;
102 }
103 if (intcsr&plxirq_dma0_active) { /* DMA0 Interrupt */
104 SPIN_LOCK_IRQSAVE(sc->lock_intcsr, flags);
105 plxwritereg(sc, INTCSR, intcsr&~plxirq_dma0);
106 SPIN_UNLOCK_IRQRESTORE(sc->lock_intcsr, flags);
107 sc->got_irqs|=got_dma0;
108 wakeup_local=1;
109 }
110 if (intcsr&plxirq_dma1_active) { /* DMA1 Interrupt */
111 SPIN_LOCK_IRQSAVE(sc->lock_intcsr, flags);
112 plxwritereg(sc, INTCSR, intcsr&~plxirq_dma1);
113 SPIN_UNLOCK_IRQRESTORE(sc->lock_intcsr, flags);
114 sc->got_irqs|=got_dma1;
115 wakeup_local=1;
116 }
117 if (local) {
118 u_int32_t status;
119
120 status=sis1100readreg(sc, sr);
121
122 if (status&irq_synch_chg) {
123 sis1100_disable_irq(sc, 0, irq_synch_chg|
124 irq_reset_req|irq_prot_end|irq_prot_l_err);
125
126 sc->got_irqs|=got_sync;
127 wakeup_local=1;
128
129 if ((status&3)==3) {
130 pINFO(sc, "link is UP status =0x%08x", status);
131 } else {
132 pINFO(sc, "link is DOWN status =0x%08x", status);
133 sc->old_remote_hw=sc->remote_hw;
134 sc->remote_hw=sis1100_hw_invalid;
135 handler_command|=handlercomm_synch;
136 wakeup_handler=1;
137 }
138#ifdef __NetBSD__
139 callout_reset(&sc->link_up_timer, hz, sis1100_link_up_handler, sc);
140#elif __linux__
141 mod_timer(&sc->link_up_timer, jiffies+HZ);
142#endif
143 }
144 if (status&irq_inh_chg)
145 pERROR(sc, "INH_CHG");
146 if (status&irq_sema_chg)
147 pERROR(sc, "SEMA_CHG");
148 if (status&irq_rec_violation)
149 pERROR(sc, "REC_VIOLATION");
150 if (status&irq_reset_req)
151 pERROR(sc, "RESET_REQ");
152 if (status&irq_dma_eot) {
153 sc->got_irqs|=got_eot;
154 wakeup_local=1;
155 }
156 if (status&irq_mbx0) {
157 sc->mbx0=sis1100readreg(sc, mailext[0]);
158 /*pINFO(sc, "irq: mbx0=0x%x", sc->mbx0);*/
159 handler_command|=handlercomm_mbx0;
160 wakeup_handler=1;
161 }
162#ifdef NEVER
163 if (status&irq_s_xoff) {
164 pINFO(sc, "S_XOFF");
165 pINFO(sc, "status=0x%08x", status);
166 sc->got_irqs|=got_xoff;
167 wakeup_local=1;
168 }
169#endif
170 if (status&irq_lemo_in_chg) {
171 /* pINFO(sc, "LEMO_IN_CHG, status=0x%08x", status); */
172 SPIN_LOCK_IRQSAVE(sc->lock_lemo_status, flags);
173 sc->lemo_status|=(status<<4)&0x30000;
174 SPIN_UNLOCK_IRQRESTORE(sc->lock_lemo_status, flags);
175 sc->last_opt_csr=sis1100readreg(sc, opt_csr);
176 handler_command|=handlercomm_lemo;
177 wakeup_handler=1;
178 }
179 if (status&irq_prot_end) {
180 sc->got_irqs|=got_end;
181 wakeup_local=1;
182 }
183 if (status&irq_prot_l_err) {
184 /*pINFO(sc, "PROT_L_ERR");*/
185 sc->got_irqs|=got_l_err;
186 wakeup_local=1;
187 }
188/*
189 * pINFO(sc, "irq: write 0x%x to sr", status);
190 */
191 sis1100writereg(sc, sr, status);
192 }
193
194 if (wakeup_local)
195#ifdef __NetBSD__
196 wakeup(&sc->local_wait);
197#elif __linux__
198 wake_up_interruptible(&sc->local_wait);
199#endif
200
201 if (wakeup_handler) {
202 SPIN_LOCK_IRQSAVE(sc->lock_intcsr, flags); /* XXX warum? */
203 sc->handlercommand.command=handler_command;
204 SPIN_UNLOCK_IRQRESTORE(sc->lock_intcsr, flags);
205#ifdef __NetBSD__
206 wakeup(&sc->handler_wait);
207#elif __linux__
208 wake_up(&sc->handler_wait);
209#endif
210 }
211
212 return IRQ_HANDLED;
213}
Note: See TracBrowser for help on using the repository browser.