1/* $Id: diva.c,v 1.33.2.6 2004/02/11 13:21:33 Exp $ 2 * 3 * low level stuff for Eicon.Diehl Diva Family 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 Eicon Technology for documents and information 15 * 16 */ 17 18#include <linux/init.h> 19#include "hisax.h" 20#include "isac.h" 21#include "hscx.h" 22#include "ipac.h" 23#include "ipacx.h" 24#include "isdnl1.h" 25#include <linux/pci.h> 26#include <linux/isapnp.h> 27 28static const char *Diva_revision = "$Revision: 1.33.2.6 $"; 29 30#define byteout(addr,val) outb(val,addr) 31#define bytein(addr) inb(addr) 32 33#define DIVA_HSCX_DATA 0 34#define DIVA_HSCX_ADR 4 35#define DIVA_ISA_ISAC_DATA 2 36#define DIVA_ISA_ISAC_ADR 6 37#define DIVA_ISA_CTRL 7 38#define DIVA_IPAC_ADR 0 39#define DIVA_IPAC_DATA 1 40 41#define DIVA_PCI_ISAC_DATA 8 42#define DIVA_PCI_ISAC_ADR 0xc 43#define DIVA_PCI_CTRL 0x10 44 45/* SUB Types */ 46#define DIVA_ISA 1 47#define DIVA_PCI 2 48#define DIVA_IPAC_ISA 3 49#define DIVA_IPAC_PCI 4 50#define DIVA_IPACX_PCI 5 51 52/* CTRL (Read) */ 53#define DIVA_IRQ_STAT 0x01 54#define DIVA_EEPROM_SDA 0x02 55 56/* CTRL (Write) */ 57#define DIVA_IRQ_REQ 0x01 58#define DIVA_RESET 0x08 59#define DIVA_EEPROM_CLK 0x40 60#define DIVA_PCI_LED_A 0x10 61#define DIVA_PCI_LED_B 0x20 62#define DIVA_ISA_LED_A 0x20 63#define DIVA_ISA_LED_B 0x40 64#define DIVA_IRQ_CLR 0x80 65 66/* Siemens PITA */ 67#define PITA_MISC_REG 0x1c 68#ifdef __BIG_ENDIAN 69#define PITA_PARA_SOFTRESET 0x00000001 70#define PITA_SER_SOFTRESET 0x00000002 71#define PITA_PARA_MPX_MODE 0x00000004 72#define PITA_INT0_ENABLE 0x00000200 73#else 74#define PITA_PARA_SOFTRESET 0x01000000 75#define PITA_SER_SOFTRESET 0x02000000 76#define PITA_PARA_MPX_MODE 0x04000000 77#define PITA_INT0_ENABLE 0x00020000 78#endif 79#define PITA_INT0_STATUS 0x02 80 81static inline u_char 82readreg(unsigned int ale, unsigned int adr, u_char off) 83{ 84 register u_char ret; 85 86 byteout(ale, off); 87 ret = bytein(adr); 88 return (ret); 89} 90 91static inline void 92readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) 93{ 94 byteout(ale, off); 95 insb(adr, data, size); 96} 97 98 99static inline void 100writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) 101{ 102 byteout(ale, off); 103 byteout(adr, data); 104} 105 106static inline void 107writefifo(unsigned int ale, unsigned int adr, u_char off, u_char *data, int size) 108{ 109 byteout(ale, off); 110 outsb(adr, data, size); 111} 112 113static inline u_char 114memreadreg(unsigned long adr, u_char off) 115{ 116 return(*((unsigned char *) 117 (((unsigned int *)adr) + off))); 118} 119 120static inline void 121memwritereg(unsigned long adr, u_char off, u_char data) 122{ 123 register u_char *p; 124 125 p = (unsigned char *)(((unsigned int *)adr) + off); 126 *p = data; 127} 128 129/* Interface functions */ 130 131static u_char 132ReadISAC(struct IsdnCardState *cs, u_char offset) 133{ 134 return(readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset)); 135} 136 137static void 138WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) 139{ 140 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, value); 141} 142 143static void 144ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size) 145{ 146 readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size); 147} 148 149static void 150WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size) 151{ 152 writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size); 153} 154 155static u_char 156ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) 157{ 158 return (readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset+0x80)); 159} 160 161static void 162WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) 163{ 164 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset|0x80, value); 165} 166 167static void 168ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) 169{ 170 readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size); 171} 172 173static void 174WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) 175{ 176 writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size); 177} 178 179static u_char 180ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) 181{ 182 return(readreg(cs->hw.diva.hscx_adr, 183 cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0))); 184} 185 186static void 187WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) 188{ 189 writereg(cs->hw.diva.hscx_adr, 190 cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0), value); 191} 192 193static u_char 194MemReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) 195{ 196 return (memreadreg(cs->hw.diva.cfg_reg, offset+0x80)); 197} 198 199static void 200MemWriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) 201{ 202 memwritereg(cs->hw.diva.cfg_reg, offset|0x80, value); 203} 204 205static void 206MemReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) 207{ 208 while(size--) 209 *data++ = memreadreg(cs->hw.diva.cfg_reg, 0x80); 210} 211 212static void 213MemWriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) 214{ 215 while(size--) 216 memwritereg(cs->hw.diva.cfg_reg, 0x80, *data++); 217} 218 219static u_char 220MemReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) 221{ 222 return(memreadreg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0))); 223} 224 225static void 226MemWriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) 227{ 228 memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value); 229} 230 231/* IO-Functions for IPACX type cards */ 232static u_char 233MemReadISAC_IPACX(struct IsdnCardState *cs, u_char offset) 234{ 235 return (memreadreg(cs->hw.diva.cfg_reg, offset)); 236} 237 238static void 239MemWriteISAC_IPACX(struct IsdnCardState *cs, u_char offset, u_char value) 240{ 241 memwritereg(cs->hw.diva.cfg_reg, offset, value); 242} 243 244static void 245MemReadISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size) 246{ 247 while(size--) 248 *data++ = memreadreg(cs->hw.diva.cfg_reg, 0); 249} 250 251static void 252MemWriteISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size) 253{ 254 while(size--) 255 memwritereg(cs->hw.diva.cfg_reg, 0, *data++); 256} 257 258static u_char 259MemReadHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset) 260{ 261 return(memreadreg(cs->hw.diva.cfg_reg, offset + 262 (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1))); 263} 264 265static void 266MemWriteHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) 267{ 268 memwritereg(cs->hw.diva.cfg_reg, offset + 269 (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1), value); 270} 271 272/* 273 * fast interrupt HSCX stuff goes here 274 */ 275 276#define READHSCX(cs, nr, reg) readreg(cs->hw.diva.hscx_adr, \ 277 cs->hw.diva.hscx, reg + (nr ? 0x40 : 0)) 278#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.diva.hscx_adr, \ 279 cs->hw.diva.hscx, reg + (nr ? 0x40 : 0), data) 280 281#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.diva.hscx_adr, \ 282 cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt) 283 284#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.diva.hscx_adr, \ 285 cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt) 286 287#include "hscx_irq.c" 288 289static irqreturn_t 290diva_interrupt(int intno, void *dev_id) 291{ 292 struct IsdnCardState *cs = dev_id; 293 u_char val, sval; 294 u_long flags; 295 int cnt=5; 296 297 spin_lock_irqsave(&cs->lock, flags); 298 while (((sval = bytein(cs->hw.diva.ctrl)) & DIVA_IRQ_REQ) && cnt) { 299 val = readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_ISTA + 0x40); 300 if (val) 301 hscx_int_main(cs, val); 302 val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA); 303 if (val) 304 isac_interrupt(cs, val); 305 cnt--; 306 } 307 if (!cnt) 308 printk(KERN_WARNING "Diva: IRQ LOOP\n"); 309 writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0xFF); 310 writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0xFF); 311 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0xFF); 312 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0); 313 writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0); 314 writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0); 315 spin_unlock_irqrestore(&cs->lock, flags); 316 return IRQ_HANDLED; 317} 318 319static irqreturn_t 320diva_irq_ipac_isa(int intno, void *dev_id) 321{ 322 struct IsdnCardState *cs = dev_id; 323 u_char ista,val; 324 u_long flags; 325 int icnt=5; 326 327 spin_lock_irqsave(&cs->lock, flags); 328 ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA); 329Start_IPACISA: 330 if (cs->debug & L1_DEB_IPAC) 331 debugl1(cs, "IPAC ISTA %02X", ista); 332 if (ista & 0x0f) { 333 val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, HSCX_ISTA + 0x40); 334 if (ista & 0x01) 335 val |= 0x01; 336 if (ista & 0x04) 337 val |= 0x02; 338 if (ista & 0x08) 339 val |= 0x04; 340 if (val) 341 hscx_int_main(cs, val); 342 } 343 if (ista & 0x20) { 344 val = 0xfe & readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA + 0x80); 345 if (val) { 346 isac_interrupt(cs, val); 347 } 348 } 349 if (ista & 0x10) { 350 val = 0x01; 351 isac_interrupt(cs, val); 352 } 353 ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA); 354 if ((ista & 0x3f) && icnt) { 355 icnt--; 356 goto Start_IPACISA; 357 } 358 if (!icnt) 359 printk(KERN_WARNING "DIVA IPAC IRQ LOOP\n"); 360 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xFF); 361 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xC0); 362 spin_unlock_irqrestore(&cs->lock, flags); 363 return IRQ_HANDLED; 364} 365 366static inline void 367MemwaitforCEC(struct IsdnCardState *cs, int hscx) 368{ 369 int to = 50; 370 371 while ((MemReadHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) { 372 udelay(1); 373 to--; 374 } 375 if (!to) 376 printk(KERN_WARNING "HiSax: waitforCEC timeout\n"); 377} 378 379 380static inline void 381MemwaitforXFW(struct IsdnCardState *cs, int hscx) 382{ 383 int to = 50; 384 385 while (((MemReadHSCX(cs, hscx, HSCX_STAR) & 0x44) != 0x40) && to) { 386 udelay(1); 387 to--; 388 } 389 if (!to) 390 printk(KERN_WARNING "HiSax: waitforXFW timeout\n"); 391} 392 393static inline void 394MemWriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data) 395{ 396 MemwaitforCEC(cs, hscx); 397 MemWriteHSCX(cs, hscx, HSCX_CMDR, data); 398} 399 400static void 401Memhscx_empty_fifo(struct BCState *bcs, int count) 402{ 403 u_char *ptr; 404 struct IsdnCardState *cs = bcs->cs; 405 int cnt; 406 407 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) 408 debugl1(cs, "hscx_empty_fifo"); 409 410 if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { 411 if (cs->debug & L1_DEB_WARN) 412 debugl1(cs, "hscx_empty_fifo: incoming packet too large"); 413 MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); 414 bcs->hw.hscx.rcvidx = 0; 415 return; 416 } 417 ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; 418 cnt = count; 419 while (cnt--) 420 *ptr++ = memreadreg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0); 421 MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); 422 ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; 423 bcs->hw.hscx.rcvidx += count; 424 if (cs->debug & L1_DEB_HSCX_FIFO) { 425 char *t = bcs->blog; 426 427 t += sprintf(t, "hscx_empty_fifo %c cnt %d", 428 bcs->hw.hscx.hscx ? 'B' : 'A', count); 429 QuickHex(t, ptr, count); 430 debugl1(cs, bcs->blog); 431 } 432} 433 434static void 435Memhscx_fill_fifo(struct BCState *bcs) 436{ 437 struct IsdnCardState *cs = bcs->cs; 438 int more, count, cnt; 439 int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; 440 u_char *ptr,*p; 441 442 if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) 443 debugl1(cs, "hscx_fill_fifo"); 444 445 if (!bcs->tx_skb) 446 return; 447 if (bcs->tx_skb->len <= 0) 448 return; 449 450 more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; 451 if (bcs->tx_skb->len > fifo_size) { 452 more = !0; 453 count = fifo_size; 454 } else 455 count = bcs->tx_skb->len; 456 cnt = count; 457 MemwaitforXFW(cs, bcs->hw.hscx.hscx); 458 p = ptr = bcs->tx_skb->data; 459 skb_pull(bcs->tx_skb, count); 460 bcs->tx_cnt -= count; 461 bcs->hw.hscx.count += count; 462 while(cnt--) 463 memwritereg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0, 464 *p++); 465 MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa); 466 if (cs->debug & L1_DEB_HSCX_FIFO) { 467 char *t = bcs->blog; 468 469 t += sprintf(t, "hscx_fill_fifo %c cnt %d", 470 bcs->hw.hscx.hscx ? 'B' : 'A', count); 471 QuickHex(t, ptr, count); 472 debugl1(cs, bcs->blog); 473 } 474} 475 476static void 477Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) 478{ 479 u_char r; 480 struct BCState *bcs = cs->bcs + hscx; 481 struct sk_buff *skb; 482 int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; 483 int count; 484 485 if (!test_bit(BC_FLG_INIT, &bcs->Flag)) 486 return; 487 488 if (val & 0x80) { /* RME */ 489 r = MemReadHSCX(cs, hscx, HSCX_RSTA); 490 if ((r & 0xf0) != 0xa0) { 491 if (!(r & 0x80)) 492 if (cs->debug & L1_DEB_WARN) 493 debugl1(cs, "HSCX invalid frame"); 494 if ((r & 0x40) && bcs->mode) 495 if (cs->debug & L1_DEB_WARN) 496 debugl1(cs, "HSCX RDO mode=%d", 497 bcs->mode); 498 if (!(r & 0x20)) 499 if (cs->debug & L1_DEB_WARN) 500 debugl1(cs, "HSCX CRC error"); 501 MemWriteHSCXCMDR(cs, hscx, 0x80); 502 } else { 503 count = MemReadHSCX(cs, hscx, HSCX_RBCL) & ( 504 test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f); 505 if (count == 0) 506 count = fifo_size; 507 Memhscx_empty_fifo(bcs, count); 508 if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { 509 if (cs->debug & L1_DEB_HSCX_FIFO) 510 debugl1(cs, "HX Frame %d", count); 511 if (!(skb = dev_alloc_skb(count))) 512 printk(KERN_WARNING "HSCX: receive out of memory\n"); 513 else { 514 memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); 515 skb_queue_tail(&bcs->rqueue, skb); 516 } 517 } 518 } 519 bcs->hw.hscx.rcvidx = 0; 520 schedule_event(bcs, B_RCVBUFREADY); 521 } 522 if (val & 0x40) { /* RPF */ 523 Memhscx_empty_fifo(bcs, fifo_size); 524 if (bcs->mode == L1_MODE_TRANS) { 525 /* receive audio data */ 526 if (!(skb = dev_alloc_skb(fifo_size))) 527 printk(KERN_WARNING "HiSax: receive out of memory\n"); 528 else { 529 memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); 530 skb_queue_tail(&bcs->rqueue, skb); 531 } 532 bcs->hw.hscx.rcvidx = 0; 533 schedule_event(bcs, B_RCVBUFREADY); 534 } 535 } 536 if (val & 0x10) { /* XPR */ 537 if (bcs->tx_skb) { 538 if (bcs->tx_skb->len) { 539 Memhscx_fill_fifo(bcs); 540 return; 541 } else { 542 if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && 543 (PACKET_NOACK != bcs->tx_skb->pkt_type)) { 544 u_long flags; 545 spin_lock_irqsave(&bcs->aclock, flags); 546 bcs->ackcnt += bcs->hw.hscx.count; 547 spin_unlock_irqrestore(&bcs->aclock, flags); 548 schedule_event(bcs, B_ACKPENDING); 549 } 550 dev_kfree_skb_irq(bcs->tx_skb); 551 bcs->hw.hscx.count = 0; 552 bcs->tx_skb = NULL; 553 } 554 } 555 if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { 556 bcs->hw.hscx.count = 0; 557 test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); 558 Memhscx_fill_fifo(bcs); 559 } else { 560 test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); 561 schedule_event(bcs, B_XMTBUFREADY); 562 } 563 } 564} 565 566static inline void 567Memhscx_int_main(struct IsdnCardState *cs, u_char val) 568{ 569 570 u_char exval; 571 struct BCState *bcs; 572 573 if (val & 0x01) { // EXB 574 bcs = cs->bcs + 1; 575 exval = MemReadHSCX(cs, 1, HSCX_EXIR); 576 if (exval & 0x40) { 577 if (bcs->mode == 1) 578 Memhscx_fill_fifo(bcs); 579 else { 580 /* Here we lost an TX interrupt, so 581 * restart transmitting the whole frame. 582 */ 583 if (bcs->tx_skb) { 584 skb_push(bcs->tx_skb, bcs->hw.hscx.count); 585 bcs->tx_cnt += bcs->hw.hscx.count; 586 bcs->hw.hscx.count = 0; 587 } 588 MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); 589 if (cs->debug & L1_DEB_WARN) 590 debugl1(cs, "HSCX B EXIR %x Lost TX", exval); 591 } 592 } else if (cs->debug & L1_DEB_HSCX) 593 debugl1(cs, "HSCX B EXIR %x", exval); 594 } 595 if (val & 0xf8) { 596 if (cs->debug & L1_DEB_HSCX) 597 debugl1(cs, "HSCX B interrupt %x", val); 598 Memhscx_interrupt(cs, val, 1); 599 } 600 if (val & 0x02) { // EXA 601 bcs = cs->bcs; 602 exval = MemReadHSCX(cs, 0, HSCX_EXIR); 603 if (exval & 0x40) { 604 if (bcs->mode == L1_MODE_TRANS) 605 Memhscx_fill_fifo(bcs); 606 else { 607 /* Here we lost an TX interrupt, so 608 * restart transmitting the whole frame. 609 */ 610 if (bcs->tx_skb) { 611 skb_push(bcs->tx_skb, bcs->hw.hscx.count); 612 bcs->tx_cnt += bcs->hw.hscx.count; 613 bcs->hw.hscx.count = 0; 614 } 615 MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); 616 if (cs->debug & L1_DEB_WARN) 617 debugl1(cs, "HSCX A EXIR %x Lost TX", exval); 618 } 619 } else if (cs->debug & L1_DEB_HSCX) 620 debugl1(cs, "HSCX A EXIR %x", exval); 621 } 622 if (val & 0x04) { // ICA 623 exval = MemReadHSCX(cs, 0, HSCX_ISTA); 624 if (cs->debug & L1_DEB_HSCX) 625 debugl1(cs, "HSCX A interrupt %x", exval); 626 Memhscx_interrupt(cs, exval, 0); 627 } 628} 629 630static irqreturn_t 631diva_irq_ipac_pci(int intno, void *dev_id) 632{ 633 struct IsdnCardState *cs = dev_id; 634 u_char ista,val; 635 int icnt=5; 636 u_char *cfg; 637 u_long flags; 638 639 spin_lock_irqsave(&cs->lock, flags); 640 cfg = (u_char *) cs->hw.diva.pci_cfg; 641 val = *cfg; 642 if (!(val & PITA_INT0_STATUS)) { 643 spin_unlock_irqrestore(&cs->lock, flags); 644 return IRQ_NONE; /* other shared IRQ */ 645 } 646 *cfg = PITA_INT0_STATUS; /* Reset pending INT0 */ 647 ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA); 648Start_IPACPCI: 649 if (cs->debug & L1_DEB_IPAC) 650 debugl1(cs, "IPAC ISTA %02X", ista); 651 if (ista & 0x0f) { 652 val = memreadreg(cs->hw.diva.cfg_reg, HSCX_ISTA + 0x40); 653 if (ista & 0x01) 654 val |= 0x01; 655 if (ista & 0x04) 656 val |= 0x02; 657 if (ista & 0x08) 658 val |= 0x04; 659 if (val) 660 Memhscx_int_main(cs, val); 661 } 662 if (ista & 0x20) { 663 val = 0xfe & memreadreg(cs->hw.diva.cfg_reg, ISAC_ISTA + 0x80); 664 if (val) { 665 isac_interrupt(cs, val); 666 } 667 } 668 if (ista & 0x10) { 669 val = 0x01; 670 isac_interrupt(cs, val); 671 } 672 ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA); 673 if ((ista & 0x3f) && icnt) { 674 icnt--; 675 goto Start_IPACPCI; 676 } 677 if (!icnt) 678 printk(KERN_WARNING "DIVA IPAC PCI IRQ LOOP\n"); 679 memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xFF); 680 memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xC0); 681 spin_unlock_irqrestore(&cs->lock, flags); 682 return IRQ_HANDLED; 683} 684 685static irqreturn_t 686diva_irq_ipacx_pci(int intno, void *dev_id) 687{ 688 struct IsdnCardState *cs = dev_id; 689 u_char val; 690 u_char *cfg; 691 u_long flags; 692 693 spin_lock_irqsave(&cs->lock, flags); 694 cfg = (u_char *) cs->hw.diva.pci_cfg; 695 val = *cfg; 696 if (!(val &PITA_INT0_STATUS)) { 697 spin_unlock_irqrestore(&cs->lock, flags); 698 return IRQ_NONE; // other shared IRQ 699 } 700 interrupt_ipacx(cs); // handler for chip 701 *cfg = PITA_INT0_STATUS; // Reset PLX interrupt 702 spin_unlock_irqrestore(&cs->lock, flags); 703 return IRQ_HANDLED; 704} 705 706static void 707release_io_diva(struct IsdnCardState *cs) 708{ 709 int bytecnt; 710 711 if ((cs->subtyp == DIVA_IPAC_PCI) || 712 (cs->subtyp == DIVA_IPACX_PCI) ) { 713 u_int *cfg = (unsigned int *)cs->hw.diva.pci_cfg; 714 715 *cfg = 0; /* disable INT0/1 */ 716 *cfg = 2; /* reset pending INT0 */ 717 if (cs->hw.diva.cfg_reg) 718 iounmap((void *)cs->hw.diva.cfg_reg); 719 if (cs->hw.diva.pci_cfg) 720 iounmap((void *)cs->hw.diva.pci_cfg); 721 return; 722 } else if (cs->subtyp != DIVA_IPAC_ISA) { 723 del_timer(&cs->hw.diva.tl); 724 if (cs->hw.diva.cfg_reg) 725 byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */ 726 } 727 if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA)) 728 bytecnt = 8; 729 else 730 bytecnt = 32; 731 if (cs->hw.diva.cfg_reg) { 732 release_region(cs->hw.diva.cfg_reg, bytecnt); 733 } 734} 735 736static void 737iounmap_diva(struct IsdnCardState *cs) 738{ 739 if ((cs->subtyp == DIVA_IPAC_PCI) || (cs->subtyp == DIVA_IPACX_PCI)) { 740 if (cs->hw.diva.cfg_reg) { 741 iounmap((void *)cs->hw.diva.cfg_reg); 742 cs->hw.diva.cfg_reg = 0; 743 } 744 if (cs->hw.diva.pci_cfg) { 745 iounmap((void *)cs->hw.diva.pci_cfg); 746 cs->hw.diva.pci_cfg = 0; 747 } 748 } 749 750 return; 751} 752 753static void 754reset_diva(struct IsdnCardState *cs) 755{ 756 if (cs->subtyp == DIVA_IPAC_ISA) { 757 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20); 758 mdelay(10); 759 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00); 760 mdelay(10); 761 writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0); 762 } else if (cs->subtyp == DIVA_IPAC_PCI) { 763 unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg + 764 PITA_MISC_REG); 765 *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE; 766 mdelay(10); 767 *ireg = PITA_PARA_MPX_MODE; 768 mdelay(10); 769 memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0); 770 } else if (cs->subtyp == DIVA_IPACX_PCI) { 771 unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg + 772 PITA_MISC_REG); 773 *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE; 774 mdelay(10); 775 *ireg = PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET; 776 mdelay(10); 777 MemWriteISAC_IPACX(cs, IPACX_MASK, 0xff); // Interrupts off 778 } else { /* DIVA 2.0 */ 779 cs->hw.diva.ctrl_reg = 0; /* Reset On */ 780 byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); 781 mdelay(10); 782 cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */ 783 byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); 784 mdelay(10); 785 if (cs->subtyp == DIVA_ISA) 786 cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A; 787 else { 788 byteout(cs->hw.diva.pci_cfg + 0x69, 9); 789 cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A; 790 } 791 byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); 792 } 793} 794 795#define DIVA_ASSIGN 1 796 797static void 798diva_led_handler(struct IsdnCardState *cs) 799{ 800 int blink = 0; 801 802 if ((cs->subtyp == DIVA_IPAC_ISA) || 803 (cs->subtyp == DIVA_IPAC_PCI) || 804 (cs->subtyp == DIVA_IPACX_PCI) ) 805 return; 806 del_timer(&cs->hw.diva.tl); 807 if (cs->hw.diva.status & DIVA_ASSIGN) 808 cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ? 809 DIVA_ISA_LED_A : DIVA_PCI_LED_A; 810 else { 811 cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ? 812 DIVA_ISA_LED_A : DIVA_PCI_LED_A; 813 blink = 250; 814 } 815 if (cs->hw.diva.status & 0xf000) 816 cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ? 817 DIVA_ISA_LED_B : DIVA_PCI_LED_B; 818 else if (cs->hw.diva.status & 0x0f00) { 819 cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ? 820 DIVA_ISA_LED_B : DIVA_PCI_LED_B; 821 blink = 500; 822 } else 823 cs->hw.diva.ctrl_reg &= ~((DIVA_ISA == cs->subtyp) ? 824 DIVA_ISA_LED_B : DIVA_PCI_LED_B); 825 826 byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); 827 if (blink) { 828 init_timer(&cs->hw.diva.tl); 829 cs->hw.diva.tl.expires = jiffies + ((blink * HZ) / 1000); 830 add_timer(&cs->hw.diva.tl); 831 } 832} 833 834static int 835Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg) 836{ 837 u_int *ireg; 838 u_long flags; 839 840 switch (mt) { 841 case CARD_RESET: 842 spin_lock_irqsave(&cs->lock, flags); 843 reset_diva(cs); 844 spin_unlock_irqrestore(&cs->lock, flags); 845 return(0); 846 case CARD_RELEASE: 847 release_io_diva(cs); 848 return(0); 849 case CARD_INIT: 850 spin_lock_irqsave(&cs->lock, flags); 851 reset_diva(cs); 852 if (cs->subtyp == DIVA_IPACX_PCI) { 853 ireg = (unsigned int *)cs->hw.diva.pci_cfg; 854 *ireg = PITA_INT0_ENABLE; 855 init_ipacx(cs, 3); // init chip and enable interrupts 856 spin_unlock_irqrestore(&cs->lock, flags); 857 return (0); 858 } 859 if (cs->subtyp == DIVA_IPAC_PCI) { 860 ireg = (unsigned int *)cs->hw.diva.pci_cfg; 861 *ireg = PITA_INT0_ENABLE; 862 } 863 inithscxisac(cs, 3); 864 spin_unlock_irqrestore(&cs->lock, flags); 865 return(0); 866 case CARD_TEST: 867 return(0); 868 case (MDL_REMOVE | REQUEST): 869 cs->hw.diva.status = 0; 870 break; 871 case (MDL_ASSIGN | REQUEST): 872 cs->hw.diva.status |= DIVA_ASSIGN; 873 break; 874 case MDL_INFO_SETUP: 875 if ((long)arg) 876 cs->hw.diva.status |= 0x0200; 877 else 878 cs->hw.diva.status |= 0x0100; 879 break; 880 case MDL_INFO_CONN: 881 if ((long)arg) 882 cs->hw.diva.status |= 0x2000; 883 else 884 cs->hw.diva.status |= 0x1000; 885 break; 886 case MDL_INFO_REL: 887 if ((long)arg) { 888 cs->hw.diva.status &= ~0x2000; 889 cs->hw.diva.status &= ~0x0200; 890 } else { 891 cs->hw.diva.status &= ~0x1000; 892 cs->hw.diva.status &= ~0x0100; 893 } 894 break; 895 } 896 if ((cs->subtyp != DIVA_IPAC_ISA) && 897 (cs->subtyp != DIVA_IPAC_PCI) && 898 (cs->subtyp != DIVA_IPACX_PCI)) { 899 spin_lock_irqsave(&cs->lock, flags); 900 diva_led_handler(cs); 901 spin_unlock_irqrestore(&cs->lock, flags); 902 } 903 return(0); 904} 905 906static int __devinit setup_diva_common(struct IsdnCardState *cs) 907{ 908 int bytecnt; 909 u_char val; 910 911 if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA)) 912 bytecnt = 8; 913 else 914 bytecnt = 32; 915 916 printk(KERN_INFO 917 "Diva: %s card configured at %#lx IRQ %d\n", 918 (cs->subtyp == DIVA_PCI) ? "PCI" : 919 (cs->subtyp == DIVA_ISA) ? "ISA" : 920 (cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" : 921 (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI", 922 cs->hw.diva.cfg_reg, cs->irq); 923 if ((cs->subtyp == DIVA_IPAC_PCI) || 924 (cs->subtyp == DIVA_IPACX_PCI) || 925 (cs->subtyp == DIVA_PCI) ) 926 printk(KERN_INFO "Diva: %s space at %#lx\n", 927 (cs->subtyp == DIVA_PCI) ? "PCI" : 928 (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI", 929 cs->hw.diva.pci_cfg); 930 if ((cs->subtyp != DIVA_IPAC_PCI) && 931 (cs->subtyp != DIVA_IPACX_PCI) ) { 932 if (!request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn")) { 933 printk(KERN_WARNING 934 "HiSax: %s config port %lx-%lx already in use\n", 935 "diva", 936 cs->hw.diva.cfg_reg, 937 cs->hw.diva.cfg_reg + bytecnt); 938 iounmap_diva(cs); 939 return (0); 940 } 941 } 942 cs->BC_Read_Reg = &ReadHSCX; 943 cs->BC_Write_Reg = &WriteHSCX; 944 cs->BC_Send_Data = &hscx_fill_fifo; 945 cs->cardmsg = &Diva_card_msg; 946 setup_isac(cs); 947 if (cs->subtyp == DIVA_IPAC_ISA) { 948 cs->readisac = &ReadISAC_IPAC; 949 cs->writeisac = &WriteISAC_IPAC; 950 cs->readisacfifo = &ReadISACfifo_IPAC; 951 cs->writeisacfifo = &WriteISACfifo_IPAC; 952 cs->irq_func = &diva_irq_ipac_isa; 953 val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ID); 954 printk(KERN_INFO "Diva: IPAC version %x\n", val); 955 } else if (cs->subtyp == DIVA_IPAC_PCI) { 956 cs->readisac = &MemReadISAC_IPAC; 957 cs->writeisac = &MemWriteISAC_IPAC; 958 cs->readisacfifo = &MemReadISACfifo_IPAC; 959 cs->writeisacfifo = &MemWriteISACfifo_IPAC; 960 cs->BC_Read_Reg = &MemReadHSCX; 961 cs->BC_Write_Reg = &MemWriteHSCX; 962 cs->BC_Send_Data = &Memhscx_fill_fifo; 963 cs->irq_func = &diva_irq_ipac_pci; 964 val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID); 965 printk(KERN_INFO "Diva: IPAC version %x\n", val); 966 } else if (cs->subtyp == DIVA_IPACX_PCI) { 967 cs->readisac = &MemReadISAC_IPACX; 968 cs->writeisac = &MemWriteISAC_IPACX; 969 cs->readisacfifo = &MemReadISACfifo_IPACX; 970 cs->writeisacfifo = &MemWriteISACfifo_IPACX; 971 cs->BC_Read_Reg = &MemReadHSCX_IPACX; 972 cs->BC_Write_Reg = &MemWriteHSCX_IPACX; 973 cs->BC_Send_Data = NULL; // function located in ipacx module 974 cs->irq_func = &diva_irq_ipacx_pci; 975 printk(KERN_INFO "Diva: IPACX Design Id: %x\n", 976 MemReadISAC_IPACX(cs, IPACX_ID) &0x3F); 977 } else { /* DIVA 2.0 */ 978 cs->hw.diva.tl.function = (void *) diva_led_handler; 979 cs->hw.diva.tl.data = (long) cs; 980 init_timer(&cs->hw.diva.tl); 981 cs->readisac = &ReadISAC; 982 cs->writeisac = &WriteISAC; 983 cs->readisacfifo = &ReadISACfifo; 984 cs->writeisacfifo = &WriteISACfifo; 985 cs->irq_func = &diva_interrupt; 986 ISACVersion(cs, "Diva:"); 987 if (HscxVersion(cs, "Diva:")) { 988 printk(KERN_WARNING 989 "Diva: wrong HSCX versions check IO address\n"); 990 release_io_diva(cs); 991 return (0); 992 } 993 } 994 return (1); 995} 996 997#ifdef CONFIG_ISA 998 999static int __devinit setup_diva_isa(struct IsdnCard *card) 1000{ 1001 struct IsdnCardState *cs = card->cs; 1002 u_char val; 1003 1004 if (!card->para[1]) 1005 return (-1); /* card not found; continue search */ 1006 1007 cs->hw.diva.ctrl_reg = 0; 1008 cs->hw.diva.cfg_reg = card->para[1]; 1009 val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR, 1010 cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID); 1011 printk(KERN_INFO "Diva: IPAC version %x\n", val); 1012 if ((val == 1) || (val==2)) { 1013 cs->subtyp = DIVA_IPAC_ISA; 1014 cs->hw.diva.ctrl = 0; 1015 cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA; 1016 cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA; 1017 cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR; 1018 cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR; 1019 test_and_set_bit(HW_IPAC, &cs->HW_Flags); 1020 } else { 1021 cs->subtyp = DIVA_ISA; 1022 cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL; 1023 cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA; 1024 cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA; 1025 cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR; 1026 cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR; 1027 } 1028 cs->irq = card->para[0]; 1029 1030 return (1); /* card found */ 1031} 1032 1033#else /* if !CONFIG_ISA */ 1034 1035static int __devinit setup_diva_isa(struct IsdnCard *card) 1036{ 1037 return (-1); /* card not found; continue search */ 1038} 1039 1040#endif /* CONFIG_ISA */ 1041 1042#ifdef __ISAPNP__ 1043static struct isapnp_device_id diva_ids[] __devinitdata = { 1044 { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), 1045 ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), 1046 (unsigned long) "Diva picola" }, 1047 { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), 1048 ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x51), 1049 (unsigned long) "Diva picola" }, 1050 { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71), 1051 ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71), 1052 (unsigned long) "Diva 2.0" }, 1053 { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71), 1054 ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x71), 1055 (unsigned long) "Diva 2.0" }, 1056 { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1), 1057 ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1), 1058 (unsigned long) "Diva 2.01" }, 1059 { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1), 1060 ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0xA1), 1061 (unsigned long) "Diva 2.01" }, 1062 { 0, } 1063}; 1064 1065static struct isapnp_device_id *ipid __devinitdata = &diva_ids[0]; 1066static struct pnp_card *pnp_c __devinitdata = NULL; 1067 1068static int __devinit setup_diva_isapnp(struct IsdnCard *card) 1069{ 1070 struct IsdnCardState *cs = card->cs; 1071 struct pnp_dev *pnp_d; 1072 1073 if (!isapnp_present()) 1074 return (-1); /* card not found; continue search */ 1075 1076 while(ipid->card_vendor) { 1077 if ((pnp_c = pnp_find_card(ipid->card_vendor, 1078 ipid->card_device, pnp_c))) { 1079 pnp_d = NULL; 1080 if ((pnp_d = pnp_find_dev(pnp_c, 1081 ipid->vendor, ipid->function, pnp_d))) { 1082 int err; 1083 1084 printk(KERN_INFO "HiSax: %s detected\n", 1085 (char *)ipid->driver_data); 1086 pnp_disable_dev(pnp_d); 1087 err = pnp_activate_dev(pnp_d); 1088 if (err<0) { 1089 printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", 1090 __func__, err); 1091 return(0); 1092 } 1093 card->para[1] = pnp_port_start(pnp_d, 0); 1094 card->para[0] = pnp_irq(pnp_d, 0); 1095 if (!card->para[0] || !card->para[1]) { 1096 printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n", 1097 card->para[0], card->para[1]); 1098 pnp_disable_dev(pnp_d); 1099 return(0); 1100 } 1101 cs->hw.diva.cfg_reg = card->para[1]; 1102 cs->irq = card->para[0]; 1103 if (ipid->function == ISAPNP_FUNCTION(0xA1)) { 1104 cs->subtyp = DIVA_IPAC_ISA; 1105 cs->hw.diva.ctrl = 0; 1106 cs->hw.diva.isac = 1107 card->para[1] + DIVA_IPAC_DATA; 1108 cs->hw.diva.hscx = 1109 card->para[1] + DIVA_IPAC_DATA; 1110 cs->hw.diva.isac_adr = 1111 card->para[1] + DIVA_IPAC_ADR; 1112 cs->hw.diva.hscx_adr = 1113 card->para[1] + DIVA_IPAC_ADR; 1114 test_and_set_bit(HW_IPAC, &cs->HW_Flags); 1115 } else { 1116 cs->subtyp = DIVA_ISA; 1117 cs->hw.diva.ctrl = 1118 card->para[1] + DIVA_ISA_CTRL; 1119 cs->hw.diva.isac = 1120 card->para[1] + DIVA_ISA_ISAC_DATA; 1121 cs->hw.diva.hscx = 1122 card->para[1] + DIVA_HSCX_DATA; 1123 cs->hw.diva.isac_adr = 1124 card->para[1] + DIVA_ISA_ISAC_ADR; 1125 cs->hw.diva.hscx_adr = 1126 card->para[1] + DIVA_HSCX_ADR; 1127 } 1128 return (1); /* card found */ 1129 } else { 1130 printk(KERN_ERR "Diva PnP: PnP error card found, no device\n"); 1131 return(0); 1132 } 1133 } 1134 ipid++; 1135 pnp_c=NULL; 1136 } 1137 1138 return (-1); /* card not found; continue search */ 1139} 1140 1141#else /* if !ISAPNP */ 1142 1143static int __devinit setup_diva_isapnp(struct IsdnCard *card) 1144{ 1145 return (-1); /* card not found; continue search */ 1146} 1147 1148#endif /* ISAPNP */ 1149 1150#ifdef CONFIG_PCI 1151static struct pci_dev *dev_diva __devinitdata = NULL; 1152static struct pci_dev *dev_diva_u __devinitdata = NULL; 1153static struct pci_dev *dev_diva201 __devinitdata = NULL; 1154static struct pci_dev *dev_diva202 __devinitdata = NULL; 1155 1156static int __devinit setup_diva_pci(struct IsdnCard *card) 1157{ 1158 struct IsdnCardState *cs = card->cs; 1159 1160 cs->subtyp = 0; 1161 if ((dev_diva = hisax_find_pci_device(PCI_VENDOR_ID_EICON, 1162 PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { 1163 if (pci_enable_device(dev_diva)) 1164 return(0); 1165 cs->subtyp = DIVA_PCI; 1166 cs->irq = dev_diva->irq; 1167 cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2); 1168 } else if ((dev_diva_u = hisax_find_pci_device(PCI_VENDOR_ID_EICON, 1169 PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) { 1170 if (pci_enable_device(dev_diva_u)) 1171 return(0); 1172 cs->subtyp = DIVA_PCI; 1173 cs->irq = dev_diva_u->irq; 1174 cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2); 1175 } else if ((dev_diva201 = hisax_find_pci_device(PCI_VENDOR_ID_EICON, 1176 PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) { 1177 if (pci_enable_device(dev_diva201)) 1178 return(0); 1179 cs->subtyp = DIVA_IPAC_PCI; 1180 cs->irq = dev_diva201->irq; 1181 cs->hw.diva.pci_cfg = 1182 (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096); 1183 cs->hw.diva.cfg_reg = 1184 (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096); 1185 } else if ((dev_diva202 = hisax_find_pci_device(PCI_VENDOR_ID_EICON, 1186 PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) { 1187 if (pci_enable_device(dev_diva202)) 1188 return(0); 1189 cs->subtyp = DIVA_IPACX_PCI; 1190 cs->irq = dev_diva202->irq; 1191 cs->hw.diva.pci_cfg = 1192 (ulong) ioremap(pci_resource_start(dev_diva202, 0), 4096); 1193 cs->hw.diva.cfg_reg = 1194 (ulong) ioremap(pci_resource_start(dev_diva202, 1), 4096); 1195 } else { 1196 return (-1); /* card not found; continue search */ 1197 } 1198 1199 if (!cs->irq) { 1200 printk(KERN_WARNING "Diva: No IRQ for PCI card found\n"); 1201 iounmap_diva(cs); 1202 return(0); 1203 } 1204 1205 if (!cs->hw.diva.cfg_reg) { 1206 printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); 1207 iounmap_diva(cs); 1208 return(0); 1209 } 1210 cs->irq_flags |= IRQF_SHARED; 1211 1212 if ((cs->subtyp == DIVA_IPAC_PCI) || 1213 (cs->subtyp == DIVA_IPACX_PCI) ) { 1214 cs->hw.diva.ctrl = 0; 1215 cs->hw.diva.isac = 0; 1216 cs->hw.diva.hscx = 0; 1217 cs->hw.diva.isac_adr = 0; 1218 cs->hw.diva.hscx_adr = 0; 1219 test_and_set_bit(HW_IPAC, &cs->HW_Flags); 1220 } else { 1221 cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL; 1222 cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA; 1223 cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA; 1224 cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR; 1225 cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR; 1226 } 1227 1228 return (1); /* card found */ 1229} 1230 1231#else /* if !CONFIG_PCI */ 1232 1233static int __devinit setup_diva_pci(struct IsdnCard *card) 1234{ 1235 return (-1); /* card not found; continue search */ 1236} 1237 1238#endif /* CONFIG_PCI */ 1239 1240int __devinit 1241setup_diva(struct IsdnCard *card) 1242{ 1243 int rc, have_card = 0; 1244 struct IsdnCardState *cs = card->cs; 1245 char tmp[64]; 1246 1247 strcpy(tmp, Diva_revision); 1248 printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp)); 1249 if (cs->typ != ISDN_CTYPE_DIEHLDIVA) 1250 return(0); 1251 cs->hw.diva.status = 0; 1252 1253 rc = setup_diva_isa(card); 1254 if (!rc) 1255 return rc; 1256 if (rc > 0) { 1257 have_card = 1; 1258 goto ready; 1259 } 1260 1261 rc = setup_diva_isapnp(card); 1262 if (!rc) 1263 return rc; 1264 if (rc > 0) { 1265 have_card = 1; 1266 goto ready; 1267 } 1268 1269 rc = setup_diva_pci(card); 1270 if (!rc) 1271 return rc; 1272 if (rc > 0) 1273 have_card = 1; 1274 1275ready: 1276 if (!have_card) { 1277 printk(KERN_WARNING "Diva: No ISA, ISAPNP or PCI card found\n"); 1278 return(0); 1279 } 1280 1281 return setup_diva_common(card->cs); 1282} 1283