1/* $Id: sedlbauer.c,v 1.34.2.6 2004/01/24 20:47:24 keil Exp $ 2 * 3 * low level stuff for Sedlbauer cards 4 * includes support for the Sedlbauer speed star (speed star II), 5 * support for the Sedlbauer speed fax+, 6 * support for the Sedlbauer ISDN-Controller PC/104 and 7 * support for the Sedlbauer speed pci 8 * derived from the original file asuscom.c from Karsten Keil 9 * 10 * Author Marcus Niemann 11 * Copyright by Marcus Niemann <niemann@www-bib.fh-bielefeld.de> 12 * 13 * This software may be used and distributed according to the terms 14 * of the GNU General Public License, incorporated herein by reference. 15 * 16 * Thanks to Karsten Keil 17 * Sedlbauer AG for informations 18 * Edgar Toernig 19 * 20 */ 21 22/* Supported cards: 23 * Card: Chip: Configuration: Comment: 24 * --------------------------------------------------------------------- 25 * Speed Card ISAC_HSCX DIP-SWITCH 26 * Speed Win ISAC_HSCX ISAPNP 27 * Speed Fax+ ISAC_ISAR ISAPNP Full analog support 28 * Speed Star ISAC_HSCX CARDMGR 29 * Speed Win2 IPAC ISAPNP 30 * ISDN PC/104 IPAC DIP-SWITCH 31 * Speed Star2 IPAC CARDMGR 32 * Speed PCI IPAC PCI PNP 33 * Speed Fax+ ISAC_ISAR PCI PNP Full analog support 34 * 35 * Important: 36 * For the sedlbauer speed fax+ to work properly you have to download 37 * the firmware onto the card. 38 * For example: hisaxctrl <DriverID> 9 ISAR.BIN 39 */ 40 41#include <linux/init.h> 42#include "hisax.h" 43#include "isac.h" 44#include "ipac.h" 45#include "hscx.h" 46#include "isar.h" 47#include "isdnl1.h" 48#include <linux/pci.h> 49#include <linux/isapnp.h> 50 51static const char *Sedlbauer_revision = "$Revision: 1.34.2.6 $"; 52 53static const char *Sedlbauer_Types[] = 54{"None", "speed card/win", "speed star", "speed fax+", 55 "speed win II / ISDN PC/104", "speed star II", "speed pci", 56 "speed fax+ pyramid", "speed fax+ pci", "HST Saphir III"}; 57 58#define PCI_SUBVENDOR_SPEEDFAX_PYRAMID 0x51 59#define PCI_SUBVENDOR_HST_SAPHIR3 0x52 60#define PCI_SUBVENDOR_SEDLBAUER_PCI 0x53 61#define PCI_SUBVENDOR_SPEEDFAX_PCI 0x54 62#define PCI_SUB_ID_SEDLBAUER 0x01 63 64#define SEDL_SPEED_CARD_WIN 1 65#define SEDL_SPEED_STAR 2 66#define SEDL_SPEED_FAX 3 67#define SEDL_SPEED_WIN2_PC104 4 68#define SEDL_SPEED_STAR2 5 69#define SEDL_SPEED_PCI 6 70#define SEDL_SPEEDFAX_PYRAMID 7 71#define SEDL_SPEEDFAX_PCI 8 72#define HST_SAPHIR3 9 73 74#define SEDL_CHIP_TEST 0 75#define SEDL_CHIP_ISAC_HSCX 1 76#define SEDL_CHIP_ISAC_ISAR 2 77#define SEDL_CHIP_IPAC 3 78 79#define SEDL_BUS_ISA 1 80#define SEDL_BUS_PCI 2 81#define SEDL_BUS_PCMCIA 3 82 83#define byteout(addr, val) outb(val, addr) 84#define bytein(addr) inb(addr) 85 86#define SEDL_HSCX_ISA_RESET_ON 0 87#define SEDL_HSCX_ISA_RESET_OFF 1 88#define SEDL_HSCX_ISA_ISAC 2 89#define SEDL_HSCX_ISA_HSCX 3 90#define SEDL_HSCX_ISA_ADR 4 91 92#define SEDL_HSCX_PCMCIA_RESET 0 93#define SEDL_HSCX_PCMCIA_ISAC 1 94#define SEDL_HSCX_PCMCIA_HSCX 2 95#define SEDL_HSCX_PCMCIA_ADR 4 96 97#define SEDL_ISAR_ISA_ISAC 4 98#define SEDL_ISAR_ISA_ISAR 6 99#define SEDL_ISAR_ISA_ADR 8 100#define SEDL_ISAR_ISA_ISAR_RESET_ON 10 101#define SEDL_ISAR_ISA_ISAR_RESET_OFF 12 102 103#define SEDL_IPAC_ANY_ADR 0 104#define SEDL_IPAC_ANY_IPAC 2 105 106#define SEDL_IPAC_PCI_BASE 0 107#define SEDL_IPAC_PCI_ADR 0xc0 108#define SEDL_IPAC_PCI_IPAC 0xc8 109#define SEDL_ISAR_PCI_ADR 0xc8 110#define SEDL_ISAR_PCI_ISAC 0xd0 111#define SEDL_ISAR_PCI_ISAR 0xe0 112#define SEDL_ISAR_PCI_ISAR_RESET_ON 0x01 113#define SEDL_ISAR_PCI_ISAR_RESET_OFF 0x18 114#define SEDL_ISAR_PCI_LED1 0x08 115#define SEDL_ISAR_PCI_LED2 0x10 116 117#define SEDL_RESET 0x3 /* same as DOS driver */ 118 119static inline u_char 120readreg(unsigned int ale, unsigned int adr, u_char off) 121{ 122 register u_char ret; 123 124 byteout(ale, off); 125 ret = bytein(adr); 126 return (ret); 127} 128 129static inline void 130readfifo(unsigned int ale, unsigned int adr, u_char off, u_char *data, int size) 131{ 132 byteout(ale, off); 133 insb(adr, data, size); 134} 135 136 137static inline void 138writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) 139{ 140 byteout(ale, off); 141 byteout(adr, data); 142} 143 144static inline void 145writefifo(unsigned int ale, unsigned int adr, u_char off, u_char *data, int size) 146{ 147 byteout(ale, off); 148 outsb(adr, data, size); 149} 150 151/* Interface functions */ 152 153static u_char 154ReadISAC(struct IsdnCardState *cs, u_char offset) 155{ 156 return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset)); 157} 158 159static void 160WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) 161{ 162 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset, value); 163} 164 165static void 166ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size) 167{ 168 readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, size); 169} 170 171static void 172WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size) 173{ 174 writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, size); 175} 176 177static u_char 178ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) 179{ 180 return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset | 0x80)); 181} 182 183static void 184WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) 185{ 186 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset | 0x80, value); 187} 188 189static void 190ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char *data, int size) 191{ 192 readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size); 193} 194 195static void 196WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char *data, int size) 197{ 198 writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size); 199} 200 201static u_char 202ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) 203{ 204 return (readreg(cs->hw.sedl.adr, 205 cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0))); 206} 207 208static void 209WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) 210{ 211 writereg(cs->hw.sedl.adr, 212 cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value); 213} 214 215/* ISAR access routines 216 * mode = 0 access with IRQ on 217 * mode = 1 access with IRQ off 218 * mode = 2 access with IRQ off and using last offset 219 */ 220 221static u_char 222ReadISAR(struct IsdnCardState *cs, int mode, u_char offset) 223{ 224 if (mode == 0) 225 return (readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset)); 226 else if (mode == 1) 227 byteout(cs->hw.sedl.adr, offset); 228 return (bytein(cs->hw.sedl.hscx)); 229} 230 231static void 232WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value) 233{ 234 if (mode == 0) 235 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset, value); 236 else { 237 if (mode == 1) 238 byteout(cs->hw.sedl.adr, offset); 239 byteout(cs->hw.sedl.hscx, value); 240 } 241} 242 243/* 244 * fast interrupt HSCX stuff goes here 245 */ 246 247#define READHSCX(cs, nr, reg) readreg(cs->hw.sedl.adr, \ 248 cs->hw.sedl.hscx, reg + (nr ? 0x40 : 0)) 249#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.sedl.adr, \ 250 cs->hw.sedl.hscx, reg + (nr ? 0x40 : 0), data) 251 252#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.sedl.adr, \ 253 cs->hw.sedl.hscx, (nr ? 0x40 : 0), ptr, cnt) 254 255#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.sedl.adr, \ 256 cs->hw.sedl.hscx, (nr ? 0x40 : 0), ptr, cnt) 257 258#include "hscx_irq.c" 259 260static irqreturn_t 261sedlbauer_interrupt(int intno, void *dev_id) 262{ 263 struct IsdnCardState *cs = dev_id; 264 u_char val; 265 u_long flags; 266 267 spin_lock_irqsave(&cs->lock, flags); 268 if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) { 269 /* The card tends to generate interrupts while being removed 270 causing us to just crash the kernel. bad. */ 271 spin_unlock_irqrestore(&cs->lock, flags); 272 printk(KERN_WARNING "Sedlbauer: card not available!\n"); 273 return IRQ_NONE; 274 } 275 276 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40); 277Start_HSCX: 278 if (val) 279 hscx_int_main(cs, val); 280 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); 281Start_ISAC: 282 if (val) 283 isac_interrupt(cs, val); 284 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40); 285 if (val) { 286 if (cs->debug & L1_DEB_HSCX) 287 debugl1(cs, "HSCX IntStat after IntRoutine"); 288 goto Start_HSCX; 289 } 290 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); 291 if (val) { 292 if (cs->debug & L1_DEB_ISAC) 293 debugl1(cs, "ISAC IntStat after IntRoutine"); 294 goto Start_ISAC; 295 } 296 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0xFF); 297 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0xFF); 298 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF); 299 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0); 300 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0x0); 301 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0x0); 302 spin_unlock_irqrestore(&cs->lock, flags); 303 return IRQ_HANDLED; 304} 305 306static irqreturn_t 307sedlbauer_interrupt_ipac(int intno, void *dev_id) 308{ 309 struct IsdnCardState *cs = dev_id; 310 u_char ista, val, icnt = 5; 311 u_long flags; 312 313 spin_lock_irqsave(&cs->lock, flags); 314 ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA); 315Start_IPAC: 316 if (cs->debug & L1_DEB_IPAC) 317 debugl1(cs, "IPAC ISTA %02X", ista); 318 if (ista & 0x0f) { 319 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40); 320 if (ista & 0x01) 321 val |= 0x01; 322 if (ista & 0x04) 323 val |= 0x02; 324 if (ista & 0x08) 325 val |= 0x04; 326 if (val) 327 hscx_int_main(cs, val); 328 } 329 if (ista & 0x20) { 330 val = 0xfe & readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA | 0x80); 331 if (val) { 332 isac_interrupt(cs, val); 333 } 334 } 335 if (ista & 0x10) { 336 val = 0x01; 337 isac_interrupt(cs, val); 338 } 339 ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA); 340 if ((ista & 0x3f) && icnt) { 341 icnt--; 342 goto Start_IPAC; 343 } 344 if (!icnt) 345 if (cs->debug & L1_DEB_ISAC) 346 debugl1(cs, "Sedlbauer IRQ LOOP"); 347 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xFF); 348 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xC0); 349 spin_unlock_irqrestore(&cs->lock, flags); 350 return IRQ_HANDLED; 351} 352 353static irqreturn_t 354sedlbauer_interrupt_isar(int intno, void *dev_id) 355{ 356 struct IsdnCardState *cs = dev_id; 357 u_char val; 358 int cnt = 5; 359 u_long flags; 360 361 spin_lock_irqsave(&cs->lock, flags); 362 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT); 363Start_ISAR: 364 if (val & ISAR_IRQSTA) 365 isar_int_main(cs); 366 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); 367Start_ISAC: 368 if (val) 369 isac_interrupt(cs, val); 370 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT); 371 if ((val & ISAR_IRQSTA) && --cnt) { 372 if (cs->debug & L1_DEB_HSCX) 373 debugl1(cs, "ISAR IntStat after IntRoutine"); 374 goto Start_ISAR; 375 } 376 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); 377 if (val && --cnt) { 378 if (cs->debug & L1_DEB_ISAC) 379 debugl1(cs, "ISAC IntStat after IntRoutine"); 380 goto Start_ISAC; 381 } 382 if (!cnt) 383 if (cs->debug & L1_DEB_ISAC) 384 debugl1(cs, "Sedlbauer IRQ LOOP"); 385 386 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0); 387 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF); 388 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0); 389 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, ISAR_IRQMSK); 390 spin_unlock_irqrestore(&cs->lock, flags); 391 return IRQ_HANDLED; 392} 393 394static void 395release_io_sedlbauer(struct IsdnCardState *cs) 396{ 397 int bytecnt = 8; 398 399 if (cs->subtyp == SEDL_SPEED_FAX) { 400 bytecnt = 16; 401 } else if (cs->hw.sedl.bus == SEDL_BUS_PCI) { 402 bytecnt = 256; 403 } 404 if (cs->hw.sedl.cfg_reg) 405 release_region(cs->hw.sedl.cfg_reg, bytecnt); 406} 407 408static void 409reset_sedlbauer(struct IsdnCardState *cs) 410{ 411 printk(KERN_INFO "Sedlbauer: resetting card\n"); 412 413 if (!((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && 414 (cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX))) { 415 if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) { 416 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20); 417 mdelay(2); 418 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0); 419 mdelay(10); 420 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0); 421 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff); 422 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_AOE, 0x0); 423 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xc0); 424 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_PCFG, 0x12); 425 } else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) && 426 (cs->hw.sedl.bus == SEDL_BUS_PCI)) { 427 byteout(cs->hw.sedl.cfg_reg + 3, cs->hw.sedl.reset_on); 428 mdelay(2); 429 byteout(cs->hw.sedl.cfg_reg + 3, cs->hw.sedl.reset_off); 430 mdelay(10); 431 } else { 432 byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */ 433 mdelay(2); 434 byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */ 435 mdelay(10); 436 } 437 } 438} 439 440static int 441Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg) 442{ 443 u_long flags; 444 445 switch (mt) { 446 case CARD_RESET: 447 spin_lock_irqsave(&cs->lock, flags); 448 reset_sedlbauer(cs); 449 spin_unlock_irqrestore(&cs->lock, flags); 450 return (0); 451 case CARD_RELEASE: 452 if (cs->hw.sedl.bus == SEDL_BUS_PCI) 453 /* disable all IRQ */ 454 byteout(cs->hw.sedl.cfg_reg + 5, 0); 455 if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { 456 spin_lock_irqsave(&cs->lock, flags); 457 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, 458 ISAR_IRQBIT, 0); 459 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, 460 ISAC_MASK, 0xFF); 461 reset_sedlbauer(cs); 462 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, 463 ISAR_IRQBIT, 0); 464 writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, 465 ISAC_MASK, 0xFF); 466 spin_unlock_irqrestore(&cs->lock, flags); 467 } 468 release_io_sedlbauer(cs); 469 return (0); 470 case CARD_INIT: 471 spin_lock_irqsave(&cs->lock, flags); 472 if (cs->hw.sedl.bus == SEDL_BUS_PCI) 473 /* enable all IRQ */ 474 byteout(cs->hw.sedl.cfg_reg + 5, 0x02); 475 reset_sedlbauer(cs); 476 if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { 477 clear_pending_isac_ints(cs); 478 writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, 479 ISAR_IRQBIT, 0); 480 initisac(cs); 481 initisar(cs); 482 /* Reenable all IRQ */ 483 cs->writeisac(cs, ISAC_MASK, 0); 484 /* RESET Receiver and Transmitter */ 485 cs->writeisac(cs, ISAC_CMDR, 0x41); 486 } else { 487 inithscxisac(cs, 3); 488 } 489 spin_unlock_irqrestore(&cs->lock, flags); 490 return (0); 491 case CARD_TEST: 492 return (0); 493 case MDL_INFO_CONN: 494 if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID) 495 return (0); 496 spin_lock_irqsave(&cs->lock, flags); 497 if ((long) arg) 498 cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2; 499 else 500 cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1; 501 byteout(cs->hw.sedl.cfg_reg + 3, cs->hw.sedl.reset_off); 502 spin_unlock_irqrestore(&cs->lock, flags); 503 break; 504 case MDL_INFO_REL: 505 if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID) 506 return (0); 507 spin_lock_irqsave(&cs->lock, flags); 508 if ((long) arg) 509 cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED2; 510 else 511 cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED1; 512 byteout(cs->hw.sedl.cfg_reg + 3, cs->hw.sedl.reset_off); 513 spin_unlock_irqrestore(&cs->lock, flags); 514 break; 515 } 516 return (0); 517} 518 519#ifdef __ISAPNP__ 520static struct isapnp_device_id sedl_ids[] = { 521 { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01), 522 ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01), 523 (unsigned long) "Speed win" }, 524 { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02), 525 ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02), 526 (unsigned long) "Speed Fax+" }, 527 { 0, } 528}; 529 530static struct isapnp_device_id *ipid = &sedl_ids[0]; 531static struct pnp_card *pnp_c = NULL; 532 533static int setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt) 534{ 535 struct IsdnCardState *cs = card->cs; 536 struct pnp_dev *pnp_d; 537 538 if (!isapnp_present()) 539 return -1; 540 541 while (ipid->card_vendor) { 542 if ((pnp_c = pnp_find_card(ipid->card_vendor, 543 ipid->card_device, pnp_c))) { 544 pnp_d = NULL; 545 if ((pnp_d = pnp_find_dev(pnp_c, 546 ipid->vendor, ipid->function, pnp_d))) { 547 int err; 548 549 printk(KERN_INFO "HiSax: %s detected\n", 550 (char *)ipid->driver_data); 551 pnp_disable_dev(pnp_d); 552 err = pnp_activate_dev(pnp_d); 553 if (err < 0) { 554 printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", 555 __func__, err); 556 return (0); 557 } 558 card->para[1] = pnp_port_start(pnp_d, 0); 559 card->para[0] = pnp_irq(pnp_d, 0); 560 561 if (!card->para[0] || !card->para[1]) { 562 printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n", 563 card->para[0], card->para[1]); 564 pnp_disable_dev(pnp_d); 565 return (0); 566 } 567 cs->hw.sedl.cfg_reg = card->para[1]; 568 cs->irq = card->para[0]; 569 if (ipid->function == ISAPNP_FUNCTION(0x2)) { 570 cs->subtyp = SEDL_SPEED_FAX; 571 cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; 572 *bytecnt = 16; 573 } else { 574 cs->subtyp = SEDL_SPEED_CARD_WIN; 575 cs->hw.sedl.chip = SEDL_CHIP_TEST; 576 } 577 578 return (1); 579 } else { 580 printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n"); 581 return (0); 582 } 583 } 584 ipid++; 585 pnp_c = NULL; 586 } 587 588 printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n"); 589 return -1; 590} 591#else 592 593static int setup_sedlbauer_isapnp(struct IsdnCard *card, int *bytecnt) 594{ 595 return -1; 596} 597#endif /* __ISAPNP__ */ 598 599#ifdef CONFIG_PCI 600static struct pci_dev *dev_sedl = NULL; 601 602static int setup_sedlbauer_pci(struct IsdnCard *card) 603{ 604 struct IsdnCardState *cs = card->cs; 605 u16 sub_vendor_id, sub_id; 606 607 if ((dev_sedl = hisax_find_pci_device(PCI_VENDOR_ID_TIGERJET, 608 PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { 609 if (pci_enable_device(dev_sedl)) 610 return (0); 611 cs->irq = dev_sedl->irq; 612 if (!cs->irq) { 613 printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n"); 614 return (0); 615 } 616 cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0); 617 } else { 618 printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); 619 return (0); 620 } 621 cs->irq_flags |= IRQF_SHARED; 622 cs->hw.sedl.bus = SEDL_BUS_PCI; 623 sub_vendor_id = dev_sedl->subsystem_vendor; 624 sub_id = dev_sedl->subsystem_device; 625 printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n", 626 sub_vendor_id, sub_id); 627 printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n", 628 cs->hw.sedl.cfg_reg); 629 if (sub_id != PCI_SUB_ID_SEDLBAUER) { 630 printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id); 631 return (0); 632 } 633 if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) { 634 cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; 635 cs->subtyp = SEDL_SPEEDFAX_PYRAMID; 636 } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) { 637 cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; 638 cs->subtyp = SEDL_SPEEDFAX_PCI; 639 } else if (sub_vendor_id == PCI_SUBVENDOR_HST_SAPHIR3) { 640 cs->hw.sedl.chip = SEDL_CHIP_IPAC; 641 cs->subtyp = HST_SAPHIR3; 642 } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) { 643 cs->hw.sedl.chip = SEDL_CHIP_IPAC; 644 cs->subtyp = SEDL_SPEED_PCI; 645 } else { 646 printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n", 647 sub_vendor_id); 648 return (0); 649 } 650 651 cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON; 652 cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF; 653 byteout(cs->hw.sedl.cfg_reg, 0xff); 654 byteout(cs->hw.sedl.cfg_reg, 0x00); 655 byteout(cs->hw.sedl.cfg_reg + 2, 0xdd); 656 byteout(cs->hw.sedl.cfg_reg + 5, 0); /* disable all IRQ */ 657 byteout(cs->hw.sedl.cfg_reg + 3, cs->hw.sedl.reset_on); 658 mdelay(2); 659 byteout(cs->hw.sedl.cfg_reg + 3, cs->hw.sedl.reset_off); 660 mdelay(10); 661 662 return (1); 663} 664 665#else 666 667static int setup_sedlbauer_pci(struct IsdnCard *card) 668{ 669 return (1); 670} 671 672#endif /* CONFIG_PCI */ 673 674int setup_sedlbauer(struct IsdnCard *card) 675{ 676 int bytecnt = 8, ver, val, rc; 677 struct IsdnCardState *cs = card->cs; 678 char tmp[64]; 679 680 strcpy(tmp, Sedlbauer_revision); 681 printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp)); 682 683 if (cs->typ == ISDN_CTYPE_SEDLBAUER) { 684 cs->subtyp = SEDL_SPEED_CARD_WIN; 685 cs->hw.sedl.bus = SEDL_BUS_ISA; 686 cs->hw.sedl.chip = SEDL_CHIP_TEST; 687 } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) { 688 cs->subtyp = SEDL_SPEED_STAR; 689 cs->hw.sedl.bus = SEDL_BUS_PCMCIA; 690 cs->hw.sedl.chip = SEDL_CHIP_TEST; 691 } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) { 692 cs->subtyp = SEDL_SPEED_FAX; 693 cs->hw.sedl.bus = SEDL_BUS_ISA; 694 cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; 695 } else 696 return (0); 697 698 bytecnt = 8; 699 if (card->para[1]) { 700 cs->hw.sedl.cfg_reg = card->para[1]; 701 cs->irq = card->para[0]; 702 if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { 703 bytecnt = 16; 704 } 705 } else { 706 rc = setup_sedlbauer_isapnp(card, &bytecnt); 707 if (!rc) 708 return (0); 709 if (rc > 0) 710 goto ready; 711 712 /* Probe for Sedlbauer speed pci */ 713 rc = setup_sedlbauer_pci(card); 714 if (!rc) 715 return (0); 716 717 bytecnt = 256; 718 } 719 720ready: 721 722 /* In case of the sedlbauer pcmcia card, this region is in use, 723 * reserved for us by the card manager. So we do not check it 724 * here, it would fail. 725 */ 726 if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA && 727 !request_region(cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn")) { 728 printk(KERN_WARNING 729 "HiSax: %s config port %x-%x already in use\n", 730 CardType[card->typ], 731 cs->hw.sedl.cfg_reg, 732 cs->hw.sedl.cfg_reg + bytecnt); 733 return (0); 734 } 735 736 printk(KERN_INFO 737 "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n", 738 cs->hw.sedl.cfg_reg, 739 cs->hw.sedl.cfg_reg + bytecnt, 740 cs->irq); 741 742 cs->BC_Read_Reg = &ReadHSCX; 743 cs->BC_Write_Reg = &WriteHSCX; 744 cs->BC_Send_Data = &hscx_fill_fifo; 745 cs->cardmsg = &Sedl_card_msg; 746 747/* 748 * testing ISA and PCMCIA Cards for IPAC, default is ISAC 749 * do not test for PCI card, because ports are different 750 * and PCI card uses only IPAC (for the moment) 751 */ 752 if (cs->hw.sedl.bus != SEDL_BUS_PCI) { 753 val = readreg(cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR, 754 cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID); 755 printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val); 756 if ((val == 1) || (val == 2)) { 757 /* IPAC */ 758 cs->subtyp = SEDL_SPEED_WIN2_PC104; 759 if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) { 760 cs->subtyp = SEDL_SPEED_STAR2; 761 } 762 cs->hw.sedl.chip = SEDL_CHIP_IPAC; 763 } else { 764 /* ISAC_HSCX oder ISAC_ISAR */ 765 if (cs->hw.sedl.chip == SEDL_CHIP_TEST) { 766 cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX; 767 } 768 } 769 } 770 771/* 772 * hw.sedl.chip is now properly set 773 */ 774 printk(KERN_INFO "Sedlbauer: %s detected\n", 775 Sedlbauer_Types[cs->subtyp]); 776 777 setup_isac(cs); 778 if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) { 779 if (cs->hw.sedl.bus == SEDL_BUS_PCI) { 780 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR; 781 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; 782 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; 783 } else { 784 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; 785 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; 786 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; 787 } 788 test_and_set_bit(HW_IPAC, &cs->HW_Flags); 789 cs->readisac = &ReadISAC_IPAC; 790 cs->writeisac = &WriteISAC_IPAC; 791 cs->readisacfifo = &ReadISACfifo_IPAC; 792 cs->writeisacfifo = &WriteISACfifo_IPAC; 793 cs->irq_func = &sedlbauer_interrupt_ipac; 794 val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ID); 795 printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val); 796 } else { 797 /* ISAC_HSCX oder ISAC_ISAR */ 798 cs->readisac = &ReadISAC; 799 cs->writeisac = &WriteISAC; 800 cs->readisacfifo = &ReadISACfifo; 801 cs->writeisacfifo = &WriteISACfifo; 802 if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { 803 if (cs->hw.sedl.bus == SEDL_BUS_PCI) { 804 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + 805 SEDL_ISAR_PCI_ADR; 806 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + 807 SEDL_ISAR_PCI_ISAC; 808 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + 809 SEDL_ISAR_PCI_ISAR; 810 } else { 811 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + 812 SEDL_ISAR_ISA_ADR; 813 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + 814 SEDL_ISAR_ISA_ISAC; 815 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + 816 SEDL_ISAR_ISA_ISAR; 817 cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + 818 SEDL_ISAR_ISA_ISAR_RESET_ON; 819 cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + 820 SEDL_ISAR_ISA_ISAR_RESET_OFF; 821 } 822 cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar; 823 cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar; 824 test_and_set_bit(HW_ISAR, &cs->HW_Flags); 825 cs->irq_func = &sedlbauer_interrupt_isar; 826 cs->auxcmd = &isar_auxcmd; 827 ISACVersion(cs, "Sedlbauer:"); 828 cs->BC_Read_Reg = &ReadISAR; 829 cs->BC_Write_Reg = &WriteISAR; 830 cs->BC_Send_Data = &isar_fill_fifo; 831 bytecnt = 3; 832 while (bytecnt) { 833 ver = ISARVersion(cs, "Sedlbauer:"); 834 if (ver < 0) 835 printk(KERN_WARNING 836 "Sedlbauer: wrong ISAR version (ret = %d)\n", ver); 837 else 838 break; 839 reset_sedlbauer(cs); 840 bytecnt--; 841 } 842 if (!bytecnt) { 843 release_io_sedlbauer(cs); 844 return (0); 845 } 846 } else { 847 if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) { 848 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR; 849 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC; 850 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX; 851 cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; 852 cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; 853 cs->irq_flags |= IRQF_SHARED; 854 } else { 855 cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR; 856 cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC; 857 cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX; 858 cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON; 859 cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF; 860 } 861 cs->irq_func = &sedlbauer_interrupt; 862 ISACVersion(cs, "Sedlbauer:"); 863 864 if (HscxVersion(cs, "Sedlbauer:")) { 865 printk(KERN_WARNING 866 "Sedlbauer: wrong HSCX versions check IO address\n"); 867 release_io_sedlbauer(cs); 868 return (0); 869 } 870 } 871 } 872 return (1); 873} 874