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

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)