Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ff50f9ed authored by Finn Thain's avatar Finn Thain Committed by Christoph Hellwig
Browse files

atari_NCR5380: Merge from NCR5380.c



The NCR5380.c core driver has moved on since the atari_NCR5380.c fork.
Some of those changes are also relevant to atari_NCR5380.c so apply them
there as well.

Signed-off-by: default avatarFinn Thain <fthain@telegraphics.com.au>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Tested-by: default avatarMichael Schmitz <schmitzmic@gmail.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 8dad0c51
Loading
Loading
Loading
Loading
+85 −120
Original line number Diff line number Diff line
@@ -104,27 +104,7 @@

/*
 * Design
 * Issues :
 *
 * The other Linux SCSI drivers were written when Linux was Intel PC-only,
 * and specifically for each board rather than each chip.  This makes their
 * adaptation to platforms like the Mac (Some of which use NCR5380's)
 * more difficult than it has to be.
 *
 * Also, many of the SCSI drivers were written before the command queuing
 * routines were implemented, meaning their implementations of queued
 * commands were hacked on rather than designed in from the start.
 *
 * When I designed the Linux SCSI drivers I figured that
 * while having two different SCSI boards in a system might be useful
 * for debugging things, two of the same type wouldn't be used.
 * Well, I was wrong and a number of users have mailed me about running
 * multiple high-performance SCSI boards in a server.
 *
 * Finally, when I get questions from users, I have no idea what
 * revision of my driver they are running.
 *
 * This driver attempts to address these problems :
 * This is a generic 5380 driver.  To use it on a different platform,
 * one simply writes appropriate system specific macros (ie, data
 * transfer - some PC's will use the I/O bus, 68K's must use
@@ -139,11 +119,6 @@
 * allowing multiple commands to propagate all the way to a SCSI-II device
 * while a command is already executing.
 *
 * To solve the multiple-boards-in-the-same-system problem,
 * there is a separate instance structure for each instance
 * of a 5380 in the system.  So, multiple NCR5380 drivers will
 * be able to coexist with appropriate changes to the high level
 * SCSI code.
 *
 * Issues specific to the NCR5380 :
 *
@@ -168,19 +143,17 @@
 * Architecture :
 *
 * At the heart of the design is a coroutine, NCR5380_main,
 * which is started when not running by the interrupt handler,
 * timer, and queue command function.  It attempts to establish
 * I_T_L or I_T_L_Q nexuses by removing the commands from the
 * issue queue and calling NCR5380_select() if a nexus
 * is not established.
 * which is started from a workqueue for each NCR5380 host in the
 * system.  It attempts to establish I_T_L or I_T_L_Q nexuses by
 * removing the commands from the issue queue and calling
 * NCR5380_select() if a nexus is not established.
 *
 * Once a nexus is established, the NCR5380_information_transfer()
 * phase goes through the various phases as instructed by the target.
 * if the target goes into MSG IN and sends a DISCONNECT message,
 * the command structure is placed into the per instance disconnected
 * queue, and NCR5380_main tries to find more work.  If USLEEP
 * was defined, and the target is idle for too long, the system
 * will try to sleep.
 * queue, and NCR5380_main tries to find more work.  If the target is
 * idle for too long, the system will try to sleep.
 *
 * If a command has disconnected, eventually an interrupt will trigger,
 * calling NCR5380_intr()  which will in turn call NCR5380_reselect
@@ -206,6 +179,9 @@
 * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
 *	for commands that return with a CHECK CONDITION status.
 *
 * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential
 *	transceivers.
 *
 * LINKED - if defined, linked commands are supported.
 *
 * REAL_DMA - if defined, REAL DMA is used during the data transfer phases.
@@ -218,6 +194,9 @@
 *
 * NCR5380_write(register, value) - write to the specific register
 *
 * NCR5380_implementation_fields  - additional fields needed for this
 *      specific implementation of the NCR5380
 *
 * Either real DMA *or* pseudo DMA may be implemented
 * REAL functions :
 * NCR5380_REAL_DMA should be defined if real DMA is to be used.
@@ -236,20 +215,6 @@
 * NCR5380_pwrite(instance, src, count)
 * NCR5380_pread(instance, dst, count);
 *
 * If nothing specific to this implementation needs doing (ie, with external
 * hardware), you must also define
 *
 * NCR5380_queue_command
 * NCR5380_reset
 * NCR5380_abort
 *
 * to be the global entry points into the specific driver, ie
 * #define NCR5380_queue_command t128_queue_command.
 *
 * If this is not done, the routines will be defined as static functions
 * with the NCR5380* names and the user must provide a globally
 * accessible wrapper function.
 *
 * The generic driver is initialized by calling NCR5380_init(instance),
 * after setting the appropriate host specific fields and ID.  If the
 * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance,
@@ -489,13 +454,11 @@ static void merge_contiguous_buffers(struct scsi_cmnd *cmd)
#endif /* !defined(CONFIG_SUN3) */
}

/*
 * Function : void initialize_SCp(struct scsi_cmnd *cmd)
 *
 * Purpose : initialize the saved data pointers for cmd to point to the
 *	start of the buffer.
/**
 * initialize_SCp - init the scsi pointer field
 * @cmd: command block to set up
 *
 * Inputs : cmd - scsi_cmnd structure to have pointers reset.
 * Set up the internal fields in the SCSI command.
 */

static inline void initialize_SCp(struct scsi_cmnd *cmd)
@@ -548,12 +511,11 @@ static struct {
	{0, NULL}
};

/*
 * Function : void NCR5380_print(struct Scsi_Host *instance)
 *
 * Purpose : print the SCSI bus signals for debugging purposes
/**
 * NCR5380_print - print scsi bus signals
 * @instance: adapter state to dump
 *
 * Input : instance - which NCR5380
 * Print the SCSI bus signals for debugging purposes
 */

static void NCR5380_print(struct Scsi_Host *instance)
@@ -596,12 +558,13 @@ static struct {
	{PHASE_UNKNOWN, "UNKNOWN"}
};

/*
 * Function : void NCR5380_print_phase(struct Scsi_Host *instance)
/**
 * NCR5380_print_phase - show SCSI phase
 * @instance: adapter to dump
 *
 * Purpose : print the current SCSI phase for debugging purposes
 * Print the current SCSI phase for debugging purposes
 *
 * Input : instance - which NCR5380
 * Locks: none
 */

static void NCR5380_print_phase(struct Scsi_Host *instance)
@@ -710,13 +673,12 @@ static void prepare_info(struct Scsi_Host *instance)
	         "");
}

/*
 * Function : void NCR5380_print_status (struct Scsi_Host *instance)
 *
 * Purpose : print commands in the various queues, called from
 *	NCR5380_abort and NCR5380_debug to aid debugging.
/**
 * NCR5380_print_status - dump controller info
 * @instance: controller to dump
 *
 * Inputs : instance, pointer to this instance.
 * Print commands in the various queues, called from NCR5380_abort
 * to aid debugging.
 */

static void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd)
@@ -807,16 +769,18 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m,
	return 0;
}

/*
 * Function : void NCR5380_init (struct Scsi_Host *instance)
 *
 * Purpose : initializes *instance and corresponding 5380 chip.
/**
 * NCR5380_init - initialise an NCR5380
 * @instance: adapter to configure
 * @flags: control flags
 *
 * Inputs : instance - instantiation of the 5380 driver.
 * Initializes *instance and corresponding 5380 chip,
 * with flags OR'd into the initial flags value.
 *
 * Notes : I assume that the host, hostno, and id bits have been
 * set correctly. I don't care about the irq and other fields.
 *
 * Returns 0 for success
 */

static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
@@ -861,27 +825,26 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
	return 0;
}

/**
 * NCR5380_exit - remove an NCR5380
 * @instance: adapter to remove
 *
 * Assumes that no more work can be queued (e.g. by NCR5380_intr).
 */

static void NCR5380_exit(struct Scsi_Host *instance)
{
	/* Empty, as we didn't schedule any delayed work */
	cancel_work_sync(&NCR5380_tqueue);
}

/*
 * Function : int NCR5380_queue_command (struct scsi_cmnd *cmd,
 *	void (*done)(struct scsi_cmnd *))
 *
 * Purpose :  enqueues a SCSI command
 *
 * Inputs : cmd - SCSI command, done - function called on completion, with
 *	a pointer to the command descriptor.
 *
 * Returns : 0
/**
 * NCR5380_queue_command - queue a command
 * @instance: the relevant SCSI adapter
 * @cmd: SCSI command
 *
 * Side effects :
 * cmd is added to the per instance issue_queue, with minor
 * twiddling done to the host specific fields of cmd.  If the
 * main coroutine is not running, it is restarted.
 *
 */

static int NCR5380_queue_command(struct Scsi_Host *instance,
@@ -935,6 +898,13 @@ static int NCR5380_queue_command(struct Scsi_Host *instance,

	local_irq_save(flags);

	/*
	 * Insert the cmd into the issue queue. Note that REQUEST SENSE
	 * commands are added to the head of the queue since any command will
	 * clear the contingent allegiance condition that exists and the
	 * sense data is only guaranteed to be valid while the condition exists.
	 */

	if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
		LIST(cmd, hostdata->issue_queue);
		SET_NEXT(cmd, hostdata->issue_queue);
@@ -977,16 +947,15 @@ static inline void maybe_release_dma_irq(struct Scsi_Host *instance)
		NCR5380_release_dma_irq(instance);
}

/*
 * Function : NCR5380_main (void)
/**
 * NCR5380_main - NCR state machines
 *
 * Purpose : NCR5380_main is a coroutine that runs as long as more work can
 * NCR5380_main is a coroutine that runs as long as more work can
 * be done on the NCR5380 host adapters in a system.  Both
 * NCR5380_queue_command() and NCR5380_intr() will try to start it
 * in case it is not running.
 *
 * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should
 *  reenable them.  This prevents reentrancy and kernel stack overflow.
 * Locks: called as its own thread with no locks held.
 */

static void NCR5380_main(struct work_struct *work)
@@ -1239,15 +1208,14 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
#endif /* REAL_DMA */


/*
 * Function : void NCR5380_intr (int irq)
/**
 * NCR5380_intr - generic NCR5380 irq handler
 * @irq: interrupt number
 * @dev_id: device info
 *
 * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
 * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses
 * from the disconnected queue, and restarting NCR5380_main()
 * as required.
 *
 * Inputs : int irq, irq that caused this interrupt.
 *
 */

static irqreturn_t NCR5380_intr(int irq, void *dev_id)
@@ -1540,7 +1508,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
	 * selection.
	 */

	timeout = jiffies + 25;
	timeout = jiffies + (250 * HZ / 1000);

	/*
	 * XXX very interesting - we're seeing a bounce where the BSY we
@@ -2123,9 +2091,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
						 * If the watchdog timer fires, all future
						 * accesses to this device will use the
						 * polled-IO. */
						printk(KERN_NOTICE "scsi%d: switching target %d "
							   "lun %llu to slow handshake\n", HOSTNO,
							   cmd->device->id, cmd->device->lun);
						scmd_printk(KERN_INFO, cmd,
							"switching to slow handshake\n");
						cmd->device->borken = 1;
						NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
							ICR_ASSERT_ATN);
@@ -2445,20 +2412,18 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
					 */
				default:
					if (!tmp) {
						printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
						printk(KERN_INFO "scsi%d: rejecting message ",
						       instance->host_no);
						spi_print_msg(extended_msg);
						printk("\n");
					} else if (tmp != EXTENDED_MESSAGE)
						printk(KERN_DEBUG "scsi%d: rejecting unknown "
						       "message %02x from target %d, lun %llu\n",
						       HOSTNO, tmp, cmd->device->id, cmd->device->lun);
						scmd_printk(KERN_INFO, cmd,
						            "rejecting unknown message %02x\n",
						            tmp);
					else
						printk(KERN_DEBUG "scsi%d: rejecting unknown "
						       "extended message "
						       "code %02x, length %d from target %d, lun %llu\n",
						       HOSTNO, extended_msg[1], extended_msg[0],
						       cmd->device->id, cmd->device->lun);

						scmd_printk(KERN_INFO, cmd,
						            "rejecting unknown extended message code %02x, length %d\n",
						            extended_msg[1], extended_msg[0]);

					msgout = MESSAGE_REJECT;
					NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);