diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/hisax/nj_s.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/isdn/hisax/nj_s.c')
-rw-r--r-- | drivers/isdn/hisax/nj_s.c | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c new file mode 100644 index 000000000000..fd664697f821 --- /dev/null +++ b/drivers/isdn/hisax/nj_s.c | |||
@@ -0,0 +1,278 @@ | |||
1 | /* $Id: nj_s.c,v 2.13.2.4 2004/01/16 01:53:48 keil Exp $ | ||
2 | * | ||
3 | * This software may be used and distributed according to the terms | ||
4 | * of the GNU General Public License, incorporated herein by reference. | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | #include <linux/config.h> | ||
9 | #include <linux/init.h> | ||
10 | #include "hisax.h" | ||
11 | #include "isac.h" | ||
12 | #include "isdnl1.h" | ||
13 | #include <linux/pci.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/ppp_defs.h> | ||
16 | #include "netjet.h" | ||
17 | |||
18 | const char *NETjet_S_revision = "$Revision: 2.13.2.4 $"; | ||
19 | |||
20 | static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off) | ||
21 | { | ||
22 | return(5); | ||
23 | } | ||
24 | |||
25 | static void dummywr(struct IsdnCardState *cs, int chan, u_char off, u_char value) | ||
26 | { | ||
27 | } | ||
28 | |||
29 | static irqreturn_t | ||
30 | netjet_s_interrupt(int intno, void *dev_id, struct pt_regs *regs) | ||
31 | { | ||
32 | struct IsdnCardState *cs = dev_id; | ||
33 | u_char val, s1val, s0val; | ||
34 | u_long flags; | ||
35 | |||
36 | spin_lock_irqsave(&cs->lock, flags); | ||
37 | s1val = bytein(cs->hw.njet.base + NETJET_IRQSTAT1); | ||
38 | if (!(s1val & NETJET_ISACIRQ)) { | ||
39 | val = NETjet_ReadIC(cs, ISAC_ISTA); | ||
40 | if (cs->debug & L1_DEB_ISAC) | ||
41 | debugl1(cs, "tiger: i1 %x %x", s1val, val); | ||
42 | if (val) { | ||
43 | isac_interrupt(cs, val); | ||
44 | NETjet_WriteIC(cs, ISAC_MASK, 0xFF); | ||
45 | NETjet_WriteIC(cs, ISAC_MASK, 0x0); | ||
46 | } | ||
47 | s1val = 1; | ||
48 | } else | ||
49 | s1val = 0; | ||
50 | /* | ||
51 | * read/write stat0 is better, because lower IRQ rate | ||
52 | * Note the IRQ is on for 125 us if a condition match | ||
53 | * thats long on modern CPU and so the IRQ is reentered | ||
54 | * all the time. | ||
55 | */ | ||
56 | s0val = bytein(cs->hw.njet.base + NETJET_IRQSTAT0); | ||
57 | if ((s0val | s1val)==0) { // shared IRQ | ||
58 | spin_unlock_irqrestore(&cs->lock, flags); | ||
59 | return IRQ_NONE; | ||
60 | } | ||
61 | if (s0val) | ||
62 | byteout(cs->hw.njet.base + NETJET_IRQSTAT0, s0val); | ||
63 | /* start new code 13/07/00 GE */ | ||
64 | /* set bits in sval to indicate which page is free */ | ||
65 | if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) < | ||
66 | inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ)) | ||
67 | /* the 2nd write page is free */ | ||
68 | s0val = 0x08; | ||
69 | else /* the 1st write page is free */ | ||
70 | s0val = 0x04; | ||
71 | if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) < | ||
72 | inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ)) | ||
73 | /* the 2nd read page is free */ | ||
74 | s0val |= 0x02; | ||
75 | else /* the 1st read page is free */ | ||
76 | s0val |= 0x01; | ||
77 | if (s0val != cs->hw.njet.last_is0) /* we have a DMA interrupt */ | ||
78 | { | ||
79 | if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { | ||
80 | printk(KERN_WARNING "nj LOCK_ATOMIC s0val %x->%x\n", | ||
81 | cs->hw.njet.last_is0, s0val); | ||
82 | spin_unlock_irqrestore(&cs->lock, flags); | ||
83 | return IRQ_HANDLED; | ||
84 | } | ||
85 | cs->hw.njet.irqstat0 = s0val; | ||
86 | if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != | ||
87 | (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) | ||
88 | /* we have a read dma int */ | ||
89 | read_tiger(cs); | ||
90 | if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) != | ||
91 | (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE)) | ||
92 | /* we have a write dma int */ | ||
93 | write_tiger(cs); | ||
94 | /* end new code 13/07/00 GE */ | ||
95 | test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); | ||
96 | } | ||
97 | spin_unlock_irqrestore(&cs->lock, flags); | ||
98 | return IRQ_HANDLED; | ||
99 | } | ||
100 | |||
101 | static void | ||
102 | reset_netjet_s(struct IsdnCardState *cs) | ||
103 | { | ||
104 | cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ | ||
105 | byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); | ||
106 | mdelay(10); | ||
107 | /* now edge triggered for TJ320 GE 13/07/00 */ | ||
108 | /* see comment in IRQ function */ | ||
109 | if (cs->subtyp) /* TJ320 */ | ||
110 | cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */ | ||
111 | else | ||
112 | cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ | ||
113 | byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); | ||
114 | mdelay(10); | ||
115 | cs->hw.njet.auxd = 0; | ||
116 | cs->hw.njet.dmactrl = 0; | ||
117 | byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); | ||
118 | byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); | ||
119 | byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); | ||
120 | } | ||
121 | |||
122 | static int | ||
123 | NETjet_S_card_msg(struct IsdnCardState *cs, int mt, void *arg) | ||
124 | { | ||
125 | u_long flags; | ||
126 | |||
127 | switch (mt) { | ||
128 | case CARD_RESET: | ||
129 | spin_lock_irqsave(&cs->lock, flags); | ||
130 | reset_netjet_s(cs); | ||
131 | spin_unlock_irqrestore(&cs->lock, flags); | ||
132 | return(0); | ||
133 | case CARD_RELEASE: | ||
134 | release_io_netjet(cs); | ||
135 | return(0); | ||
136 | case CARD_INIT: | ||
137 | reset_netjet_s(cs); | ||
138 | inittiger(cs); | ||
139 | spin_lock_irqsave(&cs->lock, flags); | ||
140 | clear_pending_isac_ints(cs); | ||
141 | initisac(cs); | ||
142 | /* Reenable all IRQ */ | ||
143 | cs->writeisac(cs, ISAC_MASK, 0); | ||
144 | spin_unlock_irqrestore(&cs->lock, flags); | ||
145 | return(0); | ||
146 | case CARD_TEST: | ||
147 | return(0); | ||
148 | } | ||
149 | return(0); | ||
150 | } | ||
151 | |||
152 | static struct pci_dev *dev_netjet __initdata = NULL; | ||
153 | |||
154 | int __init | ||
155 | setup_netjet_s(struct IsdnCard *card) | ||
156 | { | ||
157 | int bytecnt,cfg; | ||
158 | struct IsdnCardState *cs = card->cs; | ||
159 | char tmp[64]; | ||
160 | |||
161 | #ifdef __BIG_ENDIAN | ||
162 | #error "not running on big endian machines now" | ||
163 | #endif | ||
164 | strcpy(tmp, NETjet_S_revision); | ||
165 | printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp)); | ||
166 | if (cs->typ != ISDN_CTYPE_NETJET_S) | ||
167 | return(0); | ||
168 | test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); | ||
169 | |||
170 | #ifdef CONFIG_PCI | ||
171 | |||
172 | for ( ;; ) | ||
173 | { | ||
174 | if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, | ||
175 | PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { | ||
176 | if (pci_enable_device(dev_netjet)) | ||
177 | return(0); | ||
178 | pci_set_master(dev_netjet); | ||
179 | cs->irq = dev_netjet->irq; | ||
180 | if (!cs->irq) { | ||
181 | printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n"); | ||
182 | return(0); | ||
183 | } | ||
184 | cs->hw.njet.base = pci_resource_start(dev_netjet, 0); | ||
185 | if (!cs->hw.njet.base) { | ||
186 | printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n"); | ||
187 | return(0); | ||
188 | } | ||
189 | /* the TJ300 and TJ320 must be detected, the IRQ handling is different | ||
190 | * unfortunatly the chips use the same device ID, but the TJ320 has | ||
191 | * the bit20 in status PCI cfg register set | ||
192 | */ | ||
193 | pci_read_config_dword(dev_netjet, 0x04, &cfg); | ||
194 | if (cfg & 0x00100000) | ||
195 | cs->subtyp = 1; /* TJ320 */ | ||
196 | else | ||
197 | cs->subtyp = 0; /* TJ300 */ | ||
198 | /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */ | ||
199 | if ((dev_netjet->subsystem_vendor == 0x55) && | ||
200 | (dev_netjet->subsystem_device == 0x02)) { | ||
201 | printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n"); | ||
202 | printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n"); | ||
203 | return(0); | ||
204 | } | ||
205 | /* end new code */ | ||
206 | } else { | ||
207 | printk(KERN_WARNING "NETjet-S: No PCI card found\n"); | ||
208 | return(0); | ||
209 | } | ||
210 | |||
211 | cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; | ||
212 | cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; | ||
213 | |||
214 | cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ | ||
215 | byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); | ||
216 | mdelay(10); | ||
217 | |||
218 | cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ | ||
219 | byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); | ||
220 | mdelay(10); | ||
221 | |||
222 | cs->hw.njet.auxd = 0xC0; | ||
223 | cs->hw.njet.dmactrl = 0; | ||
224 | |||
225 | byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); | ||
226 | byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); | ||
227 | byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); | ||
228 | |||
229 | switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) ) | ||
230 | { | ||
231 | case 0 : | ||
232 | break; | ||
233 | |||
234 | case 3 : | ||
235 | printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" ); | ||
236 | continue; | ||
237 | |||
238 | default : | ||
239 | printk( KERN_WARNING "NETjet-S: No PCI card found\n" ); | ||
240 | return 0; | ||
241 | } | ||
242 | break; | ||
243 | } | ||
244 | #else | ||
245 | |||
246 | printk(KERN_WARNING "NETjet-S: NO_PCI_BIOS\n"); | ||
247 | printk(KERN_WARNING "NETjet-S: unable to config NETJET-S PCI\n"); | ||
248 | return (0); | ||
249 | |||
250 | #endif /* CONFIG_PCI */ | ||
251 | |||
252 | bytecnt = 256; | ||
253 | |||
254 | printk(KERN_INFO | ||
255 | "NETjet-S: %s card configured at %#lx IRQ %d\n", | ||
256 | cs->subtyp ? "TJ320" : "TJ300", cs->hw.njet.base, cs->irq); | ||
257 | if (!request_region(cs->hw.njet.base, bytecnt, "netjet-s isdn")) { | ||
258 | printk(KERN_WARNING | ||
259 | "HiSax: %s config port %#lx-%#lx already in use\n", | ||
260 | CardType[card->typ], | ||
261 | cs->hw.njet.base, | ||
262 | cs->hw.njet.base + bytecnt); | ||
263 | return (0); | ||
264 | } | ||
265 | cs->readisac = &NETjet_ReadIC; | ||
266 | cs->writeisac = &NETjet_WriteIC; | ||
267 | cs->readisacfifo = &NETjet_ReadICfifo; | ||
268 | cs->writeisacfifo = &NETjet_WriteICfifo; | ||
269 | cs->BC_Read_Reg = &dummyrr; | ||
270 | cs->BC_Write_Reg = &dummywr; | ||
271 | cs->BC_Send_Data = &netjet_fill_dma; | ||
272 | setup_isac(cs); | ||
273 | cs->cardmsg = &NETjet_S_card_msg; | ||
274 | cs->irq_func = &netjet_s_interrupt; | ||
275 | cs->irq_flags |= SA_SHIRQ; | ||
276 | ISACVersion(cs, "NETjet-S:"); | ||
277 | return (1); | ||
278 | } | ||