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