1 /* 2 * Generic Generic NCR5380 driver 3 * 4 * Copyright 1993, Drew Eckhardt 5 * Visionary Computing 6 * (Unix and Linux consulting and custom programming) 7 * drew@colorado.edu 8 * +1 (303) 440-4894 9 * 10 * NCR53C400 extensions (c) 1994,1995,1996, Kevin Lentin 11 * K.Lentin@cs.monash.edu.au 12 * 13 * NCR53C400A extensions (c) 1996, Ingmar Baumgart 14 * ingmar@gonzo.schwaben.de 15 * 16 * DTC3181E extensions (c) 1997, Ronald van Cuijlenborg 17 * ronald.van.cuijlenborg@tip.nl or nutty@dds.nl 18 * 19 * Added ISAPNP support for DTC436 adapters, 20 * Thomas Sailer, sailer@ife.ee.ethz.ch 21 * 22 * See Documentation/scsi/g_NCR5380.txt for more info. 23 */ 24 25 #include <asm/io.h> 26 #include <linux/blkdev.h> 27 #include <linux/module.h> 28 #include <scsi/scsi_host.h> 29 #include "g_NCR5380.h" 30 #include "NCR5380.h" 31 #include <linux/init.h> 32 #include <linux/ioport.h> 33 #include <linux/isa.h> 34 #include <linux/pnp.h> 35 #include <linux/interrupt.h> 36 37 #define MAX_CARDS 8 38 39 /* old-style parameters for compatibility */ 40 static int ncr_irq; 41 static int ncr_addr; 42 static int ncr_5380; 43 static int ncr_53c400; 44 static int ncr_53c400a; 45 static int dtc_3181e; 46 static int hp_c2502; 47 module_param(ncr_irq, int, 0); 48 module_param(ncr_addr, int, 0); 49 module_param(ncr_5380, int, 0); 50 module_param(ncr_53c400, int, 0); 51 module_param(ncr_53c400a, int, 0); 52 module_param(dtc_3181e, int, 0); 53 module_param(hp_c2502, int, 0); 54 55 static int irq[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 56 module_param_array(irq, int, NULL, 0); 57 MODULE_PARM_DESC(irq, "IRQ number(s)"); 58 59 static int base[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 60 module_param_array(base, int, NULL, 0); 61 MODULE_PARM_DESC(base, "base address(es)"); 62 63 static int card[] = { -1, -1, -1, -1, -1, -1, -1, -1 }; 64 module_param_array(card, int, NULL, 0); 65 MODULE_PARM_DESC(card, "card type (0=NCR5380, 1=NCR53C400, 2=NCR53C400A, 3=DTC3181E, 4=HP C2502)"); 66 67 MODULE_ALIAS("g_NCR5380_mmio"); 68 MODULE_LICENSE("GPL"); 69 70 /* 71 * Configure I/O address of 53C400A or DTC436 by writing magic numbers 72 * to ports 0x779 and 0x379. 73 */ 74 static void magic_configure(int idx, u8 irq, u8 magic[]) 75 { 76 u8 cfg = 0; 77 78 outb(magic[0], 0x779); 79 outb(magic[1], 0x379); 80 outb(magic[2], 0x379); 81 outb(magic[3], 0x379); 82 outb(magic[4], 0x379); 83 84 /* allowed IRQs for HP C2502 */ 85 if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7) 86 irq = 0; 87 if (idx >= 0 && idx <= 7) 88 cfg = 0x80 | idx | (irq << 4); 89 outb(cfg, 0x379); 90 } 91 92 static unsigned int ncr_53c400a_ports[] = { 93 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 94 }; 95 static unsigned int dtc_3181e_ports[] = { 96 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0 97 }; 98 static u8 ncr_53c400a_magic[] = { /* 53C400A & DTC436 */ 99 0x59, 0xb9, 0xc5, 0xae, 0xa6 100 }; 101 static u8 hp_c2502_magic[] = { /* HP C2502 */ 102 0x0f, 0x22, 0xf0, 0x20, 0x80 103 }; 104 105 static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, 106 struct device *pdev, int base, int irq, int board) 107 { 108 bool is_pmio = base <= 0xffff; 109 int ret; 110 int flags = 0; 111 unsigned int *ports = NULL; 112 u8 *magic = NULL; 113 int i; 114 int port_idx = -1; 115 unsigned long region_size; 116 struct Scsi_Host *instance; 117 struct NCR5380_hostdata *hostdata; 118 u8 __iomem *iomem; 119 120 switch (board) { 121 case BOARD_NCR5380: 122 flags = FLAG_NO_PSEUDO_DMA | FLAG_DMA_FIXUP; 123 break; 124 case BOARD_NCR53C400A: 125 ports = ncr_53c400a_ports; 126 magic = ncr_53c400a_magic; 127 break; 128 case BOARD_HP_C2502: 129 ports = ncr_53c400a_ports; 130 magic = hp_c2502_magic; 131 break; 132 case BOARD_DTC3181E: 133 ports = dtc_3181e_ports; 134 magic = ncr_53c400a_magic; 135 break; 136 } 137 138 if (is_pmio && ports && magic) { 139 /* wakeup sequence for the NCR53C400A and DTC3181E */ 140 141 /* Disable the adapter and look for a free io port */ 142 magic_configure(-1, 0, magic); 143 144 region_size = 16; 145 if (base) 146 for (i = 0; ports[i]; i++) { 147 if (base == ports[i]) { /* index found */ 148 if (!request_region(ports[i], 149 region_size, 150 "ncr53c80")) 151 return -EBUSY; 152 break; 153 } 154 } 155 else 156 for (i = 0; ports[i]; i++) { 157 if (!request_region(ports[i], region_size, 158 "ncr53c80")) 159 continue; 160 if (inb(ports[i]) == 0xff) 161 break; 162 release_region(ports[i], region_size); 163 } 164 if (ports[i]) { 165 /* At this point we have our region reserved */ 166 magic_configure(i, 0, magic); /* no IRQ yet */ 167 base = ports[i]; 168 outb(0xc0, base + 9); 169 if (inb(base + 9) != 0x80) { 170 ret = -ENODEV; 171 goto out_release; 172 } 173 port_idx = i; 174 } else 175 return -EINVAL; 176 } else if (is_pmio) { 177 /* NCR5380 - no configuration, just grab */ 178 region_size = 8; 179 if (!base || !request_region(base, region_size, "ncr5380")) 180 return -EBUSY; 181 } else { /* MMIO */ 182 region_size = NCR53C400_region_size; 183 if (!request_mem_region(base, region_size, "ncr5380")) 184 return -EBUSY; 185 } 186 187 if (is_pmio) 188 iomem = ioport_map(base, region_size); 189 else 190 iomem = ioremap(base, region_size); 191 192 if (!iomem) { 193 ret = -ENOMEM; 194 goto out_release; 195 } 196 197 instance = scsi_host_alloc(tpnt, sizeof(struct NCR5380_hostdata)); 198 if (instance == NULL) { 199 ret = -ENOMEM; 200 goto out_unmap; 201 } 202 hostdata = shost_priv(instance); 203 204 hostdata->io = iomem; 205 hostdata->region_size = region_size; 206 207 if (is_pmio) { 208 hostdata->io_port = base; 209 hostdata->io_width = 1; /* 8-bit PDMA by default */ 210 hostdata->offset = 0; 211 212 /* 213 * On NCR53C400 boards, NCR5380 registers are mapped 8 past 214 * the base address. 215 */ 216 switch (board) { 217 case BOARD_NCR53C400: 218 hostdata->io_port += 8; 219 hostdata->c400_ctl_status = 0; 220 hostdata->c400_blk_cnt = 1; 221 hostdata->c400_host_buf = 4; 222 break; 223 case BOARD_DTC3181E: 224 hostdata->io_width = 2; /* 16-bit PDMA */ 225 /* fall through */ 226 case BOARD_NCR53C400A: 227 case BOARD_HP_C2502: 228 hostdata->c400_ctl_status = 9; 229 hostdata->c400_blk_cnt = 10; 230 hostdata->c400_host_buf = 8; 231 break; 232 } 233 } else { 234 hostdata->base = base; 235 hostdata->offset = NCR53C400_mem_base; 236 switch (board) { 237 case BOARD_NCR53C400: 238 hostdata->c400_ctl_status = 0x100; 239 hostdata->c400_blk_cnt = 0x101; 240 hostdata->c400_host_buf = 0x104; 241 break; 242 case BOARD_DTC3181E: 243 case BOARD_NCR53C400A: 244 case BOARD_HP_C2502: 245 pr_err(DRV_MODULE_NAME ": unknown register offsets\n"); 246 ret = -EINVAL; 247 goto out_unregister; 248 } 249 } 250 251 ret = NCR5380_init(instance, flags | FLAG_LATE_DMA_SETUP); 252 if (ret) 253 goto out_unregister; 254 255 switch (board) { 256 case BOARD_NCR53C400: 257 case BOARD_DTC3181E: 258 case BOARD_NCR53C400A: 259 case BOARD_HP_C2502: 260 NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); 261 } 262 263 NCR5380_maybe_reset_bus(instance); 264 265 if (irq != IRQ_AUTO) 266 instance->irq = irq; 267 else 268 instance->irq = NCR5380_probe_irq(instance, 0xffff); 269 270 /* Compatibility with documented NCR5380 kernel parameters */ 271 if (instance->irq == 255) 272 instance->irq = NO_IRQ; 273 274 if (instance->irq != NO_IRQ) { 275 /* set IRQ for HP C2502 */ 276 if (board == BOARD_HP_C2502) 277 magic_configure(port_idx, instance->irq, magic); 278 if (request_irq(instance->irq, generic_NCR5380_intr, 279 0, "NCR5380", instance)) { 280 printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); 281 instance->irq = NO_IRQ; 282 } 283 } 284 285 if (instance->irq == NO_IRQ) { 286 printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); 287 printk(KERN_INFO "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); 288 } 289 290 ret = scsi_add_host(instance, pdev); 291 if (ret) 292 goto out_free_irq; 293 scsi_scan_host(instance); 294 dev_set_drvdata(pdev, instance); 295 return 0; 296 297 out_free_irq: 298 if (instance->irq != NO_IRQ) 299 free_irq(instance->irq, instance); 300 NCR5380_exit(instance); 301 out_unregister: 302 scsi_host_put(instance); 303 out_unmap: 304 iounmap(iomem); 305 out_release: 306 if (is_pmio) 307 release_region(base, region_size); 308 else 309 release_mem_region(base, region_size); 310 return ret; 311 } 312 313 static void generic_NCR5380_release_resources(struct Scsi_Host *instance) 314 { 315 struct NCR5380_hostdata *hostdata = shost_priv(instance); 316 void __iomem *iomem = hostdata->io; 317 unsigned long io_port = hostdata->io_port; 318 unsigned long base = hostdata->base; 319 unsigned long region_size = hostdata->region_size; 320 321 scsi_remove_host(instance); 322 if (instance->irq != NO_IRQ) 323 free_irq(instance->irq, instance); 324 NCR5380_exit(instance); 325 scsi_host_put(instance); 326 iounmap(iomem); 327 if (io_port) 328 release_region(io_port, region_size); 329 else 330 release_mem_region(base, region_size); 331 } 332 333 /** 334 * generic_NCR5380_pread - pseudo DMA read 335 * @hostdata: scsi host private data 336 * @dst: buffer to read into 337 * @len: buffer length 338 * 339 * Perform a pseudo DMA mode read from an NCR53C400 or equivalent 340 * controller 341 */ 342 343 static inline int generic_NCR5380_pread(struct NCR5380_hostdata *hostdata, 344 unsigned char *dst, int len) 345 { 346 int blocks = len / 128; 347 int start = 0; 348 349 NCR5380_write(hostdata->c400_ctl_status, CSR_BASE | CSR_TRANS_DIR); 350 NCR5380_write(hostdata->c400_blk_cnt, blocks); 351 while (1) { 352 if (NCR5380_read(hostdata->c400_blk_cnt) == 0) 353 break; 354 if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) { 355 printk(KERN_ERR "53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks); 356 return -1; 357 } 358 while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) 359 ; /* FIXME - no timeout */ 360 361 if (hostdata->io_port && hostdata->io_width == 2) 362 insw(hostdata->io_port + hostdata->c400_host_buf, 363 dst + start, 64); 364 else if (hostdata->io_port) 365 insb(hostdata->io_port + hostdata->c400_host_buf, 366 dst + start, 128); 367 else 368 memcpy_fromio(dst + start, 369 hostdata->io + NCR53C400_host_buffer, 128); 370 371 start += 128; 372 blocks--; 373 } 374 375 if (blocks) { 376 while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) 377 ; /* FIXME - no timeout */ 378 379 if (hostdata->io_port && hostdata->io_width == 2) 380 insw(hostdata->io_port + hostdata->c400_host_buf, 381 dst + start, 64); 382 else if (hostdata->io_port) 383 insb(hostdata->io_port + hostdata->c400_host_buf, 384 dst + start, 128); 385 else 386 memcpy_fromio(dst + start, 387 hostdata->io + NCR53C400_host_buffer, 128); 388 389 start += 128; 390 blocks--; 391 } 392 393 if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) 394 printk("53C400r: no 53C80 gated irq after transfer"); 395 396 /* wait for 53C80 registers to be available */ 397 while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)) 398 ; 399 400 if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) 401 printk(KERN_ERR "53C400r: no end dma signal\n"); 402 403 return 0; 404 } 405 406 /** 407 * generic_NCR5380_pwrite - pseudo DMA write 408 * @hostdata: scsi host private data 409 * @dst: buffer to read into 410 * @len: buffer length 411 * 412 * Perform a pseudo DMA mode read from an NCR53C400 or equivalent 413 * controller 414 */ 415 416 static inline int generic_NCR5380_pwrite(struct NCR5380_hostdata *hostdata, 417 unsigned char *src, int len) 418 { 419 int blocks = len / 128; 420 int start = 0; 421 422 NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); 423 NCR5380_write(hostdata->c400_blk_cnt, blocks); 424 while (1) { 425 if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) { 426 printk(KERN_ERR "53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks); 427 return -1; 428 } 429 430 if (NCR5380_read(hostdata->c400_blk_cnt) == 0) 431 break; 432 while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) 433 ; // FIXME - timeout 434 435 if (hostdata->io_port && hostdata->io_width == 2) 436 outsw(hostdata->io_port + hostdata->c400_host_buf, 437 src + start, 64); 438 else if (hostdata->io_port) 439 outsb(hostdata->io_port + hostdata->c400_host_buf, 440 src + start, 128); 441 else 442 memcpy_toio(hostdata->io + NCR53C400_host_buffer, 443 src + start, 128); 444 445 start += 128; 446 blocks--; 447 } 448 if (blocks) { 449 while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) 450 ; // FIXME - no timeout 451 452 if (hostdata->io_port && hostdata->io_width == 2) 453 outsw(hostdata->io_port + hostdata->c400_host_buf, 454 src + start, 64); 455 else if (hostdata->io_port) 456 outsb(hostdata->io_port + hostdata->c400_host_buf, 457 src + start, 128); 458 else 459 memcpy_toio(hostdata->io + NCR53C400_host_buffer, 460 src + start, 128); 461 462 start += 128; 463 blocks--; 464 } 465 466 /* wait for 53C80 registers to be available */ 467 while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)) { 468 udelay(4); /* DTC436 chip hangs without this */ 469 /* FIXME - no timeout */ 470 } 471 472 if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) { 473 printk(KERN_ERR "53C400w: no end dma signal\n"); 474 } 475 476 while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT)) 477 ; // TIMEOUT 478 return 0; 479 } 480 481 static int generic_NCR5380_dma_xfer_len(struct NCR5380_hostdata *hostdata, 482 struct scsi_cmnd *cmd) 483 { 484 int transfersize = cmd->transfersize; 485 486 if (hostdata->flags & FLAG_NO_PSEUDO_DMA) 487 return 0; 488 489 /* Limit transfers to 32K, for xx400 & xx406 490 * pseudoDMA that transfers in 128 bytes blocks. 491 */ 492 if (transfersize > 32 * 1024 && cmd->SCp.this_residual && 493 !(cmd->SCp.this_residual % transfersize)) 494 transfersize = 32 * 1024; 495 496 /* 53C400 datasheet: non-modulo-128-byte transfers should use PIO */ 497 if (transfersize % 128) 498 transfersize = 0; 499 500 return transfersize; 501 } 502 503 /* 504 * Include the NCR5380 core code that we build our driver around 505 */ 506 507 #include "NCR5380.c" 508 509 static struct scsi_host_template driver_template = { 510 .module = THIS_MODULE, 511 .proc_name = DRV_MODULE_NAME, 512 .name = "Generic NCR5380/NCR53C400 SCSI", 513 .info = generic_NCR5380_info, 514 .queuecommand = generic_NCR5380_queue_command, 515 .eh_abort_handler = generic_NCR5380_abort, 516 .eh_bus_reset_handler = generic_NCR5380_bus_reset, 517 .can_queue = 16, 518 .this_id = 7, 519 .sg_tablesize = SG_ALL, 520 .cmd_per_lun = 2, 521 .use_clustering = DISABLE_CLUSTERING, 522 .cmd_size = NCR5380_CMD_SIZE, 523 .max_sectors = 128, 524 }; 525 526 527 static int generic_NCR5380_isa_match(struct device *pdev, unsigned int ndev) 528 { 529 int ret = generic_NCR5380_init_one(&driver_template, pdev, base[ndev], 530 irq[ndev], card[ndev]); 531 if (ret) { 532 if (base[ndev]) 533 printk(KERN_WARNING "Card not found at address 0x%03x\n", 534 base[ndev]); 535 return 0; 536 } 537 538 return 1; 539 } 540 541 static int generic_NCR5380_isa_remove(struct device *pdev, 542 unsigned int ndev) 543 { 544 generic_NCR5380_release_resources(dev_get_drvdata(pdev)); 545 dev_set_drvdata(pdev, NULL); 546 return 0; 547 } 548 549 static struct isa_driver generic_NCR5380_isa_driver = { 550 .match = generic_NCR5380_isa_match, 551 .remove = generic_NCR5380_isa_remove, 552 .driver = { 553 .name = DRV_MODULE_NAME 554 }, 555 }; 556 557 #ifdef CONFIG_PNP 558 static struct pnp_device_id generic_NCR5380_pnp_ids[] = { 559 { .id = "DTC436e", .driver_data = BOARD_DTC3181E }, 560 { .id = "" } 561 }; 562 MODULE_DEVICE_TABLE(pnp, generic_NCR5380_pnp_ids); 563 564 static int generic_NCR5380_pnp_probe(struct pnp_dev *pdev, 565 const struct pnp_device_id *id) 566 { 567 int base, irq; 568 569 if (pnp_activate_dev(pdev) < 0) 570 return -EBUSY; 571 572 base = pnp_port_start(pdev, 0); 573 irq = pnp_irq(pdev, 0); 574 575 return generic_NCR5380_init_one(&driver_template, &pdev->dev, base, irq, 576 id->driver_data); 577 } 578 579 static void generic_NCR5380_pnp_remove(struct pnp_dev *pdev) 580 { 581 generic_NCR5380_release_resources(pnp_get_drvdata(pdev)); 582 pnp_set_drvdata(pdev, NULL); 583 } 584 585 static struct pnp_driver generic_NCR5380_pnp_driver = { 586 .name = DRV_MODULE_NAME, 587 .id_table = generic_NCR5380_pnp_ids, 588 .probe = generic_NCR5380_pnp_probe, 589 .remove = generic_NCR5380_pnp_remove, 590 }; 591 #endif /* defined(CONFIG_PNP) */ 592 593 static int pnp_registered, isa_registered; 594 595 static int __init generic_NCR5380_init(void) 596 { 597 int ret = 0; 598 599 /* compatibility with old-style parameters */ 600 if (irq[0] == 0 && base[0] == 0 && card[0] == -1) { 601 irq[0] = ncr_irq; 602 base[0] = ncr_addr; 603 if (ncr_5380) 604 card[0] = BOARD_NCR5380; 605 if (ncr_53c400) 606 card[0] = BOARD_NCR53C400; 607 if (ncr_53c400a) 608 card[0] = BOARD_NCR53C400A; 609 if (dtc_3181e) 610 card[0] = BOARD_DTC3181E; 611 if (hp_c2502) 612 card[0] = BOARD_HP_C2502; 613 } 614 615 #ifdef CONFIG_PNP 616 if (!pnp_register_driver(&generic_NCR5380_pnp_driver)) 617 pnp_registered = 1; 618 #endif 619 ret = isa_register_driver(&generic_NCR5380_isa_driver, MAX_CARDS); 620 if (!ret) 621 isa_registered = 1; 622 623 return (pnp_registered || isa_registered) ? 0 : ret; 624 } 625 626 static void __exit generic_NCR5380_exit(void) 627 { 628 #ifdef CONFIG_PNP 629 if (pnp_registered) 630 pnp_unregister_driver(&generic_NCR5380_pnp_driver); 631 #endif 632 if (isa_registered) 633 isa_unregister_driver(&generic_NCR5380_isa_driver); 634 } 635 636 module_init(generic_NCR5380_init); 637 module_exit(generic_NCR5380_exit); 638