Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* $Id: elsa.c,v 2.32.2.4 2004/01/24 20:47:21 keil Exp $ |
| 2 | * |
| 3 | * low level stuff for Elsa isdn cards |
| 4 | * |
| 5 | * Author Karsten Keil |
| 6 | * Copyright by Karsten Keil <keil@isdn4linux.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 | * For changes and modifications please read |
| 12 | * Documentation/isdn/HiSax.cert |
| 13 | * |
| 14 | * Thanks to Elsa GmbH for documents and information |
| 15 | * |
| 16 | * Klaus Lichtenwalder (Klaus.Lichtenwalder@WebForum.DE) |
| 17 | * for ELSA PCMCIA support |
| 18 | * |
| 19 | */ |
| 20 | |
| 21 | #include <linux/init.h> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 22 | #include "hisax.h" |
| 23 | #include "arcofi.h" |
| 24 | #include "isac.h" |
| 25 | #include "ipac.h" |
| 26 | #include "hscx.h" |
| 27 | #include "isdnl1.h" |
| 28 | #include <linux/pci.h> |
| 29 | #include <linux/isapnp.h> |
| 30 | #include <linux/serial.h> |
| 31 | #include <linux/serial_reg.h> |
| 32 | |
Adrian Bunk | 672c3fd | 2005-06-25 14:59:18 -0700 | [diff] [blame] | 33 | static const char *Elsa_revision = "$Revision: 2.32.2.4 $"; |
| 34 | static const char *Elsa_Types[] = |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 35 | {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro", |
| 36 | "PCMCIA", "QS 1000", "QS 3000", "Microlink PCI", "QS 3000 PCI", |
| 37 | "PCMCIA-IPAC" }; |
| 38 | |
Adrian Bunk | 672c3fd | 2005-06-25 14:59:18 -0700 | [diff] [blame] | 39 | static const char *ITACVer[] = |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 40 | {"?0?", "?1?", "?2?", "?3?", "?4?", "V2.2", |
| 41 | "B1", "A1"}; |
| 42 | |
| 43 | #define byteout(addr,val) outb(val,addr) |
| 44 | #define bytein(addr) inb(addr) |
| 45 | |
| 46 | #define ELSA_ISAC 0 |
| 47 | #define ELSA_ISAC_PCM 1 |
| 48 | #define ELSA_ITAC 1 |
| 49 | #define ELSA_HSCX 2 |
| 50 | #define ELSA_ALE 3 |
| 51 | #define ELSA_ALE_PCM 4 |
| 52 | #define ELSA_CONTROL 4 |
| 53 | #define ELSA_CONFIG 5 |
| 54 | #define ELSA_START_TIMER 6 |
| 55 | #define ELSA_TRIG_IRQ 7 |
| 56 | |
| 57 | #define ELSA_PC 1 |
| 58 | #define ELSA_PCC8 2 |
| 59 | #define ELSA_PCC16 3 |
| 60 | #define ELSA_PCF 4 |
| 61 | #define ELSA_PCFPRO 5 |
| 62 | #define ELSA_PCMCIA 6 |
| 63 | #define ELSA_QS1000 7 |
| 64 | #define ELSA_QS3000 8 |
| 65 | #define ELSA_QS1000PCI 9 |
| 66 | #define ELSA_QS3000PCI 10 |
| 67 | #define ELSA_PCMCIA_IPAC 11 |
| 68 | |
| 69 | /* PCI stuff */ |
| 70 | #define ELSA_PCI_IRQ_MASK 0x04 |
| 71 | |
| 72 | /* ITAC Registeradressen (only Microlink PC) */ |
| 73 | #define ITAC_SYS 0x34 |
| 74 | #define ITAC_ISEN 0x48 |
| 75 | #define ITAC_RFIE 0x4A |
| 76 | #define ITAC_XFIE 0x4C |
| 77 | #define ITAC_SCIE 0x4E |
| 78 | #define ITAC_STIE 0x46 |
| 79 | |
| 80 | /*** *** |
| 81 | *** Makros als Befehle fuer die Kartenregister *** |
| 82 | *** (mehrere Befehle werden durch Bit-Oderung kombiniert) *** |
| 83 | *** ***/ |
| 84 | |
| 85 | /* Config-Register (Read) */ |
Thomas Gleixner | 9ba02be | 2006-07-01 19:29:36 -0700 | [diff] [blame] | 86 | #define ELIRQF_TIMER_RUN 0x02 /* Bit 1 des Config-Reg */ |
| 87 | #define ELIRQF_TIMER_RUN_PCC8 0x01 /* Bit 0 des Config-Reg bei PCC */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 88 | #define ELSA_IRQ_IDX 0x38 /* Bit 3,4,5 des Config-Reg */ |
| 89 | #define ELSA_IRQ_IDX_PCC8 0x30 /* Bit 4,5 des Config-Reg */ |
| 90 | #define ELSA_IRQ_IDX_PC 0x0c /* Bit 2,3 des Config-Reg */ |
| 91 | |
| 92 | /* Control-Register (Write) */ |
| 93 | #define ELSA_LINE_LED 0x02 /* Bit 1 Gelbe LED */ |
| 94 | #define ELSA_STAT_LED 0x08 /* Bit 3 Gruene LED */ |
| 95 | #define ELSA_ISDN_RESET 0x20 /* Bit 5 Reset-Leitung */ |
| 96 | #define ELSA_ENA_TIMER_INT 0x80 /* Bit 7 Freigabe Timer Interrupt */ |
| 97 | |
| 98 | /* ALE-Register (Read) */ |
| 99 | #define ELSA_HW_RELEASE 0x07 /* Bit 0-2 Hardwarerkennung */ |
| 100 | #define ELSA_S0_POWER_BAD 0x08 /* Bit 3 S0-Bus Spannung fehlt */ |
| 101 | |
| 102 | /* Status Flags */ |
Thomas Gleixner | 9ba02be | 2006-07-01 19:29:36 -0700 | [diff] [blame] | 103 | #define ELIRQF_TIMER_AKTIV 1 |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 104 | #define ELSA_BAD_PWR 2 |
| 105 | #define ELSA_ASSIGN 4 |
| 106 | |
| 107 | #define RS_ISR_PASS_LIMIT 256 |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 108 | #define FLG_MODEM_ACTIVE 1 |
| 109 | /* IPAC AUX */ |
| 110 | #define ELSA_IPAC_LINE_LED 0x40 /* Bit 6 Gelbe LED */ |
| 111 | #define ELSA_IPAC_STAT_LED 0x80 /* Bit 7 Gruene LED */ |
| 112 | |
| 113 | #if ARCOFI_USE |
| 114 | static struct arcofi_msg ARCOFI_XOP_F = |
| 115 | {NULL,0,2,{0xa1,0x3f,0,0,0,0,0,0,0,0}}; /* Normal OP */ |
| 116 | static struct arcofi_msg ARCOFI_XOP_1 = |
| 117 | {&ARCOFI_XOP_F,0,2,{0xa1,0x31,0,0,0,0,0,0,0,0}}; /* PWR UP */ |
| 118 | static struct arcofi_msg ARCOFI_SOP_F = |
| 119 | {&ARCOFI_XOP_1,0,10,{0xa1,0x1f,0x00,0x50,0x10,0x00,0x00,0x80,0x02,0x12}}; |
| 120 | static struct arcofi_msg ARCOFI_COP_9 = |
| 121 | {&ARCOFI_SOP_F,0,10,{0xa1,0x29,0x80,0xcb,0xe9,0x88,0x00,0xc8,0xd8,0x80}}; /* RX */ |
| 122 | static struct arcofi_msg ARCOFI_COP_8 = |
| 123 | {&ARCOFI_COP_9,0,10,{0xa1,0x28,0x49,0x31,0x8,0x13,0x6e,0x88,0x2a,0x61}}; /* TX */ |
| 124 | static struct arcofi_msg ARCOFI_COP_7 = |
| 125 | {&ARCOFI_COP_8,0,4,{0xa1,0x27,0x80,0x80,0,0,0,0,0,0}}; /* GZ */ |
| 126 | static struct arcofi_msg ARCOFI_COP_6 = |
| 127 | {&ARCOFI_COP_7,0,6,{0xa1,0x26,0,0,0x82,0x7c,0,0,0,0}}; /* GRL GRH */ |
| 128 | static struct arcofi_msg ARCOFI_COP_5 = |
| 129 | {&ARCOFI_COP_6,0,4,{0xa1,0x25,0xbb,0x4a,0,0,0,0,0,0}}; /* GTX */ |
| 130 | static struct arcofi_msg ARCOFI_VERSION = |
| 131 | {NULL,1,2,{0xa0,0,0,0,0,0,0,0,0,0}}; |
| 132 | static struct arcofi_msg ARCOFI_XOP_0 = |
| 133 | {NULL,0,2,{0xa1,0x30,0,0,0,0,0,0,0,0}}; /* PWR Down */ |
| 134 | |
| 135 | static void set_arcofi(struct IsdnCardState *cs, int bc); |
| 136 | |
| 137 | #include "elsa_ser.c" |
| 138 | #endif /* ARCOFI_USE */ |
| 139 | |
| 140 | static inline u_char |
| 141 | readreg(unsigned int ale, unsigned int adr, u_char off) |
| 142 | { |
| 143 | register u_char ret; |
| 144 | |
| 145 | byteout(ale, off); |
| 146 | ret = bytein(adr); |
| 147 | return (ret); |
| 148 | } |
| 149 | |
| 150 | static inline void |
| 151 | readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) |
| 152 | { |
| 153 | byteout(ale, off); |
| 154 | insb(adr, data, size); |
| 155 | } |
| 156 | |
| 157 | |
| 158 | static inline void |
| 159 | writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) |
| 160 | { |
| 161 | byteout(ale, off); |
| 162 | byteout(adr, data); |
| 163 | } |
| 164 | |
| 165 | static inline void |
| 166 | writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) |
| 167 | { |
| 168 | byteout(ale, off); |
| 169 | outsb(adr, data, size); |
| 170 | } |
| 171 | |
| 172 | /* Interface functions */ |
| 173 | |
| 174 | static u_char |
| 175 | ReadISAC(struct IsdnCardState *cs, u_char offset) |
| 176 | { |
| 177 | return (readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset)); |
| 178 | } |
| 179 | |
| 180 | static void |
| 181 | WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) |
| 182 | { |
| 183 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset, value); |
| 184 | } |
| 185 | |
| 186 | static void |
| 187 | ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) |
| 188 | { |
| 189 | readfifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0, data, size); |
| 190 | } |
| 191 | |
| 192 | static void |
| 193 | WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) |
| 194 | { |
| 195 | writefifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0, data, size); |
| 196 | } |
| 197 | |
| 198 | static u_char |
| 199 | ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) |
| 200 | { |
| 201 | return (readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset+0x80)); |
| 202 | } |
| 203 | |
| 204 | static void |
| 205 | WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) |
| 206 | { |
| 207 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset|0x80, value); |
| 208 | } |
| 209 | |
| 210 | static void |
| 211 | ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) |
| 212 | { |
| 213 | readfifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0x80, data, size); |
| 214 | } |
| 215 | |
| 216 | static void |
| 217 | WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) |
| 218 | { |
| 219 | writefifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0x80, data, size); |
| 220 | } |
| 221 | |
| 222 | static u_char |
| 223 | ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) |
| 224 | { |
| 225 | return (readreg(cs->hw.elsa.ale, |
| 226 | cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0))); |
| 227 | } |
| 228 | |
| 229 | static void |
| 230 | WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) |
| 231 | { |
| 232 | writereg(cs->hw.elsa.ale, |
| 233 | cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0), value); |
| 234 | } |
| 235 | |
| 236 | static inline u_char |
| 237 | readitac(struct IsdnCardState *cs, u_char off) |
| 238 | { |
| 239 | register u_char ret; |
| 240 | |
| 241 | byteout(cs->hw.elsa.ale, off); |
| 242 | ret = bytein(cs->hw.elsa.itac); |
| 243 | return (ret); |
| 244 | } |
| 245 | |
| 246 | static inline void |
| 247 | writeitac(struct IsdnCardState *cs, u_char off, u_char data) |
| 248 | { |
| 249 | byteout(cs->hw.elsa.ale, off); |
| 250 | byteout(cs->hw.elsa.itac, data); |
| 251 | } |
| 252 | |
| 253 | static inline int |
| 254 | TimerRun(struct IsdnCardState *cs) |
| 255 | { |
| 256 | register u_char v; |
| 257 | |
| 258 | v = bytein(cs->hw.elsa.cfg); |
| 259 | if ((cs->subtyp == ELSA_QS1000) || (cs->subtyp == ELSA_QS3000)) |
Thomas Gleixner | 9ba02be | 2006-07-01 19:29:36 -0700 | [diff] [blame] | 260 | return (0 == (v & ELIRQF_TIMER_RUN)); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 261 | else if (cs->subtyp == ELSA_PCC8) |
Thomas Gleixner | 9ba02be | 2006-07-01 19:29:36 -0700 | [diff] [blame] | 262 | return (v & ELIRQF_TIMER_RUN_PCC8); |
| 263 | return (v & ELIRQF_TIMER_RUN); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 264 | } |
| 265 | /* |
| 266 | * fast interrupt HSCX stuff goes here |
| 267 | */ |
| 268 | |
| 269 | #define READHSCX(cs, nr, reg) readreg(cs->hw.elsa.ale, \ |
| 270 | cs->hw.elsa.hscx, reg + (nr ? 0x40 : 0)) |
| 271 | #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.elsa.ale, \ |
| 272 | cs->hw.elsa.hscx, reg + (nr ? 0x40 : 0), data) |
| 273 | |
| 274 | #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.elsa.ale, \ |
| 275 | cs->hw.elsa.hscx, (nr ? 0x40 : 0), ptr, cnt) |
| 276 | |
| 277 | #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.elsa.ale, \ |
| 278 | cs->hw.elsa.hscx, (nr ? 0x40 : 0), ptr, cnt) |
| 279 | |
| 280 | #include "hscx_irq.c" |
| 281 | |
| 282 | static irqreturn_t |
David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 283 | elsa_interrupt(int intno, void *dev_id) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 284 | { |
| 285 | struct IsdnCardState *cs = dev_id; |
| 286 | u_long flags; |
| 287 | u_char val; |
| 288 | int icnt=5; |
| 289 | |
| 290 | if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) { |
| 291 | /* The card tends to generate interrupts while being removed |
| 292 | causing us to just crash the kernel. bad. */ |
| 293 | printk(KERN_WARNING "Elsa: card not available!\n"); |
| 294 | return IRQ_NONE; |
| 295 | } |
| 296 | spin_lock_irqsave(&cs->lock, flags); |
| 297 | #if ARCOFI_USE |
| 298 | if (cs->hw.elsa.MFlag) { |
| 299 | val = serial_inp(cs, UART_IIR); |
| 300 | if (!(val & UART_IIR_NO_INT)) { |
| 301 | debugl1(cs,"IIR %02x", val); |
Jeff Garzik | 896c6fa | 2007-10-31 05:42:50 -0400 | [diff] [blame] | 302 | rs_interrupt_elsa(cs); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 303 | } |
| 304 | } |
| 305 | #endif |
| 306 | val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40); |
| 307 | Start_HSCX: |
| 308 | if (val) { |
| 309 | hscx_int_main(cs, val); |
| 310 | } |
| 311 | val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA); |
| 312 | Start_ISAC: |
| 313 | if (val) { |
| 314 | isac_interrupt(cs, val); |
| 315 | } |
| 316 | val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40); |
| 317 | if (val && icnt) { |
| 318 | if (cs->debug & L1_DEB_HSCX) |
| 319 | debugl1(cs, "HSCX IntStat after IntRoutine"); |
| 320 | icnt--; |
| 321 | goto Start_HSCX; |
| 322 | } |
| 323 | val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA); |
| 324 | if (val && icnt) { |
| 325 | if (cs->debug & L1_DEB_ISAC) |
| 326 | debugl1(cs, "ISAC IntStat after IntRoutine"); |
| 327 | icnt--; |
| 328 | goto Start_ISAC; |
| 329 | } |
| 330 | if (!icnt) |
| 331 | printk(KERN_WARNING"ELSA IRQ LOOP\n"); |
| 332 | writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0xFF); |
| 333 | writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0xFF); |
| 334 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0xFF); |
Thomas Gleixner | 9ba02be | 2006-07-01 19:29:36 -0700 | [diff] [blame] | 335 | if (cs->hw.elsa.status & ELIRQF_TIMER_AKTIV) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 336 | if (!TimerRun(cs)) { |
| 337 | /* Timer Restart */ |
| 338 | byteout(cs->hw.elsa.timer, 0); |
| 339 | cs->hw.elsa.counter++; |
| 340 | } |
| 341 | } |
| 342 | #if ARCOFI_USE |
| 343 | if (cs->hw.elsa.MFlag) { |
| 344 | val = serial_inp(cs, UART_MCR); |
| 345 | val ^= 0x8; |
| 346 | serial_outp(cs, UART_MCR, val); |
| 347 | val = serial_inp(cs, UART_MCR); |
| 348 | val ^= 0x8; |
| 349 | serial_outp(cs, UART_MCR, val); |
| 350 | } |
| 351 | #endif |
| 352 | if (cs->hw.elsa.trig) |
| 353 | byteout(cs->hw.elsa.trig, 0x00); |
| 354 | writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0x0); |
| 355 | writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0x0); |
| 356 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0x0); |
| 357 | spin_unlock_irqrestore(&cs->lock, flags); |
| 358 | return IRQ_HANDLED; |
| 359 | } |
| 360 | |
| 361 | static irqreturn_t |
David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 362 | elsa_interrupt_ipac(int intno, void *dev_id) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 363 | { |
| 364 | struct IsdnCardState *cs = dev_id; |
| 365 | u_long flags; |
| 366 | u_char ista,val; |
| 367 | int icnt=5; |
| 368 | |
| 369 | spin_lock_irqsave(&cs->lock, flags); |
| 370 | if (cs->subtyp == ELSA_QS1000PCI || cs->subtyp == ELSA_QS3000PCI) { |
| 371 | val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */ |
| 372 | if (!(val & ELSA_PCI_IRQ_MASK)) { |
| 373 | spin_unlock_irqrestore(&cs->lock, flags); |
| 374 | return IRQ_NONE; |
| 375 | } |
| 376 | } |
| 377 | #if ARCOFI_USE |
| 378 | if (cs->hw.elsa.MFlag) { |
| 379 | val = serial_inp(cs, UART_IIR); |
| 380 | if (!(val & UART_IIR_NO_INT)) { |
| 381 | debugl1(cs,"IIR %02x", val); |
Jeff Garzik | 896c6fa | 2007-10-31 05:42:50 -0400 | [diff] [blame] | 382 | rs_interrupt_elsa(cs); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 383 | } |
| 384 | } |
| 385 | #endif |
| 386 | ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA); |
| 387 | Start_IPAC: |
| 388 | if (cs->debug & L1_DEB_IPAC) |
| 389 | debugl1(cs, "IPAC ISTA %02X", ista); |
| 390 | if (ista & 0x0f) { |
| 391 | val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40); |
| 392 | if (ista & 0x01) |
| 393 | val |= 0x01; |
| 394 | if (ista & 0x04) |
| 395 | val |= 0x02; |
| 396 | if (ista & 0x08) |
| 397 | val |= 0x04; |
| 398 | if (val) |
| 399 | hscx_int_main(cs, val); |
| 400 | } |
| 401 | if (ista & 0x20) { |
| 402 | val = 0xfe & readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA + 0x80); |
| 403 | if (val) { |
| 404 | isac_interrupt(cs, val); |
| 405 | } |
| 406 | } |
| 407 | if (ista & 0x10) { |
| 408 | val = 0x01; |
| 409 | isac_interrupt(cs, val); |
| 410 | } |
| 411 | ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA); |
| 412 | if ((ista & 0x3f) && icnt) { |
| 413 | icnt--; |
| 414 | goto Start_IPAC; |
| 415 | } |
| 416 | if (!icnt) |
| 417 | printk(KERN_WARNING "ELSA IRQ LOOP\n"); |
| 418 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xFF); |
| 419 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xC0); |
| 420 | spin_unlock_irqrestore(&cs->lock, flags); |
| 421 | return IRQ_HANDLED; |
| 422 | } |
| 423 | |
Adrian Bunk | 672c3fd | 2005-06-25 14:59:18 -0700 | [diff] [blame] | 424 | static void |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 425 | release_io_elsa(struct IsdnCardState *cs) |
| 426 | { |
| 427 | int bytecnt = 8; |
| 428 | |
| 429 | del_timer(&cs->hw.elsa.tl); |
| 430 | #if ARCOFI_USE |
| 431 | clear_arcofi(cs); |
| 432 | #endif |
| 433 | if (cs->hw.elsa.ctrl) |
| 434 | byteout(cs->hw.elsa.ctrl, 0); /* LEDs Out */ |
| 435 | if (cs->subtyp == ELSA_QS1000PCI) { |
| 436 | byteout(cs->hw.elsa.cfg + 0x4c, 0x01); /* disable IRQ */ |
| 437 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); |
| 438 | bytecnt = 2; |
| 439 | release_region(cs->hw.elsa.cfg, 0x80); |
| 440 | } |
| 441 | if (cs->subtyp == ELSA_QS3000PCI) { |
| 442 | byteout(cs->hw.elsa.cfg + 0x4c, 0x03); /* disable ELSA PCI IRQ */ |
| 443 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); |
| 444 | release_region(cs->hw.elsa.cfg, 0x80); |
| 445 | } |
| 446 | if (cs->subtyp == ELSA_PCMCIA_IPAC) { |
| 447 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); |
| 448 | } |
| 449 | if ((cs->subtyp == ELSA_PCFPRO) || |
| 450 | (cs->subtyp == ELSA_QS3000) || |
| 451 | (cs->subtyp == ELSA_PCF) || |
| 452 | (cs->subtyp == ELSA_QS3000PCI)) { |
| 453 | bytecnt = 16; |
| 454 | #if ARCOFI_USE |
| 455 | release_modem(cs); |
| 456 | #endif |
| 457 | } |
| 458 | if (cs->hw.elsa.base) |
| 459 | release_region(cs->hw.elsa.base, bytecnt); |
| 460 | } |
| 461 | |
| 462 | static void |
| 463 | reset_elsa(struct IsdnCardState *cs) |
| 464 | { |
| 465 | if (cs->hw.elsa.timer) { |
| 466 | /* Wait 1 Timer */ |
| 467 | byteout(cs->hw.elsa.timer, 0); |
| 468 | while (TimerRun(cs)); |
| 469 | cs->hw.elsa.ctrl_reg |= 0x50; |
| 470 | cs->hw.elsa.ctrl_reg &= ~ELSA_ISDN_RESET; /* Reset On */ |
| 471 | byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); |
| 472 | /* Wait 1 Timer */ |
| 473 | byteout(cs->hw.elsa.timer, 0); |
| 474 | while (TimerRun(cs)); |
| 475 | cs->hw.elsa.ctrl_reg |= ELSA_ISDN_RESET; /* Reset Off */ |
| 476 | byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); |
| 477 | /* Wait 1 Timer */ |
| 478 | byteout(cs->hw.elsa.timer, 0); |
| 479 | while (TimerRun(cs)); |
| 480 | if (cs->hw.elsa.trig) |
| 481 | byteout(cs->hw.elsa.trig, 0xff); |
| 482 | } |
| 483 | if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) { |
| 484 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20); |
| 485 | mdelay(10); |
| 486 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00); |
| 487 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0); |
| 488 | mdelay(10); |
| 489 | if (cs->subtyp != ELSA_PCMCIA_IPAC) { |
| 490 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x0); |
| 491 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0x3c); |
| 492 | } else { |
| 493 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_PCFG, 0x10); |
| 494 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x4); |
| 495 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0xf8); |
| 496 | } |
| 497 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); |
| 498 | if (cs->subtyp == ELSA_QS1000PCI) |
| 499 | byteout(cs->hw.elsa.cfg + 0x4c, 0x41); /* enable ELSA PCI IRQ */ |
| 500 | else if (cs->subtyp == ELSA_QS3000PCI) |
| 501 | byteout(cs->hw.elsa.cfg + 0x4c, 0x43); /* enable ELSA PCI IRQ */ |
| 502 | } |
| 503 | } |
| 504 | |
| 505 | #if ARCOFI_USE |
| 506 | |
| 507 | static void |
| 508 | set_arcofi(struct IsdnCardState *cs, int bc) { |
| 509 | cs->dc.isac.arcofi_bc = bc; |
| 510 | arcofi_fsm(cs, ARCOFI_START, &ARCOFI_COP_5); |
| 511 | interruptible_sleep_on(&cs->dc.isac.arcofi_wait); |
| 512 | } |
| 513 | |
| 514 | static int |
| 515 | check_arcofi(struct IsdnCardState *cs) |
| 516 | { |
| 517 | int arcofi_present = 0; |
| 518 | char tmp[40]; |
| 519 | char *t; |
| 520 | u_char *p; |
| 521 | |
| 522 | if (!cs->dc.isac.mon_tx) |
| 523 | if (!(cs->dc.isac.mon_tx=kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { |
| 524 | if (cs->debug & L1_DEB_WARN) |
| 525 | debugl1(cs, "ISAC MON TX out of buffers!"); |
| 526 | return(0); |
| 527 | } |
| 528 | cs->dc.isac.arcofi_bc = 0; |
| 529 | arcofi_fsm(cs, ARCOFI_START, &ARCOFI_VERSION); |
| 530 | interruptible_sleep_on(&cs->dc.isac.arcofi_wait); |
| 531 | if (!test_and_clear_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags)) { |
| 532 | debugl1(cs, "Arcofi response received %d bytes", cs->dc.isac.mon_rxp); |
| 533 | p = cs->dc.isac.mon_rx; |
| 534 | t = tmp; |
| 535 | t += sprintf(tmp, "Arcofi data"); |
| 536 | QuickHex(t, p, cs->dc.isac.mon_rxp); |
| 537 | debugl1(cs, tmp); |
| 538 | if ((cs->dc.isac.mon_rxp == 2) && (cs->dc.isac.mon_rx[0] == 0xa0)) { |
| 539 | switch(cs->dc.isac.mon_rx[1]) { |
| 540 | case 0x80: |
| 541 | debugl1(cs, "Arcofi 2160 detected"); |
| 542 | arcofi_present = 1; |
| 543 | break; |
| 544 | case 0x82: |
| 545 | debugl1(cs, "Arcofi 2165 detected"); |
| 546 | arcofi_present = 2; |
| 547 | break; |
| 548 | case 0x84: |
| 549 | debugl1(cs, "Arcofi 2163 detected"); |
| 550 | arcofi_present = 3; |
| 551 | break; |
| 552 | default: |
| 553 | debugl1(cs, "unknown Arcofi response"); |
| 554 | break; |
| 555 | } |
| 556 | } else |
| 557 | debugl1(cs, "undefined Monitor response"); |
| 558 | cs->dc.isac.mon_rxp = 0; |
| 559 | } else if (cs->dc.isac.mon_tx) { |
| 560 | debugl1(cs, "Arcofi not detected"); |
| 561 | } |
| 562 | if (arcofi_present) { |
| 563 | if (cs->subtyp==ELSA_QS1000) { |
| 564 | cs->subtyp = ELSA_QS3000; |
| 565 | printk(KERN_INFO |
| 566 | "Elsa: %s detected modem at 0x%lx\n", |
| 567 | Elsa_Types[cs->subtyp], |
| 568 | cs->hw.elsa.base+8); |
| 569 | release_region(cs->hw.elsa.base, 8); |
| 570 | if (!request_region(cs->hw.elsa.base, 16, "elsa isdn modem")) { |
| 571 | printk(KERN_WARNING |
| 572 | "HiSax: %s config port %lx-%lx already in use\n", |
| 573 | Elsa_Types[cs->subtyp], |
| 574 | cs->hw.elsa.base + 8, |
| 575 | cs->hw.elsa.base + 16); |
| 576 | } |
| 577 | } else if (cs->subtyp==ELSA_PCC16) { |
| 578 | cs->subtyp = ELSA_PCF; |
| 579 | printk(KERN_INFO |
| 580 | "Elsa: %s detected modem at 0x%lx\n", |
| 581 | Elsa_Types[cs->subtyp], |
| 582 | cs->hw.elsa.base+8); |
| 583 | release_region(cs->hw.elsa.base, 8); |
| 584 | if (!request_region(cs->hw.elsa.base, 16, "elsa isdn modem")) { |
| 585 | printk(KERN_WARNING |
| 586 | "HiSax: %s config port %lx-%lx already in use\n", |
| 587 | Elsa_Types[cs->subtyp], |
| 588 | cs->hw.elsa.base + 8, |
| 589 | cs->hw.elsa.base + 16); |
| 590 | } |
| 591 | } else |
| 592 | printk(KERN_INFO |
| 593 | "Elsa: %s detected modem at 0x%lx\n", |
| 594 | Elsa_Types[cs->subtyp], |
| 595 | cs->hw.elsa.base+8); |
| 596 | arcofi_fsm(cs, ARCOFI_START, &ARCOFI_XOP_0); |
| 597 | interruptible_sleep_on(&cs->dc.isac.arcofi_wait); |
| 598 | return(1); |
| 599 | } |
| 600 | return(0); |
| 601 | } |
| 602 | #endif /* ARCOFI_USE */ |
| 603 | |
| 604 | static void |
| 605 | elsa_led_handler(struct IsdnCardState *cs) |
| 606 | { |
| 607 | int blink = 0; |
| 608 | |
| 609 | if (cs->subtyp == ELSA_PCMCIA || cs->subtyp == ELSA_PCMCIA_IPAC) |
| 610 | return; |
| 611 | del_timer(&cs->hw.elsa.tl); |
| 612 | if (cs->hw.elsa.status & ELSA_ASSIGN) |
| 613 | cs->hw.elsa.ctrl_reg |= ELSA_STAT_LED; |
| 614 | else if (cs->hw.elsa.status & ELSA_BAD_PWR) |
| 615 | cs->hw.elsa.ctrl_reg &= ~ELSA_STAT_LED; |
| 616 | else { |
| 617 | cs->hw.elsa.ctrl_reg ^= ELSA_STAT_LED; |
| 618 | blink = 250; |
| 619 | } |
| 620 | if (cs->hw.elsa.status & 0xf000) |
| 621 | cs->hw.elsa.ctrl_reg |= ELSA_LINE_LED; |
| 622 | else if (cs->hw.elsa.status & 0x0f00) { |
| 623 | cs->hw.elsa.ctrl_reg ^= ELSA_LINE_LED; |
| 624 | blink = 500; |
| 625 | } else |
| 626 | cs->hw.elsa.ctrl_reg &= ~ELSA_LINE_LED; |
| 627 | |
| 628 | if ((cs->subtyp == ELSA_QS1000PCI) || |
| 629 | (cs->subtyp == ELSA_QS3000PCI)) { |
| 630 | u_char led = 0xff; |
| 631 | if (cs->hw.elsa.ctrl_reg & ELSA_LINE_LED) |
| 632 | led ^= ELSA_IPAC_LINE_LED; |
| 633 | if (cs->hw.elsa.ctrl_reg & ELSA_STAT_LED) |
| 634 | led ^= ELSA_IPAC_STAT_LED; |
| 635 | writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, led); |
| 636 | } else |
| 637 | byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); |
| 638 | if (blink) { |
| 639 | init_timer(&cs->hw.elsa.tl); |
| 640 | cs->hw.elsa.tl.expires = jiffies + ((blink * HZ) / 1000); |
| 641 | add_timer(&cs->hw.elsa.tl); |
| 642 | } |
| 643 | } |
| 644 | |
| 645 | static int |
| 646 | Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg) |
| 647 | { |
| 648 | int ret = 0; |
| 649 | u_long flags; |
| 650 | |
| 651 | switch (mt) { |
| 652 | case CARD_RESET: |
| 653 | spin_lock_irqsave(&cs->lock, flags); |
| 654 | reset_elsa(cs); |
| 655 | spin_unlock_irqrestore(&cs->lock, flags); |
| 656 | return(0); |
| 657 | case CARD_RELEASE: |
| 658 | release_io_elsa(cs); |
| 659 | return(0); |
| 660 | case CARD_INIT: |
| 661 | spin_lock_irqsave(&cs->lock, flags); |
| 662 | cs->debug |= L1_DEB_IPAC; |
| 663 | reset_elsa(cs); |
| 664 | inithscxisac(cs, 1); |
| 665 | if ((cs->subtyp == ELSA_QS1000) || |
| 666 | (cs->subtyp == ELSA_QS3000)) |
| 667 | { |
| 668 | byteout(cs->hw.elsa.timer, 0); |
| 669 | } |
| 670 | if (cs->hw.elsa.trig) |
| 671 | byteout(cs->hw.elsa.trig, 0xff); |
| 672 | inithscxisac(cs, 2); |
| 673 | spin_unlock_irqrestore(&cs->lock, flags); |
| 674 | return(0); |
| 675 | case CARD_TEST: |
| 676 | if ((cs->subtyp == ELSA_PCMCIA) || |
| 677 | (cs->subtyp == ELSA_PCMCIA_IPAC) || |
| 678 | (cs->subtyp == ELSA_QS1000PCI)) { |
| 679 | return(0); |
| 680 | } else if (cs->subtyp == ELSA_QS3000PCI) { |
| 681 | ret = 0; |
| 682 | } else { |
| 683 | spin_lock_irqsave(&cs->lock, flags); |
| 684 | cs->hw.elsa.counter = 0; |
| 685 | cs->hw.elsa.ctrl_reg |= ELSA_ENA_TIMER_INT; |
Thomas Gleixner | 9ba02be | 2006-07-01 19:29:36 -0700 | [diff] [blame] | 686 | cs->hw.elsa.status |= ELIRQF_TIMER_AKTIV; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 687 | byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); |
| 688 | byteout(cs->hw.elsa.timer, 0); |
| 689 | spin_unlock_irqrestore(&cs->lock, flags); |
| 690 | msleep(110); |
| 691 | spin_lock_irqsave(&cs->lock, flags); |
| 692 | cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT; |
| 693 | byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); |
Thomas Gleixner | 9ba02be | 2006-07-01 19:29:36 -0700 | [diff] [blame] | 694 | cs->hw.elsa.status &= ~ELIRQF_TIMER_AKTIV; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 695 | spin_unlock_irqrestore(&cs->lock, flags); |
| 696 | printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n", |
| 697 | cs->hw.elsa.counter); |
| 698 | if ((cs->hw.elsa.counter > 10) && |
| 699 | (cs->hw.elsa.counter < 16)) { |
| 700 | printk(KERN_INFO "Elsa: timer and irq OK\n"); |
| 701 | ret = 0; |
| 702 | } else { |
| 703 | printk(KERN_WARNING |
| 704 | "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n", |
| 705 | cs->hw.elsa.counter, cs->irq); |
| 706 | ret = 1; |
| 707 | } |
| 708 | } |
| 709 | #if ARCOFI_USE |
| 710 | if (check_arcofi(cs)) { |
| 711 | init_modem(cs); |
| 712 | } |
| 713 | #endif |
| 714 | elsa_led_handler(cs); |
| 715 | return(ret); |
| 716 | case (MDL_REMOVE | REQUEST): |
| 717 | cs->hw.elsa.status &= 0; |
| 718 | break; |
| 719 | case (MDL_ASSIGN | REQUEST): |
| 720 | cs->hw.elsa.status |= ELSA_ASSIGN; |
| 721 | break; |
| 722 | case MDL_INFO_SETUP: |
| 723 | if ((long) arg) |
| 724 | cs->hw.elsa.status |= 0x0200; |
| 725 | else |
| 726 | cs->hw.elsa.status |= 0x0100; |
| 727 | break; |
| 728 | case MDL_INFO_CONN: |
| 729 | if ((long) arg) |
| 730 | cs->hw.elsa.status |= 0x2000; |
| 731 | else |
| 732 | cs->hw.elsa.status |= 0x1000; |
| 733 | break; |
| 734 | case MDL_INFO_REL: |
| 735 | if ((long) arg) { |
| 736 | cs->hw.elsa.status &= ~0x2000; |
| 737 | cs->hw.elsa.status &= ~0x0200; |
| 738 | } else { |
| 739 | cs->hw.elsa.status &= ~0x1000; |
| 740 | cs->hw.elsa.status &= ~0x0100; |
| 741 | } |
| 742 | break; |
| 743 | #if ARCOFI_USE |
| 744 | case CARD_AUX_IND: |
| 745 | if (cs->hw.elsa.MFlag) { |
| 746 | int len; |
| 747 | u_char *msg; |
| 748 | |
| 749 | if (!arg) |
| 750 | return(0); |
| 751 | msg = arg; |
| 752 | len = *msg; |
| 753 | msg++; |
| 754 | modem_write_cmd(cs, msg, len); |
| 755 | } |
| 756 | break; |
| 757 | #endif |
| 758 | } |
| 759 | if (cs->typ == ISDN_CTYPE_ELSA) { |
| 760 | int pwr = bytein(cs->hw.elsa.ale); |
| 761 | if (pwr & 0x08) |
| 762 | cs->hw.elsa.status |= ELSA_BAD_PWR; |
| 763 | else |
| 764 | cs->hw.elsa.status &= ~ELSA_BAD_PWR; |
| 765 | } |
| 766 | elsa_led_handler(cs); |
| 767 | return(ret); |
| 768 | } |
| 769 | |
| 770 | static unsigned char |
| 771 | probe_elsa_adr(unsigned int adr, int typ) |
| 772 | { |
| 773 | int i, in1, in2, p16_1 = 0, p16_2 = 0, p8_1 = 0, p8_2 = 0, pc_1 = 0, |
| 774 | pc_2 = 0, pfp_1 = 0, pfp_2 = 0; |
| 775 | |
| 776 | /* In case of the elsa pcmcia card, this region is in use, |
| 777 | reserved for us by the card manager. So we do not check it |
| 778 | here, it would fail. */ |
| 779 | if (typ != ISDN_CTYPE_ELSA_PCMCIA) { |
| 780 | if (request_region(adr, 8, "elsa card")) { |
| 781 | release_region(adr, 8); |
| 782 | } else { |
| 783 | printk(KERN_WARNING |
| 784 | "Elsa: Probing Port 0x%x: already in use\n", adr); |
| 785 | return (0); |
| 786 | } |
| 787 | } |
| 788 | for (i = 0; i < 16; i++) { |
| 789 | in1 = inb(adr + ELSA_CONFIG); /* 'toggelt' bei */ |
| 790 | in2 = inb(adr + ELSA_CONFIG); /* jedem Zugriff */ |
| 791 | p16_1 += 0x04 & in1; |
| 792 | p16_2 += 0x04 & in2; |
| 793 | p8_1 += 0x02 & in1; |
| 794 | p8_2 += 0x02 & in2; |
| 795 | pc_1 += 0x01 & in1; |
| 796 | pc_2 += 0x01 & in2; |
| 797 | pfp_1 += 0x40 & in1; |
| 798 | pfp_2 += 0x40 & in2; |
| 799 | } |
| 800 | printk(KERN_INFO "Elsa: Probing IO 0x%x", adr); |
| 801 | if (65 == ++p16_1 * ++p16_2) { |
| 802 | printk(" PCC-16/PCF found\n"); |
| 803 | return (ELSA_PCC16); |
| 804 | } else if (1025 == ++pfp_1 * ++pfp_2) { |
| 805 | printk(" PCF-Pro found\n"); |
| 806 | return (ELSA_PCFPRO); |
| 807 | } else if (33 == ++p8_1 * ++p8_2) { |
| 808 | printk(" PCC8 found\n"); |
| 809 | return (ELSA_PCC8); |
| 810 | } else if (17 == ++pc_1 * ++pc_2) { |
| 811 | printk(" PC found\n"); |
| 812 | return (ELSA_PC); |
| 813 | } else { |
| 814 | printk(" failed\n"); |
| 815 | return (0); |
| 816 | } |
| 817 | } |
| 818 | |
| 819 | static unsigned int |
| 820 | probe_elsa(struct IsdnCardState *cs) |
| 821 | { |
| 822 | int i; |
| 823 | unsigned int CARD_portlist[] = |
| 824 | {0x160, 0x170, 0x260, 0x360, 0}; |
| 825 | |
| 826 | for (i = 0; CARD_portlist[i]; i++) { |
| 827 | if ((cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ))) |
| 828 | break; |
| 829 | } |
| 830 | return (CARD_portlist[i]); |
| 831 | } |
| 832 | |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 833 | static int __devinit |
| 834 | setup_elsa_isa(struct IsdnCard *card) |
| 835 | { |
| 836 | struct IsdnCardState *cs = card->cs; |
| 837 | u_char val; |
| 838 | |
| 839 | cs->hw.elsa.base = card->para[0]; |
| 840 | printk(KERN_INFO "Elsa: Microlink IO probing\n"); |
| 841 | if (cs->hw.elsa.base) { |
| 842 | if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, |
| 843 | cs->typ))) { |
| 844 | printk(KERN_WARNING |
| 845 | "Elsa: no Elsa Microlink at %#lx\n", |
| 846 | cs->hw.elsa.base); |
| 847 | return (0); |
| 848 | } |
| 849 | } else |
| 850 | cs->hw.elsa.base = probe_elsa(cs); |
| 851 | |
| 852 | if (!cs->hw.elsa.base) { |
| 853 | printk(KERN_WARNING |
| 854 | "No Elsa Microlink found\n"); |
| 855 | return (0); |
| 856 | } |
| 857 | |
| 858 | cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; |
| 859 | cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; |
| 860 | cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; |
| 861 | cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; |
| 862 | cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC; |
| 863 | cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; |
| 864 | cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; |
| 865 | cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; |
| 866 | val = bytein(cs->hw.elsa.cfg); |
| 867 | if (cs->subtyp == ELSA_PC) { |
| 868 | const u_char CARD_IrqTab[8] = |
| 869 | {7, 3, 5, 9, 0, 0, 0, 0}; |
| 870 | cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2]; |
| 871 | } else if (cs->subtyp == ELSA_PCC8) { |
| 872 | const u_char CARD_IrqTab[8] = |
| 873 | {7, 3, 5, 9, 0, 0, 0, 0}; |
| 874 | cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4]; |
| 875 | } else { |
| 876 | const u_char CARD_IrqTab[8] = |
| 877 | {15, 10, 15, 3, 11, 5, 11, 9}; |
| 878 | cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3]; |
| 879 | } |
| 880 | val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE; |
| 881 | if (val < 3) |
| 882 | val |= 8; |
| 883 | val += 'A' - 3; |
| 884 | if (val == 'B' || val == 'C') |
| 885 | val ^= 1; |
Roel Kluin | df59ebc | 2007-11-05 14:50:51 -0800 | [diff] [blame] | 886 | if ((cs->subtyp == ELSA_PCFPRO) && (val == 'G')) |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 887 | val = 'C'; |
| 888 | printk(KERN_INFO |
| 889 | "Elsa: %s found at %#lx Rev.:%c IRQ %d\n", |
| 890 | Elsa_Types[cs->subtyp], |
| 891 | cs->hw.elsa.base, |
| 892 | val, cs->irq); |
| 893 | val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD; |
| 894 | if (val) { |
| 895 | printk(KERN_WARNING |
| 896 | "Elsa: Microlink S0 bus power bad\n"); |
| 897 | cs->hw.elsa.status |= ELSA_BAD_PWR; |
| 898 | } |
| 899 | |
| 900 | return (1); |
| 901 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 902 | |
| 903 | #ifdef __ISAPNP__ |
| 904 | static struct isapnp_device_id elsa_ids[] __devinitdata = { |
| 905 | { ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0133), |
| 906 | ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0133), |
| 907 | (unsigned long) "Elsa QS1000" }, |
| 908 | { ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0134), |
| 909 | ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0134), |
| 910 | (unsigned long) "Elsa QS3000" }, |
| 911 | { 0, } |
| 912 | }; |
| 913 | |
| 914 | static struct isapnp_device_id *ipid __devinitdata = &elsa_ids[0]; |
| 915 | static struct pnp_card *pnp_c __devinitdata = NULL; |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 916 | #endif /* __ISAPNP__ */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 917 | |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 918 | static int __devinit |
| 919 | setup_elsa_isapnp(struct IsdnCard *card) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 920 | { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 921 | struct IsdnCardState *cs = card->cs; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 922 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 923 | #ifdef __ISAPNP__ |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 924 | if (!card->para[1] && isapnp_present()) { |
| 925 | struct pnp_dev *pnp_d; |
| 926 | while(ipid->card_vendor) { |
| 927 | if ((pnp_c = pnp_find_card(ipid->card_vendor, |
| 928 | ipid->card_device, pnp_c))) { |
| 929 | pnp_d = NULL; |
| 930 | if ((pnp_d = pnp_find_dev(pnp_c, |
| 931 | ipid->vendor, ipid->function, pnp_d))) { |
| 932 | int err; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 933 | |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 934 | printk(KERN_INFO "HiSax: %s detected\n", |
| 935 | (char *)ipid->driver_data); |
| 936 | pnp_disable_dev(pnp_d); |
| 937 | err = pnp_activate_dev(pnp_d); |
| 938 | if (err<0) { |
| 939 | printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", |
Harvey Harrison | 156f1ed | 2008-04-28 02:14:40 -0700 | [diff] [blame] | 940 | __func__, err); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 941 | return(0); |
| 942 | } |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 943 | card->para[1] = pnp_port_start(pnp_d, 0); |
| 944 | card->para[0] = pnp_irq(pnp_d, 0); |
| 945 | |
| 946 | if (!card->para[0] || !card->para[1]) { |
| 947 | printk(KERN_ERR "Elsa PnP:some resources are missing %ld/%lx\n", |
| 948 | card->para[0], card->para[1]); |
| 949 | pnp_disable_dev(pnp_d); |
| 950 | return(0); |
| 951 | } |
| 952 | if (ipid->function == ISAPNP_FUNCTION(0x133)) |
| 953 | cs->subtyp = ELSA_QS1000; |
| 954 | else |
| 955 | cs->subtyp = ELSA_QS3000; |
| 956 | break; |
| 957 | } else { |
| 958 | printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n"); |
| 959 | return(0); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 960 | } |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 961 | } |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 962 | ipid++; |
| 963 | pnp_c=NULL; |
| 964 | } |
| 965 | if (!ipid->card_vendor) { |
| 966 | printk(KERN_INFO "Elsa PnP: no ISAPnP card found\n"); |
| 967 | return(0); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 968 | } |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 969 | } |
| 970 | #endif /* __ISAPNP__ */ |
| 971 | |
| 972 | if (card->para[1] && card->para[0]) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 973 | cs->hw.elsa.base = card->para[1]; |
| 974 | cs->irq = card->para[0]; |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 975 | if (!cs->subtyp) |
| 976 | cs->subtyp = ELSA_QS1000; |
| 977 | } else { |
| 978 | printk(KERN_ERR "Elsa PnP: no parameter\n"); |
| 979 | } |
| 980 | cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; |
| 981 | cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; |
| 982 | cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; |
| 983 | cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; |
| 984 | cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; |
| 985 | cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; |
| 986 | cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; |
| 987 | printk(KERN_INFO |
| 988 | "Elsa: %s defined at %#lx IRQ %d\n", |
| 989 | Elsa_Types[cs->subtyp], |
| 990 | cs->hw.elsa.base, |
| 991 | cs->irq); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 992 | |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 993 | return (1); |
| 994 | } |
| 995 | |
| 996 | static void __devinit |
| 997 | setup_elsa_pcmcia(struct IsdnCard *card) |
| 998 | { |
| 999 | struct IsdnCardState *cs = card->cs; |
| 1000 | u_char val; |
| 1001 | |
| 1002 | cs->hw.elsa.base = card->para[1]; |
| 1003 | cs->irq = card->para[0]; |
| 1004 | val = readreg(cs->hw.elsa.base + 0, cs->hw.elsa.base + 2, IPAC_ID); |
| 1005 | if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */ |
| 1006 | cs->subtyp = ELSA_PCMCIA_IPAC; |
| 1007 | cs->hw.elsa.ale = cs->hw.elsa.base + 0; |
| 1008 | cs->hw.elsa.isac = cs->hw.elsa.base + 2; |
| 1009 | cs->hw.elsa.hscx = cs->hw.elsa.base + 2; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1010 | test_and_set_bit(HW_IPAC, &cs->HW_Flags); |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 1011 | } else { |
| 1012 | cs->subtyp = ELSA_PCMCIA; |
| 1013 | cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM; |
| 1014 | cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM; |
| 1015 | cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; |
| 1016 | } |
| 1017 | cs->hw.elsa.timer = 0; |
| 1018 | cs->hw.elsa.trig = 0; |
| 1019 | cs->hw.elsa.ctrl = 0; |
| 1020 | cs->irq_flags |= IRQF_SHARED; |
| 1021 | printk(KERN_INFO |
| 1022 | "Elsa: %s defined at %#lx IRQ %d\n", |
| 1023 | Elsa_Types[cs->subtyp], |
| 1024 | cs->hw.elsa.base, |
| 1025 | cs->irq); |
| 1026 | } |
| 1027 | |
Jeff Garzik | bd3989e | 2007-10-29 09:48:09 -0400 | [diff] [blame] | 1028 | #ifdef CONFIG_PCI_LEGACY |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 1029 | static struct pci_dev *dev_qs1000 __devinitdata = NULL; |
| 1030 | static struct pci_dev *dev_qs3000 __devinitdata = NULL; |
| 1031 | |
| 1032 | static int __devinit |
| 1033 | setup_elsa_pci(struct IsdnCard *card) |
| 1034 | { |
| 1035 | struct IsdnCardState *cs = card->cs; |
| 1036 | |
| 1037 | cs->subtyp = 0; |
| 1038 | if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, |
| 1039 | PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { |
| 1040 | if (pci_enable_device(dev_qs1000)) |
| 1041 | return(0); |
| 1042 | cs->subtyp = ELSA_QS1000PCI; |
| 1043 | cs->irq = dev_qs1000->irq; |
| 1044 | cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1); |
| 1045 | cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3); |
| 1046 | } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA, |
| 1047 | PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) { |
| 1048 | if (pci_enable_device(dev_qs3000)) |
| 1049 | return(0); |
| 1050 | cs->subtyp = ELSA_QS3000PCI; |
| 1051 | cs->irq = dev_qs3000->irq; |
| 1052 | cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1); |
| 1053 | cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3); |
| 1054 | } else { |
| 1055 | printk(KERN_WARNING "Elsa: No PCI card found\n"); |
| 1056 | return(0); |
| 1057 | } |
| 1058 | if (!cs->irq) { |
| 1059 | printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n"); |
| 1060 | return(0); |
| 1061 | } |
| 1062 | |
| 1063 | if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) { |
| 1064 | printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n"); |
| 1065 | return(0); |
| 1066 | } |
| 1067 | if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) { |
| 1068 | printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n"); |
| 1069 | printk(KERN_WARNING "Elsa: If your system hangs now, read\n"); |
| 1070 | printk(KERN_WARNING "Elsa: Documentation/isdn/README.HiSax\n"); |
| 1071 | } |
| 1072 | cs->hw.elsa.ale = cs->hw.elsa.base; |
| 1073 | cs->hw.elsa.isac = cs->hw.elsa.base +1; |
| 1074 | cs->hw.elsa.hscx = cs->hw.elsa.base +1; |
| 1075 | test_and_set_bit(HW_IPAC, &cs->HW_Flags); |
| 1076 | cs->hw.elsa.timer = 0; |
| 1077 | cs->hw.elsa.trig = 0; |
| 1078 | cs->irq_flags |= IRQF_SHARED; |
| 1079 | printk(KERN_INFO |
| 1080 | "Elsa: %s defined at %#lx/0x%x IRQ %d\n", |
| 1081 | Elsa_Types[cs->subtyp], |
| 1082 | cs->hw.elsa.base, |
| 1083 | cs->hw.elsa.cfg, |
| 1084 | cs->irq); |
| 1085 | |
| 1086 | return (1); |
| 1087 | } |
| 1088 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1089 | #else |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 1090 | |
Al Viro | cc11942 | 2007-10-13 19:42:42 +0100 | [diff] [blame] | 1091 | static int __devinit |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 1092 | setup_elsa_pci(struct IsdnCard *card) |
| 1093 | { |
| 1094 | return (1); |
| 1095 | } |
Jeff Garzik | bd3989e | 2007-10-29 09:48:09 -0400 | [diff] [blame] | 1096 | #endif /* CONFIG_PCI_LEGACY */ |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 1097 | |
| 1098 | static int __devinit |
| 1099 | setup_elsa_common(struct IsdnCard *card) |
| 1100 | { |
| 1101 | struct IsdnCardState *cs = card->cs; |
| 1102 | u_char val; |
| 1103 | int bytecnt; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1104 | |
| 1105 | switch (cs->subtyp) { |
| 1106 | case ELSA_PC: |
| 1107 | case ELSA_PCC8: |
| 1108 | case ELSA_PCC16: |
| 1109 | case ELSA_QS1000: |
| 1110 | case ELSA_PCMCIA: |
| 1111 | case ELSA_PCMCIA_IPAC: |
| 1112 | bytecnt = 8; |
| 1113 | break; |
| 1114 | case ELSA_PCFPRO: |
| 1115 | case ELSA_PCF: |
| 1116 | case ELSA_QS3000: |
| 1117 | case ELSA_QS3000PCI: |
| 1118 | bytecnt = 16; |
| 1119 | break; |
| 1120 | case ELSA_QS1000PCI: |
| 1121 | bytecnt = 2; |
| 1122 | break; |
| 1123 | default: |
| 1124 | printk(KERN_WARNING |
| 1125 | "Unknown ELSA subtype %d\n", cs->subtyp); |
| 1126 | return (0); |
| 1127 | } |
| 1128 | /* In case of the elsa pcmcia card, this region is in use, |
| 1129 | reserved for us by the card manager. So we do not check it |
| 1130 | here, it would fail. */ |
| 1131 | if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(cs->hw.elsa.base, bytecnt, "elsa isdn")) { |
| 1132 | printk(KERN_WARNING |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 1133 | "HiSax: ELSA config port %#lx-%#lx already in use\n", |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1134 | cs->hw.elsa.base, |
| 1135 | cs->hw.elsa.base + bytecnt); |
| 1136 | return (0); |
| 1137 | } |
| 1138 | if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) { |
| 1139 | if (!request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) { |
| 1140 | printk(KERN_WARNING |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 1141 | "HiSax: ELSA pci port %x-%x already in use\n", |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1142 | cs->hw.elsa.cfg, |
| 1143 | cs->hw.elsa.cfg + 0x80); |
| 1144 | release_region(cs->hw.elsa.base, bytecnt); |
| 1145 | return (0); |
| 1146 | } |
| 1147 | } |
| 1148 | #if ARCOFI_USE |
| 1149 | init_arcofi(cs); |
| 1150 | #endif |
| 1151 | setup_isac(cs); |
| 1152 | cs->hw.elsa.tl.function = (void *) elsa_led_handler; |
| 1153 | cs->hw.elsa.tl.data = (long) cs; |
| 1154 | init_timer(&cs->hw.elsa.tl); |
| 1155 | /* Teste Timer */ |
| 1156 | if (cs->hw.elsa.timer) { |
| 1157 | byteout(cs->hw.elsa.trig, 0xff); |
| 1158 | byteout(cs->hw.elsa.timer, 0); |
| 1159 | if (!TimerRun(cs)) { |
| 1160 | byteout(cs->hw.elsa.timer, 0); /* 2. Versuch */ |
| 1161 | if (!TimerRun(cs)) { |
| 1162 | printk(KERN_WARNING |
| 1163 | "Elsa: timer do not start\n"); |
| 1164 | release_io_elsa(cs); |
| 1165 | return (0); |
| 1166 | } |
| 1167 | } |
| 1168 | HZDELAY((HZ/100) + 1); /* wait >=10 ms */ |
| 1169 | if (TimerRun(cs)) { |
| 1170 | printk(KERN_WARNING "Elsa: timer do not run down\n"); |
| 1171 | release_io_elsa(cs); |
| 1172 | return (0); |
| 1173 | } |
| 1174 | printk(KERN_INFO "Elsa: timer OK; resetting card\n"); |
| 1175 | } |
| 1176 | cs->BC_Read_Reg = &ReadHSCX; |
| 1177 | cs->BC_Write_Reg = &WriteHSCX; |
| 1178 | cs->BC_Send_Data = &hscx_fill_fifo; |
| 1179 | cs->cardmsg = &Elsa_card_msg; |
| 1180 | if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) { |
| 1181 | cs->readisac = &ReadISAC_IPAC; |
| 1182 | cs->writeisac = &WriteISAC_IPAC; |
| 1183 | cs->readisacfifo = &ReadISACfifo_IPAC; |
| 1184 | cs->writeisacfifo = &WriteISACfifo_IPAC; |
| 1185 | cs->irq_func = &elsa_interrupt_ipac; |
| 1186 | val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ID); |
| 1187 | printk(KERN_INFO "Elsa: IPAC version %x\n", val); |
| 1188 | } else { |
| 1189 | cs->readisac = &ReadISAC; |
| 1190 | cs->writeisac = &WriteISAC; |
| 1191 | cs->readisacfifo = &ReadISACfifo; |
| 1192 | cs->writeisacfifo = &WriteISACfifo; |
| 1193 | cs->irq_func = &elsa_interrupt; |
| 1194 | ISACVersion(cs, "Elsa:"); |
| 1195 | if (HscxVersion(cs, "Elsa:")) { |
| 1196 | printk(KERN_WARNING |
| 1197 | "Elsa: wrong HSCX versions check IO address\n"); |
| 1198 | release_io_elsa(cs); |
| 1199 | return (0); |
| 1200 | } |
| 1201 | } |
| 1202 | if (cs->subtyp == ELSA_PC) { |
| 1203 | val = readitac(cs, ITAC_SYS); |
| 1204 | printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]); |
| 1205 | writeitac(cs, ITAC_ISEN, 0); |
| 1206 | writeitac(cs, ITAC_RFIE, 0); |
| 1207 | writeitac(cs, ITAC_XFIE, 0); |
| 1208 | writeitac(cs, ITAC_SCIE, 0); |
| 1209 | writeitac(cs, ITAC_STIE, 0); |
| 1210 | } |
| 1211 | return (1); |
| 1212 | } |
Jeff Garzik | 1e5d82e | 2007-10-03 15:27:22 -0400 | [diff] [blame] | 1213 | |
| 1214 | int __devinit |
| 1215 | setup_elsa(struct IsdnCard *card) |
| 1216 | { |
| 1217 | int rc; |
| 1218 | struct IsdnCardState *cs = card->cs; |
| 1219 | char tmp[64]; |
| 1220 | |
| 1221 | strcpy(tmp, Elsa_revision); |
| 1222 | printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp)); |
| 1223 | cs->hw.elsa.ctrl_reg = 0; |
| 1224 | cs->hw.elsa.status = 0; |
| 1225 | cs->hw.elsa.MFlag = 0; |
| 1226 | cs->subtyp = 0; |
| 1227 | |
| 1228 | if (cs->typ == ISDN_CTYPE_ELSA) { |
| 1229 | rc = setup_elsa_isa(card); |
| 1230 | if (!rc) |
| 1231 | return (0); |
| 1232 | |
| 1233 | } else if (cs->typ == ISDN_CTYPE_ELSA_PNP) { |
| 1234 | rc = setup_elsa_isapnp(card); |
| 1235 | if (!rc) |
| 1236 | return (0); |
| 1237 | |
| 1238 | } else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) |
| 1239 | setup_elsa_pcmcia(card); |
| 1240 | |
| 1241 | else if (cs->typ == ISDN_CTYPE_ELSA_PCI) { |
| 1242 | rc = setup_elsa_pci(card); |
| 1243 | if (!rc) |
| 1244 | return (0); |
| 1245 | |
| 1246 | } else |
| 1247 | return (0); |
| 1248 | |
| 1249 | return setup_elsa_common(card); |
| 1250 | } |