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