1/* $Id: gazel.c,v 2.19.2.4 2004/01/14 16:04:48 Exp $ 2 * 3 * low level stuff for Gazel isdn cards 4 * 5 * Author BeWan Systems 6 * based on source code from Karsten Keil 7 * Copyright by BeWan Systems 8 * 9 * This software may be used and distributed according to the terms 10 * of the GNU General Public License, incorporated herein by reference. 11 * 12 */ 13 14#include <linux/init.h> 15#include "hisax.h" 16#include "isac.h" 17#include "hscx.h" 18#include "isdnl1.h" 19#include "ipac.h" 20#include <linux/pci.h> 21 22static const char *gazel_revision = "$Revision: 2.19.2.4 $"; 23 24#define R647 1 25#define R685 2 26#define R753 3 27#define R742 4 28 29#define PLX_CNTRL 0x50 /* registre de controle PLX */ 30#define RESET_GAZEL 0x4 31#define RESET_9050 0x40000000 32#define PLX_INCSR 0x4C /* registre d'IT du 9050 */ 33#define INT_ISAC_EN 0x8 /* 1 = enable IT isac */ 34#define INT_ISAC 0x20 /* 1 = IT isac en cours */ 35#define INT_HSCX_EN 0x1 /* 1 = enable IT hscx */ 36#define INT_HSCX 0x4 /* 1 = IT hscx en cours */ 37#define INT_PCI_EN 0x40 /* 1 = enable IT PCI */ 38#define INT_IPAC_EN 0x3 /* enable IT ipac */ 39 40 41#define byteout(addr,val) outb(val,addr) 42#define bytein(addr) inb(addr) 43 44static inline u_char 45readreg(unsigned int adr, u_short off) 46{ 47 return bytein(adr + off); 48} 49 50static inline void 51writereg(unsigned int adr, u_short off, u_char data) 52{ 53 byteout(adr + off, data); 54} 55 56 57static inline void 58read_fifo(unsigned int adr, u_char * data, int size) 59{ 60 insb(adr, data, size); 61} 62 63static void 64write_fifo(unsigned int adr, u_char * data, int size) 65{ 66 outsb(adr, data, size); 67} 68 69static inline u_char 70readreg_ipac(unsigned int adr, u_short off) 71{ 72 register u_char ret; 73 74 byteout(adr, off); 75 ret = bytein(adr + 4); 76 return ret; 77} 78 79static inline void 80writereg_ipac(unsigned int adr, u_short off, u_char data) 81{ 82 byteout(adr, off); 83 byteout(adr + 4, data); 84} 85 86 87static inline void 88read_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size) 89{ 90 byteout(adr, off); 91 insb(adr + 4, data, size); 92} 93 94static void 95write_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size) 96{ 97 byteout(adr, off); 98 outsb(adr + 4, data, size); 99} 100 101/* Interface functions */ 102 103static u_char 104ReadISAC(struct IsdnCardState *cs, u_char offset) 105{ 106 u_short off2 = offset; 107 108 switch (cs->subtyp) { 109 case R647: 110 off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); 111 case R685: 112 return (readreg(cs->hw.gazel.isac, off2)); 113 case R753: 114 case R742: 115 return (readreg_ipac(cs->hw.gazel.ipac, 0x80 + off2)); 116 } 117 return 0; 118} 119 120static void 121WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) 122{ 123 u_short off2 = offset; 124 125 switch (cs->subtyp) { 126 case R647: 127 off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); 128 case R685: 129 writereg(cs->hw.gazel.isac, off2, value); 130 break; 131 case R753: 132 case R742: 133 writereg_ipac(cs->hw.gazel.ipac, 0x80 + off2, value); 134 break; 135 } 136} 137 138static void 139ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) 140{ 141 switch (cs->subtyp) { 142 case R647: 143 case R685: 144 read_fifo(cs->hw.gazel.isacfifo, data, size); 145 break; 146 case R753: 147 case R742: 148 read_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size); 149 break; 150 } 151} 152 153static void 154WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) 155{ 156 switch (cs->subtyp) { 157 case R647: 158 case R685: 159 write_fifo(cs->hw.gazel.isacfifo, data, size); 160 break; 161 case R753: 162 case R742: 163 write_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size); 164 break; 165 } 166} 167 168static void 169ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size) 170{ 171 switch (cs->subtyp) { 172 case R647: 173 case R685: 174 read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); 175 break; 176 case R753: 177 case R742: 178 read_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size); 179 break; 180 } 181} 182 183static void 184WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size) 185{ 186 switch (cs->subtyp) { 187 case R647: 188 case R685: 189 write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); 190 break; 191 case R753: 192 case R742: 193 write_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size); 194 break; 195 } 196} 197 198static u_char 199ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) 200{ 201 u_short off2 = offset; 202 203 switch (cs->subtyp) { 204 case R647: 205 off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); 206 case R685: 207 return (readreg(cs->hw.gazel.hscx[hscx], off2)); 208 case R753: 209 case R742: 210 return (readreg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2)); 211 } 212 return 0; 213} 214 215static void 216WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) 217{ 218 u_short off2 = offset; 219 220 switch (cs->subtyp) { 221 case R647: 222 off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); 223 case R685: 224 writereg(cs->hw.gazel.hscx[hscx], off2, value); 225 break; 226 case R753: 227 case R742: 228 writereg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2, value); 229 break; 230 } 231} 232 233/* 234 * fast interrupt HSCX stuff goes here 235 */ 236 237#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg) 238#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data) 239#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt) 240#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt) 241 242#include "hscx_irq.c" 243 244static irqreturn_t 245gazel_interrupt(int intno, void *dev_id) 246{ 247#define MAXCOUNT 5 248 struct IsdnCardState *cs = dev_id; 249 u_char valisac, valhscx; 250 int count = 0; 251 u_long flags; 252 253 spin_lock_irqsave(&cs->lock, flags); 254 do { 255 valhscx = ReadHSCX(cs, 1, HSCX_ISTA); 256 if (valhscx) 257 hscx_int_main(cs, valhscx); 258 valisac = ReadISAC(cs, ISAC_ISTA); 259 if (valisac) 260 isac_interrupt(cs, valisac); 261 count++; 262 } while ((valhscx || valisac) && (count < MAXCOUNT)); 263 264 WriteHSCX(cs, 0, HSCX_MASK, 0xFF); 265 WriteHSCX(cs, 1, HSCX_MASK, 0xFF); 266 WriteISAC(cs, ISAC_MASK, 0xFF); 267 WriteISAC(cs, ISAC_MASK, 0x0); 268 WriteHSCX(cs, 0, HSCX_MASK, 0x0); 269 WriteHSCX(cs, 1, HSCX_MASK, 0x0); 270 spin_unlock_irqrestore(&cs->lock, flags); 271 return IRQ_HANDLED; 272} 273 274 275static irqreturn_t 276gazel_interrupt_ipac(int intno, void *dev_id) 277{ 278 struct IsdnCardState *cs = dev_id; 279 u_char ista, val; 280 int count = 0; 281 u_long flags; 282 283 spin_lock_irqsave(&cs->lock, flags); 284 ista = ReadISAC(cs, IPAC_ISTA - 0x80); 285 do { 286 if (ista & 0x0f) { 287 val = ReadHSCX(cs, 1, HSCX_ISTA); 288 if (ista & 0x01) 289 val |= 0x01; 290 if (ista & 0x04) 291 val |= 0x02; 292 if (ista & 0x08) 293 val |= 0x04; 294 if (val) { 295 hscx_int_main(cs, val); 296 } 297 } 298 if (ista & 0x20) { 299 val = 0xfe & ReadISAC(cs, ISAC_ISTA); 300 if (val) { 301 isac_interrupt(cs, val); 302 } 303 } 304 if (ista & 0x10) { 305 val = 0x01; 306 isac_interrupt(cs, val); 307 } 308 ista = ReadISAC(cs, IPAC_ISTA - 0x80); 309 count++; 310 } 311 while ((ista & 0x3f) && (count < MAXCOUNT)); 312 313 WriteISAC(cs, IPAC_MASK - 0x80, 0xFF); 314 WriteISAC(cs, IPAC_MASK - 0x80, 0xC0); 315 spin_unlock_irqrestore(&cs->lock, flags); 316 return IRQ_HANDLED; 317} 318 319static void 320release_io_gazel(struct IsdnCardState *cs) 321{ 322 unsigned int i; 323 324 switch (cs->subtyp) { 325 case R647: 326 for (i = 0x0000; i < 0xC000; i += 0x1000) 327 release_region(i + cs->hw.gazel.hscx[0], 16); 328 release_region(0xC000 + cs->hw.gazel.hscx[0], 1); 329 break; 330 331 case R685: 332 release_region(cs->hw.gazel.hscx[0], 0x100); 333 release_region(cs->hw.gazel.cfg_reg, 0x80); 334 break; 335 336 case R753: 337 release_region(cs->hw.gazel.ipac, 0x8); 338 release_region(cs->hw.gazel.cfg_reg, 0x80); 339 break; 340 341 case R742: 342 release_region(cs->hw.gazel.ipac, 8); 343 break; 344 } 345} 346 347static int 348reset_gazel(struct IsdnCardState *cs) 349{ 350 unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg; 351 352 switch (cs->subtyp) { 353 case R647: 354 writereg(addr, 0, 0); 355 HZDELAY(10); 356 writereg(addr, 0, 1); 357 HZDELAY(2); 358 break; 359 case R685: 360 plxcntrl = inl(addr + PLX_CNTRL); 361 plxcntrl |= (RESET_9050 + RESET_GAZEL); 362 outl(plxcntrl, addr + PLX_CNTRL); 363 plxcntrl &= ~(RESET_9050 + RESET_GAZEL); 364 HZDELAY(4); 365 outl(plxcntrl, addr + PLX_CNTRL); 366 HZDELAY(10); 367 outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR); 368 break; 369 case R753: 370 plxcntrl = inl(addr + PLX_CNTRL); 371 plxcntrl |= (RESET_9050 + RESET_GAZEL); 372 outl(plxcntrl, addr + PLX_CNTRL); 373 plxcntrl &= ~(RESET_9050 + RESET_GAZEL); 374 WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20); 375 HZDELAY(4); 376 outl(plxcntrl, addr + PLX_CNTRL); 377 HZDELAY(10); 378 WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00); 379 WriteISAC(cs, IPAC_ACFG - 0x80, 0xff); 380 WriteISAC(cs, IPAC_AOE - 0x80, 0x0); 381 WriteISAC(cs, IPAC_MASK - 0x80, 0xff); 382 WriteISAC(cs, IPAC_CONF - 0x80, 0x1); 383 outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR); 384 WriteISAC(cs, IPAC_MASK - 0x80, 0xc0); 385 break; 386 case R742: 387 WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20); 388 HZDELAY(4); 389 WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00); 390 WriteISAC(cs, IPAC_ACFG - 0x80, 0xff); 391 WriteISAC(cs, IPAC_AOE - 0x80, 0x0); 392 WriteISAC(cs, IPAC_MASK - 0x80, 0xff); 393 WriteISAC(cs, IPAC_CONF - 0x80, 0x1); 394 WriteISAC(cs, IPAC_MASK - 0x80, 0xc0); 395 break; 396 } 397 return (0); 398} 399 400static int 401Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg) 402{ 403 u_long flags; 404 405 switch (mt) { 406 case CARD_RESET: 407 spin_lock_irqsave(&cs->lock, flags); 408 reset_gazel(cs); 409 spin_unlock_irqrestore(&cs->lock, flags); 410 return (0); 411 case CARD_RELEASE: 412 release_io_gazel(cs); 413 return (0); 414 case CARD_INIT: 415 spin_lock_irqsave(&cs->lock, flags); 416 inithscxisac(cs, 1); 417 if ((cs->subtyp==R647)||(cs->subtyp==R685)) { 418 int i; 419 for (i=0;i<(2+MAX_WAITING_CALLS);i++) { 420 cs->bcs[i].hw.hscx.tsaxr0 = 0x1f; 421 cs->bcs[i].hw.hscx.tsaxr1 = 0x23; 422 } 423 } 424 spin_unlock_irqrestore(&cs->lock, flags); 425 return (0); 426 case CARD_TEST: 427 return (0); 428 } 429 return (0); 430} 431 432static int 433reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs) 434{ 435 unsigned int i, j, base = 0, adr = 0, len = 0; 436 437 switch (cs->subtyp) { 438 case R647: 439 base = cs->hw.gazel.hscx[0]; 440 if (!request_region(adr = (0xC000 + base), len = 1, "gazel")) 441 goto error; 442 for (i = 0x0000; i < 0xC000; i += 0x1000) { 443 if (!request_region(adr = (i + base), len = 16, "gazel")) 444 goto error; 445 } 446 if (i != 0xC000) { 447 for (j = 0; j < i; j+= 0x1000) 448 release_region(j + base, 16); 449 release_region(0xC000 + base, 1); 450 goto error; 451 } 452 break; 453 454 case R685: 455 if (!request_region(adr = cs->hw.gazel.hscx[0], len = 0x100, "gazel")) 456 goto error; 457 if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) { 458 release_region(cs->hw.gazel.hscx[0],0x100); 459 goto error; 460 } 461 break; 462 463 case R753: 464 if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel")) 465 goto error; 466 if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) { 467 release_region(cs->hw.gazel.ipac, 8); 468 goto error; 469 } 470 break; 471 472 case R742: 473 if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel")) 474 goto error; 475 break; 476 } 477 478 return 0; 479 480 error: 481 printk(KERN_WARNING "Gazel: io ports 0x%x-0x%x already in use\n", 482 adr, adr + len); 483 return 1; 484} 485 486static int __devinit 487setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) 488{ 489 printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n"); 490 // we got an irq parameter, assume it is an ISA card 491 // R742 decodes address even in not started... 492 // R647 returns FF if not present or not started 493 // eventually needs improvment 494 if (readreg_ipac(card->para[1], IPAC_ID) == 1) 495 cs->subtyp = R742; 496 else 497 cs->subtyp = R647; 498 499 setup_isac(cs); 500 cs->hw.gazel.cfg_reg = card->para[1] + 0xC000; 501 cs->hw.gazel.ipac = card->para[1]; 502 cs->hw.gazel.isac = card->para[1] + 0x8000; 503 cs->hw.gazel.hscx[0] = card->para[1]; 504 cs->hw.gazel.hscx[1] = card->para[1] + 0x4000; 505 cs->irq = card->para[0]; 506 cs->hw.gazel.isacfifo = cs->hw.gazel.isac; 507 cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; 508 cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; 509 510 switch (cs->subtyp) { 511 case R647: 512 printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n"); 513 cs->dc.isac.adf2 = 0x87; 514 printk(KERN_INFO 515 "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", 516 cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); 517 printk(KERN_INFO 518 "Gazel: hscx A:0x%X hscx B:0x%X\n", 519 cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); 520 521 break; 522 case R742: 523 printk(KERN_INFO "Gazel: Card ISA R742 found\n"); 524 test_and_set_bit(HW_IPAC, &cs->HW_Flags); 525 printk(KERN_INFO 526 "Gazel: config irq:%d ipac:0x%X\n", 527 cs->irq, cs->hw.gazel.ipac); 528 break; 529 } 530 531 return (0); 532} 533 534#ifdef CONFIG_PCI 535static struct pci_dev *dev_tel __devinitdata = NULL; 536 537static int __devinit 538setup_gazelpci(struct IsdnCardState *cs) 539{ 540 u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0; 541 u_char pci_irq = 0, found; 542 u_int nbseek, seekcard; 543 544 printk(KERN_WARNING "Gazel: PCI card automatic recognition\n"); 545 546 found = 0; 547 seekcard = PCI_DEVICE_ID_PLX_R685; 548 for (nbseek = 0; nbseek < 4; nbseek++) { 549 if ((dev_tel = hisax_find_pci_device(PCI_VENDOR_ID_PLX, 550 seekcard, dev_tel))) { 551 if (pci_enable_device(dev_tel)) 552 return 1; 553 pci_irq = dev_tel->irq; 554 pci_ioaddr0 = pci_resource_start(dev_tel, 1); 555 pci_ioaddr1 = pci_resource_start(dev_tel, 2); 556 found = 1; 557 } 558 if (found) 559 break; 560 else { 561 switch (seekcard) { 562 case PCI_DEVICE_ID_PLX_R685: 563 seekcard = PCI_DEVICE_ID_PLX_R753; 564 break; 565 case PCI_DEVICE_ID_PLX_R753: 566 seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO; 567 break; 568 case PCI_DEVICE_ID_PLX_DJINN_ITOO: 569 seekcard = PCI_DEVICE_ID_PLX_OLITEC; 570 break; 571 } 572 } 573 } 574 if (!found) { 575 printk(KERN_WARNING "Gazel: No PCI card found\n"); 576 return (1); 577 } 578 if (!pci_irq) { 579 printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n"); 580 return 1; 581 } 582 cs->hw.gazel.pciaddr[0] = pci_ioaddr0; 583 cs->hw.gazel.pciaddr[1] = pci_ioaddr1; 584 setup_isac(cs); 585 pci_ioaddr1 &= 0xfffe; 586 cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe; 587 cs->hw.gazel.ipac = pci_ioaddr1; 588 cs->hw.gazel.isac = pci_ioaddr1 + 0x80; 589 cs->hw.gazel.hscx[0] = pci_ioaddr1; 590 cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40; 591 cs->hw.gazel.isacfifo = cs->hw.gazel.isac; 592 cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; 593 cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; 594 cs->irq = pci_irq; 595 cs->irq_flags |= IRQF_SHARED; 596 597 switch (seekcard) { 598 case PCI_DEVICE_ID_PLX_R685: 599 printk(KERN_INFO "Gazel: Card PCI R685 found\n"); 600 cs->subtyp = R685; 601 cs->dc.isac.adf2 = 0x87; 602 printk(KERN_INFO 603 "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", 604 cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); 605 printk(KERN_INFO 606 "Gazel: hscx A:0x%X hscx B:0x%X\n", 607 cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); 608 break; 609 case PCI_DEVICE_ID_PLX_R753: 610 case PCI_DEVICE_ID_PLX_DJINN_ITOO: 611 case PCI_DEVICE_ID_PLX_OLITEC: 612 printk(KERN_INFO "Gazel: Card PCI R753 found\n"); 613 cs->subtyp = R753; 614 test_and_set_bit(HW_IPAC, &cs->HW_Flags); 615 printk(KERN_INFO 616 "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", 617 cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); 618 break; 619 } 620 621 return (0); 622} 623#endif /* CONFIG_PCI */ 624 625int __devinit 626setup_gazel(struct IsdnCard *card) 627{ 628 struct IsdnCardState *cs = card->cs; 629 char tmp[64]; 630 u_char val; 631 632 strcpy(tmp, gazel_revision); 633 printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp)); 634 635 if (cs->typ != ISDN_CTYPE_GAZEL) 636 return (0); 637 638 if (card->para[0]) { 639 if (setup_gazelisa(card, cs)) 640 return (0); 641 } else { 642 643#ifdef CONFIG_PCI 644 if (setup_gazelpci(cs)) 645 return (0); 646#else 647 printk(KERN_WARNING "Gazel: Card PCI requested and NO_PCI_BIOS, unable to config\n"); 648 return (0); 649#endif /* CONFIG_PCI */ 650 } 651 652 if (reserve_regions(card, cs)) { 653 return (0); 654 } 655 if (reset_gazel(cs)) { 656 printk(KERN_WARNING "Gazel: wrong IRQ\n"); 657 release_io_gazel(cs); 658 return (0); 659 } 660 cs->readisac = &ReadISAC; 661 cs->writeisac = &WriteISAC; 662 cs->readisacfifo = &ReadISACfifo; 663 cs->writeisacfifo = &WriteISACfifo; 664 cs->BC_Read_Reg = &ReadHSCX; 665 cs->BC_Write_Reg = &WriteHSCX; 666 cs->BC_Send_Data = &hscx_fill_fifo; 667 cs->cardmsg = &Gazel_card_msg; 668 669 switch (cs->subtyp) { 670 case R647: 671 case R685: 672 cs->irq_func = &gazel_interrupt; 673 ISACVersion(cs, "Gazel:"); 674 if (HscxVersion(cs, "Gazel:")) { 675 printk(KERN_WARNING 676 "Gazel: wrong HSCX versions check IO address\n"); 677 release_io_gazel(cs); 678 return (0); 679 } 680 break; 681 case R742: 682 case R753: 683 cs->irq_func = &gazel_interrupt_ipac; 684 val = ReadISAC(cs, IPAC_ID - 0x80); 685 printk(KERN_INFO "Gazel: IPAC version %x\n", val); 686 break; 687 } 688 689 return (1); 690} 691