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