1/* 2 * Generic Macintosh NCR5380 driver 3 * 4 * Copyright 1998, Michael Schmitz <mschmitz@lbl.gov> 5 * 6 * derived in part from: 7 */ 8/* 9 * Generic Generic NCR5380 driver 10 * 11 * Copyright 1995, Russell King 12 * 13 * ALPHA RELEASE 1. 14 * 15 * For more information, please consult 16 * 17 * NCR 5380 Family 18 * SCSI Protocol Controller 19 * Databook 20 * 21 * NCR Microelectronics 22 * 1635 Aeroplaza Drive 23 * Colorado Springs, CO 80916 24 * 1+ (719) 578-3400 25 * 1+ (800) 334-5454 26 */ 27 28 29/* 30 * Options : 31 * 32 * PARITY - enable parity checking. Not supported. 33 * 34 * SCSI2 - enable support for SCSI-II tagged queueing. Untested. 35 * 36 * USLEEP - enable support for devices that don't disconnect. Untested. 37 */ 38 39/* 40 * $Log: mac_scsi.c,v $ 41 * Revision 1.1.1.1 2008/10/15 03:26:53 james26_jang 42 * Initial. 43 * 44 * Revision 1.1.1.1 2008/07/21 09:15:23 james26_jang 45 * New UI, New QoS, New wireless driver(4.151.10.29), ipmonitor. 46 * 47 * Revision 1.1.1.1 2008/07/02 14:39:38 james26_jang 48 * 4.100.10.29, New QoS and New UI. 49 * 50 * Revision 1.1.1.1 2003/02/03 22:37:53 mhuang 51 * LINUX_2_4 branch snapshot from linux-mips.org CVS 52 * 53 */ 54 55#define AUTOSENSE 56 57#include <linux/types.h> 58#include <linux/stddef.h> 59#include <linux/ctype.h> 60#include <linux/delay.h> 61 62#include <linux/module.h> 63#include <linux/signal.h> 64#include <linux/sched.h> 65#include <linux/ioport.h> 66#include <linux/init.h> 67#include <linux/blk.h> 68 69#include <asm/io.h> 70#include <asm/irq.h> 71#include <asm/system.h> 72 73#include <asm/macintosh.h> 74#include <asm/macints.h> 75#include <asm/machw.h> 76#include <asm/mac_via.h> 77 78#include "scsi.h" 79#include "hosts.h" 80#include "mac_scsi.h" 81#include "NCR5380.h" 82#include "constants.h" 83 84#define NDEBUG (NDEBUG_ABORT) 85 86#define RESET_BOOT 87#define DRIVER_SETUP 88 89/* 90 * BUG can be used to trigger a strange code-size related hang on 2.1 kernels 91 */ 92#ifdef BUG 93#undef RESET_BOOT 94#undef DRIVER_SETUP 95#endif 96 97#define ENABLE_IRQ() mac_enable_irq( IRQ_MAC_SCSI ); 98#define DISABLE_IRQ() mac_disable_irq( IRQ_MAC_SCSI ); 99 100#ifdef RESET_BOOT 101static void mac_scsi_reset_boot(struct Scsi_Host *instance); 102#endif 103static char macscsi_read(struct Scsi_Host *instance, int reg); 104static void macscsi_write(struct Scsi_Host *instance, int reg, int value); 105 106static int setup_can_queue = -1; 107static int setup_cmd_per_lun = -1; 108static int setup_sg_tablesize = -1; 109#ifdef SUPPORT_TAGS 110static int setup_use_tagged_queuing = -1; 111#endif 112static int setup_hostid = -1; 113 114static int polled_scsi_on = 0; 115 116/* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms, 117 * we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more 118 * need ten times the standard value... */ 119#define TOSHIBA_DELAY 120 121#ifdef TOSHIBA_DELAY 122#define AFTER_RESET_DELAY (5*HZ/2) 123#else 124#define AFTER_RESET_DELAY (HZ/2) 125#endif 126 127static volatile unsigned char *mac_scsi_regp = NULL; 128static volatile unsigned char *mac_scsi_drq = NULL; 129static volatile unsigned char *mac_scsi_nodrq = NULL; 130 131/* 132 * Function : mac_scsi_setup(char *str, int *ints) 133 * 134 * Purpose : booter command line initialization of the overrides array, 135 * 136 * Inputs : str - unused, ints - array of integer parameters with ints[0] 137 * equal to the number of ints. 138 * 139 */ 140 141static int __init mac_scsi_setup(char *str, int *ints) { 142#ifdef DRIVER_SETUP 143 /* Format of mac5380 parameter is: 144 * mac5380=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags> 145 * Negative values mean don't change. 146 */ 147 148 /* Grmbl... the standard parameter parsing can't handle negative numbers 149 * :-( So let's do it ourselves! 150 */ 151 152 int i = ints[0]+1, fact; 153 154 while( str && (isdigit(*str) || *str == '-') && i <= 10) { 155 if (*str == '-') 156 fact = -1, ++str; 157 else 158 fact = 1; 159 ints[i++] = simple_strtoul( str, NULL, 0 ) * fact; 160 if ((str = strchr( str, ',' )) != NULL) 161 ++str; 162 } 163 ints[0] = i-1; 164 165 if (ints[0] < 1) { 166 printk( "mac_scsi_setup: no arguments!\n" ); 167 return 0; 168 } 169 170 if (ints[0] >= 1) { 171 if (ints[1] > 0) 172 /* no limits on this, just > 0 */ 173 setup_can_queue = ints[1]; 174 } 175 if (ints[0] >= 2) { 176 if (ints[2] > 0) 177 setup_cmd_per_lun = ints[2]; 178 } 179 if (ints[0] >= 3) { 180 if (ints[3] >= 0) { 181 setup_sg_tablesize = ints[3]; 182 /* Must be <= SG_ALL (255) */ 183 if (setup_sg_tablesize > SG_ALL) 184 setup_sg_tablesize = SG_ALL; 185 } 186 } 187 if (ints[0] >= 4) { 188 /* Must be between 0 and 7 */ 189 if (ints[4] >= 0 && ints[4] <= 7) 190 setup_hostid = ints[4]; 191 else if (ints[4] > 7) 192 printk( "mac_scsi_setup: invalid host ID %d !\n", ints[4] ); 193 } 194#ifdef SUPPORT_TAGS 195 if (ints[0] >= 5) { 196 if (ints[5] >= 0) 197 setup_use_tagged_queuing = !!ints[5]; 198 } 199#endif 200#endif 201 return 1; 202} 203 204__setup("mac5380=", mac_scsi_setup); 205 206 207static struct Scsi_Host *default_instance; 208 209/* 210 * Function : int macscsi_detect(Scsi_Host_Template * tpnt) 211 * 212 * Purpose : initializes mac NCR5380 driver based on the 213 * command line / compile time port and irq definitions. 214 * 215 * Inputs : tpnt - template for this SCSI adapter. 216 * 217 * Returns : 1 if a host adapter was found, 0 if not. 218 * 219 */ 220 221int macscsi_detect(Scsi_Host_Template * tpnt) 222{ 223 int count = 0; 224 static int called = 0; 225 struct Scsi_Host *instance; 226 227 if (!MACH_IS_MAC || called) 228 return( 0 ); 229 230 if (macintosh_config->scsi_type != MAC_SCSI_OLD) 231 return( 0 ); 232 233 tpnt->proc_name = "mac5380"; 234 235 /* setup variables */ 236 tpnt->can_queue = 237 (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE; 238 tpnt->cmd_per_lun = 239 (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN; 240 tpnt->sg_tablesize = 241 (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE; 242 243 if (setup_hostid >= 0) 244 tpnt->this_id = setup_hostid; 245 else { 246 /* use 7 as default */ 247 tpnt->this_id = 7; 248 } 249 250#ifdef SUPPORT_TAGS 251 if (setup_use_tagged_queuing < 0) 252 setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING; 253#endif 254 255 instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); 256 if(instance == NULL) 257 continue; 258 default_instance = instance; 259 260 if (macintosh_config->ident == MAC_MODEL_IIFX) { 261 mac_scsi_regp = via1+0x8000; 262 mac_scsi_drq = via1+0xE000; 263 mac_scsi_nodrq = via1+0xC000; 264 } else { 265 mac_scsi_regp = via1+0x10000; 266 mac_scsi_drq = via1+0x6000; 267 mac_scsi_nodrq = via1+0x12000; 268 } 269 270 271 instance->io_port = (unsigned long) mac_scsi_regp; 272 instance->irq = IRQ_MAC_SCSI; 273 274#ifdef RESET_BOOT 275 mac_scsi_reset_boot(instance); 276#endif 277 278 NCR5380_init(instance, 0); 279 280 instance->n_io_port = 255; 281 282 ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0; 283 284 if (instance->irq != IRQ_NONE) 285 if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW, "ncr5380", NCR5380_intr)) { 286 printk("scsi%d: IRQ%d not free, interrupts disabled\n", 287 instance->host_no, instance->irq); 288 instance->irq = IRQ_NONE; 289 } 290 291 printk("scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port); 292 if (instance->irq == IRQ_NONE) 293 printk ("s disabled"); 294 else 295 printk (" %d", instance->irq); 296 printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", 297 instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE); 298 printk("\nscsi%d:", instance->host_no); 299 NCR5380_print_options(instance); 300 printk("\n"); 301 called = 1; 302 return 1; 303 304} 305 306int macscsi_release (struct Scsi_Host *shpnt) 307{ 308 if (shpnt->irq != IRQ_NONE) 309 free_irq (shpnt->irq, NCR5380_intr); 310 311 return 0; 312} 313 314#ifdef RESET_BOOT 315/* 316 * Our 'bus reset on boot' function 317 */ 318 319static void mac_scsi_reset_boot(struct Scsi_Host *instance) 320{ 321 unsigned long end; 322 323 NCR5380_local_declare(); 324 NCR5380_setup(instance); 325 326 /* 327 * Do a SCSI reset to clean up the bus during initialization. No messing 328 * with the queues, interrupts, or locks necessary here. 329 */ 330 331 printk( "Macintosh SCSI: resetting the SCSI bus..." ); 332 333 /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */ 334 mac_disable_irq(IRQ_MAC_SCSI); 335 336 /* get in phase */ 337 NCR5380_write( TARGET_COMMAND_REG, 338 PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) )); 339 340 /* assert RST */ 341 NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST ); 342 /* The min. reset hold time is 25us, so 40us should be enough */ 343 udelay( 50 ); 344 /* reset RST and interrupt */ 345 NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE ); 346 NCR5380_read( RESET_PARITY_INTERRUPT_REG ); 347 348 for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); ) 349 barrier(); 350 351 /* switch on SCSI IRQ again */ 352 mac_enable_irq(IRQ_MAC_SCSI); 353 354 printk( " done\n" ); 355} 356#endif 357 358const char * macscsi_info (struct Scsi_Host *spnt) { 359 return ""; 360} 361 362void restore_irq(struct pt_regs *regs) 363{ 364 unsigned long flags; 365 366 save_flags(flags); 367 flags = (flags & ~0x0700) | (regs->sr & 0x0700); 368 restore_flags(flags); 369} 370 371/* 372 * pseudo-DMA transfer functions, copied and modified from Russel King's 373 * ARM 5380 driver (cumana_1) 374 * 375 * Work in progress (sort of), didn't work last time I checked, don't use! 376 */ 377 378#ifdef NOT_EFFICIENT 379#define CTRL(p,v) outb(*ctrl = (v), (p) - 577) 380#define STAT(p) inb((p)+1) 381#define IN(p) inb((p)) 382#define OUT(v,p) outb((v), (p)) 383#else 384#define CTRL(p,v) (*ctrl = (v)) 385#define STAT(p) (p[1<<4]) 386#define IN(p) (*(p)) 387#define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p))) 388#define OUT(v,p) (*(p) = (v)) 389#define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v)) 390#endif 391#define L(v) (((v)<<16)|((v) & 0x0000ffff)) 392#define H(v) (((v)>>16)|((v) & 0xffff0000)) 393#define ioaddr(v) (v) 394 395static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, 396 int len) 397{ 398 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; 399 int oldctrl = *ctrl; 400 unsigned long *laddr; 401#ifdef NOT_EFFICIENT 402 int iobase = instance->io_port; 403 int dma_io = mac_scsi_nodrq; 404#else 405 volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port); 406 volatile unsigned char *dma_io = (unsigned char *)(mac_scsi_nodrq); 407#endif 408 409 if(!len) return 0; 410 411 CTRL(iobase, 0x02); 412 laddr = (unsigned long *)addr; 413 while(len >= 32) 414 { 415 int status; 416 unsigned long v; 417 status = STAT(iobase); 418 if(status & 0x80) 419 goto end; 420 if(!(status & 0x40)) 421 continue; 422 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); 423 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); 424 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); 425 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); 426 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); 427 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); 428 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); 429 v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); 430 len -= 32; 431 if(len == 0) 432 break; 433 } 434 435 addr = (unsigned char *)laddr; 436 CTRL(iobase, 0x12); 437 while(len > 0) 438 { 439 int status; 440 status = STAT(iobase); 441 if(status & 0x80) 442 goto end; 443 if(status & 0x40) 444 { 445 OUT(*addr++, dma_io); 446 if(--len == 0) 447 break; 448 } 449 450 status = STAT(iobase); 451 if(status & 0x80) 452 goto end; 453 if(status & 0x40) 454 { 455 OUT(*addr++, dma_io); 456 if(--len == 0) 457 break; 458 } 459 } 460end: 461 CTRL(iobase, oldctrl|0x40); 462 return len; 463} 464 465static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, 466 int len) 467{ 468 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; 469 int oldctrl = *ctrl; 470 unsigned long *laddr; 471#ifdef NOT_EFFICIENT 472 int iobase = instance->io_port; 473 int dma_io = mac_scsi_nodrq; 474#else 475 volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port); 476 volatile unsigned char *dma_io = (unsigned char *)((int)mac_scsi_nodrq); 477#endif 478 479 if(!len) return 0; 480 481 CTRL(iobase, 0x00); 482 laddr = (unsigned long *)addr; 483 while(len >= 32) 484 { 485 int status; 486 status = STAT(iobase); 487 if(status & 0x80) 488 goto end; 489 if(!(status & 0x40)) 490 continue; 491 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); 492 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); 493 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); 494 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); 495 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); 496 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); 497 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); 498 *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); 499 len -= 32; 500 if(len == 0) 501 break; 502 } 503 504 addr = (unsigned char *)laddr; 505 CTRL(iobase, 0x10); 506 while(len > 0) 507 { 508 int status; 509 status = STAT(iobase); 510 if(status & 0x80) 511 goto end; 512 if(status & 0x40) 513 { 514 *addr++ = IN(dma_io); 515 if(--len == 0) 516 break; 517 } 518 519 status = STAT(iobase); 520 if(status & 0x80) 521 goto end; 522 if(status & 0x40) 523 { 524 *addr++ = IN(dma_io); 525 if(--len == 0) 526 break; 527 } 528 } 529end: 530 CTRL(iobase, oldctrl|0x40); 531 return len; 532} 533 534#undef STAT 535#undef CTRL 536#undef IN 537#undef OUT 538 539/* 540 * NCR 5380 register access functions 541 */ 542 543#ifdef ORIG 544#define CTRL(p,v) (*ctrl = (v)) 545 546static char macscsi_read(struct Scsi_Host *instance, int reg) 547{ 548 int iobase = instance->io_port; 549 int i; 550 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; 551 552 CTRL(iobase, 0); 553 i = inb(iobase + reg<<4); 554 CTRL(iobase, 0x40); 555 556 return i; 557} 558 559static void macscsi_write(struct Scsi_Host *instance, int reg, int value) 560{ 561 int iobase = instance->io_port; 562 int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; 563 564 CTRL(iobase, 0); 565 outb(value, iobase + reg<<4); 566 CTRL(iobase, 0x40); 567} 568 569#undef CTRL 570 571#else 572static char macscsi_read(struct Scsi_Host *instance, int reg) 573{ 574 return( mac_scsi_regp[reg << 4] ); 575} 576 577static void macscsi_write(struct Scsi_Host *instance, int reg, int value) 578{ 579 mac_scsi_regp[reg << 4] = value; 580} 581 582#endif 583 584#include "NCR5380.c" 585 586/* 587 * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk; 588 * reentering NCR5380_print_status seems to have ugly side effects 589 */ 590 591void scsi_mac_debug (void) 592{ 593 unsigned long flags; 594 NCR5380_local_declare(); 595 596 if (default_instance) { 597 save_flags(flags); 598 cli(); 599 NCR5380_print_status(default_instance); 600 restore_flags(flags); 601 } 602} 603/* 604 * Helper function for interrupt trouble. More ugly side effects here. 605 */ 606 607void scsi_mac_polled (void) 608{ 609 unsigned long flags; 610 NCR5380_local_declare(); 611 struct Scsi_Host *instance; 612 613 instance = default_instance; 614 NCR5380_setup(instance); 615 if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ) 616 { 617 printk("SCSI poll\n"); 618 save_flags(flags); 619 cli(); 620 NCR5380_intr(IRQ_MAC_SCSI, instance, NULL); 621 restore_flags(flags); 622 } 623} 624 625 626 627static Scsi_Host_Template driver_template = MAC_NCR5380; 628 629#include "scsi_module.c" 630