1 /* 2 * 68k mac 53c9[46] scsi driver 3 * 4 * copyright (c) 1998, David Weis weisd3458@uni.edu 5 * 6 * debugging on Quadra 800 and 660AV Michael Schmitz, Dave Kilzer 7/98 7 * 8 * based loosely on cyber_esp.c 9 */ 10 11 /* these are unused for now */ 12 #define myreadl(addr) (*(volatile unsigned int *) (addr)) 13 #define mywritel(b, addr) ((*(volatile unsigned int *) (addr)) = (b)) 14 15 16 #include <linux/kernel.h> 17 #include <linux/delay.h> 18 #include <linux/types.h> 19 #include <linux/ctype.h> 20 #include <linux/string.h> 21 #include <linux/slab.h> 22 #include <linux/blkdev.h> 23 #include <linux/proc_fs.h> 24 #include <linux/stat.h> 25 #include <linux/init.h> 26 #include <linux/interrupt.h> 27 28 #include "scsi.h" 29 #include <scsi/scsi_host.h> 30 #include "NCR53C9x.h" 31 32 #include <asm/io.h> 33 34 #include <asm/setup.h> 35 #include <asm/irq.h> 36 #include <asm/macints.h> 37 #include <asm/machw.h> 38 #include <asm/mac_via.h> 39 40 #include <asm/pgtable.h> 41 42 #include <asm/macintosh.h> 43 44 /* #define DEBUG_MAC_ESP */ 45 46 extern void esp_handle(struct NCR_ESP *esp); 47 extern void mac_esp_intr(int irq, void *dev_id); 48 49 static int dma_bytes_sent(struct NCR_ESP * esp, int fifo_count); 50 static int dma_can_transfer(struct NCR_ESP * esp, Scsi_Cmnd *sp); 51 static void dma_dump_state(struct NCR_ESP * esp); 52 static void dma_init_read(struct NCR_ESP * esp, char * vaddress, int length); 53 static void dma_init_write(struct NCR_ESP * esp, char * vaddress, int length); 54 static void dma_ints_off(struct NCR_ESP * esp); 55 static void dma_ints_on(struct NCR_ESP * esp); 56 static int dma_irq_p(struct NCR_ESP * esp); 57 static int dma_irq_p_quick(struct NCR_ESP * esp); 58 static void dma_led_off(struct NCR_ESP * esp); 59 static void dma_led_on(struct NCR_ESP *esp); 60 static int dma_ports_p(struct NCR_ESP *esp); 61 static void dma_setup(struct NCR_ESP * esp, __u32 addr, int count, int write); 62 static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int write); 63 64 static int esp_dafb_dma_irq_p(struct NCR_ESP * espdev); 65 static int esp_iosb_dma_irq_p(struct NCR_ESP * espdev); 66 67 static volatile unsigned char cmd_buffer[16]; 68 /* This is where all commands are put 69 * before they are transferred to the ESP chip 70 * via PIO. 71 */ 72 73 static int esp_initialized = 0; 74 75 static int setup_num_esps = -1; 76 static int setup_disconnect = -1; 77 static int setup_nosync = -1; 78 static int setup_can_queue = -1; 79 static int setup_cmd_per_lun = -1; 80 static int setup_sg_tablesize = -1; 81 #ifdef SUPPORT_TAGS 82 static int setup_use_tagged_queuing = -1; 83 #endif 84 static int setup_hostid = -1; 85 86 /* 87 * Experimental ESP inthandler; check macints.c to make sure dev_id is 88 * set up properly! 89 */ 90 91 void mac_esp_intr(int irq, void *dev_id) 92 { 93 struct NCR_ESP *esp = (struct NCR_ESP *) dev_id; 94 int irq_p = 0; 95 96 /* Handle the one ESP interrupt showing at this IRQ level. */ 97 if(((esp)->irq & 0xff) == irq) { 98 /* 99 * Debug .. 100 */ 101 irq_p = esp->dma_irq_p(esp); 102 printk("mac_esp: irq_p %x current %p disconnected %p\n", 103 irq_p, esp->current_SC, esp->disconnected_SC); 104 105 /* 106 * Mac: if we're here, it's an ESP interrupt for sure! 107 */ 108 if((esp->current_SC || esp->disconnected_SC)) { 109 esp->dma_ints_off(esp); 110 111 ESPIRQ(("I%d(", esp->esp_id)); 112 esp_handle(esp); 113 ESPIRQ((")")); 114 115 esp->dma_ints_on(esp); 116 } 117 } 118 } 119 120 /* 121 * Debug hooks; use for playing with the interrupt flag testing and interrupt 122 * acknowledge on the various machines 123 */ 124 125 void scsi_esp_polled(int irq, void *dev_id) 126 { 127 if (esp_initialized == 0) 128 return; 129 130 mac_esp_intr(irq, dev_id); 131 } 132 133 void fake_intr(int irq, void *dev_id) 134 { 135 #ifdef DEBUG_MAC_ESP 136 printk("mac_esp: got irq\n"); 137 #endif 138 139 mac_esp_intr(irq, dev_id); 140 } 141 142 irqreturn_t fake_drq(int irq, void *dev_id) 143 { 144 printk("mac_esp: got drq\n"); 145 return IRQ_HANDLED; 146 } 147 148 #define DRIVER_SETUP 149 150 /* 151 * Function : mac_esp_setup(char *str) 152 * 153 * Purpose : booter command line initialization of the overrides array, 154 * 155 * Inputs : str - parameters, separated by commas. 156 * 157 * Currently unused in the new driver; need to add settable parameters to the 158 * detect function. 159 * 160 */ 161 162 static int __init mac_esp_setup(char *str) { 163 #ifdef DRIVER_SETUP 164 /* Format of mac53c9x parameter is: 165 * mac53c9x=<num_esps>,<disconnect>,<nosync>,<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags> 166 * Negative values mean don't change. 167 */ 168 169 char *this_opt; 170 long opt; 171 172 this_opt = strsep (&str, ","); 173 if(this_opt) { 174 opt = simple_strtol( this_opt, NULL, 0 ); 175 176 if (opt >= 0 && opt <= 2) 177 setup_num_esps = opt; 178 else if (opt > 2) 179 printk( "mac_esp_setup: invalid number of hosts %ld !\n", opt ); 180 181 this_opt = strsep (&str, ","); 182 } 183 if(this_opt) { 184 opt = simple_strtol( this_opt, NULL, 0 ); 185 186 if (opt > 0) 187 setup_disconnect = opt; 188 189 this_opt = strsep (&str, ","); 190 } 191 if(this_opt) { 192 opt = simple_strtol( this_opt, NULL, 0 ); 193 194 if (opt >= 0) 195 setup_nosync = opt; 196 197 this_opt = strsep (&str, ","); 198 } 199 if(this_opt) { 200 opt = simple_strtol( this_opt, NULL, 0 ); 201 202 if (opt > 0) 203 setup_can_queue = opt; 204 205 this_opt = strsep (&str, ","); 206 } 207 if(this_opt) { 208 opt = simple_strtol( this_opt, NULL, 0 ); 209 210 if (opt > 0) 211 setup_cmd_per_lun = opt; 212 213 this_opt = strsep (&str, ","); 214 } 215 if(this_opt) { 216 opt = simple_strtol( this_opt, NULL, 0 ); 217 218 if (opt >= 0) { 219 setup_sg_tablesize = opt; 220 /* Must be <= SG_ALL (255) */ 221 if (setup_sg_tablesize > SG_ALL) 222 setup_sg_tablesize = SG_ALL; 223 } 224 225 this_opt = strsep (&str, ","); 226 } 227 if(this_opt) { 228 opt = simple_strtol( this_opt, NULL, 0 ); 229 230 /* Must be between 0 and 7 */ 231 if (opt >= 0 && opt <= 7) 232 setup_hostid = opt; 233 else if (opt > 7) 234 printk( "mac_esp_setup: invalid host ID %ld !\n", opt); 235 236 this_opt = strsep (&str, ","); 237 } 238 #ifdef SUPPORT_TAGS 239 if(this_opt) { 240 opt = simple_strtol( this_opt, NULL, 0 ); 241 if (opt >= 0) 242 setup_use_tagged_queuing = !!opt; 243 } 244 #endif 245 #endif 246 return 1; 247 } 248 249 __setup("mac53c9x=", mac_esp_setup); 250 251 252 /* 253 * ESP address 'detection' 254 */ 255 256 unsigned long get_base(int chip_num) 257 { 258 /* 259 * using the chip_num and mac model, figure out where the 260 * chips are mapped 261 */ 262 263 unsigned long io_base = 0x50f00000; 264 unsigned int second_offset = 0x402; 265 unsigned long scsi_loc = 0; 266 267 switch (macintosh_config->scsi_type) { 268 269 /* 950, 900, 700 */ 270 case MAC_SCSI_QUADRA2: 271 scsi_loc = io_base + 0xf000 + ((chip_num == 0) ? 0 : second_offset); 272 break; 273 274 /* av's */ 275 case MAC_SCSI_QUADRA3: 276 scsi_loc = io_base + 0x18000 + ((chip_num == 0) ? 0 : second_offset); 277 break; 278 279 /* most quadra/centris models are like this */ 280 case MAC_SCSI_QUADRA: 281 scsi_loc = io_base + 0x10000; 282 break; 283 284 default: 285 printk("mac_esp: get_base: hit default!\n"); 286 scsi_loc = io_base + 0x10000; 287 break; 288 289 } /* switch */ 290 291 printk("mac_esp: io base at 0x%lx\n", scsi_loc); 292 293 return scsi_loc; 294 } 295 296 /* 297 * Model dependent ESP setup 298 */ 299 300 int mac_esp_detect(struct scsi_host_template * tpnt) 301 { 302 int quick = 0; 303 int chipnum, chipspresent = 0; 304 #if 0 305 unsigned long timeout; 306 #endif 307 308 if (esp_initialized > 0) 309 return -ENODEV; 310 311 /* what do we have in this machine... */ 312 if (MACHW_PRESENT(MAC_SCSI_96)) { 313 chipspresent ++; 314 } 315 316 if (MACHW_PRESENT(MAC_SCSI_96_2)) { 317 chipspresent ++; 318 } 319 320 /* number of ESPs present ? */ 321 if (setup_num_esps >= 0) { 322 if (chipspresent >= setup_num_esps) 323 chipspresent = setup_num_esps; 324 else 325 printk("mac_esp_detect: num_hosts detected %d setup %d \n", 326 chipspresent, setup_num_esps); 327 } 328 329 /* TODO: add disconnect / nosync flags */ 330 331 /* setup variables */ 332 tpnt->can_queue = 333 (setup_can_queue > 0) ? setup_can_queue : 7; 334 tpnt->cmd_per_lun = 335 (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : 1; 336 tpnt->sg_tablesize = 337 (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_ALL; 338 339 if (setup_hostid >= 0) 340 tpnt->this_id = setup_hostid; 341 else { 342 /* use 7 as default */ 343 tpnt->this_id = 7; 344 } 345 346 #ifdef SUPPORT_TAGS 347 if (setup_use_tagged_queuing < 0) 348 setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING; 349 #endif 350 351 for (chipnum = 0; chipnum < chipspresent; chipnum ++) { 352 struct NCR_ESP * esp; 353 354 esp = esp_allocate(tpnt, NULL, 0); 355 esp->eregs = (struct ESP_regs *) get_base(chipnum); 356 357 esp->dma_irq_p = &esp_dafb_dma_irq_p; 358 if (chipnum == 0) { 359 360 if (macintosh_config->scsi_type == MAC_SCSI_QUADRA) { 361 /* most machines except those below :-) */ 362 quick = 1; 363 esp->dma_irq_p = &esp_iosb_dma_irq_p; 364 } else if (macintosh_config->scsi_type == MAC_SCSI_QUADRA3) { 365 /* mostly av's */ 366 quick = 0; 367 } else { 368 /* q950, 900, 700 */ 369 quick = 1; 370 out_be32(0xf9800024, 0x1d1); 371 esp->dregs = (void *) 0xf9800024; 372 } 373 374 } else { /* chipnum */ 375 376 quick = 1; 377 out_be32(0xf9800028, 0x1d1); 378 esp->dregs = (void *) 0xf9800028; 379 380 } /* chipnum == 0 */ 381 382 /* use pio for command bytes; pio for message/data: TBI */ 383 esp->do_pio_cmds = 1; 384 385 /* Set the command buffer */ 386 esp->esp_command = (volatile unsigned char*) cmd_buffer; 387 esp->esp_command_dvma = (__u32) cmd_buffer; 388 389 /* various functions */ 390 esp->dma_bytes_sent = &dma_bytes_sent; 391 esp->dma_can_transfer = &dma_can_transfer; 392 esp->dma_dump_state = &dma_dump_state; 393 esp->dma_init_read = NULL; 394 esp->dma_init_write = NULL; 395 esp->dma_ints_off = &dma_ints_off; 396 esp->dma_ints_on = &dma_ints_on; 397 398 esp->dma_ports_p = &dma_ports_p; 399 400 401 /* Optional functions */ 402 esp->dma_barrier = NULL; 403 esp->dma_drain = NULL; 404 esp->dma_invalidate = NULL; 405 esp->dma_irq_entry = NULL; 406 esp->dma_irq_exit = NULL; 407 esp->dma_led_on = NULL; 408 esp->dma_led_off = NULL; 409 esp->dma_poll = NULL; 410 esp->dma_reset = NULL; 411 412 /* SCSI chip speed */ 413 /* below esp->cfreq = 40000000; */ 414 415 416 if (quick) { 417 /* 'quick' means there's handshake glue logic like in the 5380 case */ 418 esp->dma_setup = &dma_setup_quick; 419 } else { 420 esp->dma_setup = &dma_setup; 421 } 422 423 if (chipnum == 0) { 424 425 esp->irq = IRQ_MAC_SCSI; 426 427 request_irq(IRQ_MAC_SCSI, esp_intr, 0, "Mac ESP SCSI", esp->ehost); 428 #if 0 /* conflicts with IOP ADB */ 429 request_irq(IRQ_MAC_SCSIDRQ, fake_drq, 0, "Mac ESP DRQ", esp->ehost); 430 #endif 431 432 if (macintosh_config->scsi_type == MAC_SCSI_QUADRA) { 433 esp->cfreq = 16500000; 434 } else { 435 esp->cfreq = 25000000; 436 } 437 438 439 } else { /* chipnum == 1 */ 440 441 esp->irq = IRQ_MAC_SCSIDRQ; 442 #if 0 /* conflicts with IOP ADB */ 443 request_irq(IRQ_MAC_SCSIDRQ, esp_intr, 0, "Mac ESP SCSI 2", esp->ehost); 444 #endif 445 446 esp->cfreq = 25000000; 447 448 } 449 450 if (quick) { 451 printk("esp: using quick version\n"); 452 } 453 454 printk("esp: addr at 0x%p\n", esp->eregs); 455 456 esp->scsi_id = 7; 457 esp->diff = 0; 458 459 esp_initialize(esp); 460 461 } /* for chipnum */ 462 463 if (chipspresent) 464 printk("\nmac_esp: %d esp controllers found\n", chipspresent); 465 466 esp_initialized = chipspresent; 467 468 return chipspresent; 469 } 470 471 static int mac_esp_release(struct Scsi_Host *shost) 472 { 473 if (shost->irq) 474 free_irq(shost->irq, NULL); 475 if (shost->io_port && shost->n_io_port) 476 release_region(shost->io_port, shost->n_io_port); 477 scsi_unregister(shost); 478 return 0; 479 } 480 481 /* 482 * I've been wondering what this is supposed to do, for some time. Talking 483 * to Allen Briggs: These machines have an extra register someplace where the 484 * DRQ pin of the ESP can be monitored. That isn't useful for determining 485 * anything else (such as reselect interrupt or other magic) though. 486 * Maybe make the semantics should be changed like 487 * if (esp->current_SC) 488 * ... check DRQ flag ... 489 * else 490 * ... disconnected, check pending VIA interrupt ... 491 * 492 * There's a problem with using the dabf flag or mac_irq_pending() here: both 493 * seem to return 1 even though no interrupt is currently pending, resulting 494 * in esp_exec_cmd() holding off the next command, and possibly infinite loops 495 * in esp_intr(). 496 * Short term fix: just use esp_status & ESP_STAT_INTR here, as long as we 497 * use simple PIO. The DRQ status will be important when implementing pseudo 498 * DMA mode (set up ESP transfer count, return, do a batch of bytes in PIO or 499 * 'hardware handshake' mode upon DRQ). 500 * If you plan on changing this (i.e. to save the esp_status register access in 501 * favor of a VIA register access or a shadow register for the IFR), make sure 502 * to try a debug version of this first to monitor what registers would be a good 503 * indicator of the ESP interrupt. 504 */ 505 506 static int esp_dafb_dma_irq_p(struct NCR_ESP * esp) 507 { 508 unsigned int ret; 509 int sreg = esp_read(esp->eregs->esp_status); 510 511 #ifdef DEBUG_MAC_ESP 512 printk("mac_esp: esp_dafb_dma_irq_p dafb %d irq %d\n", 513 readl(esp->dregs), mac_irq_pending(IRQ_MAC_SCSI)); 514 #endif 515 516 sreg &= ESP_STAT_INTR; 517 518 /* 519 * maybe working; this is essentially what's used for iosb_dma_irq_p 520 */ 521 if (sreg) 522 return 1; 523 else 524 return 0; 525 526 /* 527 * didn't work ... 528 */ 529 #if 0 530 if (esp->current_SC) 531 ret = readl(esp->dregs) & 0x200; 532 else if (esp->disconnected_SC) 533 ret = 1; /* sreg ?? */ 534 else 535 ret = mac_irq_pending(IRQ_MAC_SCSI); 536 537 return(ret); 538 #endif 539 540 } 541 542 /* 543 * See above: testing mac_irq_pending always returned 8 (SCSI IRQ) regardless 544 * of the actual ESP status. 545 */ 546 547 static int esp_iosb_dma_irq_p(struct NCR_ESP * esp) 548 { 549 int ret = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ); 550 int sreg = esp_read(esp->eregs->esp_status); 551 552 #ifdef DEBUG_MAC_ESP 553 printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n", 554 mac_irq_pending(IRQ_MAC_SCSIDRQ), mac_irq_pending(IRQ_MAC_SCSI), 555 sreg, esp->current_SC, esp->disconnected_SC); 556 #endif 557 558 sreg &= ESP_STAT_INTR; 559 560 if (sreg) 561 return (sreg); 562 else 563 return 0; 564 } 565 566 /* 567 * This seems to be OK for PIO at least ... usually 0 after PIO. 568 */ 569 570 static int dma_bytes_sent(struct NCR_ESP * esp, int fifo_count) 571 { 572 573 #ifdef DEBUG_MAC_ESP 574 printk("mac_esp: dma bytes sent = %x\n", fifo_count); 575 #endif 576 577 return fifo_count; 578 } 579 580 /* 581 * dma_can_transfer is used to switch between DMA and PIO, if DMA (pseudo) 582 * is ever implemented. Returning 0 here will use PIO. 583 */ 584 585 static int dma_can_transfer(struct NCR_ESP * esp, Scsi_Cmnd * sp) 586 { 587 unsigned long sz = sp->SCp.this_residual; 588 #if 0 /* no DMA yet; make conditional */ 589 if (sz > 0x10000000) { 590 sz = 0x10000000; 591 } 592 printk("mac_esp: dma can transfer = 0lx%x\n", sz); 593 #else 594 595 #ifdef DEBUG_MAC_ESP 596 printk("mac_esp: pio to transfer = %ld\n", sz); 597 #endif 598 599 sz = 0; 600 #endif 601 return sz; 602 } 603 604 /* 605 * Not yet ... 606 */ 607 608 static void dma_dump_state(struct NCR_ESP * esp) 609 { 610 #ifdef DEBUG_MAC_ESP 611 printk("mac_esp: dma_dump_state: called\n"); 612 #endif 613 #if 0 614 ESPLOG(("esp%d: dma -- cond_reg<%02x>\n", 615 esp->esp_id, ((struct mac_dma_registers *) 616 (esp->dregs))->cond_reg)); 617 #endif 618 } 619 620 /* 621 * DMA setup: should be used to set up the ESP transfer count for pseudo 622 * DMA transfers; need a DRQ transfer function to do the actual transfer 623 */ 624 625 static void dma_init_read(struct NCR_ESP * esp, char * vaddress, int length) 626 { 627 printk("mac_esp: dma_init_read\n"); 628 } 629 630 631 static void dma_init_write(struct NCR_ESP * esp, char * vaddress, int length) 632 { 633 printk("mac_esp: dma_init_write\n"); 634 } 635 636 637 static void dma_ints_off(struct NCR_ESP * esp) 638 { 639 disable_irq(esp->irq); 640 } 641 642 643 static void dma_ints_on(struct NCR_ESP * esp) 644 { 645 enable_irq(esp->irq); 646 } 647 648 /* 649 * generic dma_irq_p(), unused 650 */ 651 652 static int dma_irq_p(struct NCR_ESP * esp) 653 { 654 int i = esp_read(esp->eregs->esp_status); 655 656 #ifdef DEBUG_MAC_ESP 657 printk("mac_esp: dma_irq_p status %d\n", i); 658 #endif 659 660 return (i & ESP_STAT_INTR); 661 } 662 663 static int dma_irq_p_quick(struct NCR_ESP * esp) 664 { 665 /* 666 * Copied from iosb_dma_irq_p() 667 */ 668 int ret = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ); 669 int sreg = esp_read(esp->eregs->esp_status); 670 671 #ifdef DEBUG_MAC_ESP 672 printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n", 673 mac_irq_pending(IRQ_MAC_SCSIDRQ), mac_irq_pending(IRQ_MAC_SCSI), 674 sreg, esp->current_SC, esp->disconnected_SC); 675 #endif 676 677 sreg &= ESP_STAT_INTR; 678 679 if (sreg) 680 return (sreg); 681 else 682 return 0; 683 684 } 685 686 static void dma_led_off(struct NCR_ESP * esp) 687 { 688 #ifdef DEBUG_MAC_ESP 689 printk("mac_esp: dma_led_off: called\n"); 690 #endif 691 } 692 693 694 static void dma_led_on(struct NCR_ESP * esp) 695 { 696 #ifdef DEBUG_MAC_ESP 697 printk("mac_esp: dma_led_on: called\n"); 698 #endif 699 } 700 701 702 static int dma_ports_p(struct NCR_ESP * esp) 703 { 704 return 0; 705 } 706 707 708 static void dma_setup(struct NCR_ESP * esp, __u32 addr, int count, int write) 709 { 710 711 #ifdef DEBUG_MAC_ESP 712 printk("mac_esp: dma_setup\n"); 713 #endif 714 715 if (write) { 716 dma_init_read(esp, (char *) addr, count); 717 } else { 718 dma_init_write(esp, (char *) addr, count); 719 } 720 } 721 722 723 static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int write) 724 { 725 #ifdef DEBUG_MAC_ESP 726 printk("mac_esp: dma_setup_quick\n"); 727 #endif 728 } 729 730 static struct scsi_host_template driver_template = { 731 .proc_name = "mac_esp", 732 .name = "Mac 53C9x SCSI", 733 .detect = mac_esp_detect, 734 .slave_alloc = esp_slave_alloc, 735 .slave_destroy = esp_slave_destroy, 736 .release = mac_esp_release, 737 .info = esp_info, 738 .queuecommand = esp_queue, 739 .eh_abort_handler = esp_abort, 740 .eh_bus_reset_handler = esp_reset, 741 .can_queue = 7, 742 .this_id = 7, 743 .sg_tablesize = SG_ALL, 744 .cmd_per_lun = 1, 745 .use_clustering = DISABLE_CLUSTERING 746 }; 747 748 749 #include "scsi_module.c" 750 751 MODULE_LICENSE("GPL"); 752