2 * Generic Macintosh NCR5380 driver 4 * Copyright 1998, Michael Schmitz <mschmitz@lbl.gov> 6 * derived in part from: 9 * Generic Generic NCR5380 driver 11 * Copyright 1995, Russell King 15 * For more information, please consult 18 * SCSI Protocol Controller 21 * NCR Microelectronics 22 * 1635 Aeroplaza Drive 23 * Colorado Springs, CO 80916 32 * PARITY - enable parity checking. Not supported. 34 * SCSI2 - enable support for SCSI-II tagged queueing. Untested. 36 * USLEEP - enable support for devices that don't disconnect. Untested. 40 * $Log: mac_NCR5380.c,v $ 48 #include <linux/types.h> 49 #include <linux/stddef.h> 50 #include <linux/ctype.h> 51 #include <linux/delay.h> 53 #include <linux/module.h> 54 #include <linux/signal.h> 55 #include <linux/sched.h> 56 #include <linux/ioport.h> 57 #include <linux/init.h> 58 #include <linux/blk.h> 62 #include <asm/system.h> 64 #include <asm/macintosh.h> 65 #include <asm/macints.h> 66 #include <asm/machw.h> 67 #include <asm/mac_via.h> 76 #define NDEBUG (NDEBUG_INTR | NDEBUG_PSEUDO_DMA | NDEBUG_ARBITRATION | NDEBUG_SELECTION | NDEBUG_RESELECTION) 78 #define NDEBUG (NDEBUG_ABORT) 85 * BUG can be used to trigger a strange code-size related hang on 2.1 kernels 92 #define ENABLE_IRQ() mac_enable_irq( IRQ_MAC_SCSI ); 93 #define DISABLE_IRQ() mac_disable_irq( IRQ_MAC_SCSI ); 96 static voidmac_scsi_reset_boot(struct Scsi_Host
*instance
); 98 static charmacscsi_read(struct Scsi_Host
*instance
,int reg
); 99 static voidmacscsi_write(struct Scsi_Host
*instance
,int reg
,int value
); 101 static int setup_can_queue
= -1; 102 static int setup_cmd_per_lun
= -1; 103 static int setup_sg_tablesize
= -1; 105 static int setup_use_tagged_queuing
= -1; 107 static int setup_hostid
= -1; 109 static int polled_scsi_on
=0; 111 /* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms, 112 * we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more 113 * need ten times the standard value... */ 114 #define TOSHIBA_DELAY 117 #define AFTER_RESET_DELAY (5*HZ/2) 119 #define AFTER_RESET_DELAY (HZ/2) 122 staticvolatileunsigned char*mac_scsi_regp
= NULL
; 123 staticvolatileunsigned char*mac_scsi_drq
= NULL
; 124 staticvolatileunsigned char*mac_scsi_nodrq
= NULL
; 127 * Function : mac_scsi_setup(char *str, int *ints) 129 * Purpose : booter command line initialization of the overrides array, 131 * Inputs : str - unused, ints - array of integer parameters with ints[0] 132 * equal to the number of ints. 136 static int __init
mac_scsi_setup(char*str
,int*ints
) { 138 /* Format of mac5380 parameter is: 139 * mac5380=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags> 140 * Negative values mean don't change. 143 /* Grmbl... the standard parameter parsing can't handle negative numbers 144 * :-( So let's do it ourselves! 147 int i
= ints
[0]+1, fact
; 149 while( str
&& (isdigit(*str
) || *str
=='-') && i
<=10) { 154 ints
[i
++] =simple_strtoul( str
, NULL
,0) * fact
; 155 if((str
=strchr( str
,',')) != NULL
) 161 printk("mac_scsi_setup: no arguments!\n"); 167 /* no limits on this, just > 0 */ 168 setup_can_queue
= ints
[1]; 172 setup_cmd_per_lun
= ints
[2]; 176 setup_sg_tablesize
= ints
[3]; 177 /* Must be <= SG_ALL (255) */ 178 if(setup_sg_tablesize
> SG_ALL
) 179 setup_sg_tablesize
= SG_ALL
; 183 /* Must be between 0 and 7 */ 184 if(ints
[4] >=0&& ints
[4] <=7) 185 setup_hostid
= ints
[4]; 187 printk("mac_scsi_setup: invalid host ID %d !\n", ints
[4] ); 192 setup_use_tagged_queuing
= !!ints
[5]; 199 __setup("mac5380=", mac_scsi_setup
); 202 #define MAC_ADDRESS(card) (ecard_address((card), ECARD_IOC, ECARD_SLOW) + 0x800) 203 #define MAC_IRQ(card) ((card)->irq) 209 static struct Scsi_Host
*default_instance
; 212 * Function : int macscsi_detect(Scsi_Host_Template * tpnt) 214 * Purpose : initializes mac NCR5380 driver based on the 215 * command line / compile time port and irq definitions. 217 * Inputs : tpnt - template for this SCSI adapter. 219 * Returns : 1 if a host adapter was found, 0 if not. 223 intmacscsi_detect(Scsi_Host_Template
* tpnt
) 226 static int called
=0; 227 struct Scsi_Host
*instance
; 229 if(!MACH_IS_MAC
|| called
) 232 if(macintosh_config
->scsi_type
!= MAC_SCSI_OLD
) 235 tpnt
->proc_name
="mac5380"; 237 /* setup variables */ 239 (setup_can_queue
>0) ? setup_can_queue
: CAN_QUEUE
; 241 (setup_cmd_per_lun
>0) ? setup_cmd_per_lun
: CMD_PER_LUN
; 243 (setup_sg_tablesize
>=0) ? setup_sg_tablesize
: SG_TABLESIZE
; 246 tpnt
->this_id
= setup_hostid
; 248 /* use 7 as default */ 253 if(setup_use_tagged_queuing
<0) 254 setup_use_tagged_queuing
= DEFAULT_USE_TAGGED_QUEUING
; 257 #if 0/* loop over multiple adapters (Powerbooks ??) */ 258 for(count
=0; count
< mac_num_scsi
; count
++) { 260 instance
=scsi_register(tpnt
,sizeof(struct NCR5380_hostdata
)); 263 default_instance
= instance
; 265 if(macintosh_config
->ident
== MAC_MODEL_IIFX
) { 266 mac_scsi_regp
= via1
+0x8000; 267 mac_scsi_drq
= via1
+0xE000; 268 mac_scsi_nodrq
= via1
+0xC000; 270 mac_scsi_regp
= via1
+0x10000; 271 mac_scsi_drq
= via1
+0x6000; 272 mac_scsi_nodrq
= via1
+0x12000; 276 instance
->io_port
= (unsigned long) mac_scsi_regp
; 277 instance
->irq
= IRQ_MAC_SCSI
; 280 mac_scsi_reset_boot(instance
); 283 NCR5380_init(instance
,0); 285 instance
->n_io_port
=255; 287 ((struct NCR5380_hostdata
*)instance
->hostdata
)->ctrl
=0; 289 if(instance
->irq
!= IRQ_NONE
) 290 if(request_irq(instance
->irq
, NCR5380_intr
, IRQ_FLG_SLOW
,"ncr5380", NCR5380_intr
)) { 291 printk("scsi%d: IRQ%d not free, interrupts disabled\n", 292 instance
->host_no
, instance
->irq
); 293 instance
->irq
= IRQ_NONE
; 296 printk("scsi%d: generic 5380 at port %lX irq", instance
->host_no
, instance
->io_port
); 297 if(instance
->irq
== IRQ_NONE
) 298 printk("s disabled"); 300 printk(" %d", instance
->irq
); 301 printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", 302 instance
->can_queue
, instance
->cmd_per_lun
, MACSCSI_PUBLIC_RELEASE
); 303 printk("\nscsi%d:", instance
->host_no
); 304 NCR5380_print_options(instance
); 306 #if 0/* multiple adapters */ 314 intmacscsi_release(struct Scsi_Host
*shpnt
) 316 if(shpnt
->irq
!= IRQ_NONE
) 317 free_irq(shpnt
->irq
, NCR5380_intr
); 324 * Our 'bus reset on boot' function 327 static voidmac_scsi_reset_boot(struct Scsi_Host
*instance
) 331 NCR5380_local_declare(); 332 NCR5380_setup(instance
); 335 * Do a SCSI reset to clean up the bus during initialization. No messing 336 * with the queues, interrupts, or locks necessary here. 339 printk("Macintosh SCSI: resetting the SCSI bus..."); 341 /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */ 342 mac_disable_irq(IRQ_MAC_SCSI
); 345 NCR5380_write( TARGET_COMMAND_REG
, 346 PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG
) )); 349 NCR5380_write( INITIATOR_COMMAND_REG
, ICR_BASE
| ICR_ASSERT_RST
); 350 /* The min. reset hold time is 25us, so 40us should be enough */ 352 /* reset RST and interrupt */ 353 NCR5380_write( INITIATOR_COMMAND_REG
, ICR_BASE
); 354 NCR5380_read( RESET_PARITY_INTERRUPT_REG
); 356 for( end
= jiffies
+ AFTER_RESET_DELAY
; jiffies
< end
; ) 359 /* switch on SCSI IRQ again */ 360 mac_enable_irq(IRQ_MAC_SCSI
); 366 const char*macscsi_info(struct Scsi_Host
*spnt
) { 370 voidrestore_irq(struct pt_regs
*regs
) 375 flags
= (flags
& ~0x0700) | (regs
->sr
&0x0700); 376 restore_flags(flags
); 380 * pseudo-DMA transfer functions, copied and modified from Russel King's 381 * ARM 5380 driver (cumana_1) 383 * Work in progress (sort of), didn't work last time I checked, don't use! 387 #define CTRL(p,v) outb(*ctrl = (v), (p) - 577) 388 #define STAT(p) inb((p)+1) 389 #define IN(p) inb((p)) 390 #define OUT(v,p) outb((v), (p)) 393 #define CTRL(p,v) (p[-2308] = (*ctrl = (v))) 395 #define CTRL(p,v) (*ctrl = (v)) 397 #define STAT(p) (p[1<<4]) 399 #define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p))) 400 #define OUT(v,p) (*(p) = (v)) 401 #define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v)) 403 #define L(v) (((v)<<16)|((v) & 0x0000ffff)) 404 #define H(v) (((v)>>16)|((v) & 0xffff0000)) 405 #define ioaddr(v) (v) 407 staticinlineintNCR5380_pwrite(struct Scsi_Host
*instance
,unsigned char*addr
, 410 int*ctrl
= &((struct NCR5380_hostdata
*)instance
->hostdata
)->ctrl
; 414 int iobase
= instance
->io_port
; 415 int dma_io
= mac_scsi_nodrq
; 417 volatileunsigned char*iobase
= (unsigned char*)ioaddr(instance
->io_port
); 418 volatileunsigned char*dma_io
= (unsigned char*)(mac_scsi_nodrq
); 424 laddr
= (unsigned long*)addr
; 429 status
=STAT(iobase
); 434 v
=*laddr
++;OUT2(L(v
),dma_io
);OUT2(H(v
),dma_io
); 435 v
=*laddr
++;OUT2(L(v
),dma_io
);OUT2(H(v
),dma_io
); 436 v
=*laddr
++;OUT2(L(v
),dma_io
);OUT2(H(v
),dma_io
); 437 v
=*laddr
++;OUT2(L(v
),dma_io
);OUT2(H(v
),dma_io
); 438 v
=*laddr
++;OUT2(L(v
),dma_io
);OUT2(H(v
),dma_io
); 439 v
=*laddr
++;OUT2(L(v
),dma_io
);OUT2(H(v
),dma_io
); 440 v
=*laddr
++;OUT2(L(v
),dma_io
);OUT2(H(v
),dma_io
); 441 v
=*laddr
++;OUT2(L(v
),dma_io
);OUT2(H(v
),dma_io
); 447 addr
= (unsigned char*)laddr
; 452 status
=STAT(iobase
); 457 OUT(*addr
++, dma_io
); 462 status
=STAT(iobase
); 467 OUT(*addr
++, dma_io
); 473 CTRL(iobase
, oldctrl
|0x40); 477 staticinlineintNCR5380_pread(struct Scsi_Host
*instance
,unsigned char*addr
, 480 int*ctrl
= &((struct NCR5380_hostdata
*)instance
->hostdata
)->ctrl
; 484 int iobase
= instance
->io_port
; 485 int dma_io
= mac_scsi_nodrq
; 487 volatileunsigned char*iobase
= (unsigned char*)ioaddr(instance
->io_port
); 488 volatileunsigned char*dma_io
= (unsigned char*)((int)mac_scsi_nodrq
); 494 laddr
= (unsigned long*)addr
; 498 status
=STAT(iobase
); 503 *laddr
++ =IN2(dma_io
)|(IN2(dma_io
)<<16); 504 *laddr
++ =IN2(dma_io
)|(IN2(dma_io
)<<16); 505 *laddr
++ =IN2(dma_io
)|(IN2(dma_io
)<<16); 506 *laddr
++ =IN2(dma_io
)|(IN2(dma_io
)<<16); 507 *laddr
++ =IN2(dma_io
)|(IN2(dma_io
)<<16); 508 *laddr
++ =IN2(dma_io
)|(IN2(dma_io
)<<16); 509 *laddr
++ =IN2(dma_io
)|(IN2(dma_io
)<<16); 510 *laddr
++ =IN2(dma_io
)|(IN2(dma_io
)<<16); 516 addr
= (unsigned char*)laddr
; 521 status
=STAT(iobase
); 531 status
=STAT(iobase
); 542 CTRL(iobase
, oldctrl
|0x40); 552 * NCR 5380 register access functions 557 #define CTRL(p,v) outb(*ctrl = (v), (p) - 577) 559 #define CTRL(p,v) (*ctrl = (v)) 562 static charmacscsi_read(struct Scsi_Host
*instance
,int reg
) 564 int iobase
= instance
->io_port
; 566 int*ctrl
= &((struct NCR5380_hostdata
*)instance
->hostdata
)->ctrl
; 570 i
=inb(iobase
+64+ reg
); 572 i
=inb(iobase
+ reg
<<4); 579 static voidmacscsi_write(struct Scsi_Host
*instance
,int reg
,int value
) 581 int iobase
= instance
->io_port
; 582 int*ctrl
= &((struct NCR5380_hostdata
*)instance
->hostdata
)->ctrl
; 586 outb(value
, iobase
+64+ reg
); 588 outb(value
, iobase
+ reg
<<4); 596 static charmacscsi_read(struct Scsi_Host
*instance
,int reg
) 598 return( mac_scsi_regp
[reg
<<4] ); 601 static voidmacscsi_write(struct Scsi_Host
*instance
,int reg
,int value
) 603 mac_scsi_regp
[reg
<<4] = value
; 611 * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk; 612 * reentering NCR5380_print_status seems to have ugly side effects 615 voidscsi_mac_debug(void) 618 NCR5380_local_declare(); 620 if(default_instance
) { 622 NCR5380_setup(default_instance
); 623 if(NCR5380_read(BUS_AND_STATUS_REG
)&BASR_IRQ
) 627 NCR5380_print_status(default_instance
); 628 restore_flags(flags
); 635 * Helper function for interrupt trouble. More ugly side effects here. 638 voidscsi_mac_polled(void) 641 NCR5380_local_declare(); 642 struct Scsi_Host
*instance
; 645 for(instance
= first_instance
; instance
&& (instance
->hostt
== 646 the_template
); instance
= instance
->next
) 647 if(instance
->irq
== IRQ_MAC_SCSI
&& polled_scsi_on
) { 649 instance
= default_instance
; 651 NCR5380_setup(instance
); 652 if(NCR5380_read(BUS_AND_STATUS_REG
)&BASR_IRQ
) 654 printk("SCSI poll\n"); 657 NCR5380_intr(IRQ_MAC_SCSI
, instance
, NULL
); 658 restore_flags(flags
); 667 static Scsi_Host_Template driver_template
= MAC_NCR5380
; 669 #include"scsi_module.c"