// SPDX-License-Identifier: GPL-2.0 /* * NCR 5380 generic driver routines. These should make it *trivial* * to implement 5380 SCSI drivers under Linux with a non-trantor * architecture. * * Note that these routines also work with NR53c400 family chips. * * Copyright 1993, Drew Eckhardt * Visionary Computing * (Unix and Linux consulting and custom programming) * [email protected] * +1 (303) 666-5836 * * For more information, please consult * * NCR 5380 Family * SCSI Protocol Controller * Databook * * NCR Microelectronics * 1635 Aeroplaza Drive * Colorado Springs, CO 80916 * 1+ (719) 578-3400 * 1+ (800) 334-5454 */ /* * With contributions from Ray Van Tassle, Ingmar Baumgart, * Ronald van Cuijlenborg, Alan Cox and others. */ /* Ported to Atari by Roman Hodek and others. */ /* Adapted for the Sun 3 by Sam Creasey. */ /* * Design * * 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 * memory mapped) and drops this file in their 'C' wrapper. * * As far as command queueing, two queues are maintained for * 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 * while a command is already executing. * * * Issues specific to the NCR5380 : * * 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 * while doing long seek operations. [...] These * 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. * * 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. * * 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 * appropriate. * * The command data pointer is 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 * and macros and include this file in your driver. * * These macros MUST be defined : * * NCR5380_read(register) - read from the specified register * * 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 * * NCR5380_dma_xfer_len - determine size of DMA/PDMA transfer * NCR5380_dma_send_setup - execute DMA/PDMA from memory to 5380 * NCR5380_dma_recv_setup - execute DMA/PDMA from 5380 to memory * NCR5380_dma_residual - residual byte count * * The generic driver is initialized by calling NCR5380_init(instance), * after setting the appropriate host specific fields and ID. */ #ifndef NCR5380_io_delay #define NCR5380_io_delay(x) … #endif #ifndef NCR5380_acquire_dma_irq #define NCR5380_acquire_dma_irq(x) … #endif #ifndef NCR5380_release_dma_irq #define NCR5380_release_dma_irq(x) … #endif static unsigned int disconnect_mask = …; module_param(disconnect_mask, int, 0444); static int do_abort(struct Scsi_Host *, unsigned int); static void do_reset(struct Scsi_Host *); static void bus_reset_cleanup(struct Scsi_Host *); /** * initialize_SCp - init the scsi pointer field * @cmd: command block to set up * * Set up the internal fields in the SCSI command. */ static inline void initialize_SCp(struct scsi_cmnd *cmd) { … } static inline void advance_sg_buffer(struct NCR5380_cmd *ncmd) { … } static inline void set_resid_from_SCp(struct scsi_cmnd *cmd) { … } /** * NCR5380_poll_politely2 - wait for two chip register values * @hostdata: host private data * @reg1: 5380 register to poll * @bit1: Bitmask to check * @val1: Expected value * @reg2: Second 5380 register to poll * @bit2: Second bitmask to check * @val2: Second expected value * @wait: Time-out in jiffies, 0 if sleeping is not allowed * * Polls the chip in a reasonably efficient manner waiting for an * event to occur. After a short quick poll we begin to yield the CPU * (if possible). In irq contexts the time-out is arbitrarily limited. * Callers may hold locks as long as they are held in irq mode. * * Returns 0 if either or both event(s) occurred otherwise -ETIMEDOUT. */ static int NCR5380_poll_politely2(struct NCR5380_hostdata *hostdata, unsigned int reg1, u8 bit1, u8 val1, unsigned int reg2, u8 bit2, u8 val2, unsigned long wait) { … } #if NDEBUG static struct { unsigned char mask; const char *name; } signals[] = { {SR_DBP, "PARITY"}, {SR_RST, "RST"}, {SR_BSY, "BSY"}, {SR_REQ, "REQ"}, {SR_MSG, "MSG"}, {SR_CD, "CD"}, {SR_IO, "IO"}, {SR_SEL, "SEL"}, {0, NULL} }, basrs[] = { {BASR_END_DMA_TRANSFER, "END OF DMA"}, {BASR_DRQ, "DRQ"}, {BASR_PARITY_ERROR, "PARITY ERROR"}, {BASR_IRQ, "IRQ"}, {BASR_PHASE_MATCH, "PHASE MATCH"}, {BASR_BUSY_ERROR, "BUSY ERROR"}, {BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL} }, icrs[] = { {ICR_ASSERT_RST, "ASSERT RST"}, {ICR_ARBITRATION_PROGRESS, "ARB. IN PROGRESS"}, {ICR_ARBITRATION_LOST, "LOST ARB."}, {ICR_ASSERT_ACK, "ASSERT ACK"}, {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"}, {ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"}, {0, NULL} }, mrs[] = { {MR_BLOCK_DMA_MODE, "BLOCK DMA MODE"}, {MR_TARGET, "TARGET"}, {MR_ENABLE_PAR_CHECK, "PARITY CHECK"}, {MR_ENABLE_PAR_INTR, "PARITY INTR"}, {MR_ENABLE_EOP_INTR, "EOP INTR"}, {MR_MONITOR_BSY, "MONITOR BSY"}, {MR_DMA_MODE, "DMA MODE"}, {MR_ARBITRATE, "ARBITRATE"}, {0, NULL} }; /** * NCR5380_print - print scsi bus signals * @instance: adapter state to dump * * Print the SCSI bus signals for debugging purposes */ static void NCR5380_print(struct Scsi_Host *instance) { struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char status, basr, mr, icr, i; status = NCR5380_read(STATUS_REG); mr = NCR5380_read(MODE_REG); icr = NCR5380_read(INITIATOR_COMMAND_REG); basr = NCR5380_read(BUS_AND_STATUS_REG); printk(KERN_DEBUG "SR = 0x%02x : ", status); for (i = 0; signals[i].mask; ++i) if (status & signals[i].mask) printk(KERN_CONT "%s, ", signals[i].name); printk(KERN_CONT "\nBASR = 0x%02x : ", basr); for (i = 0; basrs[i].mask; ++i) if (basr & basrs[i].mask) printk(KERN_CONT "%s, ", basrs[i].name); printk(KERN_CONT "\nICR = 0x%02x : ", icr); for (i = 0; icrs[i].mask; ++i) if (icr & icrs[i].mask) printk(KERN_CONT "%s, ", icrs[i].name); printk(KERN_CONT "\nMR = 0x%02x : ", mr); for (i = 0; mrs[i].mask; ++i) if (mr & mrs[i].mask) printk(KERN_CONT "%s, ", mrs[i].name); printk(KERN_CONT "\n"); } static struct { unsigned char value; const char *name; } phases[] = { {PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"}, {PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"}, {PHASE_UNKNOWN, "UNKNOWN"} }; /** * NCR5380_print_phase - show SCSI phase * @instance: adapter to dump * * Print the current SCSI phase for debugging purposes */ static void NCR5380_print_phase(struct Scsi_Host *instance) { struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char status; int i; status = NCR5380_read(STATUS_REG); if (!(status & SR_REQ)) shost_printk(KERN_DEBUG, instance, "REQ not asserted, phase unknown.\n"); else { for (i = 0; (phases[i].value != PHASE_UNKNOWN) && (phases[i].value != (status & PHASE_MASK)); ++i) ; shost_printk(KERN_DEBUG, instance, "phase %s\n", phases[i].name); } } #endif /** * NCR5380_info - report driver and host information * @instance: relevant scsi host instance * * For use as the host template info() handler. */ static const char *NCR5380_info(struct Scsi_Host *instance) { … } /** * NCR5380_init - initialise an NCR5380 * @instance: adapter to configure * @flags: control flags * * 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 NCR5380_init(struct Scsi_Host *instance, int flags) { … } /** * NCR5380_maybe_reset_bus - Detect and correct bus wedge problems. * @instance: adapter to check * * If the system crashed, it may have crashed with a connected target and * the SCSI bus busy. Check for BUS FREE phase. If not, try to abort the * currently established nexus, which we know nothing about. Failing that * do a bus reset. * * Note that a bus reset will cause the chip to assert IRQ. * * Returns 0 if successful, otherwise -ENXIO. */ static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) { … } /** * 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) { … } /** * complete_cmd - finish processing a command and return it to the SCSI ML * @instance: the host instance * @cmd: command to complete */ static void complete_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd) { … } /** * NCR5380_queue_command - queue a command * @instance: the relevant SCSI adapter * @cmd: SCSI command * * 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, struct scsi_cmnd *cmd) { … } static inline void maybe_release_dma_irq(struct Scsi_Host *instance) { … } /** * dequeue_next_cmd - dequeue a command for processing * @instance: the scsi host instance * * Priority is given to commands on the autosense queue. These commands * need autosense because of a CHECK CONDITION result. * * Returns a command pointer if a command is found for a target that is * not already busy. Otherwise returns NULL. */ static struct scsi_cmnd *dequeue_next_cmd(struct Scsi_Host *instance) { … } static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd) { … } /** * NCR5380_main - NCR state machines * * 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. */ static void NCR5380_main(struct work_struct *work) { … } /* * NCR5380_dma_complete - finish DMA transfer * @instance: the scsi host instance * * Called by the interrupt handler when DMA finishes or a phase * mismatch occurs (which would end the DMA transfer). */ static void NCR5380_dma_complete(struct Scsi_Host *instance) { … } /** * NCR5380_intr - generic NCR5380 irq handler * @irq: interrupt number * @dev_id: device info * * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses * from the disconnected queue, and restarting NCR5380_main() * as required. * * The chip can assert IRQ in any of six different conditions. The IRQ flag * is then cleared by reading the Reset Parity/Interrupt Register (RPIR). * Three of these six conditions are latched in the Bus and Status Register: * - End of DMA (cleared by ending DMA Mode) * - Parity error (cleared by reading RPIR) * - Loss of BSY (cleared by reading RPIR) * Two conditions have flag bits that are not latched: * - Bus phase mismatch (non-maskable in DMA Mode, cleared by ending DMA Mode) * - Bus reset (non-maskable) * The remaining condition has no flag bit at all: * - Selection/reselection * * Hence, establishing the cause(s) of any interrupt is partly guesswork. * In "The DP8490 and DP5380 Comparison Guide", National Semiconductor * claimed that "the design of the [DP8490] interrupt logic ensures * interrupts will not be lost (they can be on the DP5380)." * The L5380/53C80 datasheet from LOGIC Devices has more details. * * Checking for bus reset by reading RST is futile because of interrupt * latency, but a bus reset will reset chip logic. Checking for parity error * is unnecessary because that interrupt is never enabled. A Loss of BSY * condition will clear DMA Mode. We can tell when this occurs because the * Busy Monitor interrupt is enabled together with DMA Mode. */ static irqreturn_t __maybe_unused NCR5380_intr(int irq, void *dev_id) { … } /** * NCR5380_select - attempt arbitration and selection for a given command * @instance: the Scsi_Host instance * @cmd: the scsi_cmnd to execute * * This routine establishes an I_T_L nexus for a SCSI command. This involves * ARBITRATION, SELECTION and MESSAGE OUT phases and an IDENTIFY message. * * Returns true if the operation should be retried. * Returns false if it should not be retried. * * Side effects : * If bus busy, arbitration failed, etc, NCR5380_select() will exit * with registers as they should have been on entry - ie * SELECT_ENABLE will be set appropriately, the NCR5380 * will cease to drive any SCSI bus signals. * * If successful : the I_T_L nexus will be established, and * hostdata->connected will be set to cmd. * SELECT interrupt will be disabled. * * If failed (no target) : scsi_done() will be called, and the * cmd->result host byte set to DID_BAD_TARGET. */ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) __releases(&hostdata->lock) __acquires(&hostdata->lock) { … } /* * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, * unsigned char *phase, int *count, unsigned char **data) * * Purpose : transfers data in given phase using polled I/O * * Inputs : instance - instance of driver, *phase - pointer to * what phase is expected, *count - pointer to number of * bytes to transfer, **data - pointer to data pointer, * can_sleep - 1 or 0 when sleeping is permitted or not, respectively. * * Returns : -1 when different phase is entered without transferring * maximum number of bytes, 0 if all bytes are transferred or exit * is in same phase. * * Also, *phase, *count, *data are modified in place. * * XXX Note : handling for bus free may be useful. */ /* * Note : this code is not as quick as it could be, however it * IS 100% reliable, and for the actual data transfer where speed * counts, we will always do a pseudo DMA or DMA transfer. */ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data, unsigned int can_sleep) { … } /** * do_reset - issue a reset command * @instance: adapter to reset * * Issue a reset sequence to the NCR5380 and try and get the bus * back into sane shape. * * This clears the reset interrupt flag because there may be no handler for * it. When the driver is initialized, the NCR5380_intr() handler has not yet * been installed. And when in EH we may have released the ST DMA interrupt. */ static void do_reset(struct Scsi_Host *instance) { … } /** * do_abort - abort the currently established nexus by going to * MESSAGE OUT phase and sending an ABORT message. * @instance: relevant scsi host instance * @can_sleep: 1 or 0 when sleeping is permitted or not, respectively * * Returns 0 on success, negative error code on failure. */ static int do_abort(struct Scsi_Host *instance, unsigned int can_sleep) { … } /* * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, * unsigned char *phase, int *count, unsigned char **data) * * Purpose : transfers data in given phase using either real * or pseudo DMA. * * Inputs : instance - instance of driver, *phase - pointer to * what phase is expected, *count - pointer to number of * bytes to transfer, **data - pointer to data pointer. * * Returns : -1 when different phase is entered without transferring * maximum number of bytes, 0 if all bytes or transferred or exit * is in same phase. * * Also, *phase, *count, *data are modified in place. */ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) { … } /* * Function : NCR5380_information_transfer (struct Scsi_Host *instance) * * Purpose : run through the various SCSI phases and do as the target * directs us to. Operates on the currently connected command, * instance->connected. * * Inputs : instance, instance for which we are doing commands * * Side effects : SCSI things happen, the disconnected queue will be * modified if a command disconnects, *instance->connected will * change. * * XXX Note : we need to watch for bus free or a reset condition here * to recover from an unexpected bus free condition. */ static void NCR5380_information_transfer(struct Scsi_Host *instance) __releases(&hostdata->lock) __acquires(&hostdata->lock) { … } /* * Function : void NCR5380_reselect (struct Scsi_Host *instance) * * Purpose : does reselection, initializing the instance->connected * field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q * nexus has been reestablished, * * Inputs : instance - this instance of the NCR5380. */ static void NCR5380_reselect(struct Scsi_Host *instance) { … } /** * list_find_cmd - test for presence of a command in a linked list * @haystack: list of commands * @needle: command to search for */ static bool list_find_cmd(struct list_head *haystack, struct scsi_cmnd *needle) { … } /** * list_remove_cmd - remove a command from linked list * @haystack: list of commands * @needle: command to remove */ static bool list_del_cmd(struct list_head *haystack, struct scsi_cmnd *needle) { … } /** * NCR5380_abort - scsi host eh_abort_handler() method * @cmd: the command to be aborted * * Try to abort a given command by removing it from queues and/or sending * the target an abort message. This may not succeed in causing a target * to abort the command. Nonetheless, the low-level driver must forget about * the command because the mid-layer reclaims it and it may be re-issued. * * The normal path taken by a command is as follows. For EH we trace this * same path to locate and abort the command. * * unissued -> selecting -> [unissued -> selecting ->]... connected -> * [disconnected -> connected ->]... * [autosense -> connected ->] done * * If cmd was not found at all then presumably it has already been completed, * in which case return SUCCESS to try to avoid further EH measures. * * If the command has not completed yet, we must not fail to find it. * We have no option but to forget the aborted command (even if it still * lacks sense data). The mid-layer may re-issue a command that is in error * recovery (see scsi_send_eh_cmnd), but the logic and data structures in * this driver are such that a command can appear on one queue only. * * The lock protects driver data structures, but EH handlers also use it * to serialize their own execution and prevent their own re-entry. */ static int NCR5380_abort(struct scsi_cmnd *cmd) { … } static void bus_reset_cleanup(struct Scsi_Host *instance) { … } /** * NCR5380_host_reset - reset the SCSI host * @cmd: SCSI command undergoing EH * * Returns SUCCESS */ static int NCR5380_host_reset(struct scsi_cmnd *cmd) { … }