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>
73 #include "constants.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 void mac_scsi_reset_boot(struct Scsi_Host
*instance
);
98 static char macscsi_read(struct Scsi_Host
*instance
, int reg
);
99 static void macscsi_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 static volatile unsigned char *mac_scsi_regp
= NULL
;
123 static volatile unsigned char *mac_scsi_drq
= NULL
;
124 static volatile unsigned 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];
186 else if (ints
[4] > 7)
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 int macscsi_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
;
245 if (setup_hostid
>= 0)
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
));
261 default_instance
= instance
;
263 if (macintosh_config
->ident
== MAC_MODEL_IIFX
) {
264 mac_scsi_regp
= via1
+0x8000;
265 mac_scsi_drq
= via1
+0xE000;
266 mac_scsi_nodrq
= via1
+0xC000;
268 mac_scsi_regp
= via1
+0x10000;
269 mac_scsi_drq
= via1
+0x6000;
270 mac_scsi_nodrq
= via1
+0x12000;
274 instance
->io_port
= (unsigned long) mac_scsi_regp
;
275 instance
->irq
= IRQ_MAC_SCSI
;
278 mac_scsi_reset_boot(instance
);
281 NCR5380_init(instance
, 0);
283 instance
->n_io_port
= 255;
285 ((struct NCR5380_hostdata
*)instance
->hostdata
)->ctrl
= 0;
287 if (instance
->irq
!= IRQ_NONE
)
288 if (request_irq(instance
->irq
, NCR5380_intr
, IRQ_FLG_SLOW
, "ncr5380", NCR5380_intr
)) {
289 printk("scsi%d: IRQ%d not free, interrupts disabled\n",
290 instance
->host_no
, instance
->irq
);
291 instance
->irq
= IRQ_NONE
;
294 printk("scsi%d: generic 5380 at port %lX irq", instance
->host_no
, instance
->io_port
);
295 if (instance
->irq
== IRQ_NONE
)
296 printk ("s disabled");
298 printk (" %d", instance
->irq
);
299 printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
300 instance
->can_queue
, instance
->cmd_per_lun
, MACSCSI_PUBLIC_RELEASE
);
301 printk("\nscsi%d:", instance
->host_no
);
302 NCR5380_print_options(instance
);
304 #if 0 /* multiple adapters */
312 int macscsi_release (struct Scsi_Host
*shpnt
)
314 if (shpnt
->irq
!= IRQ_NONE
)
315 free_irq (shpnt
->irq
, NCR5380_intr
);
322 * Our 'bus reset on boot' function
325 static void mac_scsi_reset_boot(struct Scsi_Host
*instance
)
329 NCR5380_local_declare();
330 NCR5380_setup(instance
);
333 * Do a SCSI reset to clean up the bus during initialization. No messing
334 * with the queues, interrupts, or locks necessary here.
337 printk( "Macintosh SCSI: resetting the SCSI bus..." );
339 /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
340 mac_disable_irq(IRQ_MAC_SCSI
);
343 NCR5380_write( TARGET_COMMAND_REG
,
344 PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG
) ));
347 NCR5380_write( INITIATOR_COMMAND_REG
, ICR_BASE
| ICR_ASSERT_RST
);
348 /* The min. reset hold time is 25us, so 40us should be enough */
350 /* reset RST and interrupt */
351 NCR5380_write( INITIATOR_COMMAND_REG
, ICR_BASE
);
352 NCR5380_read( RESET_PARITY_INTERRUPT_REG
);
354 for( end
= jiffies
+ AFTER_RESET_DELAY
; jiffies
< end
; )
357 /* switch on SCSI IRQ again */
358 mac_enable_irq(IRQ_MAC_SCSI
);
364 const char * macscsi_info (struct Scsi_Host
*spnt
) {
368 void restore_irq(struct pt_regs
*regs
)
373 flags
= (flags
& ~0x0700) | (regs
->sr
& 0x0700);
374 restore_flags(flags
);
378 * pseudo-DMA transfer functions, copied and modified from Russel King's
379 * ARM 5380 driver (cumana_1)
381 * Work in progress (sort of), didn't work last time I checked, don't use!
385 #define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
386 #define STAT(p) inb((p)+1)
387 #define IN(p) inb((p))
388 #define OUT(v,p) outb((v), (p))
391 #define CTRL(p,v) (p[-2308] = (*ctrl = (v)))
393 #define CTRL(p,v) (*ctrl = (v))
395 #define STAT(p) (p[1<<4])
397 #define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p)))
398 #define OUT(v,p) (*(p) = (v))
399 #define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v))
401 #define L(v) (((v)<<16)|((v) & 0x0000ffff))
402 #define H(v) (((v)>>16)|((v) & 0xffff0000))
403 #define ioaddr(v) (v)
405 static inline int NCR5380_pwrite(struct Scsi_Host
*instance
, unsigned char *addr
,
408 int *ctrl
= &((struct NCR5380_hostdata
*)instance
->hostdata
)->ctrl
;
410 unsigned long *laddr
;
412 int iobase
= instance
->io_port
;
413 int dma_io
= mac_scsi_nodrq
;
415 volatile unsigned char *iobase
= (unsigned char *)ioaddr(instance
->io_port
);
416 volatile unsigned char *dma_io
= (unsigned char *)(mac_scsi_nodrq
);
422 laddr
= (unsigned long *)addr
;
427 status
= STAT(iobase
);
432 v
=*laddr
++; OUT2(L(v
),dma_io
); OUT2(H(v
),dma_io
);
433 v
=*laddr
++; OUT2(L(v
),dma_io
); OUT2(H(v
),dma_io
);
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
);
445 addr
= (unsigned char *)laddr
;
450 status
= STAT(iobase
);
455 OUT(*addr
++, dma_io
);
460 status
= STAT(iobase
);
465 OUT(*addr
++, dma_io
);
471 CTRL(iobase
, oldctrl
|0x40);
475 static inline int NCR5380_pread(struct Scsi_Host
*instance
, unsigned char *addr
,
478 int *ctrl
= &((struct NCR5380_hostdata
*)instance
->hostdata
)->ctrl
;
480 unsigned long *laddr
;
482 int iobase
= instance
->io_port
;
483 int dma_io
= mac_scsi_nodrq
;
485 volatile unsigned char *iobase
= (unsigned char *)ioaddr(instance
->io_port
);
486 volatile unsigned char *dma_io
= (unsigned char *)((int)mac_scsi_nodrq
);
492 laddr
= (unsigned long *)addr
;
496 status
= STAT(iobase
);
501 *laddr
++ = IN2(dma_io
)|(IN2(dma_io
)<<16);
502 *laddr
++ = IN2(dma_io
)|(IN2(dma_io
)<<16);
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);
514 addr
= (unsigned char *)laddr
;
519 status
= STAT(iobase
);
524 *addr
++ = IN(dma_io
);
529 status
= STAT(iobase
);
534 *addr
++ = IN(dma_io
);
540 CTRL(iobase
, oldctrl
|0x40);
550 * NCR 5380 register access functions
555 #define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
557 #define CTRL(p,v) (*ctrl = (v))
560 static char macscsi_read(struct Scsi_Host
*instance
, int reg
)
562 int iobase
= instance
->io_port
;
564 int *ctrl
= &((struct NCR5380_hostdata
*)instance
->hostdata
)->ctrl
;
568 i
= inb(iobase
+ 64 + reg
);
570 i
= inb(iobase
+ reg
<<4);
577 static void macscsi_write(struct Scsi_Host
*instance
, int reg
, int value
)
579 int iobase
= instance
->io_port
;
580 int *ctrl
= &((struct NCR5380_hostdata
*)instance
->hostdata
)->ctrl
;
584 outb(value
, iobase
+ 64 + reg
);
586 outb(value
, iobase
+ reg
<<4);
594 static char macscsi_read(struct Scsi_Host
*instance
, int reg
)
596 return( mac_scsi_regp
[reg
<< 4] );
599 static void macscsi_write(struct Scsi_Host
*instance
, int reg
, int value
)
601 mac_scsi_regp
[reg
<< 4] = value
;
609 * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk;
610 * reentering NCR5380_print_status seems to have ugly side effects
613 void scsi_mac_debug (void)
616 NCR5380_local_declare();
618 if (default_instance
) {
620 NCR5380_setup(default_instance
);
621 if(NCR5380_read(BUS_AND_STATUS_REG
)&BASR_IRQ
)
625 NCR5380_print_status(default_instance
);
626 restore_flags(flags
);
633 * Helper function for interrupt trouble. More ugly side effects here.
636 void scsi_mac_polled (void)
639 NCR5380_local_declare();
640 struct Scsi_Host
*instance
;
643 for (instance
= first_instance
; instance
&& (instance
->hostt
==
644 the_template
); instance
= instance
->next
)
645 if (instance
->irq
== IRQ_MAC_SCSI
&& polled_scsi_on
) {
647 instance
= default_instance
;
649 NCR5380_setup(instance
);
650 if(NCR5380_read(BUS_AND_STATUS_REG
)&BASR_IRQ
)
652 printk("SCSI poll\n");
655 NCR5380_intr(IRQ_MAC_SCSI
, instance
, NULL
);
656 restore_flags(flags
);
667 Scsi_Host_Template driver_template
= MAC_NCR5380
;
669 #include "scsi_module.c"