1/* $Id: gazel.c,v 2.19.2.4 2004/01/14 16:04:48 keil 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 480error: 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 setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) 487{ 488 printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n"); 489 // we got an irq parameter, assume it is an ISA card 490 // R742 decodes address even in not started... 491 // R647 returns FF if not present or not started 492 // eventually needs improvment 493 if (readreg_ipac(card->para[1], IPAC_ID) == 1) 494 cs->subtyp = R742; 495 else 496 cs->subtyp = R647; 497 498 setup_isac(cs); 499 cs->hw.gazel.cfg_reg = card->para[1] + 0xC000; 500 cs->hw.gazel.ipac = card->para[1]; 501 cs->hw.gazel.isac = card->para[1] + 0x8000; 502 cs->hw.gazel.hscx[0] = card->para[1]; 503 cs->hw.gazel.hscx[1] = card->para[1] + 0x4000; 504 cs->irq = card->para[0]; 505 cs->hw.gazel.isacfifo = cs->hw.gazel.isac; 506 cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; 507 cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; 508 509 switch (cs->subtyp) { 510 case R647: 511 printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n"); 512 cs->dc.isac.adf2 = 0x87; 513 printk(KERN_INFO 514 "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", 515 cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); 516 printk(KERN_INFO 517 "Gazel: hscx A:0x%X hscx B:0x%X\n", 518 cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); 519 520 break; 521 case R742: 522 printk(KERN_INFO "Gazel: Card ISA R742 found\n"); 523 test_and_set_bit(HW_IPAC, &cs->HW_Flags); 524 printk(KERN_INFO 525 "Gazel: config irq:%d ipac:0x%X\n", 526 cs->irq, cs->hw.gazel.ipac); 527 break; 528 } 529 530 return (0); 531} 532 533#ifdef CONFIG_PCI 534static struct pci_dev *dev_tel = NULL; 535 536static int setup_gazelpci(struct IsdnCardState *cs) 537{ 538 u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0; 539 u_char pci_irq = 0, found; 540 u_int nbseek, seekcard; 541 542 printk(KERN_WARNING "Gazel: PCI card automatic recognition\n"); 543 544 found = 0; 545 seekcard = PCI_DEVICE_ID_PLX_R685; 546 for (nbseek = 0; nbseek < 4; nbseek++) { 547 if ((dev_tel = hisax_find_pci_device(PCI_VENDOR_ID_PLX, 548 seekcard, dev_tel))) { 549 if (pci_enable_device(dev_tel)) 550 return 1; 551 pci_irq = dev_tel->irq; 552 pci_ioaddr0 = pci_resource_start(dev_tel, 1); 553 pci_ioaddr1 = pci_resource_start(dev_tel, 2); 554 found = 1; 555 } 556 if (found) 557 break; 558 else { 559 switch (seekcard) { 560 case PCI_DEVICE_ID_PLX_R685: 561 seekcard = PCI_DEVICE_ID_PLX_R753; 562 break; 563 case PCI_DEVICE_ID_PLX_R753: 564 seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO; 565 break; 566 case PCI_DEVICE_ID_PLX_DJINN_ITOO: 567 seekcard = PCI_DEVICE_ID_PLX_OLITEC; 568 break; 569 } 570 } 571 } 572 if (!found) { 573 printk(KERN_WARNING "Gazel: No PCI card found\n"); 574 return (1); 575 } 576 if (!pci_irq) { 577 printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n"); 578 return 1; 579 } 580 cs->hw.gazel.pciaddr[0] = pci_ioaddr0; 581 cs->hw.gazel.pciaddr[1] = pci_ioaddr1; 582 setup_isac(cs); 583 pci_ioaddr1 &= 0xfffe; 584 cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe; 585 cs->hw.gazel.ipac = pci_ioaddr1; 586 cs->hw.gazel.isac = pci_ioaddr1 + 0x80; 587 cs->hw.gazel.hscx[0] = pci_ioaddr1; 588 cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40; 589 cs->hw.gazel.isacfifo = cs->hw.gazel.isac; 590 cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; 591 cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; 592 cs->irq = pci_irq; 593 cs->irq_flags |= IRQF_SHARED; 594 595 switch (seekcard) { 596 case PCI_DEVICE_ID_PLX_R685: 597 printk(KERN_INFO "Gazel: Card PCI R685 found\n"); 598 cs->subtyp = R685; 599 cs->dc.isac.adf2 = 0x87; 600 printk(KERN_INFO 601 "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", 602 cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); 603 printk(KERN_INFO 604 "Gazel: hscx A:0x%X hscx B:0x%X\n", 605 cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); 606 break; 607 case PCI_DEVICE_ID_PLX_R753: 608 case PCI_DEVICE_ID_PLX_DJINN_ITOO: 609 case PCI_DEVICE_ID_PLX_OLITEC: 610 printk(KERN_INFO "Gazel: Card PCI R753 found\n"); 611 cs->subtyp = R753; 612 test_and_set_bit(HW_IPAC, &cs->HW_Flags); 613 printk(KERN_INFO 614 "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", 615 cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); 616 break; 617 } 618 619 return (0); 620} 621#endif /* CONFIG_PCI */ 622 623int setup_gazel(struct IsdnCard *card) 624{ 625 struct IsdnCardState *cs = card->cs; 626 char tmp[64]; 627 u_char val; 628 629 strcpy(tmp, gazel_revision); 630 printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp)); 631 632 if (cs->typ != ISDN_CTYPE_GAZEL) 633 return (0); 634 635 if (card->para[0]) { 636 if (setup_gazelisa(card, cs)) 637 return (0); 638 } else { 639 640#ifdef CONFIG_PCI 641 if (setup_gazelpci(cs)) 642 return (0); 643#else 644 printk(KERN_WARNING "Gazel: Card PCI requested and NO_PCI_BIOS, unable to config\n"); 645 return (0); 646#endif /* CONFIG_PCI */ 647 } 648 649 if (reserve_regions(card, cs)) { 650 return (0); 651 } 652 if (reset_gazel(cs)) { 653 printk(KERN_WARNING "Gazel: wrong IRQ\n"); 654 release_io_gazel(cs); 655 return (0); 656 } 657 cs->readisac = &ReadISAC; 658 cs->writeisac = &WriteISAC; 659 cs->readisacfifo = &ReadISACfifo; 660 cs->writeisacfifo = &WriteISACfifo; 661 cs->BC_Read_Reg = &ReadHSCX; 662 cs->BC_Write_Reg = &WriteHSCX; 663 cs->BC_Send_Data = &hscx_fill_fifo; 664 cs->cardmsg = &Gazel_card_msg; 665 666 switch (cs->subtyp) { 667 case R647: 668 case R685: 669 cs->irq_func = &gazel_interrupt; 670 ISACVersion(cs, "Gazel:"); 671 if (HscxVersion(cs, "Gazel:")) { 672 printk(KERN_WARNING 673 "Gazel: wrong HSCX versions check IO address\n"); 674 release_io_gazel(cs); 675 return (0); 676 } 677 break; 678 case R742: 679 case R753: 680 cs->irq_func = &gazel_interrupt_ipac; 681 val = ReadISAC(cs, IPAC_ID - 0x80); 682 printk(KERN_INFO "Gazel: IPAC version %x\n", val); 683 break; 684 } 685 686 return (1); 687} 688