Date: Thu, 10 Sep 1998 08:11:30 +0100
From: Jesper Skov <jskov@cygnus.co.uk>
To: linux-m68k@lists.linux-m68k.org
Subject: L68K: another NCR patch from Carsten (or is it the same?)
Sender: owner-linux-m68k@phil.uni-sb.de

diff -urN -X exclude linux-2.1.115/drivers/scsi/NCR53C9x.c linux-2.1.115-current/drivers/scsi/NCR53C9x.c
--- linux-2.1.115/drivers/scsi/NCR53C9x.c	Mon Sep  7 18:35:21 1998
+++ linux-2.1.115-current/drivers/scsi/NCR53C9x.c	Mon Sep  7 19:21:05 1998
@@ -694,6 +694,7 @@
 	/* Initialize the command queues */
 	esp->current_SC = 0;
 	esp->disconnected_SC = 0;
+	esp->disconnected_mask = 0;
 	esp->issue_SC = 0;
 	
 	/* Clear the state machines. */
@@ -987,22 +988,41 @@
 static inline void esp_exec_cmd(struct NCR_ESP *esp)
 {
 	struct ESP_regs *eregs = esp->eregs;
-	Scsi_Cmnd *SCptr;
+	Scsi_Cmnd *SCptr, **SCptr2;
 	Scsi_Device *SDptr;
 	volatile unchar *cmdp = esp->esp_command;
 	unsigned char the_esp_command;
 	int lun, target;
 	int i;
 
-	/* Hold off if we've been reselected or an IRQ is showing... */
-	if(esp->disconnected_SC || esp->dma_irq_p(esp))
-		return;
+	/* Hold off if an IRQ is showing... */
+	if(esp->dma_irq_p(esp)) return;
 
-	/* Grab first member of the issue queue. */
-	SCptr = esp->current_SC = remove_first_SC(&esp->issue_SC);
+	SCptr2 = &(esp->issue_SC);
 
 	/* Safe to panic here because current_SC is null. */
-	if(!SCptr) panic("esp: esp_exec_cmd and issue queue is NULL");
+	if(!(*SCptr2)) panic("esp: esp_exec_cmd and issue queue is NULL");
+
+	/* Search for first command whose target is not disconnected
+	 * (free bus means target is idle in that case)
+	 */
+	while(*SCptr2)
+	 {
+	  if(!(esp->disconnected_mask & (1 << ((*SCptr2)->target)))) break;
+	  SCptr2 = (Scsi_Cmnd **) &((*SCptr2)->host_scribble);
+	 }
+
+	/* Here it means no suitable command found. */
+	if(!(*SCptr2)) return;
+	
+	/* Grab member of the issue queue. */
+	SCptr = esp->current_SC = remove_first_SC(SCptr2);
+
+	/*
+	 * Some devices (like my scanner) are so slow that we really need to
+	 * make sure that the bus is free.
+	 */
+        while(esp->eregs->esp_status & ESP_STAT_PMASK);
 
 	SDptr = SCptr->device;
 	lun = SCptr->lun;
@@ -2130,6 +2150,7 @@
 		esp_cmd(esp, eregs, ESP_CMD_ESEL);
 		ESPDISC(("D<%02x,%02x>", SCptr->target, SCptr->lun));
 		append_SC(&esp->disconnected_SC, SCptr);
+		esp->disconnected_mask |= (1 << (SCptr->target));
 		esp->current_SC = NULL;
 		if(esp->issue_SC)
 			esp_exec_cmd(esp);
@@ -2180,6 +2201,8 @@
 		esp_cmd(esp, eregs, ESP_CMD_NULL);
 	}
 
+	esp->disconnected_mask &= ~(1 << target);
+	
 	SCptr = remove_SC(&esp->disconnected_SC, (unchar) target, (unchar) lun);
 	if(!SCptr) {
 		Scsi_Cmnd *sp;
diff -urN -X exclude linux-2.1.115/drivers/scsi/NCR53C9x.h linux-2.1.115-current/drivers/scsi/NCR53C9x.h
--- linux-2.1.115/drivers/scsi/NCR53C9x.h	Mon Aug 17 20:32:16 1998
+++ linux-2.1.115-current/drivers/scsi/NCR53C9x.h	Mon Sep  7 18:45:26 1998
@@ -282,6 +282,11 @@
   Scsi_Cmnd *current_SC;         /* Who is currently working the bus */
   Scsi_Cmnd *disconnected_SC;    /* Commands disconnected from the bus */
 
+  /* when fetching the next command out of issue_SC, ignore the targets
+   * whose bit is set; they're currently busy.
+   */
+  int disconnected_mask;         /* bit mask of disconnected targets */
+
   /* Message goo */
   unchar cur_msgout[16];
   unchar cur_msgin[16];
