patch-2.4.21 linux-2.4.21/drivers/scsi/mac_scsi.c
Next file: linux-2.4.21/drivers/scsi/mac_scsi.h
Previous file: linux-2.4.21/drivers/scsi/ips.h
Back to the patch index
Back to the overall index
- Lines: 847
- Date:
2003-06-13 07:51:36.000000000 -0700
- Orig file:
linux-2.4.20/drivers/scsi/mac_scsi.c
- Orig date:
2002-02-25 11:38:04.000000000 -0800
diff -urN linux-2.4.20/drivers/scsi/mac_scsi.c linux-2.4.21/drivers/scsi/mac_scsi.c
@@ -25,26 +25,10 @@
* 1+ (800) 334-5454
*/
-
-/*
- * Options :
- *
- * PARITY - enable parity checking. Not supported.
- *
- * SCSI2 - enable support for SCSI-II tagged queueing. Untested.
- *
- * USLEEP - enable support for devices that don't disconnect. Untested.
- */
-
/*
* $Log: mac_NCR5380.c,v $
*/
-#define AUTOSENSE
-#if 0
-#define PSEUDO_DMA
-#endif
-
#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/ctype.h>
@@ -81,33 +65,28 @@
#define RESET_BOOT
#define DRIVER_SETUP
-/*
- * BUG can be used to trigger a strange code-size related hang on 2.1 kernels
- */
-#ifdef BUG
-#undef RESET_BOOT
-#undef DRIVER_SETUP
-#endif
-
#define ENABLE_IRQ() mac_enable_irq( IRQ_MAC_SCSI );
#define DISABLE_IRQ() mac_disable_irq( IRQ_MAC_SCSI );
+extern void via_scsi_clear(void);
+
#ifdef RESET_BOOT
static void mac_scsi_reset_boot(struct Scsi_Host *instance);
#endif
-static char macscsi_read(struct Scsi_Host *instance, int reg);
-static void macscsi_write(struct Scsi_Host *instance, int reg, int value);
+static __inline__ char macscsi_read(struct Scsi_Host *instance, int reg);
+static __inline__ void macscsi_write(struct Scsi_Host *instance, int reg, int value);
+
+static int setup_called = 0;
static int setup_can_queue = -1;
static int setup_cmd_per_lun = -1;
static int setup_sg_tablesize = -1;
+static int setup_use_pdma = -1;
#ifdef SUPPORT_TAGS
static int setup_use_tagged_queuing = -1;
#endif
static int setup_hostid = -1;
-static int polled_scsi_on = 0;
-
/* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms,
* we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more
* need ten times the standard value... */
@@ -124,44 +103,27 @@
static volatile unsigned char *mac_scsi_nodrq = NULL;
/*
- * Function : mac_scsi_setup(char *str, int *ints)
+ * Function : mac_scsi_setup(char *str)
*
* Purpose : booter command line initialization of the overrides array,
*
- * Inputs : str - unused, ints - array of integer parameters with ints[0]
- * equal to the number of ints.
+ * Inputs : str - comma delimited list of options
*
*/
-static int __init mac_scsi_setup(char *str, int *ints) {
-#ifdef DRIVER_SETUP
- /* Format of mac5380 parameter is:
- * mac5380=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
- * Negative values mean don't change.
- */
+static int __init mac_scsi_setup(char *str) {
+#ifdef DRIVER_SETUP
+ int ints[7];
- /* Grmbl... the standard parameter parsing can't handle negative numbers
- * :-( So let's do it ourselves!
- */
-
- int i = ints[0]+1, fact;
-
- while( str && (isdigit(*str) || *str == '-') && i <= 10) {
- if (*str == '-')
- fact = -1, ++str;
- else
- fact = 1;
- ints[i++] = simple_strtoul( str, NULL, 0 ) * fact;
- if ((str = strchr( str, ',' )) != NULL)
- ++str;
- }
- ints[0] = i-1;
+ (void)get_options( str, ARRAY_SIZE(ints), ints);
- if (ints[0] < 1) {
- printk( "mac_scsi_setup: no arguments!\n" );
- return 0;
+ if (setup_called++ || ints[0] < 1 || ints[0] > 6) {
+ printk(KERN_WARNING "scsi: <mac5380>"
+ " Usage: mac5380=<can_queue>[,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>,<use_pdma>]\n");
+ printk(KERN_ALERT "scsi: <mac5380> Bad Penguin parameters?\n");
+ return 0;
}
-
+
if (ints[0] >= 1) {
if (ints[1] > 0)
/* no limits on this, just > 0 */
@@ -184,25 +146,31 @@
if (ints[4] >= 0 && ints[4] <= 7)
setup_hostid = ints[4];
else if (ints[4] > 7)
- printk( "mac_scsi_setup: invalid host ID %d !\n", ints[4] );
+ printk(KERN_WARNING "mac_scsi_setup: invalid host ID %d !\n", ints[4] );
}
-#ifdef SUPPORT_TAGS
+#ifdef SUPPORT_TAGS
if (ints[0] >= 5) {
if (ints[5] >= 0)
setup_use_tagged_queuing = !!ints[5];
}
+
+ if (ints[0] == 6) {
+ if (ints[6] >= 0)
+ setup_use_pdma = ints[6];
+ }
+#else
+ if (ints[0] == 5) {
+ if (ints[5] >= 0)
+ setup_use_pdma = ints[5];
+ }
#endif
+
#endif
- return 1;
+ return 1;
}
__setup("mac5380=", mac_scsi_setup);
-#if 0
-#define MAC_ADDRESS(card) (ecard_address((card), ECARD_IOC, ECARD_SLOW) + 0x800)
-#define MAC_IRQ(card) ((card)->irq)
-#endif
-
/*
* XXX: status debug
*/
@@ -222,93 +190,89 @@
int macscsi_detect(Scsi_Host_Template * tpnt)
{
- int count = 0;
static int called = 0;
+ int flags = 0;
struct Scsi_Host *instance;
if (!MACH_IS_MAC || called)
return( 0 );
if (macintosh_config->scsi_type != MAC_SCSI_OLD)
- return( 0 );
-
- tpnt->proc_name = "mac5380";
+ return( 0 );
/* setup variables */
tpnt->can_queue =
- (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
+ (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
tpnt->cmd_per_lun =
- (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
+ (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
tpnt->sg_tablesize =
- (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
+ (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
if (setup_hostid >= 0)
- tpnt->this_id = setup_hostid;
+ tpnt->this_id = setup_hostid;
else {
- /* use 7 as default */
- tpnt->this_id = 7;
+ /* use 7 as default */
+ tpnt->this_id = 7;
}
#ifdef SUPPORT_TAGS
- if (setup_use_tagged_queuing < 0)
- setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
+ if (setup_use_tagged_queuing < 0)
+ setup_use_tagged_queuing = USE_TAGGED_QUEUING;
#endif
-#if 0 /* loop over multiple adapters (Powerbooks ??) */
- for (count = 0; count < mac_num_scsi; count++) {
-#endif
- instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
- if(instance == NULL)
- continue;
- default_instance = instance;
-
- if (macintosh_config->ident == MAC_MODEL_IIFX) {
- mac_scsi_regp = via1+0x8000;
- mac_scsi_drq = via1+0xE000;
- mac_scsi_nodrq = via1+0xC000;
- } else {
- mac_scsi_regp = via1+0x10000;
- mac_scsi_drq = via1+0x6000;
- mac_scsi_nodrq = via1+0x12000;
- }
-
+ /* Once we support multiple 5380s (e.g. DuoDock) we'll do
+ something different here */
+ instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
+ default_instance = instance;
+
+ if (macintosh_config->ident == MAC_MODEL_IIFX) {
+ mac_scsi_regp = via1+0x8000;
+ mac_scsi_drq = via1+0xE000;
+ mac_scsi_nodrq = via1+0xC000;
+ /* The IIFX should be able to do true DMA, but pseudo-dma doesn't work */
+ flags = FLAG_NO_PSEUDO_DMA;
+ } else {
+ mac_scsi_regp = via1+0x10000;
+ mac_scsi_drq = via1+0x6000;
+ mac_scsi_nodrq = via1+0x12000;
+ }
- instance->io_port = (unsigned long) mac_scsi_regp;
- instance->irq = IRQ_MAC_SCSI;
+ if (! setup_use_pdma)
+ flags = FLAG_NO_PSEUDO_DMA;
+
+ instance->io_port = (unsigned long) mac_scsi_regp;
+ instance->irq = IRQ_MAC_SCSI;
-#ifdef RESET_BOOT
- mac_scsi_reset_boot(instance);
+#ifdef RESET_BOOT
+ mac_scsi_reset_boot(instance);
#endif
+
+ NCR5380_init(instance, flags);
- NCR5380_init(instance, 0);
+ instance->n_io_port = 255;
- instance->n_io_port = 255;
+ ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
- ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0;
+ if (instance->irq != IRQ_NONE)
+ if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW,
+ "ncr5380", NCR5380_intr)) {
+ printk(KERN_WARNING "scsi%d: IRQ%d not free, interrupts disabled\n",
+ instance->host_no, instance->irq);
+ instance->irq = IRQ_NONE;
+ }
- if (instance->irq != IRQ_NONE)
- if (request_irq(instance->irq, NCR5380_intr, IRQ_FLG_SLOW, "ncr5380", NCR5380_intr)) {
- printk("scsi%d: IRQ%d not free, interrupts disabled\n",
- instance->host_no, instance->irq);
- instance->irq = IRQ_NONE;
- }
-
- printk("scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port);
- if (instance->irq == IRQ_NONE)
- printk ("s disabled");
- else
- printk (" %d", instance->irq);
- printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
- instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE);
- printk("\nscsi%d:", instance->host_no);
- NCR5380_print_options(instance);
- printk("\n");
-#if 0 /* multiple adapters */
- }
-#endif
+ printk(KERN_INFO "scsi%d: generic 5380 at port %lX irq", instance->host_no, instance->io_port);
+ if (instance->irq == IRQ_NONE)
+ printk (KERN_INFO "s disabled");
+ else
+ printk (KERN_INFO " %d", instance->irq);
+ printk(KERN_INFO " options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
+ instance->can_queue, instance->cmd_per_lun, MACSCSI_PUBLIC_RELEASE);
+ printk(KERN_INFO "\nscsi%d:", instance->host_no);
+ NCR5380_print_options(instance);
+ printk("\n");
called = 1;
return 1;
-
}
int macscsi_release (struct Scsi_Host *shpnt)
@@ -336,10 +300,10 @@
* with the queues, interrupts, or locks necessary here.
*/
- printk( "Macintosh SCSI: resetting the SCSI bus..." );
+ printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." );
/* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
- mac_disable_irq(IRQ_MAC_SCSI);
+ mac_disable_irq(IRQ_MAC_SCSI);
/* get in phase */
NCR5380_write( TARGET_COMMAND_REG,
@@ -357,207 +321,22 @@
barrier();
/* switch on SCSI IRQ again */
- mac_enable_irq(IRQ_MAC_SCSI);
+ mac_enable_irq(IRQ_MAC_SCSI);
- printk( " done\n" );
+ printk(KERN_INFO " done\n" );
}
#endif
const char * macscsi_info (struct Scsi_Host *spnt) {
- return "";
-}
-
-void restore_irq(struct pt_regs *regs)
-{
- unsigned long flags;
-
- save_flags(flags);
- flags = (flags & ~0x0700) | (regs->sr & 0x0700);
- restore_flags(flags);
+ return "";
}
/*
- * pseudo-DMA transfer functions, copied and modified from Russel King's
- * ARM 5380 driver (cumana_1)
- *
- * Work in progress (sort of), didn't work last time I checked, don't use!
- */
-
-#ifdef NOT_EFFICIENT
-#define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
-#define STAT(p) inb((p)+1)
-#define IN(p) inb((p))
-#define OUT(v,p) outb((v), (p))
-#else
-#if 0
-#define CTRL(p,v) (p[-2308] = (*ctrl = (v)))
-#else
-#define CTRL(p,v) (*ctrl = (v))
-#endif
-#define STAT(p) (p[1<<4])
-#define IN(p) (*(p))
-#define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p)))
-#define OUT(v,p) (*(p) = (v))
-#define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v))
-#endif
-#define L(v) (((v)<<16)|((v) & 0x0000ffff))
-#define H(v) (((v)>>16)|((v) & 0xffff0000))
-#define ioaddr(v) (v)
-
-static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr,
- int len)
-{
- int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
- int oldctrl = *ctrl;
- unsigned long *laddr;
-#ifdef NOT_EFFICIENT
- int iobase = instance->io_port;
- int dma_io = mac_scsi_nodrq;
-#else
- volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
- volatile unsigned char *dma_io = (unsigned char *)(mac_scsi_nodrq);
-#endif
-
- if(!len) return 0;
-
- CTRL(iobase, 0x02);
- laddr = (unsigned long *)addr;
- while(len >= 32)
- {
- int status;
- unsigned long v;
- status = STAT(iobase);
- if(status & 0x80)
- goto end;
- if(!(status & 0x40))
- continue;
- v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
- v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
- v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
- v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
- v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
- v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
- v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
- v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io);
- len -= 32;
- if(len == 0)
- break;
- }
-
- addr = (unsigned char *)laddr;
- CTRL(iobase, 0x12);
- while(len > 0)
- {
- int status;
- status = STAT(iobase);
- if(status & 0x80)
- goto end;
- if(status & 0x40)
- {
- OUT(*addr++, dma_io);
- if(--len == 0)
- break;
- }
-
- status = STAT(iobase);
- if(status & 0x80)
- goto end;
- if(status & 0x40)
- {
- OUT(*addr++, dma_io);
- if(--len == 0)
- break;
- }
- }
-end:
- CTRL(iobase, oldctrl|0x40);
- return len;
-}
-
-static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr,
- int len)
-{
- int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
- int oldctrl = *ctrl;
- unsigned long *laddr;
-#ifdef NOT_EFFICIENT
- int iobase = instance->io_port;
- int dma_io = mac_scsi_nodrq;
-#else
- volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port);
- volatile unsigned char *dma_io = (unsigned char *)((int)mac_scsi_nodrq);
-#endif
-
- if(!len) return 0;
-
- CTRL(iobase, 0x00);
- laddr = (unsigned long *)addr;
- while(len >= 32)
- {
- int status;
- status = STAT(iobase);
- if(status & 0x80)
- goto end;
- if(!(status & 0x40))
- continue;
- *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
- *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
- *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
- *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
- *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
- *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
- *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
- *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16);
- len -= 32;
- if(len == 0)
- break;
- }
-
- addr = (unsigned char *)laddr;
- CTRL(iobase, 0x10);
- while(len > 0)
- {
- int status;
- status = STAT(iobase);
- if(status & 0x80)
- goto end;
- if(status & 0x40)
- {
- *addr++ = IN(dma_io);
- if(--len == 0)
- break;
- }
-
- status = STAT(iobase);
- if(status & 0x80)
- goto end;
- if(status & 0x40)
- {
- *addr++ = IN(dma_io);
- if(--len == 0)
- break;
- }
- }
-end:
- CTRL(iobase, oldctrl|0x40);
- return len;
-}
-
-#undef STAT
-#undef CTRL
-#undef IN
-#undef OUT
-
-/*
* NCR 5380 register access functions
*/
-#ifdef ORIG
-#if 0
-#define CTRL(p,v) outb(*ctrl = (v), (p) - 577)
-#else
+/* Debug versions
#define CTRL(p,v) (*ctrl = (v))
-#endif
static char macscsi_read(struct Scsi_Host *instance, int reg)
{
@@ -566,11 +345,7 @@
int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
CTRL(iobase, 0);
-#if 0
- i = inb(iobase + 64 + reg);
-#else
- i = inb(iobase + reg<<4);
-#endif
+ i = in_8(iobase + (reg<<4));
CTRL(iobase, 0x40);
return i;
@@ -582,87 +357,224 @@
int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl;
CTRL(iobase, 0);
-#if 0
- outb(value, iobase + 64 + reg);
-#else
- outb(value, iobase + reg<<4);
-#endif
+ out_8(value, iobase + (reg<<4));
CTRL(iobase, 0x40);
}
+*/
-#undef CTRL
-
-#else
-static char macscsi_read(struct Scsi_Host *instance, int reg)
+/* Fast versions */
+static __inline__ char macscsi_read(struct Scsi_Host *instance, int reg)
{
- return( mac_scsi_regp[reg << 4] );
+ return in_8(instance->io_port + (reg<<4));
}
-static void macscsi_write(struct Scsi_Host *instance, int reg, int value)
-{
- mac_scsi_regp[reg << 4] = value;
+static __inline__ void macscsi_write(struct Scsi_Host *instance, int reg, int value)
+{
+ out_8(value, instance->io_port + (reg<<4));
+}
+
+
+/*
+ Pseudo-DMA: (Ove Edlund)
+ The code attempts to catch bus errors that occur if one for example
+ "trips over the cable".
+ XXX: Since bus errors in the PDMA routines never happen on my
+ computer, the bus error code is untested.
+ If the code works as intended, a bus error results in Pseudo-DMA
+ beeing disabled, meaning that the driver switches to slow handshake.
+ If bus errors are NOT extremely rare, this has to be changed.
+*/
+
+#define CP_IO_TO_MEM(s,d,len) \
+__asm__ __volatile__ \
+ (" cmp.w #4,%2\n" \
+ " bls 8f\n" \
+ " move.w %1,%%d0\n" \
+ " neg.b %%d0\n" \
+ " and.w #3,%%d0\n" \
+ " sub.w %%d0,%2\n" \
+ " bra 2f\n" \
+ " 1: move.b (%0),(%1)+\n" \
+ " 2: dbf %%d0,1b\n" \
+ " move.w %2,%%d0\n" \
+ " lsr.w #5,%%d0\n" \
+ " bra 4f\n" \
+ " 3: move.l (%0),(%1)+\n" \
+ "31: move.l (%0),(%1)+\n" \
+ "32: move.l (%0),(%1)+\n" \
+ "33: move.l (%0),(%1)+\n" \
+ "34: move.l (%0),(%1)+\n" \
+ "35: move.l (%0),(%1)+\n" \
+ "36: move.l (%0),(%1)+\n" \
+ "37: move.l (%0),(%1)+\n" \
+ " 4: dbf %%d0,3b\n" \
+ " move.w %2,%%d0\n" \
+ " lsr.w #2,%%d0\n" \
+ " and.w #7,%%d0\n" \
+ " bra 6f\n" \
+ " 5: move.l (%0),(%1)+\n" \
+ " 6: dbf %%d0,5b\n" \
+ " and.w #3,%2\n" \
+ " bra 8f\n" \
+ " 7: move.b (%0),(%1)+\n" \
+ " 8: dbf %2,7b\n" \
+ " moveq.l #0, %2\n" \
+ " 9: \n" \
+ ".section .fixup,\"ax\"\n" \
+ " .even\n" \
+ "90: moveq.l #1, %2\n" \
+ " jra 9b\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 4\n" \
+ " .long 1b,90b\n" \
+ " .long 3b,90b\n" \
+ " .long 31b,90b\n" \
+ " .long 32b,90b\n" \
+ " .long 33b,90b\n" \
+ " .long 34b,90b\n" \
+ " .long 35b,90b\n" \
+ " .long 36b,90b\n" \
+ " .long 37b,90b\n" \
+ " .long 5b,90b\n" \
+ " .long 7b,90b\n" \
+ ".previous" \
+ : "=a"(s), "=a"(d), "=d"(len) \
+ : "0"(s), "1"(d), "2"(len) \
+ : "d0")
+
+
+static int macscsi_pread (struct Scsi_Host *instance,
+ unsigned char *dst, int len)
+{
+ unsigned char *d;
+ volatile unsigned char *s;
+
+ NCR5380_local_declare();
+ NCR5380_setup(instance);
+
+ s = mac_scsi_drq+0x60;
+ d = dst;
+
+/* These conditions are derived from MacOS */
+
+ while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
+ && !(NCR5380_read(STATUS_REG) & SR_REQ))
+ ;
+ if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
+ && (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
+ printk(KERN_ERR "Error in macscsi_pread\n");
+ return -1;
+ }
+
+ CP_IO_TO_MEM(s, d, len);
+
+ if (len != 0) {
+ printk(KERN_NOTICE "Bus error in macscsi_pread\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+#define CP_MEM_TO_IO(s,d,len) \
+__asm__ __volatile__ \
+ (" cmp.w #4,%2\n" \
+ " bls 8f\n" \
+ " move.w %0,%%d0\n" \
+ " neg.b %%d0\n" \
+ " and.w #3,%%d0\n" \
+ " sub.w %%d0,%2\n" \
+ " bra 2f\n" \
+ " 1: move.b (%0)+,(%1)\n" \
+ " 2: dbf %%d0,1b\n" \
+ " move.w %2,%%d0\n" \
+ " lsr.w #5,%%d0\n" \
+ " bra 4f\n" \
+ " 3: move.l (%0)+,(%1)\n" \
+ "31: move.l (%0)+,(%1)\n" \
+ "32: move.l (%0)+,(%1)\n" \
+ "33: move.l (%0)+,(%1)\n" \
+ "34: move.l (%0)+,(%1)\n" \
+ "35: move.l (%0)+,(%1)\n" \
+ "36: move.l (%0)+,(%1)\n" \
+ "37: move.l (%0)+,(%1)\n" \
+ " 4: dbf %%d0,3b\n" \
+ " move.w %2,%%d0\n" \
+ " lsr.w #2,%%d0\n" \
+ " and.w #7,%%d0\n" \
+ " bra 6f\n" \
+ " 5: move.l (%0)+,(%1)\n" \
+ " 6: dbf %%d0,5b\n" \
+ " and.w #3,%2\n" \
+ " bra 8f\n" \
+ " 7: move.b (%0)+,(%1)\n" \
+ " 8: dbf %2,7b\n" \
+ " moveq.l #0, %2\n" \
+ " 9: \n" \
+ ".section .fixup,\"ax\"\n" \
+ " .even\n" \
+ "90: moveq.l #1, %2\n" \
+ " jra 9b\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 4\n" \
+ " .long 1b,90b\n" \
+ " .long 3b,90b\n" \
+ " .long 31b,90b\n" \
+ " .long 32b,90b\n" \
+ " .long 33b,90b\n" \
+ " .long 34b,90b\n" \
+ " .long 35b,90b\n" \
+ " .long 36b,90b\n" \
+ " .long 37b,90b\n" \
+ " .long 5b,90b\n" \
+ " .long 7b,90b\n" \
+ ".previous" \
+ : "=a"(s), "=a"(d), "=d"(len) \
+ : "0"(s), "1"(d), "2"(len) \
+ : "d0")
+
+static int macscsi_pwrite (struct Scsi_Host *instance,
+ unsigned char *src, int len)
+{
+ unsigned char *s;
+ volatile unsigned char *d;
+
+ NCR5380_local_declare();
+ NCR5380_setup(instance);
+
+ s = src;
+ d = mac_scsi_drq;
+
+/* These conditions are derived from MacOS */
+
+ while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)
+ && (!(NCR5380_read(STATUS_REG) & SR_REQ)
+ || (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)))
+ ;
+ if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)) {
+ printk(KERN_ERR "Error in macscsi_pwrite\n");
+ return -1;
+ }
+
+ CP_MEM_TO_IO(s, d, len);
+
+ if (len != 0) {
+ printk(KERN_NOTICE "Bus error in macscsi_pwrite\n");
+ return -1;
+ }
+
+ return 0;
}
-#endif
-
-#include "NCR5380.c"
-
-/*
- * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk;
- * reentering NCR5380_print_status seems to have ugly side effects
- */
-
-void scsi_mac_debug (void)
-{
- unsigned long flags;
- NCR5380_local_declare();
-
- if (default_instance) {
-#if 0
- NCR5380_setup(default_instance);
- if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ)
-#endif
- save_flags(flags);
- cli();
- NCR5380_print_status(default_instance);
- restore_flags(flags);
- }
-#if 0
- polled_scsi_on = 1;
-#endif
-}
-/*
- * Helper function for interrupt trouble. More ugly side effects here.
- */
-
-void scsi_mac_polled (void)
-{
- unsigned long flags;
- NCR5380_local_declare();
- struct Scsi_Host *instance;
-
-#if 0
- for (instance = first_instance; instance && (instance->hostt ==
- the_template); instance = instance->next)
- if (instance->irq == IRQ_MAC_SCSI && polled_scsi_on) {
-#else
- instance = default_instance;
-#endif
- NCR5380_setup(instance);
- if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ)
- {
- printk("SCSI poll\n");
- save_flags(flags);
- cli();
- NCR5380_intr(IRQ_MAC_SCSI, instance, NULL);
- restore_flags(flags);
- }
-#if 0
- }
-#endif
-}
+/* These control the behaviour of the generic 5380 core */
+#define AUTOSENSE
+#define PSEUDO_DMA
+#include "NCR5380.c"
static Scsi_Host_Template driver_template = MAC_NCR5380;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)