Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
nj_s.c
Go to the documentation of this file.
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/init.h>
9 #include "hisax.h"
10 #include "isac.h"
11 #include "isdnl1.h"
12 #include <linux/pci.h>
13 #include <linux/interrupt.h>
14 #include <linux/ppp_defs.h>
15 #include "netjet.h"
16 
17 static const char *NETjet_S_revision = "$Revision: 2.13.2.4 $";
18 
19 static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
20 {
21  return (5);
22 }
23 
24 static void dummywr(struct IsdnCardState *cs, int chan, u_char off, u_char value)
25 {
26 }
27 
28 static irqreturn_t
29 netjet_s_interrupt(int intno, void *dev_id)
30 {
31  struct IsdnCardState *cs = dev_id;
32  u_char val, s1val, s0val;
33  u_long flags;
34 
35  spin_lock_irqsave(&cs->lock, flags);
36  s1val = bytein(cs->hw.njet.base + NETJET_IRQSTAT1);
37  if (!(s1val & NETJET_ISACIRQ)) {
38  val = NETjet_ReadIC(cs, ISAC_ISTA);
39  if (cs->debug & L1_DEB_ISAC)
40  debugl1(cs, "tiger: i1 %x %x", s1val, val);
41  if (val) {
42  isac_interrupt(cs, val);
43  NETjet_WriteIC(cs, ISAC_MASK, 0xFF);
44  NETjet_WriteIC(cs, ISAC_MASK, 0x0);
45  }
46  s1val = 1;
47  } else
48  s1val = 0;
49  /*
50  * read/write stat0 is better, because lower IRQ rate
51  * Note the IRQ is on for 125 us if a condition match
52  * thats long on modern CPU and so the IRQ is reentered
53  * all the time.
54  */
55  s0val = bytein(cs->hw.njet.base + NETJET_IRQSTAT0);
56  if ((s0val | s1val) == 0) { // shared IRQ
57  spin_unlock_irqrestore(&cs->lock, flags);
58  return IRQ_NONE;
59  }
60  if (s0val)
61  byteout(cs->hw.njet.base + NETJET_IRQSTAT0, s0val);
62  /* start new code 13/07/00 GE */
63  /* set bits in sval to indicate which page is free */
64  if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) <
65  inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ))
66  /* the 2nd write page is free */
67  s0val = 0x08;
68  else /* the 1st write page is free */
69  s0val = 0x04;
70  if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) <
71  inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ))
72  /* the 2nd read page is free */
73  s0val |= 0x02;
74  else /* the 1st read page is free */
75  s0val |= 0x01;
76  if (s0val != cs->hw.njet.last_is0) /* we have a DMA interrupt */
77  {
78  if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
79  printk(KERN_WARNING "nj LOCK_ATOMIC s0val %x->%x\n",
80  cs->hw.njet.last_is0, s0val);
81  spin_unlock_irqrestore(&cs->lock, flags);
82  return IRQ_HANDLED;
83  }
84  cs->hw.njet.irqstat0 = s0val;
85  if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) !=
86  (cs->hw.njet.last_is0 & NETJET_IRQM0_READ))
87  /* we have a read dma int */
88  read_tiger(cs);
89  if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) !=
90  (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE))
91  /* we have a write dma int */
92  write_tiger(cs);
93  /* end new code 13/07/00 GE */
94  test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
95  }
96  spin_unlock_irqrestore(&cs->lock, flags);
97  return IRQ_HANDLED;
98 }
99 
100 static void
101 reset_netjet_s(struct IsdnCardState *cs)
102 {
103  cs->hw.njet.ctrl_reg = 0xff; /* Reset On */
104  byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
105  mdelay(10);
106  /* now edge triggered for TJ320 GE 13/07/00 */
107  /* see comment in IRQ function */
108  if (cs->subtyp) /* TJ320 */
109  cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */
110  else
111  cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
112  byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
113  mdelay(10);
114  cs->hw.njet.auxd = 0;
115  cs->hw.njet.dmactrl = 0;
116  byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
117  byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
118  byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
119 }
120 
121 static int
122 NETjet_S_card_msg(struct IsdnCardState *cs, int mt, void *arg)
123 {
124  u_long flags;
125 
126  switch (mt) {
127  case CARD_RESET:
128  spin_lock_irqsave(&cs->lock, flags);
129  reset_netjet_s(cs);
130  spin_unlock_irqrestore(&cs->lock, flags);
131  return (0);
132  case CARD_RELEASE:
133  release_io_netjet(cs);
134  return (0);
135  case CARD_INIT:
136  reset_netjet_s(cs);
137  inittiger(cs);
138  spin_lock_irqsave(&cs->lock, flags);
140  initisac(cs);
141  /* Reenable all IRQ */
142  cs->writeisac(cs, ISAC_MASK, 0);
143  spin_unlock_irqrestore(&cs->lock, flags);
144  return (0);
145  case CARD_TEST:
146  return (0);
147  }
148  return (0);
149 }
150 
151 static int __devinit njs_pci_probe(struct pci_dev *dev_netjet,
152  struct IsdnCardState *cs)
153 {
154  u32 cfg;
155 
156  if (pci_enable_device(dev_netjet))
157  return (0);
158  pci_set_master(dev_netjet);
159  cs->irq = dev_netjet->irq;
160  if (!cs->irq) {
161  printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n");
162  return (0);
163  }
164  cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
165  if (!cs->hw.njet.base) {
166  printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n");
167  return (0);
168  }
169  /* the TJ300 and TJ320 must be detected, the IRQ handling is different
170  * unfortunately the chips use the same device ID, but the TJ320 has
171  * the bit20 in status PCI cfg register set
172  */
173  pci_read_config_dword(dev_netjet, 0x04, &cfg);
174  if (cfg & 0x00100000)
175  cs->subtyp = 1; /* TJ320 */
176  else
177  cs->subtyp = 0; /* TJ300 */
178  /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
179  if ((dev_netjet->subsystem_vendor == 0x55) &&
180  (dev_netjet->subsystem_device == 0x02)) {
181  printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n");
182  printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n");
183  return (0);
184  }
185  /* end new code */
186 
187  return (1);
188 }
189 
190 static int __devinit njs_cs_init(struct IsdnCard *card,
191  struct IsdnCardState *cs)
192 {
193 
194  cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
195  cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
196 
197  cs->hw.njet.ctrl_reg = 0xff; /* Reset On */
198  byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
199  mdelay(10);
200 
201  cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */
202  byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
203  mdelay(10);
204 
205  cs->hw.njet.auxd = 0xC0;
206  cs->hw.njet.dmactrl = 0;
207 
208  byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ);
209  byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ);
210  byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
211 
212  switch (((NETjet_ReadIC(cs, ISAC_RBCH) >> 5) & 3))
213  {
214  case 0:
215  return 1; /* end loop */
216 
217  case 3:
218  printk(KERN_WARNING "NETjet-S: NETspider-U PCI card found\n");
219  return -1; /* continue looping */
220 
221  default:
222  printk(KERN_WARNING "NETjet-S: No PCI card found\n");
223  return 0; /* end loop & function */
224  }
225  return 1; /* end loop */
226 }
227 
228 static int __devinit njs_cs_init_rest(struct IsdnCard *card,
229  struct IsdnCardState *cs)
230 {
231  const int bytecnt = 256;
232 
234  "NETjet-S: %s card configured at %#lx IRQ %d\n",
235  cs->subtyp ? "TJ320" : "TJ300", cs->hw.njet.base, cs->irq);
236  if (!request_region(cs->hw.njet.base, bytecnt, "netjet-s isdn")) {
238  "HiSax: NETjet-S config port %#lx-%#lx already in use\n",
239  cs->hw.njet.base,
240  cs->hw.njet.base + bytecnt);
241  return (0);
242  }
243  cs->readisac = &NETjet_ReadIC;
244  cs->writeisac = &NETjet_WriteIC;
245  cs->readisacfifo = &NETjet_ReadICfifo;
246  cs->writeisacfifo = &NETjet_WriteICfifo;
247  cs->BC_Read_Reg = &dummyrr;
248  cs->BC_Write_Reg = &dummywr;
249  cs->BC_Send_Data = &netjet_fill_dma;
250  setup_isac(cs);
251  cs->cardmsg = &NETjet_S_card_msg;
252  cs->irq_func = &netjet_s_interrupt;
253  cs->irq_flags |= IRQF_SHARED;
254  ISACVersion(cs, "NETjet-S:");
255 
256  return (1);
257 }
258 
259 static struct pci_dev *dev_netjet __devinitdata = NULL;
260 
261 int __devinit
263 {
264  int ret;
265  struct IsdnCardState *cs = card->cs;
266  char tmp[64];
267 
268 #ifdef __BIG_ENDIAN
269 #error "not running on big endian machines now"
270 #endif
271  strcpy(tmp, NETjet_S_revision);
272  printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp));
273  if (cs->typ != ISDN_CTYPE_NETJET_S)
274  return (0);
275  test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
276 
277  for (;;)
278  {
279  if ((dev_netjet = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET,
280  PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) {
281  ret = njs_pci_probe(dev_netjet, cs);
282  if (!ret)
283  return (0);
284  } else {
285  printk(KERN_WARNING "NETjet-S: No PCI card found\n");
286  return (0);
287  }
288 
289  ret = njs_cs_init(card, cs);
290  if (!ret)
291  return (0);
292  if (ret > 0)
293  break;
294  /* otherwise, ret < 0, continue looping */
295  }
296 
297  return njs_cs_init_rest(card, cs);
298 }