📄 ncr5380.c
字号:
#ifndef NDEBUG#define NDEBUG (NDEBUG_RESTART_SELECT | NDEBUG_ABORT)#endif/* * 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) * drew@colorado.edu * +1 (303) 666-5836 * * DISTRIBUTION RELEASE 6. * * 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 *//* * $Log: NCR5380.c,v $ * Revision 1.10 1998/9/2 Alan Cox * (alan@redhat.com) * Fixed up the timer lockups reported so far. Things still suck. Looking * forward to 2.3 and per device request queues. Then it'll be possible to * SMP thread this beast and improve life no end. * Revision 1.9 1997/7/27 Ronald van Cuijlenborg * (ronald.van.cuijlenborg@tip.nl or nutty@dds.nl) * (hopefully) fixed and enhanced USLEEP * added support for DTC3181E card (for Mustek scanner) * * Revision 1.8 Ingmar Baumgart * (ingmar@gonzo.schwaben.de) * added support for NCR53C400a card * * Revision 1.7 1996/3/2 Ray Van Tassle (rayvt@comm.mot.com) * added proc_info * added support needed for DTC 3180/3280 * fixed a couple of bugs * * Revision 1.5 1994/01/19 09:14:57 drew * Fixed udelay() hack that was being used on DATAOUT phases * instead of a proper wait for the final handshake. * * Revision 1.4 1994/01/19 06:44:25 drew * *** empty log message *** * * Revision 1.3 1994/01/19 05:24:40 drew * Added support for TCR LAST_BYTE_SENT bit. * * Revision 1.2 1994/01/15 06:14:11 drew * REAL DMA support, bug fixes. * * Revision 1.1 1994/01/15 06:00:54 drew * Initial revision * *//* * Further development / testing that should be done : * 1. Cleanup the NCR5380_transfer_dma function and DMA operation complete * code so that everything does the same thing that's done at the * end of a pseudo-DMA read operation. * * 2. Fix REAL_DMA (interrupt driven, polled works fine) - * basically, transfer size needs to be reduced by one * and the last byte read as is done with PSEUDO_DMA. * * 4. Test SCSI-II tagged queueing (I have no devices which support * tagged queueing) * * 5. Test linked command handling code after Eric is ready with * the high level code. */#if (NDEBUG & NDEBUG_LISTS)#define LIST(x,y) {printk("LINE:%d Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); if ((x)==(y)) udelay(5); }#define REMOVE(w,x,y,z) {printk("LINE:%d Removing: %p->%p %p->%p \n", __LINE__, (void*)(w), (void*)(x), (void*)(y), (void*)(z)); if ((x)==(y)) udelay(5); }#else#define LIST(x,y)#define REMOVE(w,x,y,z)#endif#ifndef notyet#undef LINKED#undef REAL_DMA#endif#ifdef REAL_DMA_POLL#undef READ_OVERRUNS#define READ_OVERRUNS#endif#ifdef BOARD_REQUIRES_NO_DELAY#define io_recovery_delay(x)#else#define io_recovery_delay(x) udelay(x)#endif/* * 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 * 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. * * 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. * * A NCR5380_PUBLIC_REVISION macro is provided, with the release * number (updated for each public release) printed by the * NCR5380_print_options command, which should be called from the * wrapper detect function, so that I know what release of the driver * users are using. * * 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. * * 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 * * 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 * 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 * 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 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. * * 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. * * SCSI pointers are maintained in the SCp field of SCSI command * 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 * and macros and include this file in your driver. * * These macros control options : * AUTOPROBE_IRQ - if defined, the NCR5380_probe_irq() function will be * defined. * * 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. * * DONT_USE_INTR - if defined, never use interrupts, even if we probe or * override-configure an IRQ. * * LIMIT_TRANSFERSIZE - if defined, limit the pseudo-dma transfers to 512 * bytes at a time. Since interrupts are disabled by default during * these transfers, we might need this to give reasonable interrupt * service time if the transfer size gets too large. * * LINKED - if defined, linked commands are supported. * * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases. * * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. * * REAL_DMA_POLL - if defined, REAL DMA is used but the driver doesn't * rely on phase mismatch and EOP interrupts to determine end * of phase. * * UNSAFE - leave interrupts enabled during pseudo-DMA transfers. You * only really want to use this if you're having a problem with * dropped characters during high speed communications, and even * then, you're going to be better off twiddling with transfersize * in the high level code. * * Defaults for these will be provided although the user may want to adjust * these to allocate CPU resources to the SCSI driver or "real" code. * * USLEEP_SLEEP - amount of time, in jiffies, to sleep * * USLEEP_POLL - amount of time, in jiffies, to poll * * These macros MUST be defined : * NCR5380_local_declare() - declare any local variables needed for your * transfer routines. * * NCR5380_setup(instance) - initialize any local variables needed from a given * instance of the host adapter for NCR5380_{read,write,pread,pwrite} * * 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 * REAL functions : * NCR5380_REAL_DMA should be defined if real DMA is to be used. * Note that the DMA setup functions should return the number of bytes * that they were able to program the controller for. * * Also note that generic i386/PC versions of these macros are * available as NCR5380_i386_dma_write_setup, * NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual. * * NCR5380_dma_write_setup(instance, src, count) - initialize * NCR5380_dma_read_setup(instance, dst, count) - initialize * NCR5380_dma_residual(instance); - residual count * * PSEUDO functions : * 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 * NCR5380_proc_info * * 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, * possible) function may be used. Before the specific driver initialization * code finishes, NCR5380_print_options should be called. */static int do_abort(struct Scsi_Host *host);static void do_reset(struct Scsi_Host *host);static struct Scsi_Host *first_instance = NULL;static Scsi_Host_Template *the_template = NULL;static struct timer_list usleep_timer;/* * 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(Scsi_Cmnd * cmd){ /* * Initialize the Scsi Pointer field so that all of the commands in the * various queues are valid. */ if (cmd->use_sg) { cmd->SCp.buffer = (struct scatterlist *) cmd->buffer; cmd->SCp.buffers_residual = cmd->use_sg - 1; cmd->SCp.ptr = (char *) cmd->SCp.buffer->address; cmd->SCp.this_residual = cmd->SCp.buffer->length; } else { cmd->SCp.buffer = NULL; cmd->SCp.buffers_residual = 0; cmd->SCp.ptr = (char *) cmd->request_buffer; cmd->SCp.this_residual = cmd->request_bufflen; }}#include <linux/delay.h>#ifdef NDEBUGstatic 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_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL}}, icrs[] = { {ICR_ASSERT_RST, "ASSERT RST"}, {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, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"}, {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR, "MODE PARITY INTR"}, {MR_MONITOR_BSY, "MODE MONITOR BSY"}, {MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"}, {0, NULL}};/** * NCR5380_print - print scsi bus signals * @instance: adapter state to dump * * Print the SCSI bus signals for debugging purposes * * Locks: none */static void NCR5380_print(struct Scsi_Host *instance){ NCR5380_local_declare(); unsigned long flags; unsigned char status, data, basr, mr, icr, i; NCR5380_setup(instance); /* FIXME - this needs proper locking */ save_flags(flags); cli();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -