Skip to content
atari_NCR5380.c 91.6 KiB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
 * NCR 5380 generic driver routines.  These should make it *trivial*
 *	to implement 5380 SCSI drivers under Linux with a non-trantor
Linus Torvalds's avatar
Linus Torvalds committed
 *	architecture.
 *
 *	Note that these routines also work with NR53c400 family chips.
 *
 * Copyright 1993, Drew Eckhardt
 *	Visionary Computing
Linus Torvalds's avatar
Linus Torvalds committed
 *	(Unix and Linux consulting and custom programming)
 *	drew@colorado.edu
Linus Torvalds's avatar
Linus Torvalds committed
 *	+1 (303) 666-5836
 *
 * For more information, please consult
Linus Torvalds's avatar
Linus Torvalds committed
 *
 * NCR 5380 Family
 * SCSI Protocol Controller
 * Databook
 *
 * NCR Microelectronics
 * 1635 Aeroplaza Drive
 * Colorado Springs, CO 80916
 * 1+ (719) 578-3400
 * 1+ (800) 334-5454
 */

/*
 * ++roman: To port the 5380 driver to the Atari, I had to do some changes in
 * this file, too:
 *
 *  - Some of the debug statements were incorrect (undefined variables and the
 *    like). I fixed that.
 *
 *  - In information_transfer(), I think a #ifdef was wrong. Looking at the
 *    possible DMA transfer size should also happen for REAL_DMA. I added this
 *    in the #if statement.
 *
 *  - When using real DMA, information_transfer() should return in a DATAOUT
 *    phase after starting the DMA. It has nothing more to do.
 *
 *  - The interrupt service routine should run main after end of DMA, too (not
 *    only after RESELECTION interrupts). Additionally, it should _not_ test
 *    for more interrupts after running main, since a DMA process may have
 *    been started and interrupts are turned on now. The new int could happen
 *    inside the execution of NCR5380_intr(), leading to recursive
 *    calls.
 *
 *  - I've added a function merge_contiguous_buffers() that tries to
 *    merge scatter-gather buffers that are located at contiguous
 *    physical addresses and can be processed with the same DMA setup.
 *    Since most scatter-gather operations work on a page (4K) of
 *    4 buffers (1K), in more than 90% of all cases three interrupts and
 *    DMA setup actions are saved.
 *
 * - I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL, PSEUDO_DMA
 *    and USLEEP, because these were messing up readability and will never be
 *    needed for Atari SCSI.
Linus Torvalds's avatar
Linus Torvalds committed
 * - I've revised the NCR5380_main() calling scheme (relax the 'main_running'
 *   stuff), and 'main' is executed in a bottom half if awoken by an
 *   interrupt.
 *
 * - The code was quite cluttered up by "#if (NDEBUG & NDEBUG_*) printk..."
 *   constructs. In my eyes, this made the source rather unreadable, so I
 *   finally replaced that by the *_PRINTK() macros.
 *
 */

/*
 * Further development / testing that should be done :
 * 1.  Test linked command handling code after Eric is ready with
Linus Torvalds's avatar
Linus Torvalds committed
 *     the high level code.
 */

/* Adapted for the sun3 by Sam Creasey. */

#include <scsi/scsi_dbg.h>
#include <scsi/scsi_transport_spi.h>
Linus Torvalds's avatar
Linus Torvalds committed

#if (NDEBUG & NDEBUG_LISTS)
#define LIST(x, y)						\
	do {							\
		printk("LINE:%d   Adding %p to %p\n",		\
		       __LINE__, (void*)(x), (void*)(y));	\
		if ((x) == (y))					\
			udelay(5);				\
	} while (0)
#define REMOVE(w, x, y, z)					\
	do {							\
		printk("LINE:%d   Removing: %p->%p  %p->%p \n",	\
		       __LINE__, (void*)(w), (void*)(x),	\
		       (void*)(y), (void*)(z));			\
		if ((x) == (y))					\
			udelay(5);				\
	} while (0)
Linus Torvalds's avatar
Linus Torvalds committed
#else
#define LIST(x,y)
#define REMOVE(w,x,y,z)
#endif

#ifndef notyet
#undef LINKED
#endif

/*
 * Design
 *
 * This is a generic 5380 driver.  To use it on a different platform,
Linus Torvalds's avatar
Linus Torvalds committed
 * one simply writes appropriate system specific macros (ie, data
 * transfer - some PC's will use the I/O bus, 68K's must use
Linus Torvalds's avatar
Linus Torvalds committed
 * memory mapped) and drops this file in their 'C' wrapper.
 *
 * As far as command queueing, two queues are maintained for
Linus Torvalds's avatar
Linus Torvalds committed
 * each 5380 in the system - commands that haven't been issued yet,
 * and commands that are currently executing.  This means that an
 * unlimited number of commands may be queued, letting
 * more commands propagate from the higher driver levels giving higher
 * throughput.  Note that both I_T_L and I_T_L_Q nexuses are supported,
 * allowing multiple commands to propagate all the way to a SCSI-II device
Linus Torvalds's avatar
Linus Torvalds committed
 * while a command is already executing.
 *
 *
 * Issues specific to the NCR5380 :
Linus Torvalds's avatar
Linus Torvalds committed
 *
 * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead
 * piece of hardware that requires you to sit in a loop polling for
 * the REQ signal as long as you are connected.  Some devices are
 * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect
Linus Torvalds's avatar
Linus Torvalds committed
 * while doing long seek operations.
Linus Torvalds's avatar
Linus Torvalds committed
 * The workaround for this is to keep track of devices that have
 * disconnected.  If the device hasn't disconnected, for commands that
 * should disconnect, we do something like
Linus Torvalds's avatar
Linus Torvalds committed
 *
 * while (!REQ is asserted) { sleep for N usecs; poll for M usecs }
 *
 * Some tweaking of N and M needs to be done.  An algorithm based
Linus Torvalds's avatar
Linus Torvalds committed
 * on "time to data" would give the best results as long as short time
 * to datas (ie, on the same track) were considered, however these
Linus Torvalds's avatar
Linus Torvalds committed
 * broken devices are the exception rather than the rule and I'd rather
 * spend my time optimizing for the normal case.
 *
 * Architecture :
 *
 * At the heart of the design is a coroutine, NCR5380_main,
 * 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.
Linus Torvalds's avatar
Linus Torvalds committed
 *
 * 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 the target is
 * idle for too long, the system will try to sleep.
Linus Torvalds's avatar
Linus Torvalds committed
 *
 * If a command has disconnected, eventually an interrupt will trigger,
 * calling NCR5380_intr()  which will in turn call NCR5380_reselect
 * to reestablish a nexus.  This will run main if necessary.
 *
 * On command termination, the done function will be called as
Linus Torvalds's avatar
Linus Torvalds committed
 * appropriate.
 *
 * SCSI pointers are maintained in the SCp field of SCSI command
Linus Torvalds's avatar
Linus Torvalds committed
 * structures, being initialized after the command is connected
 * in NCR5380_select, and set as appropriate in NCR5380_information_transfer.
 * Note that in violation of the standard, an implicit SAVE POINTERS operation
 * is done, since some BROKEN disks fail to issue an explicit SAVE POINTERS.
 */

/*
 * Using this file :
 * This file a skeleton Linux SCSI driver for the NCR 5380 series
 * of chips.  To use it, you write an architecture specific functions
Linus Torvalds's avatar
Linus Torvalds committed
 * and macros and include this file in your driver.
 *
 * These macros control options :
Linus Torvalds's avatar
Linus Torvalds committed
 * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
 *	for commands that return with a CHECK CONDITION status.
Linus Torvalds's avatar
Linus Torvalds committed
 *
 * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential
 *	transceivers.
 *
Linus Torvalds's avatar
Linus Torvalds committed
 * LINKED - if defined, linked commands are supported.
 *
 * REAL_DMA - if defined, REAL DMA is used during the data transfer phases.
 *
 * SUPPORT_TAGS - if defined, SCSI-2 tagged queuing is used where possible
 *
 * These macros MUST be defined :
Linus Torvalds's avatar
Linus Torvalds committed
 * NCR5380_read(register)  - read from the specified register
 *
 * NCR5380_write(register, value) - write to the specific register
Linus Torvalds's avatar
Linus Torvalds committed
 *
 * NCR5380_implementation_fields  - additional fields needed for this
 *      specific implementation of the NCR5380
 *
Linus Torvalds's avatar
Linus Torvalds committed
 * Either real DMA *or* pseudo DMA may be implemented
Loading
Loading full blame...