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/bkm_a4t.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/bkm_a4t.c')
-rw-r--r-- | drivers/isdn/hisax/bkm_a4t.c | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c new file mode 100644 index 000000000000..f410f628a3e2 --- /dev/null +++ b/drivers/isdn/hisax/bkm_a4t.c | |||
@@ -0,0 +1,344 @@ | |||
1 | /* $Id: bkm_a4t.c,v 1.22.2.4 2004/01/14 16:04:48 keil Exp $ | ||
2 | * | ||
3 | * low level stuff for T-Berkom A4T | ||
4 | * | ||
5 | * Author Roland Klabunde | ||
6 | * Copyright by Roland Klabunde <R.Klabunde@Berkom.de> | ||
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 | */ | ||
12 | |||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/init.h> | ||
16 | #include "hisax.h" | ||
17 | #include "isac.h" | ||
18 | #include "hscx.h" | ||
19 | #include "jade.h" | ||
20 | #include "isdnl1.h" | ||
21 | #include <linux/pci.h> | ||
22 | #include "bkm_ax.h" | ||
23 | |||
24 | extern const char *CardType[]; | ||
25 | |||
26 | const char *bkm_a4t_revision = "$Revision: 1.22.2.4 $"; | ||
27 | |||
28 | |||
29 | static inline u_char | ||
30 | readreg(unsigned int ale, unsigned long adr, u_char off) | ||
31 | { | ||
32 | register u_int ret; | ||
33 | unsigned int *po = (unsigned int *) adr; /* Postoffice */ | ||
34 | |||
35 | *po = (GCS_2 | PO_WRITE | off); | ||
36 | __WAITI20__(po); | ||
37 | *po = (ale | PO_READ); | ||
38 | __WAITI20__(po); | ||
39 | ret = *po; | ||
40 | return ((unsigned char) ret); | ||
41 | } | ||
42 | |||
43 | |||
44 | static inline void | ||
45 | readfifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size) | ||
46 | { | ||
47 | int i; | ||
48 | for (i = 0; i < size; i++) | ||
49 | *data++ = readreg(ale, adr, off); | ||
50 | } | ||
51 | |||
52 | |||
53 | static inline void | ||
54 | writereg(unsigned int ale, unsigned long adr, u_char off, u_char data) | ||
55 | { | ||
56 | unsigned int *po = (unsigned int *) adr; /* Postoffice */ | ||
57 | *po = (GCS_2 | PO_WRITE | off); | ||
58 | __WAITI20__(po); | ||
59 | *po = (ale | PO_WRITE | data); | ||
60 | __WAITI20__(po); | ||
61 | } | ||
62 | |||
63 | |||
64 | static inline void | ||
65 | writefifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size) | ||
66 | { | ||
67 | int i; | ||
68 | |||
69 | for (i = 0; i < size; i++) | ||
70 | writereg(ale, adr, off, *data++); | ||
71 | } | ||
72 | |||
73 | |||
74 | /* Interface functions */ | ||
75 | |||
76 | static u_char | ||
77 | ReadISAC(struct IsdnCardState *cs, u_char offset) | ||
78 | { | ||
79 | return (readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset)); | ||
80 | } | ||
81 | |||
82 | static void | ||
83 | WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) | ||
84 | { | ||
85 | writereg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset, value); | ||
86 | } | ||
87 | |||
88 | static void | ||
89 | ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) | ||
90 | { | ||
91 | readfifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size); | ||
92 | } | ||
93 | |||
94 | static void | ||
95 | WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) | ||
96 | { | ||
97 | writefifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size); | ||
98 | } | ||
99 | |||
100 | static u_char | ||
101 | ReadJADE(struct IsdnCardState *cs, int jade, u_char offset) | ||
102 | { | ||
103 | return (readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)))); | ||
104 | } | ||
105 | |||
106 | static void | ||
107 | WriteJADE(struct IsdnCardState *cs, int jade, u_char offset, u_char value) | ||
108 | { | ||
109 | writereg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)), value); | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * fast interrupt JADE stuff goes here | ||
114 | */ | ||
115 | |||
116 | #define READJADE(cs, nr, reg) readreg(cs->hw.ax.jade_ale,\ | ||
117 | cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80))) | ||
118 | #define WRITEJADE(cs, nr, reg, data) writereg(cs->hw.ax.jade_ale,\ | ||
119 | cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), data) | ||
120 | |||
121 | #define READJADEFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.jade_ale,\ | ||
122 | cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt) | ||
123 | #define WRITEJADEFIFO(cs, nr, ptr, cnt) writefifo( cs->hw.ax.jade_ale,\ | ||
124 | cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt) | ||
125 | |||
126 | #include "jade_irq.c" | ||
127 | |||
128 | static irqreturn_t | ||
129 | bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs) | ||
130 | { | ||
131 | struct IsdnCardState *cs = dev_id; | ||
132 | u_char val = 0; | ||
133 | u_long flags; | ||
134 | I20_REGISTER_FILE *pI20_Regs; | ||
135 | |||
136 | spin_lock_irqsave(&cs->lock, flags); | ||
137 | pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); | ||
138 | |||
139 | /* ISDN interrupt pending? */ | ||
140 | if (pI20_Regs->i20IntStatus & intISDN) { | ||
141 | /* Reset the ISDN interrupt */ | ||
142 | pI20_Regs->i20IntStatus = intISDN; | ||
143 | /* Disable ISDN interrupt */ | ||
144 | pI20_Regs->i20IntCtrl &= ~intISDN; | ||
145 | /* Channel A first */ | ||
146 | val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0x80); | ||
147 | if (val) { | ||
148 | jade_int_main(cs, val, 0); | ||
149 | } | ||
150 | /* Channel B */ | ||
151 | val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0xC0); | ||
152 | if (val) { | ||
153 | jade_int_main(cs, val, 1); | ||
154 | } | ||
155 | /* D-Channel */ | ||
156 | val = readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, ISAC_ISTA); | ||
157 | if (val) { | ||
158 | isac_interrupt(cs, val); | ||
159 | } | ||
160 | /* Reenable ISDN interrupt */ | ||
161 | pI20_Regs->i20IntCtrl |= intISDN; | ||
162 | spin_unlock_irqrestore(&cs->lock, flags); | ||
163 | return IRQ_HANDLED; | ||
164 | } else { | ||
165 | spin_unlock_irqrestore(&cs->lock, flags); | ||
166 | return IRQ_NONE; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | void | ||
171 | release_io_bkm(struct IsdnCardState *cs) | ||
172 | { | ||
173 | if (cs->hw.ax.base) { | ||
174 | iounmap((void *) cs->hw.ax.base); | ||
175 | cs->hw.ax.base = 0; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | static void | ||
180 | enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable) | ||
181 | { | ||
182 | if (cs->typ == ISDN_CTYPE_BKM_A4T) { | ||
183 | I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); | ||
184 | if (bEnable) | ||
185 | pI20_Regs->i20IntCtrl |= (intISDN | intPCI); | ||
186 | else | ||
187 | /* CAUTION: This disables the video capture driver too */ | ||
188 | pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI); | ||
189 | } | ||
190 | } | ||
191 | |||
192 | static void | ||
193 | reset_bkm(struct IsdnCardState *cs) | ||
194 | { | ||
195 | if (cs->typ == ISDN_CTYPE_BKM_A4T) { | ||
196 | I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); | ||
197 | /* Issue the I20 soft reset */ | ||
198 | pI20_Regs->i20SysControl = 0xFF; /* all in */ | ||
199 | mdelay(10); | ||
200 | /* Remove the soft reset */ | ||
201 | pI20_Regs->i20SysControl = sysRESET | 0xFF; | ||
202 | mdelay(10); | ||
203 | /* Set our configuration */ | ||
204 | pI20_Regs->i20SysControl = sysRESET | sysCFG; | ||
205 | /* Issue ISDN reset */ | ||
206 | pI20_Regs->i20GuestControl = guestWAIT_CFG | | ||
207 | g_A4T_JADE_RES | | ||
208 | g_A4T_ISAR_RES | | ||
209 | g_A4T_ISAC_RES | | ||
210 | g_A4T_JADE_BOOTR | | ||
211 | g_A4T_ISAR_BOOTR; | ||
212 | mdelay(10); | ||
213 | |||
214 | /* Remove RESET state from ISDN */ | ||
215 | pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES | | ||
216 | g_A4T_JADE_RES | | ||
217 | g_A4T_ISAR_RES); | ||
218 | mdelay(10); | ||
219 | } | ||
220 | } | ||
221 | |||
222 | static int | ||
223 | BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg) | ||
224 | { | ||
225 | u_long flags; | ||
226 | |||
227 | switch (mt) { | ||
228 | case CARD_RESET: | ||
229 | /* Disable ints */ | ||
230 | spin_lock_irqsave(&cs->lock, flags); | ||
231 | enable_bkm_int(cs, 0); | ||
232 | reset_bkm(cs); | ||
233 | spin_unlock_irqrestore(&cs->lock, flags); | ||
234 | return (0); | ||
235 | case CARD_RELEASE: | ||
236 | /* Sanity */ | ||
237 | spin_lock_irqsave(&cs->lock, flags); | ||
238 | enable_bkm_int(cs, 0); | ||
239 | reset_bkm(cs); | ||
240 | spin_unlock_irqrestore(&cs->lock, flags); | ||
241 | release_io_bkm(cs); | ||
242 | return (0); | ||
243 | case CARD_INIT: | ||
244 | spin_lock_irqsave(&cs->lock, flags); | ||
245 | clear_pending_isac_ints(cs); | ||
246 | clear_pending_jade_ints(cs); | ||
247 | initisac(cs); | ||
248 | initjade(cs); | ||
249 | /* Enable ints */ | ||
250 | enable_bkm_int(cs, 1); | ||
251 | spin_unlock_irqrestore(&cs->lock, flags); | ||
252 | return (0); | ||
253 | case CARD_TEST: | ||
254 | return (0); | ||
255 | } | ||
256 | return (0); | ||
257 | } | ||
258 | |||
259 | static struct pci_dev *dev_a4t __initdata = NULL; | ||
260 | |||
261 | int __init | ||
262 | setup_bkm_a4t(struct IsdnCard *card) | ||
263 | { | ||
264 | struct IsdnCardState *cs = card->cs; | ||
265 | char tmp[64]; | ||
266 | u_int pci_memaddr = 0, found = 0; | ||
267 | I20_REGISTER_FILE *pI20_Regs; | ||
268 | #ifdef CONFIG_PCI | ||
269 | #endif | ||
270 | |||
271 | strcpy(tmp, bkm_a4t_revision); | ||
272 | printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp)); | ||
273 | if (cs->typ == ISDN_CTYPE_BKM_A4T) { | ||
274 | cs->subtyp = BKM_A4T; | ||
275 | } else | ||
276 | return (0); | ||
277 | |||
278 | #ifdef CONFIG_PCI | ||
279 | while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN, | ||
280 | PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) { | ||
281 | u16 sub_sys; | ||
282 | u16 sub_vendor; | ||
283 | |||
284 | sub_vendor = dev_a4t->subsystem_vendor; | ||
285 | sub_sys = dev_a4t->subsystem_device; | ||
286 | if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) { | ||
287 | if (pci_enable_device(dev_a4t)) | ||
288 | return(0); | ||
289 | found = 1; | ||
290 | pci_memaddr = pci_resource_start(dev_a4t, 0); | ||
291 | cs->irq = dev_a4t->irq; | ||
292 | break; | ||
293 | } | ||
294 | } | ||
295 | if (!found) { | ||
296 | printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]); | ||
297 | return (0); | ||
298 | } | ||
299 | if (!cs->irq) { /* IRQ range check ?? */ | ||
300 | printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]); | ||
301 | return (0); | ||
302 | } | ||
303 | if (!pci_memaddr) { | ||
304 | printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]); | ||
305 | return (0); | ||
306 | } | ||
307 | cs->hw.ax.base = (long) ioremap(pci_memaddr, 4096); | ||
308 | /* Check suspecious address */ | ||
309 | pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); | ||
310 | if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) { | ||
311 | printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n", | ||
312 | CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096); | ||
313 | iounmap((void *) cs->hw.ax.base); | ||
314 | cs->hw.ax.base = 0; | ||
315 | return (0); | ||
316 | } | ||
317 | cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET; | ||
318 | cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET; | ||
319 | cs->hw.ax.isac_ale = GCS_1; | ||
320 | cs->hw.ax.jade_ale = GCS_3; | ||
321 | #else | ||
322 | printk(KERN_WARNING "HiSax: %s: NO_PCI_BIOS\n", CardType[card->typ]); | ||
323 | printk(KERN_WARNING "HiSax: %s: unable to configure\n", CardType[card->typ]); | ||
324 | return (0); | ||
325 | #endif /* CONFIG_PCI */ | ||
326 | printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n", | ||
327 | CardType[card->typ], cs->hw.ax.base, cs->irq); | ||
328 | |||
329 | setup_isac(cs); | ||
330 | cs->readisac = &ReadISAC; | ||
331 | cs->writeisac = &WriteISAC; | ||
332 | cs->readisacfifo = &ReadISACfifo; | ||
333 | cs->writeisacfifo = &WriteISACfifo; | ||
334 | cs->BC_Read_Reg = &ReadJADE; | ||
335 | cs->BC_Write_Reg = &WriteJADE; | ||
336 | cs->BC_Send_Data = &jade_fill_fifo; | ||
337 | cs->cardmsg = &BKM_card_msg; | ||
338 | cs->irq_func = &bkm_interrupt; | ||
339 | cs->irq_flags |= SA_SHIRQ; | ||
340 | ISACVersion(cs, "Telekom A4T:"); | ||
341 | /* Jade version */ | ||
342 | JadeVersion(cs, "Telekom A4T:"); | ||
343 | return (1); | ||
344 | } | ||