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 46extern void esp_handle(struct NCR_ESP *esp); 47extern void mac_esp_intr(int irq, void *dev_id); 48 49static int dma_bytes_sent(struct NCR_ESP * esp, int fifo_count); 50static int dma_can_transfer(struct NCR_ESP * esp, Scsi_Cmnd *sp); 51static void dma_dump_state(struct NCR_ESP * esp); 52static void dma_init_read(struct NCR_ESP * esp, char * vaddress, int length); 53static void dma_init_write(struct NCR_ESP * esp, char * vaddress, int length); 54static void dma_ints_off(struct NCR_ESP * esp); 55static void dma_ints_on(struct NCR_ESP * esp); 56static int dma_irq_p(struct NCR_ESP * esp); 57static int dma_irq_p_quick(struct NCR_ESP * esp); 58static void dma_led_off(struct NCR_ESP * esp); 59static void dma_led_on(struct NCR_ESP *esp); 60static int dma_ports_p(struct NCR_ESP *esp); 61static void dma_setup(struct NCR_ESP * esp, __u32 addr, int count, int write); 62static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int write); 63 64static int esp_dafb_dma_irq_p(struct NCR_ESP * espdev); 65static int esp_iosb_dma_irq_p(struct NCR_ESP * espdev); 66 67static 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 73static int esp_initialized = 0; 74 75static int setup_num_esps = -1; 76static int setup_disconnect = -1; 77static int setup_nosync = -1; 78static int setup_can_queue = -1; 79static int setup_cmd_per_lun = -1; 80static int setup_sg_tablesize = -1; 81#ifdef SUPPORT_TAGS 82static int setup_use_tagged_queuing = -1; 83#endif 84static 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 91void 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 125void 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 133void 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 142irqreturn_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 162static 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 256unsigned 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 300int mac_esp_detect(struct scsi_host_template * tpnt) 301{ 302 int quick = 0; 303 int chipnum, chipspresent = 0; 304 305 if (esp_initialized > 0) 306 return -ENODEV; 307 308 /* what do we have in this machine... */ 309 if (MACHW_PRESENT(MAC_SCSI_96)) { 310 chipspresent ++; 311 } 312 313 if (MACHW_PRESENT(MAC_SCSI_96_2)) { 314 chipspresent ++; 315 } 316 317 /* number of ESPs present ? */ 318 if (setup_num_esps >= 0) { 319 if (chipspresent >= setup_num_esps) 320 chipspresent = setup_num_esps; 321 else 322 printk("mac_esp_detect: num_hosts detected %d setup %d \n", 323 chipspresent, setup_num_esps); 324 } 325 326 /* TODO: add disconnect / nosync flags */ 327 328 /* setup variables */ 329 tpnt->can_queue = 330 (setup_can_queue > 0) ? setup_can_queue : 7; 331 tpnt->cmd_per_lun = 332 (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : 1; 333 tpnt->sg_tablesize = 334 (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_ALL; 335 336 if (setup_hostid >= 0) 337 tpnt->this_id = setup_hostid; 338 else { 339 /* use 7 as default */ 340 tpnt->this_id = 7; 341 } 342 343#ifdef SUPPORT_TAGS 344 if (setup_use_tagged_queuing < 0) 345 setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING; 346#endif 347 348 for (chipnum = 0; chipnum < chipspresent; chipnum ++) { 349 struct NCR_ESP * esp; 350 351 esp = esp_allocate(tpnt, NULL, 0); 352 esp->eregs = (struct ESP_regs *) get_base(chipnum); 353 354 esp->dma_irq_p = &esp_dafb_dma_irq_p; 355 if (chipnum == 0) { 356 357 if (macintosh_config->scsi_type == MAC_SCSI_QUADRA) { 358 /* most machines except those below :-) */ 359 quick = 1; 360 esp->dma_irq_p = &esp_iosb_dma_irq_p; 361 } else if (macintosh_config->scsi_type == MAC_SCSI_QUADRA3) { 362 /* mostly av's */ 363 quick = 0; 364 } else { 365 /* q950, 900, 700 */ 366 quick = 1; 367 out_be32(0xf9800024, 0x1d1); 368 esp->dregs = (void *) 0xf9800024; 369 } 370 371 } else { /* chipnum */ 372 373 quick = 1; 374 out_be32(0xf9800028, 0x1d1); 375 esp->dregs = (void *) 0xf9800028; 376 377 } /* chipnum == 0 */ 378 379 /* use pio for command bytes; pio for message/data: TBI */ 380 esp->do_pio_cmds = 1; 381 382 /* Set the command buffer */ 383 esp->esp_command = (volatile unsigned char*) cmd_buffer; 384 esp->esp_command_dvma = (__u32) cmd_buffer; 385 386 /* various functions */ 387 esp->dma_bytes_sent = &dma_bytes_sent; 388 esp->dma_can_transfer = &dma_can_transfer; 389 esp->dma_dump_state = &dma_dump_state; 390 esp->dma_init_read = NULL; 391 esp->dma_init_write = NULL; 392 esp->dma_ints_off = &dma_ints_off; 393 esp->dma_ints_on = &dma_ints_on; 394 395 esp->dma_ports_p = &dma_ports_p; 396 397 398 /* Optional functions */ 399 esp->dma_barrier = NULL; 400 esp->dma_drain = NULL; 401 esp->dma_invalidate = NULL; 402 esp->dma_irq_entry = NULL; 403 esp->dma_irq_exit = NULL; 404 esp->dma_led_on = NULL; 405 esp->dma_led_off = NULL; 406 esp->dma_poll = NULL; 407 esp->dma_reset = NULL; 408 409 /* SCSI chip speed */ 410 /* below esp->cfreq = 40000000; */ 411 412 413 if (quick) { 414 /* 'quick' means there's handshake glue logic like in the 5380 case */ 415 esp->dma_setup = &dma_setup_quick; 416 } else { 417 esp->dma_setup = &dma_setup; 418 } 419 420 if (chipnum == 0) { 421 422 esp->irq = IRQ_MAC_SCSI; 423 424 request_irq(IRQ_MAC_SCSI, esp_intr, 0, "Mac ESP SCSI", esp->ehost); 425 426 if (macintosh_config->scsi_type == MAC_SCSI_QUADRA) { 427 esp->cfreq = 16500000; 428 } else { 429 esp->cfreq = 25000000; 430 } 431 432 433 } else { /* chipnum == 1 */ 434 435 esp->irq = IRQ_MAC_SCSIDRQ; 436 437 esp->cfreq = 25000000; 438 439 } 440 441 if (quick) { 442 printk("esp: using quick version\n"); 443 } 444 445 printk("esp: addr at 0x%p\n", esp->eregs); 446 447 esp->scsi_id = 7; 448 esp->diff = 0; 449 450 esp_initialize(esp); 451 452 } /* for chipnum */ 453 454 if (chipspresent) 455 printk("\nmac_esp: %d esp controllers found\n", chipspresent); 456 457 esp_initialized = chipspresent; 458 459 return chipspresent; 460} 461 462static int mac_esp_release(struct Scsi_Host *shost) 463{ 464 if (shost->irq) 465 free_irq(shost->irq, NULL); 466 if (shost->io_port && shost->n_io_port) 467 release_region(shost->io_port, shost->n_io_port); 468 scsi_unregister(shost); 469 return 0; 470} 471 472/* 473 * I've been wondering what this is supposed to do, for some time. Talking 474 * to Allen Briggs: These machines have an extra register someplace where the 475 * DRQ pin of the ESP can be monitored. That isn't useful for determining 476 * anything else (such as reselect interrupt or other magic) though. 477 * Maybe make the semantics should be changed like 478 * if (esp->current_SC) 479 * ... check DRQ flag ... 480 * else 481 * ... disconnected, check pending VIA interrupt ... 482 * 483 * There's a problem with using the dabf flag or mac_irq_pending() here: both 484 * seem to return 1 even though no interrupt is currently pending, resulting 485 * in esp_exec_cmd() holding off the next command, and possibly infinite loops 486 * in esp_intr(). 487 * Short term fix: just use esp_status & ESP_STAT_INTR here, as long as we 488 * use simple PIO. The DRQ status will be important when implementing pseudo 489 * DMA mode (set up ESP transfer count, return, do a batch of bytes in PIO or 490 * 'hardware handshake' mode upon DRQ). 491 * If you plan on changing this (i.e. to save the esp_status register access in 492 * favor of a VIA register access or a shadow register for the IFR), make sure 493 * to try a debug version of this first to monitor what registers would be a good 494 * indicator of the ESP interrupt. 495 */ 496 497static int esp_dafb_dma_irq_p(struct NCR_ESP * esp) 498{ 499 unsigned int ret; 500 int sreg = esp_read(esp->eregs->esp_status); 501 502#ifdef DEBUG_MAC_ESP 503 printk("mac_esp: esp_dafb_dma_irq_p dafb %d irq %d\n", 504 readl(esp->dregs), mac_irq_pending(IRQ_MAC_SCSI)); 505#endif 506 507 sreg &= ESP_STAT_INTR; 508 509 /* 510 * maybe working; this is essentially what's used for iosb_dma_irq_p 511 */ 512 if (sreg) 513 return 1; 514 else 515 return 0; 516 517 /* 518 * didn't work ... 519 */ 520 521} 522 523/* 524 * See above: testing mac_irq_pending always returned 8 (SCSI IRQ) regardless 525 * of the actual ESP status. 526 */ 527 528static int esp_iosb_dma_irq_p(struct NCR_ESP * esp) 529{ 530 int ret = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ); 531 int sreg = esp_read(esp->eregs->esp_status); 532 533#ifdef DEBUG_MAC_ESP 534 printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n", 535 mac_irq_pending(IRQ_MAC_SCSIDRQ), mac_irq_pending(IRQ_MAC_SCSI), 536 sreg, esp->current_SC, esp->disconnected_SC); 537#endif 538 539 sreg &= ESP_STAT_INTR; 540 541 if (sreg) 542 return (sreg); 543 else 544 return 0; 545} 546 547/* 548 * This seems to be OK for PIO at least ... usually 0 after PIO. 549 */ 550 551static int dma_bytes_sent(struct NCR_ESP * esp, int fifo_count) 552{ 553 554#ifdef DEBUG_MAC_ESP 555 printk("mac_esp: dma bytes sent = %x\n", fifo_count); 556#endif 557 558 return fifo_count; 559} 560 561/* 562 * dma_can_transfer is used to switch between DMA and PIO, if DMA (pseudo) 563 * is ever implemented. Returning 0 here will use PIO. 564 */ 565 566static int dma_can_transfer(struct NCR_ESP * esp, Scsi_Cmnd * sp) 567{ 568 unsigned long sz = sp->SCp.this_residual; 569 570#ifdef DEBUG_MAC_ESP 571 printk("mac_esp: pio to transfer = %ld\n", sz); 572#endif 573 574 sz = 0; 575 return sz; 576} 577 578/* 579 * Not yet ... 580 */ 581 582static void dma_dump_state(struct NCR_ESP * esp) 583{ 584#ifdef DEBUG_MAC_ESP 585 printk("mac_esp: dma_dump_state: called\n"); 586#endif 587} 588 589/* 590 * DMA setup: should be used to set up the ESP transfer count for pseudo 591 * DMA transfers; need a DRQ transfer function to do the actual transfer 592 */ 593 594static void dma_init_read(struct NCR_ESP * esp, char * vaddress, int length) 595{ 596 printk("mac_esp: dma_init_read\n"); 597} 598 599 600static void dma_init_write(struct NCR_ESP * esp, char * vaddress, int length) 601{ 602 printk("mac_esp: dma_init_write\n"); 603} 604 605 606static void dma_ints_off(struct NCR_ESP * esp) 607{ 608 disable_irq(esp->irq); 609} 610 611 612static void dma_ints_on(struct NCR_ESP * esp) 613{ 614 enable_irq(esp->irq); 615} 616 617/* 618 * generic dma_irq_p(), unused 619 */ 620 621static int dma_irq_p(struct NCR_ESP * esp) 622{ 623 int i = esp_read(esp->eregs->esp_status); 624 625#ifdef DEBUG_MAC_ESP 626 printk("mac_esp: dma_irq_p status %d\n", i); 627#endif 628 629 return (i & ESP_STAT_INTR); 630} 631 632static int dma_irq_p_quick(struct NCR_ESP * esp) 633{ 634 /* 635 * Copied from iosb_dma_irq_p() 636 */ 637 int ret = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ); 638 int sreg = esp_read(esp->eregs->esp_status); 639 640#ifdef DEBUG_MAC_ESP 641 printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n", 642 mac_irq_pending(IRQ_MAC_SCSIDRQ), mac_irq_pending(IRQ_MAC_SCSI), 643 sreg, esp->current_SC, esp->disconnected_SC); 644#endif 645 646 sreg &= ESP_STAT_INTR; 647 648 if (sreg) 649 return (sreg); 650 else 651 return 0; 652 653} 654 655static void dma_led_off(struct NCR_ESP * esp) 656{ 657#ifdef DEBUG_MAC_ESP 658 printk("mac_esp: dma_led_off: called\n"); 659#endif 660} 661 662 663static void dma_led_on(struct NCR_ESP * esp) 664{ 665#ifdef DEBUG_MAC_ESP 666 printk("mac_esp: dma_led_on: called\n"); 667#endif 668} 669 670 671static int dma_ports_p(struct NCR_ESP * esp) 672{ 673 return 0; 674} 675 676 677static void dma_setup(struct NCR_ESP * esp, __u32 addr, int count, int write) 678{ 679 680#ifdef DEBUG_MAC_ESP 681 printk("mac_esp: dma_setup\n"); 682#endif 683 684 if (write) { 685 dma_init_read(esp, (char *) addr, count); 686 } else { 687 dma_init_write(esp, (char *) addr, count); 688 } 689} 690 691 692static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int write) 693{ 694#ifdef DEBUG_MAC_ESP 695 printk("mac_esp: dma_setup_quick\n"); 696#endif 697} 698 699static struct scsi_host_template driver_template = { 700 .proc_name = "mac_esp", 701 .name = "Mac 53C9x SCSI", 702 .detect = mac_esp_detect, 703 .slave_alloc = esp_slave_alloc, 704 .slave_destroy = esp_slave_destroy, 705 .release = mac_esp_release, 706 .info = esp_info, 707 .queuecommand = esp_queue, 708 .eh_abort_handler = esp_abort, 709 .eh_bus_reset_handler = esp_reset, 710 .can_queue = 7, 711 .this_id = 7, 712 .sg_tablesize = SG_ALL, 713 .cmd_per_lun = 1, 714 .use_clustering = DISABLE_CLUSTERING 715}; 716 717 718#include "scsi_module.c" 719 720MODULE_LICENSE("GPL"); 721