1/* $Id: eicon_isa.c,v 1.1.1.1 2008/10/15 03:26:33 james26_jang Exp $ 2 * 3 * ISDN low-level module for Eicon active ISDN-Cards. 4 * Hardware-specific code for old ISA cards. 5 * 6 * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) 7 * Copyright 1998-2000 by Armin Schindler (mac@melware.de) 8 * Copyright 1999,2000 Cytronics & Melware (info@melware.de) 9 * 10 * This software may be used and distributed according to the terms 11 * of the GNU General Public License, incorporated herein by reference. 12 * 13 */ 14 15#include <linux/config.h> 16#include "eicon.h" 17#include "eicon_isa.h" 18 19#define check_shmem check_region 20#define release_shmem release_region 21#define request_shmem request_region 22 23char *eicon_isa_revision = "$Revision: 1.1.1.1 $"; 24 25#undef EICON_MCA_DEBUG 26 27#ifdef CONFIG_ISDN_DRV_EICON_ISA 28 29/* Mask for detecting invalid IRQ parameter */ 30static int eicon_isa_valid_irq[] = { 31 0x1c1c, /* 2, 3, 4, 10, 11, 12 (S)*/ 32 0x1c1c, /* 2, 3, 4, 10, 11, 12 (SX) */ 33 0x1cbc, /* 2, 3, 4, 5, 7, 10, 11, 12 (SCOM) */ 34 0x1cbc, /* 2, 3, 4, 5, 6, 10, 11, 12 (Quadro) */ 35 0x1cbc /* 2, 3, 4, 5, 7, 10, 11, 12 (S2M) */ 36}; 37 38static void 39eicon_isa_release_shmem(eicon_isa_card *card) { 40 if (card->mvalid) { 41 iounmap(card->shmem); 42 release_mem_region(card->physmem, card->ramsize); 43 } 44 card->mvalid = 0; 45} 46 47static void 48eicon_isa_release_irq(eicon_isa_card *card) { 49 if (!card->master) 50 return; 51 if (card->ivalid) 52 free_irq(card->irq, card); 53 card->ivalid = 0; 54} 55 56void 57eicon_isa_release(eicon_isa_card *card) { 58 eicon_isa_release_irq(card); 59 eicon_isa_release_shmem(card); 60} 61 62void 63eicon_isa_printpar(eicon_isa_card *card) { 64 switch (card->type) { 65 case EICON_CTYPE_S: 66 case EICON_CTYPE_SX: 67 case EICON_CTYPE_SCOM: 68 case EICON_CTYPE_QUADRO: 69 case EICON_CTYPE_S2M: 70 printk(KERN_INFO "Eicon %s at 0x%lx, irq %d.\n", 71 eicon_ctype_name[card->type], 72 card->physmem, 73 card->irq); 74 } 75} 76 77int 78eicon_isa_find_card(int Mem, int Irq, char * Id) 79{ 80 int primary = 1; 81 unsigned long amem; 82 83 if (!strlen(Id)) 84 return -1; 85 86 if (Mem == -1) 87 return -1; 88 89 /* Check for valid membase address */ 90 if ((Mem < 0x0c0000) || 91 (Mem > 0x0fc000) || 92 (Mem & 0xfff)) { 93 printk(KERN_WARNING "eicon_isa: illegal membase 0x%x for %s\n", 94 Mem, Id); 95 return -1; 96 } 97 if (check_mem_region(Mem, RAMSIZE)) { 98 printk(KERN_WARNING "eicon_isa_boot: memory at 0x%x already in use.\n", Mem); 99 return -1; 100 } 101 102 amem = (unsigned long) ioremap(Mem, RAMSIZE); 103 writew(0x55aa, amem + 0x402); 104 if (readw(amem + 0x402) != 0x55aa) primary = 0; 105 writew(0, amem + 0x402); 106 if (readw(amem + 0x402) != 0) primary = 0; 107 108 printk(KERN_INFO "Eicon: Driver-ID: %s\n", Id); 109 if (primary) { 110 printk(KERN_INFO "Eicon: assuming pri card at 0x%x\n", Mem); 111 writeb(0, amem + 0x3ffe); 112 iounmap((unsigned char *)amem); 113 return EICON_CTYPE_ISAPRI; 114 } else { 115 printk(KERN_INFO "Eicon: assuming bri card at 0x%x\n", Mem); 116 writeb(0, amem + 0x400); 117 iounmap((unsigned char *)amem); 118 return EICON_CTYPE_ISABRI; 119 } 120 return -1; 121} 122 123int 124eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) { 125 int tmp; 126 int timeout; 127 eicon_isa_codebuf cbuf; 128 unsigned char *code; 129 eicon_isa_boot *boot; 130 131 if (copy_from_user(&cbuf, cb, sizeof(eicon_isa_codebuf))) 132 return -EFAULT; 133 134 /* Allocate code-buffer and copy code from userspace */ 135 if (cbuf.bootstrap_len > 1024) { 136 printk(KERN_WARNING "eicon_isa_boot: Invalid startup-code size %ld\n", 137 cbuf.bootstrap_len); 138 return -EINVAL; 139 } 140 if (!(code = kmalloc(cbuf.bootstrap_len, GFP_KERNEL))) { 141 printk(KERN_WARNING "eicon_isa_boot: Couldn't allocate code buffer\n"); 142 return -ENOMEM; 143 } 144 if (copy_from_user(code, &cb->code, cbuf.bootstrap_len)) { 145 kfree(code); 146 return -EFAULT; 147 } 148 149 if (card->type == EICON_CTYPE_ISAPRI) 150 card->ramsize = RAMSIZE_P; 151 else 152 card->ramsize = RAMSIZE; 153 154 if (check_mem_region(card->physmem, card->ramsize)) { 155 printk(KERN_WARNING "eicon_isa_boot: memory at 0x%lx already in use.\n", 156 card->physmem); 157 kfree(code); 158 return -EBUSY; 159 } 160 request_mem_region(card->physmem, card->ramsize, "Eicon ISA ISDN"); 161 card->shmem = (eicon_isa_shmem *) ioremap(card->physmem, card->ramsize); 162#ifdef EICON_MCA_DEBUG 163 printk(KERN_INFO "eicon_isa_boot: card->ramsize = %d.\n", card->ramsize); 164#endif 165 card->mvalid = 1; 166 167 switch(card->type) { 168 case EICON_CTYPE_S: 169 case EICON_CTYPE_SX: 170 case EICON_CTYPE_SCOM: 171 case EICON_CTYPE_QUADRO: 172 case EICON_CTYPE_ISABRI: 173 card->intack = (__u8 *)card->shmem + INTACK; 174 card->startcpu = (__u8 *)card->shmem + STARTCPU; 175 card->stopcpu = (__u8 *)card->shmem + STOPCPU; 176 break; 177 case EICON_CTYPE_S2M: 178 case EICON_CTYPE_ISAPRI: 179 card->intack = (__u8 *)card->shmem + INTACK_P; 180 card->startcpu = (__u8 *)card->shmem + STARTCPU_P; 181 card->stopcpu = (__u8 *)card->shmem + STOPCPU_P; 182 break; 183 default: 184 printk(KERN_WARNING "eicon_isa_boot: Invalid card type %d\n", card->type); 185 eicon_isa_release_shmem(card); 186 kfree(code); 187 return -EINVAL; 188 } 189 190 /* clear any pending irq's */ 191 readb(card->intack); 192#ifdef CONFIG_MCA 193 if (MCA_bus) { 194 if (card->type == EICON_CTYPE_SCOM) { 195 outb_p(0,card->io+1); 196 } 197 else { 198 printk(KERN_WARNING "eicon_isa_boot: Card type not supported yet.\n"); 199 eicon_isa_release_shmem(card); 200 return -EINVAL; 201 }; 202 203#ifdef EICON_MCA_DEBUG 204 printk(KERN_INFO "eicon_isa_boot: card->io = %x.\n", card->io); 205 printk(KERN_INFO "eicon_isa_boot: card->irq = %d.\n", (int)card->irq); 206#endif 207 } 208#else 209 /* set reset-line active */ 210 writeb(0, card->stopcpu); 211#endif /* CONFIG_MCA */ 212 /* clear irq-requests */ 213 writeb(0, card->intack); 214 readb(card->intack); 215 216 /* Copy code into card */ 217 memcpy_toio(&card->shmem->c, code, cbuf.bootstrap_len); 218 219 /* Check for properly loaded code */ 220 if (!check_signature((unsigned long)&card->shmem->c, code, 1020)) { 221 printk(KERN_WARNING "eicon_isa_boot: Could not load startup-code\n"); 222 eicon_isa_release_shmem(card); 223 kfree(code); 224 return -EIO; 225 } 226 /* if 16k-ramsize, duplicate the reset-jump-code */ 227 if (card->ramsize == RAMSIZE_P) 228 memcpy_toio((__u8 *)card->shmem + 0x3ff0, &code[0x3f0], 12); 229 230 kfree(code); 231 boot = &card->shmem->boot; 232 233 /* Delay 0.2 sec. */ 234 SLEEP(HZ / 5); 235 236 /* Start CPU */ 237 writeb(cbuf.boot_opt, &boot->ctrl); 238#ifdef CONFIG_MCA 239 if (MCA_bus) { 240 outb_p(0, card->io); 241 } 242#else 243 writeb(0, card->startcpu); 244#endif /* CONFIG_MCA */ 245 246 /* Delay 0.2 sec. */ 247 SLEEP(HZ / 5); 248 249 timeout = jiffies + (HZ * 22); 250 while (time_before(jiffies, timeout)) { 251 if (readb(&boot->ctrl) == 0) 252 break; 253 SLEEP(10); 254 } 255 if (readb(&boot->ctrl) != 0) { 256 printk(KERN_WARNING "eicon_isa_boot: CPU test failed.\n"); 257#ifdef EICON_MCA_DEBUG 258 printk(KERN_INFO "eicon_isa_boot: &boot->ctrl = %d.\n", 259 readb(&boot->ctrl)); 260#endif 261 eicon_isa_release_shmem(card); 262 return -EIO; 263 } 264 265 /* Check for memory-test errors */ 266 if (readw(&boot->ebit)) { 267 printk(KERN_WARNING "eicon_isa_boot: memory test failed (bit 0x%04x at 0x%08x)\n", 268 readw(&boot->ebit), readl(&boot->eloc)); 269 eicon_isa_release_shmem(card); 270 return -EIO; 271 } 272 273 /* Check card type and memory size */ 274 tmp = readb(&boot->card); 275 if ((tmp < 0) || (tmp > 4)) { 276 printk(KERN_WARNING "eicon_isa_boot: Type detect failed\n"); 277 eicon_isa_release_shmem(card); 278 return -EIO; 279 } 280 card->type = tmp; 281 ((eicon_card *)card->card)->type = tmp; 282 283 tmp = readb(&boot->msize); 284 if (tmp != 8 && tmp != 16 && tmp != 24 && 285 tmp != 32 && tmp != 48 && tmp != 60) { 286 printk(KERN_WARNING "eicon_isa_boot: invalid memsize\n"); 287 eicon_isa_release_shmem(card); 288 return -EIO; 289 } 290 printk(KERN_INFO "%s: startup-code loaded\n", eicon_ctype_name[card->type]); 291 if ((card->type == EICON_CTYPE_QUADRO) && (card->master)) { 292 tmp = eicon_addcard(card->type, card->physmem, card->irq, 293 ((eicon_card *)card->card)->regname, 0); 294 printk(KERN_INFO "Eicon: %d adapters added\n", tmp); 295 } 296 return 0; 297} 298 299int 300eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { 301 eicon_isa_boot *boot; 302 int tmp; 303 int timeout; 304 int j; 305 eicon_isa_codebuf cbuf; 306 unsigned char *code; 307 unsigned char *p; 308 309 if (copy_from_user(&cbuf, cb, sizeof(eicon_isa_codebuf))) 310 return -EFAULT; 311 312 if (!(code = kmalloc(cbuf.firmware_len, GFP_KERNEL))) { 313 printk(KERN_WARNING "eicon_isa_load: Couldn't allocate code buffer\n"); 314 return -ENOMEM; 315 } 316 317 if (copy_from_user(code, &cb->code, cbuf.firmware_len)) { 318 kfree(code); 319 return -EFAULT; 320 } 321 322 boot = &card->shmem->boot; 323 324 if ((!card->ivalid) && card->master) { 325 card->irqprobe = 1; 326 /* Check for valid IRQ */ 327 if ((card->irq < 0) || (card->irq > 15) || 328 (!((1 << card->irq) & eicon_isa_valid_irq[card->type & 0x0f]))) { 329 printk(KERN_WARNING "eicon_isa_load: illegal irq: %d\n", card->irq); 330 eicon_isa_release_shmem(card); 331 kfree(code); 332 return -EINVAL; 333 } 334 /* Register irq */ 335 if (!request_irq(card->irq, &eicon_irq, 0, "Eicon ISA ISDN", card)) 336 card->ivalid = 1; 337 else { 338 printk(KERN_WARNING "eicon_isa_load: irq %d already in use.\n", 339 card->irq); 340 eicon_isa_release_shmem(card); 341 kfree(code); 342 return -EBUSY; 343 } 344 } 345 346 tmp = readb(&boot->msize); 347 if (tmp != 8 && tmp != 16 && tmp != 24 && 348 tmp != 32 && tmp != 48 && tmp != 60) { 349 printk(KERN_WARNING "eicon_isa_load: invalid memsize\n"); 350 eicon_isa_release_shmem(card); 351 return -EIO; 352 } 353 354 eicon_isa_printpar(card); 355 356 /* Download firmware */ 357 printk(KERN_INFO "%s %dkB, loading firmware ...\n", 358 eicon_ctype_name[card->type], 359 tmp * 16); 360 tmp = cbuf.firmware_len >> 8; 361 p = code; 362 while (tmp--) { 363 memcpy_toio(&boot->b, p, 256); 364 writeb(1, &boot->ctrl); 365 timeout = jiffies + HZ / 10; 366 while (time_before(jiffies, timeout)) { 367 if (readb(&boot->ctrl) == 0) 368 break; 369 SLEEP(2); 370 } 371 if (readb(&boot->ctrl)) { 372 printk(KERN_WARNING "eicon_isa_load: download timeout at 0x%x\n", p-code); 373 eicon_isa_release(card); 374 kfree(code); 375 return -EIO; 376 } 377 p += 256; 378 } 379 kfree(code); 380 381 /* Initialize firmware parameters */ 382 memcpy_toio(&card->shmem->c[8], &cbuf.tei, 14); 383 memcpy_toio(&card->shmem->c[32], &cbuf.oad, 96); 384 memcpy_toio(&card->shmem->c[128], &cbuf.oad, 96); 385 386 /* Start firmware, wait for signature */ 387 writeb(2, &boot->ctrl); 388 timeout = jiffies + (5*HZ); 389 while (time_before(jiffies, timeout)) { 390 if (readw(&boot->signature) == 0x4447) 391 break; 392 SLEEP(2); 393 } 394 if (readw(&boot->signature) != 0x4447) { 395 printk(KERN_WARNING "eicon_isa_load: firmware selftest failed %04x\n", 396 readw(&boot->signature)); 397 eicon_isa_release(card); 398 return -EIO; 399 } 400 401 card->channels = readb(&card->shmem->c[0x3f6]); 402 403 /* clear irq-requests, reset irq-count */ 404 readb(card->intack); 405 writeb(0, card->intack); 406 407 if (card->master) { 408 card->irqprobe = 1; 409 /* Trigger an interrupt and check if it is delivered */ 410 tmp = readb(&card->shmem->com.ReadyInt); 411 tmp ++; 412 writeb(tmp, &card->shmem->com.ReadyInt); 413 timeout = jiffies + HZ / 5; 414 while (time_before(jiffies, timeout)) { 415 if (card->irqprobe > 1) 416 break; 417 SLEEP(2); 418 } 419 if (card->irqprobe == 1) { 420 printk(KERN_WARNING "eicon_isa_load: IRQ # %d test failed\n", card->irq); 421 eicon_isa_release(card); 422 return -EIO; 423 } 424 } 425#ifdef EICON_MCA_DEBUG 426 printk(KERN_INFO "eicon_isa_load: IRQ # %d test succeeded.\n", card->irq); 427#endif 428 429 writeb(card->irq, &card->shmem->com.Int); 430 431 /* initializing some variables */ 432 ((eicon_card *)card->card)->ReadyInt = 0; 433 ((eicon_card *)card->card)->ref_in = 1; 434 ((eicon_card *)card->card)->ref_out = 1; 435 for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL; 436 for(j=0; j< (card->channels + 1); j++) { 437 ((eicon_card *)card->card)->bch[j].e.busy = 0; 438 ((eicon_card *)card->card)->bch[j].e.D3Id = 0; 439 ((eicon_card *)card->card)->bch[j].e.B2Id = 0; 440 ((eicon_card *)card->card)->bch[j].e.ref = 0; 441 ((eicon_card *)card->card)->bch[j].e.Req = 0; 442 ((eicon_card *)card->card)->bch[j].e.complete = 1; 443 ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL; 444 } 445 446 printk(KERN_INFO "Eicon: Supported channels: %d\n", card->channels); 447 printk(KERN_INFO "%s successfully started\n", eicon_ctype_name[card->type]); 448 449 /* Enable normal IRQ processing */ 450 card->irqprobe = 0; 451 return 0; 452} 453 454#endif /* CONFIG_ISDN_DRV_EICON_ISA */ 455