Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
saphir.c
Go to the documentation of this file.
1 /* $Id: saphir.c,v 1.10.2.4 2004/01/13 23:48:39 keil Exp $
2  *
3  * low level stuff for HST Saphir 1
4  *
5  * Author Karsten Keil
6  * Copyright by Karsten Keil <[email protected]>
7  *
8  * This software may be used and distributed according to the terms
9  * of the GNU General Public License, incorporated herein by reference.
10  *
11  * Thanks to HST High Soft Tech GmbH
12  *
13  */
14 
15 #include <linux/init.h>
16 #include "hisax.h"
17 #include "isac.h"
18 #include "hscx.h"
19 #include "isdnl1.h"
20 
21 static char *saphir_rev = "$Revision: 1.10.2.4 $";
22 
23 #define byteout(addr, val) outb(val, addr)
24 #define bytein(addr) inb(addr)
25 
26 #define ISAC_DATA 0
27 #define HSCX_DATA 1
28 #define ADDRESS_REG 2
29 #define IRQ_REG 3
30 #define SPARE_REG 4
31 #define RESET_REG 5
32 
33 static inline u_char
34 readreg(unsigned int ale, unsigned int adr, u_char off)
35 {
36  register u_char ret;
37 
38  byteout(ale, off);
39  ret = bytein(adr);
40  return (ret);
41 }
42 
43 static inline void
44 readfifo(unsigned int ale, unsigned int adr, u_char off, u_char *data, int size)
45 {
46  byteout(ale, off);
47  insb(adr, data, size);
48 }
49 
50 
51 static inline void
52 writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
53 {
54  byteout(ale, off);
55  byteout(adr, data);
56 }
57 
58 static inline void
59 writefifo(unsigned int ale, unsigned int adr, u_char off, u_char *data, int size)
60 {
61  byteout(ale, off);
62  outsb(adr, data, size);
63 }
64 
65 /* Interface functions */
66 
67 static u_char
68 ReadISAC(struct IsdnCardState *cs, u_char offset)
69 {
70  return (readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset));
71 }
72 
73 static void
74 WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
75 {
76  writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset, value);
77 }
78 
79 static void
80 ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size)
81 {
82  readfifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
83 }
84 
85 static void
86 WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
87 {
88  writefifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
89 }
90 
91 static u_char
92 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
93 {
94  return (readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
95  offset + (hscx ? 0x40 : 0)));
96 }
97 
98 static void
99 WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
100 {
101  writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
102  offset + (hscx ? 0x40 : 0), value);
103 }
104 
105 #define READHSCX(cs, nr, reg) readreg(cs->hw.saphir.ale, \
106  cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0))
107 #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.saphir.ale, \
108  cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0), data)
109 
110 #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.saphir.ale, \
111  cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
112 
113 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.saphir.ale, \
114  cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
115 
116 #include "hscx_irq.c"
117 
118 static irqreturn_t
119 saphir_interrupt(int intno, void *dev_id)
120 {
121  struct IsdnCardState *cs = dev_id;
122  u_char val;
123  u_long flags;
124 
125  spin_lock_irqsave(&cs->lock, flags);
126  val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
127 Start_HSCX:
128  if (val)
129  hscx_int_main(cs, val);
130  val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
131 Start_ISAC:
132  if (val)
133  isac_interrupt(cs, val);
134  val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
135  if (val) {
136  if (cs->debug & L1_DEB_HSCX)
137  debugl1(cs, "HSCX IntStat after IntRoutine");
138  goto Start_HSCX;
139  }
140  val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
141  if (val) {
142  if (cs->debug & L1_DEB_ISAC)
143  debugl1(cs, "ISAC IntStat after IntRoutine");
144  goto Start_ISAC;
145  }
146  /* Watchdog */
147  if (cs->hw.saphir.timer.function)
148  mod_timer(&cs->hw.saphir.timer, jiffies + 1 * HZ);
149  else
150  printk(KERN_WARNING "saphir: Spurious timer!\n");
151  writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0xFF);
152  writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0xFF);
153  writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0xFF);
154  writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0);
155  writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0);
156  writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0);
157  spin_unlock_irqrestore(&cs->lock, flags);
158  return IRQ_HANDLED;
159 }
160 
161 static void
162 SaphirWatchDog(struct IsdnCardState *cs)
163 {
164  u_long flags;
165 
166  spin_lock_irqsave(&cs->lock, flags);
167  /* 5 sec WatchDog, so read at least every 4 sec */
168  cs->readisac(cs, ISAC_RBCH);
169  spin_unlock_irqrestore(&cs->lock, flags);
170  mod_timer(&cs->hw.saphir.timer, jiffies + 1 * HZ);
171 }
172 
173 static void
174 release_io_saphir(struct IsdnCardState *cs)
175 {
176  byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff);
177  del_timer(&cs->hw.saphir.timer);
178  cs->hw.saphir.timer.function = NULL;
179  if (cs->hw.saphir.cfg_reg)
180  release_region(cs->hw.saphir.cfg_reg, 6);
181 }
182 
183 static int
184 saphir_reset(struct IsdnCardState *cs)
185 {
186  u_char irq_val;
187 
188  switch (cs->irq) {
189  case 5: irq_val = 0;
190  break;
191  case 3: irq_val = 1;
192  break;
193  case 11:
194  irq_val = 2;
195  break;
196  case 12:
197  irq_val = 3;
198  break;
199  case 15:
200  irq_val = 4;
201  break;
202  default:
203  printk(KERN_WARNING "HiSax: saphir wrong IRQ %d\n",
204  cs->irq);
205  return (1);
206  }
207  byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
208  byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1);
209  mdelay(10);
210  byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0);
211  mdelay(10);
212  byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
213  byteout(cs->hw.saphir.cfg_reg + SPARE_REG, 0x02);
214  return (0);
215 }
216 
217 static int
218 saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg)
219 {
220  u_long flags;
221 
222  switch (mt) {
223  case CARD_RESET:
224  spin_lock_irqsave(&cs->lock, flags);
225  saphir_reset(cs);
226  spin_unlock_irqrestore(&cs->lock, flags);
227  return (0);
228  case CARD_RELEASE:
229  release_io_saphir(cs);
230  return (0);
231  case CARD_INIT:
232  spin_lock_irqsave(&cs->lock, flags);
233  inithscxisac(cs, 3);
234  spin_unlock_irqrestore(&cs->lock, flags);
235  return (0);
236  case CARD_TEST:
237  return (0);
238  }
239  return (0);
240 }
241 
242 
243 int __devinit
245 {
246  struct IsdnCardState *cs = card->cs;
247  char tmp[64];
248 
249  strcpy(tmp, saphir_rev);
250  printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp));
251  if (cs->typ != ISDN_CTYPE_HSTSAPHIR)
252  return (0);
253 
254  /* IO-Ports */
255  cs->hw.saphir.cfg_reg = card->para[1];
256  cs->hw.saphir.isac = card->para[1] + ISAC_DATA;
257  cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
258  cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
259  cs->irq = card->para[0];
260  if (!request_region(cs->hw.saphir.cfg_reg, 6, "saphir")) {
262  "HiSax: HST Saphir config port %x-%x already in use\n",
263  cs->hw.saphir.cfg_reg,
264  cs->hw.saphir.cfg_reg + 5);
265  return (0);
266  }
267 
268  printk(KERN_INFO "HiSax: HST Saphir config irq:%d io:0x%X\n",
269  cs->irq, cs->hw.saphir.cfg_reg);
270 
271  setup_isac(cs);
272  cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
273  cs->hw.saphir.timer.data = (long) cs;
274  init_timer(&cs->hw.saphir.timer);
275  cs->hw.saphir.timer.expires = jiffies + 4 * HZ;
276  add_timer(&cs->hw.saphir.timer);
277  if (saphir_reset(cs)) {
278  release_io_saphir(cs);
279  return (0);
280  }
281  cs->readisac = &ReadISAC;
282  cs->writeisac = &WriteISAC;
283  cs->readisacfifo = &ReadISACfifo;
284  cs->writeisacfifo = &WriteISACfifo;
285  cs->BC_Read_Reg = &ReadHSCX;
286  cs->BC_Write_Reg = &WriteHSCX;
287  cs->BC_Send_Data = &hscx_fill_fifo;
288  cs->cardmsg = &saphir_card_msg;
289  cs->irq_func = &saphir_interrupt;
290  ISACVersion(cs, "saphir:");
291  if (HscxVersion(cs, "saphir:")) {
293  "saphir: wrong HSCX versions check IO address\n");
294  release_io_saphir(cs);
295  return (0);
296  }
297  return (1);
298 }