// SPDX-License-Identifier: GPL-2.0-or-later /****************************************************************************** ** Device driver for the PCI-SCSI NCR538XX controller family. ** ** Copyright (C) 1994 Wolfgang Stanglmeier ** ** **----------------------------------------------------------------------------- ** ** This driver has been ported to Linux from the FreeBSD NCR53C8XX driver ** and is currently maintained by ** ** Gerard Roudier <groudier@free.fr> ** ** Being given that this driver originates from the FreeBSD version, and ** in order to keep synergy on both, any suggested enhancements and corrections ** received on Linux are automatically a potential candidate for the FreeBSD ** version. ** ** The original driver has been written for 386bsd and FreeBSD by ** Wolfgang Stanglmeier <wolf@cologne.de> ** Stefan Esser <se@mi.Uni-Koeln.de> ** ** And has been ported to NetBSD by ** Charles M. Hannum <mycroft@gnu.ai.mit.edu> ** **----------------------------------------------------------------------------- ** ** Brief history ** ** December 10 1995 by Gerard Roudier: ** Initial port to Linux. ** ** June 23 1996 by Gerard Roudier: ** Support for 64 bits architectures (Alpha). ** ** November 30 1996 by Gerard Roudier: ** Support for Fast-20 scsi. ** Support for large DMA fifo and 128 dwords bursting. ** ** February 27 1997 by Gerard Roudier: ** Support for Fast-40 scsi. ** Support for on-Board RAM. ** ** May 3 1997 by Gerard Roudier: ** Full support for scsi scripts instructions pre-fetching. ** ** May 19 1997 by Richard Waltham <dormouse@farsrobt.demon.co.uk>: ** Support for NvRAM detection and reading. ** ** August 18 1997 by Cort <cort@cs.nmt.edu>: ** Support for Power/PC (Big Endian). ** ** June 20 1998 by Gerard Roudier ** Support for up to 64 tags per lun. ** O(1) everywhere (C and SCRIPTS) for normal cases. ** Low PCI traffic for command handling when on-chip RAM is present. ** Aggressive SCSI SCRIPTS optimizations. ** ** 2005 by Matthew Wilcox and James Bottomley ** PCI-ectomy. This driver now supports only the 720 chip (see the ** NCR_Q720 and zalon drivers for the bus probe logic). ** *******************************************************************************
*/
/*========================================================== ** ** Simple power of two buddy-like allocator. ** ** This simple code is not intended to be fast, but to ** provide power of 2 aligned memory allocations. ** Since the SCRIPTS processor only supplies 8 bit ** arithmetic, this allocator allows simple and fast ** address calculations from the SCRIPTS code. ** In addition, cache line alignment is guaranteed for ** power of 2 cache line size. ** Enhanced in linux-2.3.44 to provide a memory pool ** per pcidev to support dynamic dma mapping. (I would ** have preferred a real bus abstraction, btw). ** **==========================================================
*/
/* * With pci bus iommu support, we use a default pool of unmapped memory * for memory we donnot need to DMA from/to and one pool per pcidev for * memory accessed by the PCI chip. `mp0' is the default not DMAable pool.
*/
static m_addr_t ___mp0_getp(m_pool_s *mp)
{
m_addr_t m = __get_free_pages(MEMO_GFP_FLAGS, MEMO_PAGE_ORDER); if (m)
++mp->nump; return m;
}
staticvoid ___mp0_freep(m_pool_s *mp, m_addr_t m)
{
free_pages(m, MEMO_PAGE_ORDER);
--mp->nump;
}
/* * With pci bus iommu support, we maintain one pool per pcidev and a * hashed reverse table for virtual to bus physical address translations.
*/ static m_addr_t ___dma_getp(m_pool_s *mp)
{
m_addr_t vp;
m_vtob_s *vbp;
vbp = __m_calloc(&mp0, sizeof(*vbp), "VTOB"); if (vbp) {
dma_addr_t daddr;
vp = (m_addr_t) dma_alloc_coherent(mp->bush,
PAGE_SIZE<<MEMO_PAGE_ORDER,
&daddr, GFP_ATOMIC); if (vp) { int hc = VTOB_HASH_CODE(vp);
vbp->vaddr = vp;
vbp->baddr = daddr;
vbp->next = mp->vtob[hc];
mp->vtob[hc] = vbp;
++mp->nump; return vp;
}
} if (vbp)
__m_free(&mp0, vbp, sizeof(*vbp), "VTOB"); return 0;
}
staticvoid ___dma_freep(m_pool_s *mp, m_addr_t m)
{
m_vtob_s **vbpp, *vbp; int hc = VTOB_HASH_CODE(m);
/*========================================================== ** ** Driver setup. ** ** This structure is initialized from linux config ** options. It can be overridden at boot-up by the boot ** command line. ** **==========================================================
*/ staticstruct ncr_driver_setup
driver_setup = SCSI_NCR_DRIVER_SETUP;
/*=================================================================== ** ** Driver setup from the boot command line ** **===================================================================
*/
staticint device_queue_depth(int unit, int target, int lun)
{ int c, h, t, u, v; char *p = driver_setup.tag_ctrl; char *ep;
h = -1;
t = NO_TARGET;
u = NO_LUN; while ((c = *p++) != 0) {
v = simple_strtoul(p, &ep, 0); switch(c) { case'/':
++h;
t = ALL_TARGETS;
u = ALL_LUNS; break; case't': if (t != target)
t = (target == v) ? v : NO_TARGET;
u = ALL_LUNS; break; case'u': if (u != lun)
u = (lun == v) ? v : NO_LUN; break; case'q': if (h == unit &&
(t == ALL_TARGETS || t == target) &&
(u == ALL_LUNS || u == lun)) return v; break; case'-':
t = ALL_TARGETS;
u = ALL_LUNS; break; default: break;
}
p = ep;
} return DEF_DEPTH;
}
/*========================================================== ** ** The CCB done queue uses an array of CCB virtual ** addresses. Empty entries are flagged using the bogus ** virtual address 0xffffffff. ** ** Since PCI ensures that only aligned DWORDs are accessed ** atomically, 64 bit little-endian architecture requires ** to test the high order DWORD of the entry to determine ** if it is empty or valid. ** ** BTW, I will make things differently as soon as I will ** have a better idea, but this is simple and should work. ** **==========================================================
*/
/* ** TAGS are actually limited to 64 tags/lun. ** We need to deal with power of 2, for alignment constraints.
*/ #if SCSI_NCR_MAX_TAGS > 64 #define MAX_TAGS (64) #else #define MAX_TAGS SCSI_NCR_MAX_TAGS #endif
#define NO_TAG (255)
/* ** Choose appropriate type for tag bitmap.
*/ #if MAX_TAGS > 32 typedef u64 tagmap_t; #else typedef u32 tagmap_t; #endif
/* ** Number of targets supported by the driver. ** n permits target numbers 0..n-1. ** Default is 16, meaning targets #0..#15. ** #7 .. is myself.
*/
/* ** Number of logic units supported by the driver. ** n enables logic unit numbers 0..n-1. ** The common SCSI devices require only ** one lun, so take 1 as the default.
*/
/* ** The maximum number of jobs scheduled for starting. ** There should be one slot per target, and one slot ** for each tag of each target in use. ** The calculation below is actually quite silly ...
*/
/* ** We limit the max number of pending IO to 250. ** since we donnot want to allocate more than 1 ** PAGE for 'scripth'.
*/ #if MAX_START > 250 #undef MAX_START #define MAX_START 250 #endif
/* ** The maximum number of segments a transfer is split into. ** We support up to 127 segments for both read and write. ** The data scripts are broken into 2 sub-scripts. ** 80 (MAX_SCATTERL) segments are moved from a sub-script ** in on-chip RAM. This makes data transfers shorter than ** 80k (assuming 1k fs) as fast as possible.
*/
/*========================================================== ** ** Command control block states. ** **==========================================================
*/
/*======================================================================== ** ** Declaration of structs: target control block ** **========================================================================
*/ struct tcb { /*---------------------------------------------------------------- ** During reselection the ncr jumps to this point with SFBR ** set to the encoded target number with bit 7 set. ** if it's not this target, jump to the next. ** ** JUMP IF (SFBR != #target#), @(next tcb) **----------------------------------------------------------------
*/ struct link jump_tcb;
/*---------------------------------------------------------------- ** Load the actual values for the sxfer and the scntl3 ** register (sync/wide mode). ** ** SCR_COPY (1), @(sval field of this tcb), @(sxfer register) ** SCR_COPY (1), @(wval field of this tcb), @(scntl3 register) **----------------------------------------------------------------
*/
ncrcmd getscr[6];
/*---------------------------------------------------------------- ** Get the IDENTIFY message and load the LUN to SFBR. ** ** CALL, <RESEL_LUN> **----------------------------------------------------------------
*/ struct link call_lun;
/*---------------------------------------------------------------- ** Now look for the right lun. ** ** For i = 0 to 3 ** SCR_JUMP ^ IFTRUE(MASK(i, 3)), @(first lcb mod. i) ** ** Recent chips will prefetch the 4 JUMPS using only 1 burst. ** It is kind of hashcoding. **----------------------------------------------------------------
*/ struct link jump_lcb[4]; /* JUMPs for reselection */ struct lcb * lp[MAX_LUN]; /* The lcb's of this tcb */
/*---------------------------------------------------------------- ** Pointer to the ccb used for negotiation. ** Prevent from starting a negotiation for all queued commands ** when tagged command queuing is enabled. **----------------------------------------------------------------
*/ struct ccb * nego_cp;
/*---------------------------------------------------------------- ** statistical data **----------------------------------------------------------------
*/
u_long transfers;
u_long bytes;
/* User settable limits and options. */
u_char usrsync;
u_char usrwide;
u_char usrtags;
u_char usrflag; struct scsi_target *starget;
};
/*======================================================================== ** ** Declaration of structs: lun control block ** **========================================================================
*/ struct lcb { /*---------------------------------------------------------------- ** During reselection the ncr jumps to this point ** with SFBR set to the "Identify" message. ** if it's not this lun, jump to the next. ** ** JUMP IF (SFBR != #lun#), @(next lcb of this target) ** ** It is this lun. Load TEMP with the nexus jumps table ** address and jump to RESEL_TAG (or RESEL_NOTAG). ** ** SCR_COPY (4), p_jump_ccb, TEMP, ** SCR_JUMP, <RESEL_TAG> **----------------------------------------------------------------
*/ struct link jump_lcb;
ncrcmd load_jump_ccb[3]; struct link jump_tag;
ncrcmd p_jump_ccb; /* Jump table bus address */
/*---------------------------------------------------------------- ** Jump table used by the script processor to directly jump ** to the CCB corresponding to the reselected nexus. ** Address is allocated on 256 bytes boundary in order to ** allow 8 bit calculation of the tag jump entry for up to ** 64 possible tags. **----------------------------------------------------------------
*/
u32 jump_ccb_0; /* Default table if no tags */
u32 *jump_ccb; /* Virtual address */
/*---------------------------------------------------------------- ** CCB queue management. **----------------------------------------------------------------
*/ struct list_head free_ccbq; /* Queue of available CCBs */ struct list_head busy_ccbq; /* Queue of busy CCBs */ struct list_head wait_ccbq; /* Queue of waiting for IO CCBs */ struct list_head skip_ccbq; /* Queue of skipped CCBs */
u_char actccbs; /* Number of allocated CCBs */
u_char busyccbs; /* CCBs busy for this lun */
u_char queuedccbs; /* CCBs queued to the controller*/
u_char queuedepth; /* Queue depth for this lun */
u_char scdev_depth; /* SCSI device queue depth */
u_char maxnxs; /* Max possible nexuses */
/*---------------------------------------------------------------- ** Control of tagged command queuing. ** Tags allocation is performed using a circular buffer. ** This avoids using a loop for tag allocation. **----------------------------------------------------------------
*/
u_char ia_tag; /* Allocation index */
u_char if_tag; /* Freeing index */
u_char cb_tags[MAX_TAGS]; /* Circular tags buffer */
u_char usetags; /* Command queuing is active */
u_char maxtags; /* Max nr of tags asked by user */
u_char numtags; /* Current number of tags */
/*---------------------------------------------------------------- ** QUEUE FULL control and ORDERED tag control. **----------------------------------------------------------------
*/ /*---------------------------------------------------------------- ** QUEUE FULL and ORDERED tag control. **----------------------------------------------------------------
*/
u16 num_good; /* Nr of GOOD since QUEUE FULL */
tagmap_t tags_umap; /* Used tags bitmap */
tagmap_t tags_smap; /* Tags in use at 'tag_stime' */
u_long tags_stime; /* Last time we set smap=umap */ struct ccb * held_ccb; /* CCB held for QUEUE FULL */
};
/*======================================================================== ** ** Declaration of structs: the launch script. ** **======================================================================== ** ** It is part of the CCB and is called by the scripts processor to ** start or restart the data structure (nexus). ** This 6 DWORDs mini script makes use of prefetching. ** **------------------------------------------------------------------------
*/ struct launch { /*---------------------------------------------------------------- ** SCR_COPY(4), @(p_phys), @(dsa register) ** SCR_JUMP, @(scheduler_point) **----------------------------------------------------------------
*/
ncrcmd setup_dsa[3]; /* Copy 'phys' address to dsa */ struct link schedule; /* Jump to scheduler point */
ncrcmd p_phys; /* 'phys' header bus address */
};
/*======================================================================== ** ** Declaration of structs: global HEADER. ** **======================================================================== ** ** This substructure is copied from the ccb to a global address after ** selection (or reselection) and copied back before disconnect. ** ** These fields are accessible to the script processor. ** **------------------------------------------------------------------------
*/
struct head { /*---------------------------------------------------------------- ** Saved data pointer. ** Points to the position in the script responsible for the ** actual transfer transfer of data. ** It's written after reception of a SAVE_DATA_POINTER message. ** The goalpointer points after the last transfer command. **----------------------------------------------------------------
*/
u32 savep;
u32 lastp;
u32 goalp;
/*---------------------------------------------------------------- ** Alternate data pointer. ** They are copied back to savep/lastp/goalp by the SCRIPTS ** when the direction is unknown and the device claims data out. **----------------------------------------------------------------
*/
u32 wlastp;
u32 wgoalp;
/*---------------------------------------------------------------- ** The virtual address of the ccb containing this header. **----------------------------------------------------------------
*/ struct ccb * cp;
/*---------------------------------------------------------------- ** Status fields. **----------------------------------------------------------------
*/
u_char scr_st[4]; /* script status */
u_char status[4]; /* host status. must be the */ /* last DWORD of the header. */
};
/* ** The status bytes are used by the host and the script processor. ** ** The byte corresponding to the host_status must be stored in the ** last DWORD of the CCB header since it is used for command ** completion (ncr_wakeup()). Doing so, we are sure that the header ** has been entirely copied back to the CCB when the host_status is ** seen complete by the CPU. ** ** The last four bytes (status[4]) are copied to the scratchb register ** (declared as scr0..scr3 in ncr_reg.h) just after the select/reselect, ** and copied back just after disconnecting. ** Inside the script the XX_REG are used. ** ** The first four bytes (scr_st[4]) are used inside the script by ** "COPY" commands. ** Because source and destination must have the same alignment ** in a DWORD, the fields HAVE to be at the chosen offsets. ** xerr_st 0 (0x34) scratcha ** sync_st 1 (0x05) sxfer ** wide_st 3 (0x03) scntl3
*/
/* ** First four bytes (script)
*/ #define xerr_st header.scr_st[0] #define sync_st header.scr_st[1] #define nego_st header.scr_st[2] #define wide_st header.scr_st[3]
/* ** First four bytes (host)
*/ #define xerr_status phys.xerr_st #define nego_status phys.nego_st
/*========================================================== ** ** Declaration of structs: Data structure block ** **========================================================== ** ** During execution of a ccb by the script processor, ** the DSA (data structure address) register points ** to this substructure of the ccb. ** This substructure contains the header with ** the script-processor-changeable data and ** data blocks for the indirect move commands. ** **----------------------------------------------------------
*/
/*======================================================================== ** ** Declaration of structs: Command control block. ** **========================================================================
*/ struct ccb { /*---------------------------------------------------------------- ** This is the data structure which is pointed by the DSA ** register when it is executed by the script processor. ** It must be the first entry because it contains the header ** as first entry that must be cache line aligned. **----------------------------------------------------------------
*/ struct dsb phys;
/*---------------------------------------------------------------- ** Mini-script used at CCB execution start-up. ** Load the DSA with the data structure address (phys) and ** jump to SELECT. Jump to CANCEL if CCB is to be canceled. **----------------------------------------------------------------
*/ struct launch start;
/*---------------------------------------------------------------- ** Mini-script used at CCB relection to restart the nexus. ** Load the DSA with the data structure address (phys) and ** jump to RESEL_DSA. Jump to ABORT if CCB is to be aborted. **----------------------------------------------------------------
*/ struct launch restart;
/*---------------------------------------------------------------- ** If a data transfer phase is terminated too early ** (after reception of a message (i.e. DISCONNECT)), ** we have to prepare a mini script to transfer ** the rest of the data. **----------------------------------------------------------------
*/
ncrcmd patch[8];
/*---------------------------------------------------------------- ** The general SCSI driver provides a ** pointer to a control block. **----------------------------------------------------------------
*/ struct scsi_cmnd *cmd; /* SCSI command */
u_char cdb_buf[16]; /* Copy of CDB */
u_char sense_buf[64]; int data_len; /* Total data length */
/*---------------------------------------------------------------- ** Message areas. ** We prepare a message to be sent after selection. ** We may use a second one if the command is rescheduled ** due to GETCC or QFULL. ** Contents are IDENTIFY and SIMPLE_TAG. ** While negotiating sync or wide transfer, ** a SDTR or WDTR message is appended. **----------------------------------------------------------------
*/
u_char scsi_smsg [8];
u_char scsi_smsg2[8];
/*---------------------------------------------------------------- ** Other fields. **----------------------------------------------------------------
*/
u_long p_ccb; /* BUS address of this CCB */
u_char sensecmd[6]; /* Sense command */
u_char tag; /* Tag for this transfer */ /* 255 means no tag */
u_char target;
u_char lun;
u_char queued;
u_char auto_sense; struct ccb * link_ccb; /* Host adapter CCB chain */ struct list_head link_ccbq; /* Link to unit CCB queue */
u32 startp; /* Initial data pointer */
u_long magic; /* Free / busy CCB flag */
};
/*======================================================================== ** ** Declaration of structs: NCR device descriptor ** **========================================================================
*/ struct ncb { /*---------------------------------------------------------------- ** The global header. ** It is accessible to both the host and the script processor. ** Must be cache line size aligned (32 for x86) in order to ** allow cache line bursting when it is copied to/from CCB. **----------------------------------------------------------------
*/ struct head header;
/*---------------------------------------------------------------- ** CCBs management queues. **----------------------------------------------------------------
*/ struct scsi_cmnd *waiting_list; /* Commands waiting for a CCB */ /* when lcb is not allocated. */ struct scsi_cmnd *done_list; /* Commands waiting for done() */ /* callback to be invoked. */
spinlock_t smp_lock; /* Lock for SMP threading */
/*---------------------------------------------------------------- ** Chip and controller identification. **----------------------------------------------------------------
*/ int unit; /* Unit number */ char inst_name[16]; /* ncb instance name */
/*---------------------------------------------------------------- ** Initial value of some IO register bits. ** These values are assumed to have been set by BIOS, and may ** be used for probing adapter implementation differences. **----------------------------------------------------------------
*/
u_char sv_scntl0, sv_scntl3, sv_dmode, sv_dcntl, sv_ctest0, sv_ctest3,
sv_ctest4, sv_ctest5, sv_gpcntl, sv_stest2, sv_stest4;
/*---------------------------------------------------------------- ** Actual initial value of IO register bits used by the ** driver. They are loaded at initialisation according to ** features that are to be enabled. **----------------------------------------------------------------
*/
u_char rv_scntl0, rv_scntl3, rv_dmode, rv_dcntl, rv_ctest0, rv_ctest3,
rv_ctest4, rv_ctest5, rv_stest2;
/*---------------------------------------------------------------- ** Targets management. ** During reselection the ncr jumps to jump_tcb. ** The SFBR register is loaded with the encoded target id. ** For i = 0 to 3 ** SCR_JUMP ^ IFTRUE(MASK(i, 3)), @(next tcb mod. i) ** ** Recent chips will prefetch the 4 JUMPS using only 1 burst. ** It is kind of hashcoding. **----------------------------------------------------------------
*/ struct link jump_tcb[4]; /* JUMPs for reselection */ struct tcb target[MAX_TARGET]; /* Target data */
/*---------------------------------------------------------------- ** Virtual and physical bus addresses of the chip. **----------------------------------------------------------------
*/ void __iomem *vaddr; /* Virtual and bus address of */ unsignedlong paddr; /* chip's IO registers. */ unsignedlong paddr2; /* On-chip RAM bus address. */ volatile/* Pointer to volatile for */ struct ncr_reg __iomem *reg; /* memory mapped IO. */
/*---------------------------------------------------------------- ** SCRIPTS virtual and physical bus addresses. ** 'script' is loaded in the on-chip RAM if present. ** 'scripth' stays in main memory. **----------------------------------------------------------------
*/ struct script *script0; /* Copies of script and scripth */ struct scripth *scripth0; /* relocated for this ncb. */ struct scripth *scripth; /* Actual scripth virt. address */
u_long p_script; /* Actual script and scripth */
u_long p_scripth; /* bus addresses. */
/*---------------------------------------------------------------- ** General controller parameters and configuration. **----------------------------------------------------------------
*/ struct device *dev;
u_char revision_id; /* PCI device revision id */
u32 irq; /* IRQ level */
u32 features; /* Chip features map */
u_char myaddr; /* SCSI id of the adapter */
u_char maxburst; /* log base 2 of dwords burst */
u_char maxwide; /* Maximum transfer width */
u_char minsync; /* Minimum sync period factor */
u_char maxsync; /* Maximum sync period factor */
u_char maxoffs; /* Max scsi offset */
u_char multiplier; /* Clock multiplier (1,2,4) */
u_char clock_divn; /* Number of clock divisors */
u_long clock_khz; /* SCSI clock frequency in KHz */
/*---------------------------------------------------------------- ** Start queue management. ** It is filled up by the host processor and accessed by the ** SCRIPTS processor in order to start SCSI commands. **----------------------------------------------------------------
*/
u16 squeueput; /* Next free slot of the queue */
u16 actccbs; /* Number of allocated CCBs */
u16 queuedccbs; /* Number of CCBs in start queue*/
u16 queuedepth; /* Start queue depth */
/*---------------------------------------------------------------- ** Timeout handler. **----------------------------------------------------------------
*/ struct timer_list timer; /* Timer handler link header */
u_long lasttime;
u_long settle_time; /* Resetting the SCSI BUS */
/*---------------------------------------------------------------- ** Debugging and profiling. **----------------------------------------------------------------
*/ struct ncr_reg regdump; /* Register dump */
u_long regtime; /* Time it has been done */
/*---------------------------------------------------------------- ** Miscellaneous buffers accessed by the scripts-processor. ** They shall be DWORD aligned, because they may be read or ** written with a SCR_COPY script command. **----------------------------------------------------------------
*/
u_char msgout[8]; /* Buffer for MESSAGE OUT */
u_char msgin [8]; /* Buffer for MESSAGE IN */
u32 lastmsg; /* Last SCSI message sent */
u_char scratch; /* Scratch for SCSI receive */
/*---------------------------------------------------------------- ** Miscellaneous configuration and status parameters. **----------------------------------------------------------------
*/
u_char disc; /* Disconnection allowed */
u_char scsi_mode; /* Current SCSI BUS mode */
u_char order; /* Tag order to use */
u_char verbose; /* Verbosity for this controller*/ int ncr_cache; /* Used for cache test at init. */
u_long p_ncb; /* BUS address of this NCB */
/*---------------------------------------------------------------- ** Command completion handling. **----------------------------------------------------------------
*/ #ifdef SCSI_NCR_CCB_DONE_SUPPORT struct ccb *(ccb_done[MAX_DONE]); int ccb_done_ic; #endif /*---------------------------------------------------------------- ** Fields that should be removed or changed. **----------------------------------------------------------------
*/ struct ccb *ccb; /* Global CCB */ struct usrcmd user; /* Command from user */ volatile u_char release_stage; /* Synchronisation stage on release */
};
/*========================================================== ** ** ** Script for NCR-Processor. ** ** Use ncr_script_fill() to create the variable parts. ** Use ncr_script_copy_and_bind() to make a copy and ** bind to physical addresses. ** ** **========================================================== ** ** We have to know the offsets of all labels before ** we reach them (for forward jumps). ** Therefore we declare a struct here. ** If you make changes inside the script, ** DONT FORGET TO CHANGE THE LENGTHS HERE! ** **----------------------------------------------------------
*/
/* ** For HP Zalon/53c720 systems, the Zalon interface ** between CPU and 53c720 does prefetches, which causes ** problems with self modifying scripts. The problem ** is overcome by calling a dummy subroutine after each ** modification, to force a refetch of the script on ** return from the subroutine.
*/
/*========================================================== ** ** ** Scripts for NCR-Processor. ** ** Use ncr_script_bind for binding to physical addresses. ** ** **========================================================== ** ** NADDR generates a reference to a field of the controller data. ** PADDR generates a reference to another part of the script. ** RADDR generates a reference to a script processor register. ** FADDR generates a reference to a script processor register ** with offset. ** **----------------------------------------------------------
*/
staticstruct script script0 __initdata = { /*--------------------------< START >-----------------------*/ { /* ** This NOP will be patched with LED ON ** SCR_REG_REG (gpreg, SCR_AND, 0xfe)
*/
SCR_NO_OP,
0, /* ** Clear SIGP.
*/
SCR_FROM_REG (ctest2),
0, /* ** Then jump to a certain point in tryloop. ** Due to the lack of indirect addressing the code ** is self modifying here.
*/
SCR_JUMP,
}/*-------------------------< STARTPOS >--------------------*/,{
PADDRH(tryloop),
}/*-------------------------< SELECT >----------------------*/,{ /* ** DSA contains the address of a scheduled ** data structure. ** ** SCRATCHA contains the address of the script, ** which starts the next entry. ** ** Set Initiator mode. ** ** (Target mode is left as an exercise for the reader)
*/
/* ** And try to select this target.
*/
SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select),
PADDR (reselect),
}/*-------------------------< SELECT2 >----------------------*/,{ /* ** Now there are 4 possibilities: ** ** (1) The ncr loses arbitration. ** This is ok, because it will try again, ** when the bus becomes idle. ** (But beware of the timeout function!) ** ** (2) The ncr is reselected. ** Then the script processor takes the jump ** to the RESELECT label. ** ** (3) The ncr wins arbitration. ** Then it will execute SCRIPTS instruction until ** the next instruction that checks SCSI phase. ** Then will stop and wait for selection to be ** complete or selection time-out to occur. ** As a result the SCRIPTS instructions until ** LOADPOS + 2 should be executed in parallel with ** the SCSI core performing selection.
*/
/* ** The MESSAGE_REJECT problem seems to be due to a selection ** timing problem. ** Wait immediately for the selection to complete. ** (2.5x behaves so)
*/
SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_OUT)),
0,
/* ** Next time use the next slot.
*/
SCR_COPY (4),
RADDR (temp),
PADDR (startpos), /* ** The ncr doesn't have an indirect load ** or store command. So we have to ** copy part of the control block to a ** fixed place, where we can access it. ** ** We patch the address part of a ** COPY command with the DSA-register.
*/
SCR_COPY_F (4),
RADDR (dsa),
PADDR (loadpos), /* ** Flush script prefetch if required
*/
PREFETCH_FLUSH /* ** then we do the actual copy.
*/
SCR_COPY (sizeof (struct head)), /* ** continued after the next label ...
*/
}/*-------------------------< LOADPOS >---------------------*/,{
0,
NADDR (header), /* ** Wait for the next phase or the selection ** to complete or time-out.
*/
SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
PADDR (prepare),
}/*-------------------------< SEND_IDENT >----------------------*/,{ /* ** Selection complete. ** Send the IDENTIFY and SIMPLE_TAG messages ** (and the EXTENDED_SDTR message)
*/
SCR_MOVE_TBL ^ SCR_MSG_OUT,
offsetof (struct dsb, smsg),
SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)),
PADDRH (resend_ident),
SCR_LOAD_REG (scratcha, 0x80),
0,
SCR_COPY (1),
RADDR (scratcha),
NADDR (lastmsg),
}/*-------------------------< PREPARE >----------------------*/,{ /* ** load the savep (saved pointer) into ** the TEMP register (actual pointer)
*/
SCR_COPY (4),
NADDR (header.savep),
RADDR (temp), /* ** Initialize the status registers
*/
SCR_COPY (4),
NADDR (header.status),
RADDR (scr0),
}/*-------------------------< PREPARE2 >---------------------*/,{ /* ** Initialize the msgout buffer with a NOOP message.
*/
SCR_LOAD_REG (scratcha, NOP),
0,
SCR_COPY (1),
RADDR (scratcha),
NADDR (msgout), /* ** Anticipate the COMMAND phase. ** This is the normal case for initial selection.
*/
SCR_JUMP ^ IFFALSE (WHEN (SCR_COMMAND)),
PADDR (dispatch),
}/*-------------------------< COMMAND >--------------------*/,{ /* ** ... and send the command
*/
SCR_MOVE_TBL ^ SCR_COMMAND,
offsetof (struct dsb, cmd), /* ** If status is still HS_NEGOTIATE, negotiation failed. ** We check this here, since we want to do that ** only once.
*/
SCR_FROM_REG (HS_REG),
0,
SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
SIR_NEGO_FAILED,
}/*-----------------------< DISPATCH >----------------------*/,{ /* ** MSG_IN is the only phase that shall be ** entered at least once for each (re)selection. ** So we test it first.
*/
SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)),
PADDR (msg_in),
SCR_RETURN ^ IFTRUE (IF (SCR_DATA_OUT)),
0, /* ** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 4. ** Possible data corruption during Memory Write and Invalidate. ** This work-around resets the addressing logic prior to the ** start of the first MOVE of a DATA IN phase. ** (See Documentation/scsi/ncr53c8xx.rst for more information)
*/
SCR_JUMPR ^ IFFALSE (IF (SCR_DATA_IN)),
20,
SCR_COPY (4),
RADDR (scratcha),
RADDR (scratcha),
SCR_RETURN,
0,
SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)),
PADDR (status),
SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)),
PADDR (command),
SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)),
PADDR (msg_out), /* ** Discard one illegal phase byte, if required.
*/
SCR_LOAD_REG (scratcha, XE_BAD_PHASE),
0,
SCR_COPY (1),
RADDR (scratcha),
NADDR (xerr_st),
SCR_JUMPR ^ IFFALSE (IF (SCR_ILG_OUT)),
8,
SCR_MOVE_ABS (1) ^ SCR_ILG_OUT,
NADDR (scratch),
SCR_JUMPR ^ IFFALSE (IF (SCR_ILG_IN)),
8,
SCR_MOVE_ABS (1) ^ SCR_ILG_IN,
NADDR (scratch),
SCR_JUMP,
PADDR (dispatch),
}/*-------------------------< NO_DATA >--------------------*/,{ /* ** The target wants to tranfer too much data ** or in the wrong direction. ** Remember that in extended error.
*/
SCR_LOAD_REG (scratcha, XE_EXTRA_DATA),
0,
SCR_COPY (1),
RADDR (scratcha),
NADDR (xerr_st), /* ** Discard one data byte, if required.
*/
SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)),
8,
SCR_MOVE_ABS (1) ^ SCR_DATA_OUT,
NADDR (scratch),
SCR_JUMPR ^ IFFALSE (IF (SCR_DATA_IN)),
8,
SCR_MOVE_ABS (1) ^ SCR_DATA_IN,
NADDR (scratch), /* ** .. and repeat as required.
*/
SCR_CALL,
PADDR (dispatch),
SCR_JUMP,
PADDR (no_data),
}/*-------------------------< STATUS >--------------------*/,{ /* ** get the status
*/
SCR_MOVE_ABS (1) ^ SCR_STATUS,
NADDR (scratch), /* ** save status to scsi_status. ** mark as complete.
*/
SCR_TO_REG (SS_REG),
0,
SCR_LOAD_REG (HS_REG, HS_COMPLETE),
0,
SCR_JUMP,
PADDR (dispatch),
}/*-------------------------< MSG_IN >--------------------*/,{ /* ** Get the first byte of the message ** and save it to SCRATCHA. ** ** The script processor doesn't negate the ** ACK signal after this transfer.
*/
SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
NADDR (msgin[0]),
}/*-------------------------< MSG_IN2 >--------------------*/,{ /* ** Handle this message.
*/
SCR_JUMP ^ IFTRUE (DATA (COMMAND_COMPLETE)),
PADDR (complete),
SCR_JUMP ^ IFTRUE (DATA (DISCONNECT)),
PADDR (disconnect),
SCR_JUMP ^ IFTRUE (DATA (SAVE_POINTERS)),
PADDR (save_dp),
SCR_JUMP ^ IFTRUE (DATA (RESTORE_POINTERS)),
PADDR (restore_dp),
SCR_JUMP ^ IFTRUE (DATA (EXTENDED_MESSAGE)),
PADDRH (msg_extended),
SCR_JUMP ^ IFTRUE (DATA (NOP)),
PADDR (clrack),
SCR_JUMP ^ IFTRUE (DATA (MESSAGE_REJECT)),
PADDRH (msg_reject),
SCR_JUMP ^ IFTRUE (DATA (IGNORE_WIDE_RESIDUE)),
PADDRH (msg_ign_residue), /* ** Rest of the messages left as ** an exercise ... ** ** Unimplemented messages: ** fall through to MSG_BAD.
*/
}/*-------------------------< MSG_BAD >------------------*/,{ /* ** unimplemented message - reject it.
*/
SCR_INT,
SIR_REJECT_SENT,
SCR_LOAD_REG (scratcha, MESSAGE_REJECT),
0,
}/*-------------------------< SETMSG >----------------------*/,{
SCR_COPY (1),
RADDR (scratcha),
NADDR (msgout),
SCR_SET (SCR_ATN),
0,
SCR_JUMP,
PADDR (clrack),
}/*-------------------------< CLEANUP >-------------------*/,{ /* ** dsa: Pointer to ccb ** or xxxxxxFF (no ccb) ** ** HS_REG: Host-Status (<>0!)
*/
SCR_FROM_REG (dsa),
0,
SCR_JUMP ^ IFTRUE (DATA (0xff)),
PADDR (start), /* ** dsa is valid. ** complete the cleanup.
*/
SCR_JUMP,
PADDR (cleanup_ok),
}/*-------------------------< COMPLETE >-----------------*/,{ /* ** Complete message. ** ** Copy TEMP register to LASTP in header.
*/
SCR_COPY (4),
RADDR (temp),
NADDR (header.lastp), /* ** When we terminate the cycle by clearing ACK, ** the target may disconnect immediately. ** ** We don't want to be told of an ** "unexpected disconnect", ** so we disable this feature.
*/
SCR_REG_REG (scntl2, SCR_AND, 0x7f),
0, /* ** Terminate cycle ...
*/
SCR_CLR (SCR_ACK|SCR_ATN),
0, /* ** ... and wait for the disconnect.
*/
SCR_WAIT_DISC,
0,
}/*-------------------------< CLEANUP_OK >----------------*/,{ /* ** Save host status to header.
*/
SCR_COPY (4),
RADDR (scr0),
NADDR (header.status), /* ** and copy back the header to the ccb.
*/
SCR_COPY_F (4),
RADDR (dsa),
PADDR (cleanup0), /* ** Flush script prefetch if required
*/
PREFETCH_FLUSH
SCR_COPY (sizeof (struct head)),
NADDR (header),
}/*-------------------------< CLEANUP0 >--------------------*/,{
0,
}/*-------------------------< SIGNAL >----------------------*/,{ /* ** if job not completed ...
*/
SCR_FROM_REG (HS_REG),
0, /* ** ... start the next command.
*/
SCR_JUMP ^ IFTRUE (MASK (0, (HS_DONEMASK|HS_SKIPMASK))),
PADDR(start), /* ** If command resulted in not GOOD status, ** call the C code if needed.
*/
SCR_FROM_REG (SS_REG),
0,
SCR_CALL ^ IFFALSE (DATA (SAM_STAT_GOOD)),
PADDRH (bad_status),
#ifndef SCSI_NCR_CCB_DONE_SUPPORT
/* ** ... signal completion to the host
*/
SCR_INT,
SIR_INTFLY, /* ** Auf zu neuen Schandtaten!
*/
SCR_JUMP,
PADDR(start),
}/*-------------------------< DISCONNECT >---------------*/,{ /* ** DISCONNECTing ... ** ** disable the "unexpected disconnect" feature, ** and remove the ACK signal.
*/
SCR_REG_REG (scntl2, SCR_AND, 0x7f),
0,
SCR_CLR (SCR_ACK|SCR_ATN),
0, /* ** Wait for the disconnect.
*/
SCR_WAIT_DISC,
0, /* ** Status is: DISCONNECTED.
*/
SCR_LOAD_REG (HS_REG, HS_DISCONNECT),
0,
SCR_JUMP,
PADDR (cleanup_ok),
}/*-------------------------< MSG_OUT >-------------------*/,{ /* ** The target requests a message.
*/
SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
NADDR (msgout),
SCR_COPY (1),
NADDR (msgout),
NADDR (lastmsg), /* ** If it was no ABORT message ...
*/
SCR_JUMP ^ IFTRUE (DATA (ABORT_TASK_SET)),
PADDRH (msg_out_abort), /* ** ... wait for the next phase ** if it's a message out, send it again, ...
*/
SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)),
PADDR (msg_out),
}/*-------------------------< MSG_OUT_DONE >--------------*/,{ /* ** ... else clear the message ...
*/
SCR_LOAD_REG (scratcha, NOP),
0,
SCR_COPY (4),
RADDR (scratcha),
NADDR (msgout), /* ** ... and process the next phase
*/
SCR_JUMP,
PADDR (dispatch),
}/*-------------------------< IDLE >------------------------*/,{ /* ** Nothing to do? ** Wait for reselect. ** This NOP will be patched with LED OFF ** SCR_REG_REG (gpreg, SCR_OR, 0x01)
*/
SCR_NO_OP,
0,
}/*-------------------------< RESELECT >--------------------*/,{ /* ** make the DSA invalid.
*/
SCR_LOAD_REG (dsa, 0xff),
0,
SCR_CLR (SCR_TRG),
0,
SCR_LOAD_REG (HS_REG, HS_IN_RESELECT),
0, /* ** Sleep waiting for a reselection. ** If SIGP is set, special treatment. ** ** Zu allem bereit ..
*/
SCR_WAIT_RESEL,
PADDR(start),
}/*-------------------------< RESELECTED >------------------*/,{ /* ** This NOP will be patched with LED ON ** SCR_REG_REG (gpreg, SCR_AND, 0xfe)
*/
SCR_NO_OP,
0, /* ** ... zu nichts zu gebrauchen ? ** ** load the target id into the SFBR ** and jump to the control block. ** ** Look at the declarations of ** - struct ncb ** - struct tcb ** - struct lcb ** - struct ccb ** to understand what's going on.
*/
SCR_REG_SFBR (ssid, SCR_AND, 0x8F),
0,
SCR_TO_REG (sdid),
0,
SCR_JUMP,
NADDR (jump_tcb),
}/*-------------------------< RESEL_DSA >-------------------*/,{ /* ** Ack the IDENTIFY or TAG previously received.
*/
SCR_CLR (SCR_ACK),
0, /* ** The ncr doesn't have an indirect load ** or store command. So we have to ** copy part of the control block to a ** fixed place, where we can access it. ** ** We patch the address part of a ** COPY command with the DSA-register.
*/
SCR_COPY_F (4),
RADDR (dsa),
PADDR (loadpos1), /* ** Flush script prefetch if required
*/
PREFETCH_FLUSH /* ** then we do the actual copy.
*/
SCR_COPY (sizeof (struct head)), /* ** continued after the next label ...
*/
}/*-------------------------< LOADPOS1 >-------------------*/,{
0,
NADDR (header), /* ** The DSA contains the data structure address.
*/
SCR_JUMP,
PADDR (prepare),
}/*-------------------------< RESEL_LUN >-------------------*/,{ /* ** come back to this point ** to get an IDENTIFY message ** Wait for a msg_in phase.
*/
SCR_INT ^ IFFALSE (WHEN (SCR_MSG_IN)),
SIR_RESEL_NO_MSG_IN, /* ** message phase. ** Read the data directly from the BUS DATA lines. ** This helps to support very old SCSI devices that ** may reselect without sending an IDENTIFY.
*/
SCR_FROM_REG (sbdl),
0, /* ** It should be an Identify message.
*/
SCR_RETURN,
0,
}/*-------------------------< RESEL_TAG >-------------------*/,{ /* ** Read IDENTIFY + SIMPLE + TAG using a single MOVE. ** Aggressive optimization, is'nt it? ** No need to test the SIMPLE TAG message, since the ** driver only supports conformant devices for tags. ;-)
*/
SCR_MOVE_ABS (3) ^ SCR_MSG_IN,
NADDR (msgin), /* ** Read the TAG from the SIDL. ** Still an aggressive optimization. ;-) ** Compute the CCB indirect jump address which ** is (#TAG*2 & 0xfc) due to tag numbering using ** 1,3,5..MAXTAGS*2+1 actual values.
*/
SCR_REG_SFBR (sidl, SCR_SHL, 0),
0,
SCR_SFBR_REG (temp, SCR_AND, 0xfc),
0,
}/*-------------------------< JUMP_TO_NEXUS >-------------------*/,{
SCR_COPY_F (4),
RADDR (temp),
PADDR (nexus_indirect), /* ** Flush script prefetch if required
*/
PREFETCH_FLUSH
SCR_COPY (4),
}/*-------------------------< NEXUS_INDIRECT >-------------------*/,{
0,
RADDR (temp),
SCR_RETURN,
0,
}/*-------------------------< RESEL_NOTAG >-------------------*/,{ /* ** No tag expected. ** Read an throw away the IDENTIFY.
*/
SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
NADDR (msgin),
SCR_JUMP,
PADDR (jump_to_nexus),
}/*-------------------------< DATA_IN >--------------------*/,{ /* ** Because the size depends on the ** #define MAX_SCATTERL parameter, ** it is filled in at runtime. ** ** ##===========< i=0; i<MAX_SCATTERL >========= ** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)), ** || PADDR (dispatch), ** || SCR_MOVE_TBL ^ SCR_DATA_IN, ** || offsetof (struct dsb, data[ i]), ** ##========================================== ** **---------------------------------------------------------
*/
0
}/*-------------------------< DATA_IN2 >-------------------*/,{
SCR_CALL,
PADDR (dispatch),
SCR_JUMP,
PADDR (no_data),
}/*-------------------------< DATA_OUT >--------------------*/,{ /* ** Because the size depends on the ** #define MAX_SCATTERL parameter, ** it is filled in at runtime. ** ** ##===========< i=0; i<MAX_SCATTERL >========= ** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)), ** || PADDR (dispatch), ** || SCR_MOVE_TBL ^ SCR_DATA_OUT, ** || offsetof (struct dsb, data[ i]), ** ##========================================== ** **---------------------------------------------------------
*/
0
}/*-------------------------< DATA_OUT2 >-------------------*/,{
SCR_CALL,
PADDR (dispatch),
SCR_JUMP,
PADDR (no_data),
}/*--------------------------------------------------------*/
};
staticstruct scripth scripth0 __initdata = { /*-------------------------< TRYLOOP >---------------------*/{ /* ** Start the next entry. ** Called addresses point to the launch script in the CCB. ** They are patched by the main processor. ** ** Because the size depends on the ** #define MAX_START parameter, it is filled ** in at runtime. ** **----------------------------------------------------------- ** ** ##===========< I=0; i<MAX_START >=========== ** || SCR_CALL, ** || PADDR (idle), ** ##========================================== ** **-----------------------------------------------------------
*/
0
}/*------------------------< TRYLOOP2 >---------------------*/,{
SCR_JUMP,
PADDRH(tryloop),
#ifdef SCSI_NCR_CCB_DONE_SUPPORT
}/*------------------------< DONE_QUEUE >-------------------*/,{ /* ** Copy the CCB address to the next done entry. ** Because the size depends on the ** #define MAX_DONE parameter, it is filled ** in at runtime. ** **----------------------------------------------------------- ** ** ##===========< I=0; i<MAX_DONE >=========== ** || SCR_COPY (sizeof(struct ccb *), ** || NADDR (header.cp), ** || NADDR (ccb_done[i]), ** || SCR_CALL, ** || PADDR (done_end), ** ##========================================== ** **-----------------------------------------------------------
*/
0
}/*------------------------< DONE_QUEUE2 >------------------*/,{
SCR_JUMP,
PADDRH (done_queue),
#endif/* SCSI_NCR_CCB_DONE_SUPPORT */
}/*------------------------< SELECT_NO_ATN >-----------------*/,{ /* ** Set Initiator mode. ** And try to select this target without ATN.
*/
SCR_LOAD_REG (scratcha, HS_ABORTED),
0,
SCR_JUMPR,
8,
}/*-------------------------< SKIP >------------------------*/,{
SCR_LOAD_REG (scratcha, 0),
0, /* ** This entry has been canceled. ** Next time use the next slot.
*/
SCR_COPY (4),
RADDR (temp),
PADDR (startpos), /* ** The ncr doesn't have an indirect load ** or store command. So we have to ** copy part of the control block to a ** fixed place, where we can access it. ** ** We patch the address part of a ** COPY command with the DSA-register.
*/
SCR_COPY_F (4),
RADDR (dsa),
PADDRH (skip2), /* ** Flush script prefetch if required
*/
PREFETCH_FLUSH /* ** then we do the actual copy.
*/
SCR_COPY (sizeof (struct head)), /* ** continued after the next label ...
*/
}/*-------------------------< SKIP2 >---------------------*/,{
0,
NADDR (header), /* ** Initialize the status registers
*/
SCR_COPY (4),
NADDR (header.status),
RADDR (scr0), /* ** Force host status.
*/
SCR_FROM_REG (scratcha),
0,
SCR_JUMPR ^ IFFALSE (MASK (0, HS_DONEMASK)),
16,
SCR_REG_REG (HS_REG, SCR_OR, HS_SKIPMASK),
0,
SCR_JUMPR,
8,
SCR_TO_REG (HS_REG),
0,
SCR_LOAD_REG (SS_REG, SAM_STAT_GOOD),
0,
SCR_JUMP,
PADDR (cleanup_ok),
},/*-------------------------< PAR_ERR_DATA_IN >---------------*/{ /* ** Ignore all data in byte, until next phase
*/
SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)),
PADDRH (par_err_other),
SCR_MOVE_ABS (1) ^ SCR_DATA_IN,
NADDR (scratch),
SCR_JUMPR,
-24,
},/*-------------------------< PAR_ERR_OTHER >------------------*/{ /* ** count it.
*/
SCR_REG_REG (PS_REG, SCR_ADD, 0x01),
0, /* ** jump to dispatcher.
*/
SCR_JUMP,
PADDR (dispatch),
}/*-------------------------< MSG_REJECT >---------------*/,{ /* ** If a negotiation was in progress, ** negotiation failed. ** Otherwise, let the C code print ** some message.
*/
SCR_FROM_REG (HS_REG),
0,
SCR_INT ^ IFFALSE (DATA (HS_NEGOTIATE)),
SIR_REJECT_RECEIVED,
SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
SIR_NEGO_FAILED,
SCR_JUMP,
PADDR (clrack),
}/*-------------------------< MSG_IGN_RESIDUE >----------*/,{ /* ** Terminate cycle
*/
SCR_CLR (SCR_ACK),
0,
SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)),
PADDR (dispatch), /* ** get residue size.
*/
SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
NADDR (msgin[1]), /* ** Size is 0 .. ignore message.
*/
SCR_JUMP ^ IFTRUE (DATA (0)),
PADDR (clrack), /* ** Size is not 1 .. have to interrupt.
*/
SCR_JUMPR ^ IFFALSE (DATA (1)),
40, /* ** Check for residue byte in swide register
*/
SCR_FROM_REG (scntl2),
0,
SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)),
16, /* ** There IS data in the swide register. ** Discard it.
*/
SCR_REG_REG (scntl2, SCR_OR, WSR),
0,
SCR_JUMP,
PADDR (clrack), /* ** Load again the size to the sfbr register.
*/
SCR_FROM_REG (scratcha),
0,
SCR_INT,
SIR_IGN_RESIDUE,
SCR_JUMP,
PADDR (clrack),
}/*-------------------------< MSG_OUT_ABORT >-------------*/,{ /* ** After ABORT message, ** ** expect an immediate disconnect, ...
*/
SCR_REG_REG (scntl2, SCR_AND, 0x7f),
0,
SCR_CLR (SCR_ACK|SCR_ATN),
0,
SCR_WAIT_DISC,
0, /* ** ... and set the status to "ABORTED"
*/
SCR_LOAD_REG (HS_REG, HS_ABORTED),
0,
SCR_JUMP,
PADDR (cleanup),
}/*-------------------------< HDATA_IN >-------------------*/,{ /* ** Because the size depends on the ** #define MAX_SCATTERH parameter, ** it is filled in at runtime. ** ** ##==< i=MAX_SCATTERL; i<MAX_SCATTERL+MAX_SCATTERH >== ** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)), ** || PADDR (dispatch), ** || SCR_MOVE_TBL ^ SCR_DATA_IN, ** || offsetof (struct dsb, data[ i]), ** ##=================================================== ** **---------------------------------------------------------
*/
0
}/*-------------------------< HDATA_IN2 >------------------*/,{
SCR_JUMP,
PADDR (data_in),
}/*-------------------------< HDATA_OUT >-------------------*/,{ /* ** Because the size depends on the ** #define MAX_SCATTERH parameter, ** it is filled in at runtime. ** ** ##==< i=MAX_SCATTERL; i<MAX_SCATTERL+MAX_SCATTERH >== ** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)), ** || PADDR (dispatch), ** || SCR_MOVE_TBL ^ SCR_DATA_OUT, ** || offsetof (struct dsb, data[ i]), ** ##=================================================== ** **---------------------------------------------------------
*/
0
}/*-------------------------< HDATA_OUT2 >------------------*/,{
SCR_JUMP,
PADDR (data_out),
}/*-------------------------< RESET >----------------------*/,{ /* ** Send a TARGET_RESET message if bad IDENTIFY ** received on reselection.
*/
SCR_LOAD_REG (scratcha, ABORT_TASK),
0,
SCR_JUMP,
PADDRH (abort_resel),
}/*-------------------------< ABORTTAG >-------------------*/,{ /* ** Abort a wrong tag received on reselection.
*/
SCR_LOAD_REG (scratcha, ABORT_TASK),
0,
SCR_JUMP,
PADDRH (abort_resel),
}/*-------------------------< ABORT >----------------------*/,{ /* ** Abort a reselection when no active CCB.
*/
SCR_LOAD_REG (scratcha, ABORT_TASK_SET),
0,
}/*-------------------------< ABORT_RESEL >----------------*/,{
SCR_COPY (1),
RADDR (scratcha),
NADDR (msgout),
SCR_SET (SCR_ATN),
0,
SCR_CLR (SCR_ACK),
0, /* ** and send it. ** we expect an immediate disconnect
*/
SCR_REG_REG (scntl2, SCR_AND, 0x7f),
0,
SCR_MOVE_ABS (1) ^ SCR_MSG_OUT,
NADDR (msgout),
SCR_COPY (1),
NADDR (msgout),
NADDR (lastmsg),
SCR_CLR (SCR_ACK|SCR_ATN),
0,
SCR_WAIT_DISC,
0,
SCR_JUMP,
PADDR (start),
}/*-------------------------< RESEND_IDENT >-------------------*/,{ /* ** The target stays in MSG OUT phase after having acked ** Identify [+ Tag [+ Extended message ]]. Targets shall ** behave this way on parity error. ** We must send it again all the messages.
*/
SCR_SET (SCR_ATN), /* Shall be asserted 2 deskew delays before the */
0, /* 1rst ACK = 90 ns. Hope the NCR is'nt too fast */
SCR_JUMP,
PADDR (send_ident),
}/*-------------------------< CLRATN_GO_ON >-------------------*/,{
SCR_CLR (SCR_ATN),
0,
SCR_JUMP,
}/*-------------------------< NXTDSP_GO_ON >-------------------*/,{
0,
}/*-------------------------< SDATA_IN >-------------------*/,{
SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)),
PADDR (dispatch),
SCR_MOVE_TBL ^ SCR_DATA_IN,
offsetof (struct dsb, sense),
SCR_CALL,
PADDR (dispatch),
SCR_JUMP,
PADDR (no_data),
}/*-------------------------< DATA_IO >--------------------*/,{ /* ** We jump here if the data direction was unknown at the ** time we had to queue the command to the scripts processor. ** Pointers had been set as follow in this situation: ** savep --> DATA_IO ** lastp --> start pointer when DATA_IN ** goalp --> goal pointer when DATA_IN ** wlastp --> start pointer when DATA_OUT ** wgoalp --> goal pointer when DATA_OUT ** This script sets savep/lastp/goalp according to the ** direction chosen by the target.
*/
SCR_JUMPR ^ IFTRUE (WHEN (SCR_DATA_OUT)),
32, /* ** Direction is DATA IN. ** Warning: we jump here, even when phase is DATA OUT.
*/
SCR_COPY (4),
NADDR (header.lastp),
NADDR (header.savep),
/* ** Jump to the SCRIPTS according to actual direction.
*/
SCR_COPY (4),
NADDR (header.savep),
RADDR (temp),
SCR_RETURN,
0, /* ** Direction is DATA OUT.
*/
SCR_COPY (4),
NADDR (header.wlastp),
NADDR (header.lastp),
SCR_COPY (4),
NADDR (header.wgoalp),
NADDR (header.goalp),
SCR_JUMPR,
-64,
}/*-------------------------< BAD_IDENTIFY >---------------*/,{ /* ** If message phase but not an IDENTIFY, ** get some help from the C code. ** Old SCSI device may behave so.
*/
SCR_JUMPR ^ IFTRUE (MASK (0x80, 0x80)),
16,
SCR_INT,
SIR_RESEL_NO_IDENTIFY,
SCR_JUMP,
PADDRH (reset), /* ** Message is an IDENTIFY, but lun is unknown. ** Read the message, since we got it directly ** from the SCSI BUS data lines. ** Signal problem to C code for logging the event. ** Send an ABORT_TASK_SET to clear all pending tasks.
*/
SCR_INT,
SIR_RESEL_BAD_LUN,
SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
NADDR (msgin),
SCR_JUMP,
PADDRH (abort),
}/*-------------------------< BAD_I_T_L >------------------*/,{ /* ** We donnot have a task for that I_T_L. ** Signal problem to C code for logging the event. ** Send an ABORT_TASK_SET message.
*/
SCR_INT,
SIR_RESEL_BAD_I_T_L,
SCR_JUMP,
PADDRH (abort),
}/*-------------------------< BAD_I_T_L_Q >----------------*/,{ /* ** We donnot have a task that matches the tag. ** Signal problem to C code for logging the event. ** Send an ABORT_TASK message.
*/
SCR_INT,
SIR_RESEL_BAD_I_T_L_Q,
SCR_JUMP,
PADDRH (aborttag),
}/*-------------------------< BAD_TARGET >-----------------*/,{ /* ** We donnot know the target that reselected us. ** Grab the first message if any (IDENTIFY). ** Signal problem to C code for logging the event. ** TARGET_RESET message.
*/
SCR_INT,
SIR_RESEL_BAD_TARGET,
SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)),
8,
SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
NADDR (msgin),
SCR_JUMP,
PADDRH (reset),
}/*-------------------------< BAD_STATUS >-----------------*/,{ /* ** If command resulted in either TASK_SET FULL, ** CHECK CONDITION or COMMAND TERMINATED, ** call the C code.
*/
SCR_INT ^ IFTRUE (DATA (SAM_STAT_TASK_SET_FULL)),
SIR_BAD_STATUS,
SCR_INT ^ IFTRUE (DATA (SAM_STAT_CHECK_CONDITION)),
SIR_BAD_STATUS,
SCR_INT ^ IFTRUE (DATA (SAM_STAT_COMMAND_TERMINATED)),
SIR_BAD_STATUS,
SCR_RETURN,
0,
}/*-------------------------< START_RAM >-------------------*/,{ /* ** Load the script into on-chip RAM, ** and jump to start point.
*/
SCR_COPY_F (4),
RADDR (scratcha),
PADDRH (start_ram0), /* ** Flush script prefetch if required
*/
PREFETCH_FLUSH
SCR_COPY (sizeof (struct script)),
}/*-------------------------< START_RAM0 >--------------------*/,{
0,
PADDR (start),
SCR_JUMP,
PADDR (start),
}/*-------------------------< STO_RESTART >-------------------*/,{ /* ** ** Repair start queue (e.g. next time use the next slot) ** and jump to start point.
*/
SCR_COPY (4),
RADDR (temp),
PADDR (startpos),
SCR_JUMP,
PADDR (start),
}/*-------------------------< WAIT_DMA >-------------------*/,{ /* ** For HP Zalon/53c720 systems, the Zalon interface ** between CPU and 53c720 does prefetches, which causes ** problems with self modifying scripts. The problem ** is overcome by calling a dummy subroutine after each ** modification, to force a refetch of the script on ** return from the subroutine.
*/
SCR_RETURN,
0,
}/*-------------------------< SNOOPTEST >-------------------*/,{ /* ** Read the variable.
*/
SCR_COPY (4),
NADDR(ncr_cache),
RADDR (scratcha), /* ** Write the variable.
*/
SCR_COPY (4),
RADDR (temp),
NADDR(ncr_cache), /* ** Read back the variable.
*/
SCR_COPY (4),
NADDR(ncr_cache),
RADDR (temp),
}/*-------------------------< SNOOPEND >-------------------*/,{ /* ** And stop.
*/
SCR_INT,
99,
}/*--------------------------------------------------------*/
};
/*========================================================== ** ** ** Fill in #define dependent parts of the script ** ** **==========================================================
*/
/*========================================================== ** ** NCR chip clock divisor table. ** Divisors are multiplied by 10,000,000 in order to make ** calculations more simple. ** **==========================================================
*/
/*=============================================================== ** ** Prepare io register values used by ncr_init() according ** to selected and supported features. ** ** NCR chips allow burst lengths of 2, 4, 8, 16, 32, 64, 128 ** transfers. 32,64,128 are only supported by 875 and 895 chips. ** We use log base 2 (burst length) as internal code, with ** value 0 meaning "burst disabled". ** **===============================================================
*/
/* ** Select all supported special features
*/ if (np->features & FE_ERL)
np->rv_dmode |= ERL; /* Enable Read Line */ if (np->features & FE_BOF)
np->rv_dmode |= BOF; /* Burst Opcode Fetch */ if (np->features & FE_ERMP)
np->rv_dmode |= ERMP; /* Enable Read Multiple */ if (np->features & FE_PFEN)
np->rv_dcntl |= PFEN; /* Prefetch Enable */ if (np->features & FE_CLSE)
np->rv_dcntl |= CLSE; /* Cache Line Size Enable */ if (np->features & FE_WRIE)
np->rv_ctest3 |= WRIE; /* Write and Invalidate */ if (np->features & FE_DFS)
np->rv_ctest5 |= DFS; /* Dma Fifo Size */ if (np->features & FE_MUX)
np->rv_ctest4 |= MUX; /* Host bus multiplex mode */ if (np->features & FE_EA)
np->rv_dcntl |= EA; /* Enable ACK */ if (np->features & FE_EHP)
np->rv_ctest0 |= EHP; /* Even host parity */
/* ** Select some other
*/ if (driver_setup.master_parity)
np->rv_ctest4 |= MPEE; /* Master parity checking */ if (driver_setup.scsi_parity)
np->rv_scntl0 |= 0x0a; /* full arb., ena parity, par->ATN */
/* ** Get SCSI addr of host adapter (set by bios?).
*/ if (np->myaddr == 255) {
np->myaddr = INB(nc_scid) & 0x07; if (!np->myaddr)
np->myaddr = SCSI_NCR_MYADDR;
}
/* ** Set SCSI BUS mode. ** ** - ULTRA2 chips (895/895A/896) report the current ** BUS mode through the STEST4 IO register. ** - For previous generation chips (825/825A/875), ** user has to tell us how to check against HVD, ** since a 100% safe algorithm is not possible.
*/
np->scsi_mode = SMODE_SE; if (np->features & FE_DIFF) { switch(driver_setup.diff_support) { case 4: /* Trust previous settings if present, then GPIO3 */ if (np->sv_scntl3) { if (np->sv_stest2 & 0x20)
np->scsi_mode = SMODE_HVD; break;
}
fallthrough; case 3: /* SYMBIOS controllers report HVD through GPIO3 */ if (INB(nc_gpreg) & 0x08) break;
fallthrough; case 2: /* Set HVD unconditionally */
np->scsi_mode = SMODE_HVD;
fallthrough; case 1: /* Trust previous settings for HVD */ if (np->sv_stest2 & 0x20)
np->scsi_mode = SMODE_HVD; break; default:/* Don't care about HVD */ break;
}
} if (np->scsi_mode == SMODE_HVD)
np->rv_stest2 |= 0x20;
/* ** Set LED support from SCRIPTS. ** Ignore this feature for boards known to use a ** specific GPIO wiring and for the 895A or 896 ** that drive the LED directly. ** Also probe initial setting of GPIO0 as output.
*/ if ((driver_setup.led_pin) &&
!(np->features & FE_LEDC) && !(np->sv_gpcntl & 0x01))
np->features |= FE_LED0;
/* ** Set irq mode.
*/ switch(driver_setup.irqm & 3) { case 2:
np->rv_dcntl |= IRQM; break; case 1:
np->rv_dcntl |= (np->sv_dcntl & IRQM); break; default: break;
}
/* ** Configure targets according to driver setup. ** Allow to override sync, wide and NOSCAN from ** boot command line.
*/ for (i = 0 ; i < MAX_TARGET ; i++) { struct tcb *tp = &np->target[i];
if (bootverbose && np->paddr2)
printk (KERN_INFO "%s: on-chip RAM at 0x%lx\n",
ncr_name(np), np->paddr2);
}
/*========================================================== ** ** ** Done SCSI commands list management. ** ** We donnot enter the scsi_done() callback immediately ** after a command has been seen as completed but we ** insert it into a list which is flushed outside any kind ** of driver critical section. ** This allows to do minimal stuff under interrupt and ** inside critical sections and to also avoid locking up ** on recursive calls to driver entry points under SMP. ** In fact, the only kernel point which is entered by the ** driver with a driver lock set is kmalloc(GFP_ATOMIC) ** that shall not reenter the driver under any circumstances, ** AFAIK. ** **==========================================================
*/ staticinlinevoid ncr_queue_done_cmd(struct ncb *np, struct scsi_cmnd *cmd)
{
unmap_scsi_data(np, cmd);
cmd->host_scribble = (char *) np->done_list;
np->done_list = cmd;
}
/*========================================================== ** ** ** Prepare the next negotiation message if needed. ** ** Fill in the part of message buffer that contains the ** negotiation and the nego_status field of the CCB. ** Returns the size of the message in bytes. ** ** **==========================================================
*/
staticint ncr_prepare_nego(struct ncb *np, struct ccb *cp, u_char *msgptr)
{ struct tcb *tp = &np->target[cp->target]; int msglen = 0; int nego = 0; struct scsi_target *starget = tp->starget;
/* negotiate wide transfers ? */ if (!tp->widedone) { if (spi_support_wide(starget)) {
nego = NS_WIDE;
} else
tp->widedone=1;
}
/* negotiate synchronous transfers? */ if (!nego && !tp->period) { if (spi_support_sync(starget)) {
nego = NS_SYNC;
} else {
tp->period =0xffff;
dev_info(&starget->dev, "target did not report SYNC.\n");
}
}
/*--------------------------------------------- ** ** Complete the 1st TEST UNIT READY command ** with error condition if the device is ** flagged NOSCAN, in order to speed up ** the boot. ** **---------------------------------------------
*/ if ((cmd->cmnd[0] == 0 || cmd->cmnd[0] == 0x12) &&
(tp->usrflag & UF_NOSCAN)) {
tp->usrflag &= ~UF_NOSCAN; return DID_BAD_TARGET;
}
if (DEBUG_FLAGS & DEBUG_TINY) {
PRINT_ADDR(cmd, "CMD=%x ", cmd->cmnd[0]);
}
/*--------------------------------------------------- ** ** Assign a ccb / bind cmd. ** If resetting, shorten settle_time if necessary ** in order to avoid spurious timeouts. ** If resetting or no free ccb, ** insert cmd into the waiting list. ** **----------------------------------------------------
*/ if (np->settle_time && scsi_cmd_to_rq(cmd)->timeout >= HZ) {
u_long tlimit = jiffies + scsi_cmd_to_rq(cmd)->timeout - HZ; if (time_after(np->settle_time, tlimit))
np->settle_time = tlimit;
}
/* ** Force ordered tag if necessary to avoid timeouts ** and to preserve interactivity.
*/ if (lp && time_after(jiffies, lp->tags_stime)) { if (lp->tags_smap) {
order = ORDERED_QUEUE_TAG; if ((DEBUG_FLAGS & DEBUG_TAGS)||bootverbose>2){
PRINT_ADDR(cmd, "ordered tag forced.\n");
}
}
lp->tags_stime = jiffies + 3*HZ;
lp->tags_smap = lp->tags_umap;
}
if (order == 0) { /* ** Ordered write ops, unordered read ops.
*/ switch (cmd->cmnd[0]) { case 0x08: /* READ_SMALL (6) */ case 0x28: /* READ_BIG (10) */ case 0xa8: /* READ_HUGE (12) */
order = SIMPLE_QUEUE_TAG; break; default:
order = ORDERED_QUEUE_TAG;
}
}
msgptr[msglen++] = order; /* ** Actual tags are numbered 1,3,5,..2*MAXTAGS+1, ** since we may have to deal with devices that have ** problems with #TAG 0 or too great #TAG numbers.
*/
msgptr[msglen++] = (cp->tag << 1) + 1;
}
/*---------------------------------------------------- ** ** Build the data descriptors ** **----------------------------------------------------
*/
/*---------------------------------------------------- ** ** Determine xfer direction. ** **----------------------------------------------------
*/ if (!cp->data_len)
direction = DMA_NONE;
/* ** If data direction is BIDIRECTIONAL, speculate FROM_DEVICE ** but prepare alternate pointers for TO_DEVICE in case ** of our speculation will be just wrong. ** SCRIPTS will swap values if needed.
*/ switch(direction) { case DMA_BIDIRECTIONAL: case DMA_TO_DEVICE:
goalp = NCB_SCRIPT_PHYS (np, data_out2) + 8; if (segments <= MAX_SCATTERL)
lastp = goalp - 8 - (segments * 16); else {
lastp = NCB_SCRIPTH_PHYS (np, hdata_out2);
lastp -= (segments - MAX_SCATTERL) * 16;
} if (direction != DMA_BIDIRECTIONAL) break;
cp->phys.header.wgoalp = cpu_to_scr(goalp);
cp->phys.header.wlastp = cpu_to_scr(lastp);
fallthrough; case DMA_FROM_DEVICE:
goalp = NCB_SCRIPT_PHYS (np, data_in2) + 8; if (segments <= MAX_SCATTERL)
lastp = goalp - 8 - (segments * 16); else {
lastp = NCB_SCRIPTH_PHYS (np, hdata_in2);
lastp -= (segments - MAX_SCATTERL) * 16;
} break; default: case DMA_NONE:
lastp = goalp = NCB_SCRIPT_PHYS (np, no_data); break;
}
/* ** Set all pointers values needed by SCRIPTS. ** If direction is unknown, start at data_io.
*/
cp->phys.header.lastp = cpu_to_scr(lastp);
cp->phys.header.goalp = cpu_to_scr(goalp);
/* ** insert next CCBs into start queue. ** 2 max at a time is enough to flush the CCB wait queue.
*/
cp->auto_sense = 0; if (lp)
ncr_start_next_ccb(np, lp, 2); else
ncr_put_start_queue(np, cp);
/* Command is successfully queued. */
return DID_OK;
}
/*========================================================== ** ** ** Insert a CCB into the start queue and wake up the ** SCRIPTS processor. ** ** **==========================================================
*/
if (DEBUG_FLAGS & DEBUG_QUEUE)
printk ("%s: queuepos=%d.\n", ncr_name (np), np->squeueput);
/* ** Script processor may be waiting for reselect. ** Wake it up.
*/
MEMORY_BARRIER();
OUTB (nc_istat, SIGP);
}
staticint ncr_reset_scsi_bus(struct ncb *np, int enab_int, int settle_delay)
{
u32 term; int retv = 0;
np->settle_time = jiffies + settle_delay * HZ;
if (bootverbose > 1)
printk("%s: resetting, " "command processing suspended for %d seconds\n",
ncr_name(np), settle_delay);
ncr_chip_reset(np, 100);
udelay(2000); /* The 895 needs time for the bus mode to settle */ if (enab_int)
OUTW (nc_sien, RST); /* ** Enable Tolerant, reset IRQD if present and ** properly set IRQ mode, prior to resetting the bus.
*/
OUTB (nc_stest3, TE);
OUTB (nc_scntl1, CRST);
udelay(200);
if (!driver_setup.bus_check) goto out; /* ** Check for no terminators or SCSI bus shorts to ground. ** Read SCSI data bus, data parity bits and control signals. ** We are expecting RESET to be TRUE and other signals to be ** FALSE.
*/
if (term != (2<<7)) {
printk("%s: suspicious SCSI data while resetting the BUS.\n",
ncr_name(np));
printk("%s: %sdp0,d7-0,rst,req,ack,bsy,sel,atn,msg,c/d,i/o = " "0x%lx, expecting 0x%lx\n",
ncr_name(np),
(np->features & FE_WIDE) ? "dp1,d15-8," : "",
(u_long)term, (u_long)(2<<7)); if (driver_setup.bus_check == 1)
retv = 1;
}
out:
OUTB (nc_scntl1, 0); return retv;
}
/* * Start reset process. * If reset in progress do nothing. * The interrupt handler will reinitialize the chip. * The timeout handler will wait for settle_time before * clearing it and so resuming command processing.
*/ staticvoid ncr_start_reset(struct ncb *np)
{ if (!np->settle_time) {
ncr_reset_scsi_bus(np, 1, driver_setup.settle_delay);
}
}
/*========================================================== ** ** ** Reset the SCSI BUS. ** This is called from the generic SCSI driver. ** ** **==========================================================
*/ staticint ncr_reset_bus (struct ncb *np)
{ /* * Return immediately if reset is in progress.
*/ if (np->settle_time) { return FAILED;
} /* * Start the reset process. * The script processor is then assumed to be stopped. * Commands will now be queued in the waiting list until a settle * delay of 2 seconds will be completed.
*/
ncr_start_reset(np); /* * Wake-up all awaiting commands with DID_RESET.
*/
reset_waiting_list(np); /* * Wake-up all pending commands with HS_RESET -> DID_RESET.
*/
ncr_wakeup(np, HS_RESET);
/*========================================================== ** ** ** Complete execution of a SCSI command. ** Signal completion to the generic SCSI driver. ** ** **==========================================================
*/
/* ** We donnot queue more than 1 ccb per target ** with negotiation at any time. If this ccb was ** used for negotiation, clear this info in the tcb.
*/
if (cp == tp->nego_cp)
tp->nego_cp = NULL;
/* ** If auto-sense performed, change scsi status.
*/ if (cp->auto_sense) {
cp->scsi_status = cp->auto_sense;
}
/* ** If we were recovering from queue full or performing ** auto-sense, requeue skipped CCBs to the wait queue.
*/
if (lp && lp->held_ccb) { if (cp == lp->held_ccb) {
list_splice_init(&lp->skip_ccbq, &lp->wait_ccbq);
lp->held_ccb = NULL;
}
}
/* ** Check for parity errors.
*/
if (cp->parity_status > 1) {
PRINT_ADDR(cmd, "%d parity error(s).\n",cp->parity_status);
}
/* ** Check for extended errors.
*/
if (cp->xerr_status != XE_OK) { switch (cp->xerr_status) { case XE_EXTRA_DATA:
PRINT_ADDR(cmd, "extraneous data discarded.\n"); break; case XE_BAD_PHASE:
PRINT_ADDR(cmd, "invalid scsi phase (4/5).\n"); break; default:
PRINT_ADDR(cmd, "extended error %d.\n",
cp->xerr_status); break;
} if (cp->host_status==HS_COMPLETE)
cp->host_status = HS_FAIL;
}
/* ** Print out any error for debugging purpose.
*/ if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) { if (cp->host_status != HS_COMPLETE ||
cp->scsi_status != SAM_STAT_GOOD) {
PRINT_ADDR(cmd, "ERROR: cmd=%x host_status=%x " "scsi_status=%x\n", cmd->cmnd[0],
cp->host_status, cp->scsi_status);
}
}
/* ** Check the status.
*/
cmd->result = 0; if ( (cp->host_status == HS_COMPLETE)
&& (cp->scsi_status == SAM_STAT_GOOD ||
cp->scsi_status == SAM_STAT_CONDITION_MET)) { /* * All went well (GOOD status). * CONDITION MET status is returned on * `Pre-Fetch' or `Search data' success.
*/
set_status_byte(cmd, cp->scsi_status);
/* ** @RESID@ ** Could dig out the correct value for resid, ** but it would be quite complicated.
*/ /* if (cp->phys.header.lastp != cp->phys.header.goalp) */
/* ** Allocate the lcb if not yet.
*/ if (!lp)
ncr_alloc_lcb (np, cmd->device->id, cmd->device->lun);
tp->bytes += cp->data_len;
tp->transfers ++;
/* ** If tags was reduced due to queue full, ** increase tags if 1000 good status received.
*/ if (lp && lp->usetags && lp->numtags < lp->maxtags) {
++lp->num_good; if (lp->num_good >= 1000) {
lp->num_good = 0;
++lp->numtags;
ncr_setup_tags (np, cmd->device);
}
}
} elseif ((cp->host_status == HS_COMPLETE)
&& (cp->scsi_status == SAM_STAT_CHECK_CONDITION)) { /* ** Check condition code
*/
set_status_byte(cmd, SAM_STAT_CHECK_CONDITION);
/* ** Copy back sense data to caller's buffer.
*/
memcpy(cmd->sense_buffer, cp->sense_buf,
min_t(size_t, SCSI_SENSE_BUFFERSIZE, sizeof(cp->sense_buf)));
if (tp->usrflag & UF_TRACE) {
u_char * p; int i;
PRINT_ADDR(cmd, " CMD:");
p = (u_char*) &cmd->cmnd[0]; for (i=0; i<cmd->cmd_len; i++) printk (" %x", *p++);
if (cp->host_status==HS_COMPLETE) { switch (cp->scsi_status) { case SAM_STAT_GOOD:
printk (" GOOD"); break; case SAM_STAT_CHECK_CONDITION:
printk (" SENSE:");
p = (u_char*) &cmd->sense_buffer; for (i=0; i<14; i++)
printk (" %x", *p++); break; default:
printk (" STAT: %x\n", cp->scsi_status); break;
}
} else printk (" HOSTERROR: %x", cp->host_status);
printk ("\n");
}
/* ** Free this ccb
*/
ncr_free_ccb (np, cp);
/* ** requeue awaiting scsi commands for this lun.
*/ if (lp && lp->queuedccbs < lp->queuedepth &&
!list_empty(&lp->wait_ccbq))
ncr_start_next_ccb(np, lp, 2);
/* ** requeue awaiting scsi commands for this controller.
*/ if (np->waiting_list)
requeue_waiting_list(np);
/* ** signal completion to generic driver.
*/
ncr_queue_done_cmd(np, cmd);
}
/*========================================================== ** ** ** Signal all (or one) control block done. ** ** **==========================================================
*/
/* ** This CCB has been skipped by the NCR. ** Queue it in the corresponding unit queue.
*/ staticvoid ncr_ccb_skipped(struct ncb *np, struct ccb *cp)
{ struct tcb *tp = &np->target[cp->target]; struct lcb *lp = tp->lp[cp->lun];
/* ** The NCR has completed CCBs. ** Look at the DONE QUEUE if enabled, otherwise scan all CCBs
*/ void ncr_wakeup_done (struct ncb *np)
{ struct ccb *cp; #ifdef SCSI_NCR_CCB_DONE_SUPPORT int i, j;
i = np->ccb_done_ic; while (1) {
j = i+1; if (j >= MAX_DONE)
j = 0;
cp = np->ccb_done[j]; if (!CCB_DONE_VALID(cp)) break;
/* ** Complete all active CCBs.
*/ void ncr_wakeup (struct ncb *np, u_long code)
{ struct ccb *cp = np->ccb;
while (cp) { if (cp->host_status != HS_IDLE) {
cp->host_status = code;
ncr_complete (np, cp);
}
cp = cp->link_ccb;
}
}
/* ** Reset ncr chip.
*/
/* Some initialisation must be done immediately following reset, for 53c720, * at least. EA (dcntl bit 5) isn't set here as it is set once only in * the _detect function.
*/ staticvoid ncr_chip_reset(struct ncb *np, int delay)
{
OUTB (nc_istat, SRST);
udelay(delay);
OUTB (nc_istat, 0 );
if (np->features & FE_EHP)
OUTB (nc_ctest0, EHP); if (np->features & FE_MUX)
OUTB (nc_ctest4, MUX);
}
/* ** widedone=0: has to negotiate wide transfer
*/
tp->widedone=0;
}
/*========================================================== ** ** Get clock factor and sync divisor for a given ** synchronous factor period. ** Returns the clock factor (in sxfer) and scntl3 ** synchronous divisor field. ** **==========================================================
*/
staticvoid ncr_getsync(struct ncb *np, u_char sfac, u_char *fakp, u_char *scntl3p)
{
u_long clk = np->clock_khz; /* SCSI clock frequency in kHz */ int div = np->clock_divn; /* Number of divisors supported */
u_long fak; /* Sync factor in sxfer */
u_long per; /* Period in tenths of ns */
u_long kpc; /* (per * clk) */
/* ** Compute the synchronous period in tenths of nano-seconds
*/ if (sfac <= 10) per = 250; elseif (sfac == 11) per = 303; elseif (sfac == 12) per = 500; else per = 40 * sfac;
/* ** Look for the greatest clock divisor that allows an ** input speed faster than the period.
*/
kpc = per * clk; while (--div > 0) if (kpc >= (div_10M[div] << 2)) break;
/* ** Calculate the lowest clock factor that allows an output ** speed not faster than the period.
*/
fak = (kpc - 1) / div_10M[div] + 1;
if (fak < 4) fak = 4; /* Should never happen, too bad ... */
/* ** Compute and return sync parameters for the ncr
*/
*fakp = fak - 4;
*scntl3p = ((div+1) << 4) + (sfac < 25 ? 0x80 : 0);
}
/*========================================================== ** ** Set actual values, sync status and patch all ccbs of ** a target according to new sync/wide agreement. ** **==========================================================
*/
/* ** set actual value and sync_status
*/
OUTB (nc_sxfer, tp->sval);
np->sync_st = tp->sval;
OUTB (nc_scntl3, tp->wval);
np->wide_st = tp->wval;
/* ** patch ALL ccbs of this target.
*/ for (cp = np->ccb; cp; cp = cp->link_ccb) { if (!cp->cmd) continue; if (scmd_id(cp->cmd) != target) continue;
cp->phys.select.sel_scntl3 = tp->wval;
cp->phys.select.sel_sxfer = tp->sval;
}
}
/*========================================================== ** ** Switch sync mode for current job and it's target ** **==========================================================
*/
/* Stop there if sync parameters are unchanged */ if (tp->sval == sxfer && tp->wval == scntl3) return;
tp->sval = sxfer;
tp->wval = scntl3;
if (sxfer & 0x01f) { /* Disable extended Sreq/Sack filtering */ if (tp->period <= 2000)
OUTOFFB(nc_stest2, EXT);
}
spi_display_xfer_agreement(tp->starget);
/* ** set actual value and sync_status ** patch ALL ccbs of this target.
*/
ncr_set_sync_wide_status(np, target);
}
/*========================================================== ** ** Switch wide mode for current job and it's target ** SCSI specs say: a SCSI device that accepts a WDTR ** message shall reset the synchronous agreement to ** asynchronous mode. ** **==========================================================
*/
/* ** Just in case ...
*/ if ((!tp) || (!lp) || !sdev) return;
/* ** If SCSI device queue depth is not yet set, leave here.
*/ if (!lp->scdev_depth) return;
/* ** Donnot allow more tags than the SCSI driver can queue ** for this device. ** Donnot allow more tags than we can handle.
*/
maxdepth = lp->scdev_depth; if (maxdepth > lp->maxnxs) maxdepth = lp->maxnxs; if (lp->maxtags > maxdepth) lp->maxtags = maxdepth; if (lp->numtags > maxdepth) lp->numtags = maxdepth;
/* ** only devices conformant to ANSI Version >= 2 ** only devices capable of tagged commands ** only if enabled by user ..
*/ if (sdev->tagged_supported && lp->numtags > 1) {
reqtags = lp->numtags;
} else {
reqtags = 1;
}
/* ** Update max number of tags
*/
lp->numtags = reqtags; if (lp->numtags > lp->maxtags)
lp->maxtags = lp->numtags;
/* ** If we want to switch tag mode, we must wait ** for no CCB to be active.
*/ if (reqtags > 1 && lp->usetags) { /* Stay in tagged mode */ if (lp->queuedepth == reqtags) /* Already announced */ return;
lp->queuedepth = reqtags;
} elseif (reqtags <= 1 && !lp->usetags) { /* Stay in untagged mode */
lp->queuedepth = reqtags; return;
} else { /* Want to switch tag mode */ if (lp->busyccbs) /* If not yet safe, return */ return;
lp->queuedepth = reqtags;
lp->usetags = reqtags > 1 ? 1 : 0;
}
/* ** Patch the lun mini-script, according to tag mode.
*/
lp->jump_tag.l_paddr = lp->usetags?
cpu_to_scr(NCB_SCRIPT_PHYS(np, resel_tag)) :
cpu_to_scr(NCB_SCRIPT_PHYS(np, resel_notag));
/* ** Announce change to user.
*/ if (bootverbose) { if (lp->usetags) {
dev_info(&sdev->sdev_gendev, "tagged command queue depth set to %d\n",
reqtags);
} else {
dev_info(&sdev->sdev_gendev, "tagged command queueing disabled\n");
}
}
}
/*========================================================== ** ** ** ncr timeout handler. ** ** **========================================================== ** ** Misused to keep the driver running when ** interrupts are not configured correctly. ** **----------------------------------------------------------
*/
/* ** If we are resetting the ncr, wait for settle_time before ** clearing it. Then command processing will be resumed.
*/ if (np->settle_time) { if (np->settle_time <= thistime) { if (bootverbose > 1)
printk("%s: command processing resumed\n", ncr_name(np));
np->settle_time = 0;
np->disc = 1;
requeue_waiting_list(np);
} return;
}
/* ** Since the generic scsi driver only allows us 0.5 second ** to perform abort of a command, we must look at ccbs about ** every 0.25 second.
*/ if (np->lasttime + 4*HZ < thistime) { /* ** block ncr interrupts
*/
np->lasttime = thistime;
}
#ifdef SCSI_NCR_BROKEN_INTR if (INB(nc_istat) & (INTF|SIP|DIP)) {
/* ** Process pending interrupts.
*/ if (DEBUG_FLAGS & DEBUG_TINY) printk ("{");
ncr_exception (np); if (DEBUG_FLAGS & DEBUG_TINY) printk ("}");
} #endif/* SCSI_NCR_BROKEN_INTR */
}
/*========================================================== ** ** log message for real hard errors ** ** "ncr0 targ 0?: ERROR (ds:si) (so-si-sd) (sxfer/scntl3) @ name (dsp:dbc)." ** " reg: r0 r1 r2 r3 r4 r5 r6 ..... rf." ** ** exception register: ** ds: dstat ** si: sist ** ** SCSI bus lines: ** so: control lines as driver by NCR. ** si: control lines as seen by NCR. ** sd: scsi data lines as seen by NCR. ** ** wide/fastmode: ** sxfer: (see the manual) ** scntl3: (see the manual) ** ** current script command: ** dsp: script address (relative to start of script). ** dbc: first word of script command. ** ** First 16 register of the chip: ** r0..rf ** **==========================================================
*/
staticvoid ncr_log_hard_error(struct ncb *np, u16 sist, u_char dstat)
{
u32 dsp; int script_ofs; int script_size; char *script_name;
u_char *script_base; int i;
/*============================================================ ** ** ncr chip exception handler. ** **============================================================ ** ** In normal cases, interrupt conditions occur one at a ** time. The ncr is able to stack in some extra registers ** other interrupts that will occur after the first one. ** But, several interrupts may occur at the same time. ** ** We probably should only try to deal with the normal ** case, but it seems that multiple interrupts occur in ** some cases that are not abnormal at all. ** ** The most frequent interrupt condition is Phase Mismatch. ** We should want to service this interrupt quickly. ** A SCSI parity error may be delivered at the same time. ** The SIR interrupt is not very frequent in this driver, ** since the INTFLY is likely used for command completion ** signaling. ** The Selection Timeout interrupt may be triggered with ** IID and/or UDC. ** The SBMC interrupt (SCSI Bus Mode Change) may probably ** occur at any time. ** ** This handler try to deal as cleverly as possible with all ** the above. ** **============================================================
*/
/* ** interrupt on the fly ? ** Since the global header may be copied back to a CCB ** using a posted PCI memory write, the last operation on ** the istat register is a READ in order to flush posted ** PCI write commands.
*/
istat = INB (nc_istat); if (istat & INTF) {
OUTB (nc_istat, (istat & SIGP) | INTF);
istat = INB (nc_istat); if (DEBUG_FLAGS & DEBUG_TINY) printk ("F ");
ncr_wakeup_done (np);
}
if (!(istat & (SIP|DIP))) return;
if (istat & CABRT)
OUTB (nc_istat, CABRT);
/* ** Steinbach's Guideline for Systems Programming: ** Never test for an error condition you don't know how to handle.
*/
if (DEBUG_FLAGS & DEBUG_TINY)
printk ("<%d|%x:%x|%x:%x>",
(int)INB(nc_scr0),
dstat,sist,
(unsigned)INL(nc_dsp),
(unsigned)INL(nc_dbc));
/*======================================================== ** First, interrupts we want to service cleanly. ** ** Phase mismatch is the most frequent interrupt, and ** so we have to service it as quickly and as cleanly ** as possible. ** Programmed interrupts are rarely used in this driver, ** but we must handle them cleanly anyway. ** We try to deal with PAR and SBMC combined with ** some other interrupt(s). **=========================================================
*/
if (!(sist & (STO|GEN|HTH|SGE|UDC|RST)) &&
!(dstat & (MDPE|BF|ABRT|IID))) { if ((sist & SBMC) && ncr_int_sbmc (np)) return; if ((sist & PAR) && ncr_int_par (np)) return; if (sist & MA) {
ncr_int_ma (np); return;
} if (dstat & SIR) {
ncr_int_sir (np); return;
} /* ** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 2.
*/ if (!(sist & (SBMC|PAR)) && !(dstat & SSI)) {
printk( "%s: unknown interrupt(s) ignored, " "ISTAT=%x DSTAT=%x SIST=%x\n",
ncr_name(np), istat, dstat, sist); return;
}
OUTONB_STD (); return;
}
/*======================================================== ** Now, interrupts that need some fixing up. ** Order and multiple interrupts is so less important. ** ** If SRST has been asserted, we just reset the chip. ** ** Selection is intirely handled by the chip. If the ** chip says STO, we trust it. Seems some other ** interrupts may occur at the same time (UDC, IID), so ** we ignore them. In any case we do enough fix-up ** in the service routine. ** We just exclude some fatal dma errors. **=========================================================
*/
if ((sist & STO) &&
!(dstat & (MDPE|BF|ABRT))) { /* ** DEL 397 - 53C875 Rev 3 - Part Number 609-0392410 - ITEM 1.
*/
OUTONB (nc_ctest3, CLF);
ncr_int_sto (np); return;
}
/*========================================================= ** Now, interrupts we are not able to recover cleanly. ** (At least for the moment). ** ** Do the register dump. ** Log message for real hard errors. ** Clear all fifos. ** For MDPE, BF, ABORT, IID, SGE and HTH we reset the ** BUS and the chip. ** We are more soft for UDC. **=========================================================
*/
if (time_after(jiffies, np->regtime)) {
np->regtime = jiffies + 10*HZ; for (i = 0; i<sizeof(np->regdump); i++)
((char*)&np->regdump)[i] = INB_OFF(i);
np->regdump.nc_dstat = dstat;
np->regdump.nc_sist = sist;
}
ncr_log_hard_error(np, sist, dstat);
printk ("%s: have to clear fifos.\n", ncr_name (np));
OUTB (nc_stest3, TE|CSF);
OUTONB (nc_ctest3, CLF);
/*========================================================= ** We just miss the cause of the interrupt. :( ** Print a message. The timeout will do the real work. **=========================================================
*/
printk ("%s: unknown interrupt\n", ncr_name(np));
}
/*========================================================== ** ** ncr chip exception handler for selection timeout ** **========================================================== ** ** There seems to be a bug in the 53c810. ** Although a STO-Interrupt is pending, ** it continues executing script commands. ** But it will fail and interrupt (IID) on ** the next instruction where it's looking ** for a valid phase. ** **----------------------------------------------------------
*/
/*========================================================== ** ** ncr chip exception handler for SCSI bus mode change ** **========================================================== ** ** spi2-r12 11.2.3 says a transceiver mode change must ** generate a reset event and a device that detects a reset ** event shall initiate a hard reset. It says also that a ** device that detects a mode change shall set data transfer ** mode to eight bit asynchronous, etc... ** So, just resetting should be enough. ** ** **----------------------------------------------------------
*/
/* * Ignore the interrupt if the NCR is not connected * to the SCSI bus, since the right work should have * been done on unexpected disconnection handling.
*/ if (!(INB (nc_scntl1) & ISCON)) return 0;
/* * If the nexus is not clearly identified, reset the bus. * We will try to do better later.
*/ if (hsts & HS_INVALMASK) goto reset_all;
/* * If the SCSI parity error occurs in MSG IN phase, prepare a * MSG PARITY message. Otherwise, prepare a INITIATOR DETECTED * ERROR message and let the device decide to retry the command * or to terminate with check condition. If we were in MSG IN * phase waiting for the response of a negotiation, we will * get SIR_NEGO_FAILED at dispatch.
*/ if (!(dbc & 0xc0000000))
phase = (dbc >> 24) & 7; if (phase == 7)
msg = MSG_PARITY_ERROR; else
msg = INITIATOR_ERROR;
/* * If the NCR stopped on a MOVE ^ DATA_IN, we jump to a * script that will ignore all data in bytes until phase * change, since we are not sure the chip will wait the phase * change prior to delivering the interrupt.
*/ if (phase == 1)
jmp = NCB_SCRIPTH_PHYS (np, par_err_data_in); else
jmp = NCB_SCRIPTH_PHYS (np, par_err_other);
/*========================================================== ** ** ** ncr chip exception handler for phase errors. ** ** **========================================================== ** ** We have to construct a new transfer descriptor, ** to transfer the rest of the current block. ** **----------------------------------------------------------
*/
/* ** The data in the dma fifo has not been transferred to ** the target -> add the amount to the rest ** and clear the data. ** Check the sstat2 register in case of wide transfer.
*/
rest += delta;
ss0 = INB (nc_sstat0); if (ss0 & OLF) rest++; if (ss0 & ORF) rest++; if (INB(nc_scntl3) & EWS) {
ss2 = INB (nc_sstat2); if (ss2 & OLF1) rest++; if (ss2 & ORF1) rest++;
}
/* ** locate matching cp. ** if the interrupted phase is DATA IN or DATA OUT, ** trust the global header.
*/
dsa = INL (nc_dsa); if (!(cmd & 6)) {
cp = np->header.cp; if (CCB_PHYS(cp, phys) != dsa)
cp = NULL;
} else {
cp = np->ccb; while (cp && (CCB_PHYS (cp, phys) != dsa))
cp = cp->link_ccb;
}
/* ** cp=0 means that the DSA does not point to a valid control ** block. This should not happen since we donnot use multi-byte ** move while we are being reselected ot after command complete. ** We are not able to recover from such a phase error.
*/ if (!cp) {
printk ("%s: SCSI phase error fixup: " "CCB already dequeued (0x%08lx)\n",
ncr_name (np), (u_long) np->header.cp); goto reset_all;
}
/* ** cp != np->header.cp means that the header of the CCB ** currently being processed has not yet been copied to ** the global header area. That may happen if the device did ** not accept all our messages after having been selected.
*/ if (cp != np->header.cp) {
printk ("%s: SCSI phase error fixup: " "CCB address mismatch (0x%08lx != 0x%08lx)\n",
ncr_name (np), (u_long) cp, (u_long) np->header.cp);
}
if (DEBUG_FLAGS & DEBUG_PHASE) {
PRINT_ADDR(cp->cmd, "newcmd[%d] %x %x %x %x.\n",
(int) (newcmd - cp->patch),
(unsigned)scr_to_cpu(newcmd[0]),
(unsigned)scr_to_cpu(newcmd[1]),
(unsigned)scr_to_cpu(newcmd[2]),
(unsigned)scr_to_cpu(newcmd[3]));
} /* ** fake the return address (to the patch). ** and restart script processor at dispatcher.
*/
OUTL (nc_temp, newtmp);
OUTL_DSP (NCB_SCRIPT_PHYS (np, dispatch)); return;
/* ** Unexpected phase changes that occurs when the current phase ** is not a DATA IN or DATA OUT phase are due to error conditions. ** Such event may only happen when the SCRIPTS is using a ** multibyte SCSI MOVE. ** ** Phase change Some possible cause ** ** COMMAND --> MSG IN SCSI parity error detected by target. ** COMMAND --> STATUS Bad command or refused by target. ** MSG OUT --> MSG IN Message rejected by target. ** MSG OUT --> COMMAND Bogus target that discards extended ** negotiation messages. ** ** The code below does not care of the new phase and so ** trusts the target. Why to annoy it ? ** If the interrupted phase is COMMAND phase, we restart at ** dispatcher. ** If a target does not get all the messages after selection, ** the code assumes blindly that the target discards extended ** messages and clears the negotiation status. ** If the target does not want all our response to negotiation, ** we force a SIR_NEGO_PROTO interrupt (it is a hack that avoids ** bloat for such a should_not_happen situation). ** In all other situation, we reset the BUS. ** Are these assumptions reasonable ? (Wait and see ...)
*/
unexpected_phase:
dsp -= 8;
nxtdsp = 0;
/* ** Let the SCRIPTS processor skip all not yet started CCBs, ** and count disconnected CCBs. Since the busy queue is in ** the same order as the chip start queue, disconnected CCBs ** are before cp and busy ones after.
*/ if (lp) {
qp = lp->busy_ccbq.prev; while (qp != &lp->busy_ccbq) {
cp2 = list_entry(qp, struct ccb, link_ccbq);
qp = qp->prev;
++busy_cnt; if (cp2 == cp) break;
cp2->start.schedule.l_paddr =
cpu_to_scr(NCB_SCRIPTH_PHYS (np, skip));
}
lp->held_ccb = cp; /* Requeue when this one completes */
disc_cnt = lp->queuedccbs - busy_cnt;
}
switch(s_status) { default: /* Just for safety, should never happen */ case SAM_STAT_TASK_SET_FULL: /* ** Decrease number of tags to the number of ** disconnected commands.
*/ if (!lp) goto out; if (bootverbose >= 1) {
PRINT_ADDR(cmd, "QUEUE FULL! %d busy, %d disconnected " "CCBs\n", busy_cnt, disc_cnt);
} if (disc_cnt < lp->numtags) {
lp->numtags = disc_cnt > 2 ? disc_cnt : 2;
lp->num_good = 0;
ncr_setup_tags (np, cmd->device);
} /* ** Requeue the command to the start queue. ** If any disconnected commands, ** Clear SIGP. ** Jump to reselect.
*/
cp->phys.header.savep = cp->startp;
cp->host_status = HS_BUSY;
cp->scsi_status = SAM_STAT_ILLEGAL;
ncr_put_start_queue(np, cp); if (disc_cnt)
INB (nc_ctest2); /* Clear SIGP */
OUTL_DSP (NCB_SCRIPT_PHYS (np, reselect)); return; case SAM_STAT_COMMAND_TERMINATED: case SAM_STAT_CHECK_CONDITION: /* ** If we were requesting sense, give up.
*/ if (cp->auto_sense) goto out;
/* ** Device returned CHECK CONDITION status. ** Prepare all needed data strutures for getting ** sense data. ** ** identify message
*/
cp->scsi_smsg2[0] = IDENTIFY(0, cmd->device->lun);
cp->phys.smsg.addr = cpu_to_scr(CCB_PHYS (cp, scsi_smsg2));
cp->phys.smsg.size = cpu_to_scr(1);
if (DEBUG_FLAGS & DEBUG_TINY) printk ("I#%d", num);
switch (num) { case SIR_INTFLY: /* ** This is used for HP Zalon/53c720 where INTFLY ** operation is currently broken.
*/
ncr_wakeup_done(np); #ifdef SCSI_NCR_CCB_DONE_SUPPORT
OUTL(nc_dsp, NCB_SCRIPT_PHYS (np, done_end) + 8); #else
OUTL(nc_dsp, NCB_SCRIPT_PHYS (np, start)); #endif return; case SIR_RESEL_NO_MSG_IN: case SIR_RESEL_NO_IDENTIFY: /* ** If devices reselecting without sending an IDENTIFY ** message still exist, this should help. ** We just assume lun=0, 1 CCB, no tag.
*/ if (tp->lp[0]) {
OUTL_DSP (scr_to_cpu(tp->lp[0]->jump_ccb[0])); return;
}
fallthrough; case SIR_RESEL_BAD_TARGET: /* Will send a TARGET RESET message */ case SIR_RESEL_BAD_LUN: /* Will send a TARGET RESET message */ case SIR_RESEL_BAD_I_T_L_Q: /* Will send an ABORT TAG message */ case SIR_RESEL_BAD_I_T_L: /* Will send an ABORT message */
printk ("%s:%d: SIR %d, " "incorrect nexus identification on reselection\n",
ncr_name (np), target, num); goto out; case SIR_DONE_OVERFLOW:
printk ("%s:%d: SIR %d, " "CCB done queue overflow\n",
ncr_name (np), target, num); goto out; case SIR_BAD_STATUS:
cp = np->header.cp; if (!cp || CCB_PHYS (cp, phys) != dsa) goto out;
ncr_sir_to_redo(np, num, cp); return; default: /* ** lookup the ccb
*/
cp = np->ccb; while (cp && (CCB_PHYS (cp, phys) != dsa))
cp = cp->link_ccb;
BUG_ON(!cp);
BUG_ON(cp != np->header.cp);
if (!cp || cp != np->header.cp) goto out;
}
switch (num) { /*----------------------------------------------------------------------------- ** ** Was Sie schon immer ueber transfermode negotiation wissen wollten ... ** ("Everything you've always wanted to know about transfer mode ** negotiation") ** ** We try to negotiate sync and wide transfer only after ** a successful inquire command. We look at byte 7 of the ** inquire data to determine the capabilities of the target. ** ** When we try to negotiate, we append the negotiation message ** to the identify and (maybe) simple tag message. ** The host status field is set to HS_NEGOTIATE to mark this ** situation. ** ** If the target doesn't answer this message immediately ** (as required by the standard), the SIR_NEGO_FAIL interrupt ** will be raised eventually. ** The handler removes the HS_NEGOTIATE status, and sets the ** negotiated value to the default (async / nowide). ** ** If we receive a matching answer immediately, we check it ** for validity, and set the values. ** ** If we receive a Reject message immediately, we assume the ** negotiation has failed, and fall back to standard values. ** ** If we receive a negotiation message while not in HS_NEGOTIATE ** state, it's a target initiated negotiation. We prepare a ** (hopefully) valid answer, set our parameters, and send back ** this answer to the target. ** ** If the target doesn't fetch the answer (no message out phase), ** we assume the negotiation has failed, and fall back to default ** settings. ** ** When we set the values, we adjust them in all ccbs belonging ** to this target, in the controller's register, and in the "phys" ** field of the controller's struct ncb. ** ** Possible cases: hs sir msg_in value send goto ** We try to negotiate: ** -> target doesn't msgin NEG FAIL noop defa. - dispatch ** -> target rejected our msg NEG FAIL reject defa. - dispatch ** -> target answered (ok) NEG SYNC sdtr set - clrack ** -> target answered (!ok) NEG SYNC sdtr defa. REJ--->msg_bad ** -> target answered (ok) NEG WIDE wdtr set - clrack ** -> target answered (!ok) NEG WIDE wdtr defa. REJ--->msg_bad ** -> any other msgin NEG FAIL noop defa. - dispatch ** ** Target tries to negotiate: ** -> incoming message --- SYNC sdtr set SDTR - ** -> incoming message --- WIDE wdtr set WDTR - ** We sent our answer: ** -> target doesn't msgout --- PROTO ? defa. - dispatch ** **-----------------------------------------------------------------------------
*/
/*-------------------------------------------------------------------- ** ** Processing of special messages ** **--------------------------------------------------------------------
*/
case SIR_REJECT_RECEIVED: /*----------------------------------------------- ** ** We received a MESSAGE_REJECT. ** **-----------------------------------------------
*/
PRINT_ADDR(cp->cmd, "MESSAGE_REJECT received (%x:%x).\n",
(unsigned)scr_to_cpu(np->lastmsg), np->msgout[0]); break;
case SIR_REJECT_SENT: /*----------------------------------------------- ** ** We received an unknown message ** **-----------------------------------------------
*/
ncr_print_msg(cp, "MESSAGE_REJECT sent for", np->msgin); break;
/*-------------------------------------------------------------------- ** ** Processing of special messages ** **--------------------------------------------------------------------
*/
case SIR_IGN_RESIDUE: /*----------------------------------------------- ** ** We received an IGNORE RESIDUE message, ** which couldn't be handled by the script. ** **-----------------------------------------------
*/
PRINT_ADDR(cp->cmd, "IGNORE_WIDE_RESIDUE received, but not yet " "implemented.\n"); break; #if 0 case SIR_MISSING_SAVE: /*----------------------------------------------- ** ** We received an DISCONNECT message, ** but the datapointer wasn't saved before. ** **-----------------------------------------------
*/
/* ** Lun structure available ?
*/ if (lp) { struct list_head *qp; /* ** Keep from using more tags than we can handle.
*/ if (lp->usetags && lp->busyccbs >= lp->maxnxs) return NULL;
/* ** Allocate a new CCB if needed.
*/ if (list_empty(&lp->free_ccbq))
ncr_alloc_ccb(np, tn, ln);
/* ** If a CCB is available, ** Get a tag for this nexus if required.
*/ if (cp) { if (lp->usetags)
tag = lp->cb_tags[lp->ia_tag];
} elseif (lp->actccbs > 0) return NULL;
}
/* ** if nothing available, take the default.
*/ if (!cp)
cp = np->ccb;
/* ** Wait until available.
*/ #if 0 while (cp->magic) { if (flags & SCSI_NOSLEEP) break; if (tsleep ((caddr_t)cp, PRIBIO|PCATCH, "ncr", 0)) break;
} #endif
if (cp->magic) return NULL;
cp->magic = 1;
/* ** Move to next available tag if tag used.
*/ if (lp) { if (tag != NO_TAG) {
++lp->ia_tag; if (lp->ia_tag == MAX_TAGS)
lp->ia_tag = 0;
lp->tags_umap |= (((tagmap_t) 1) << tag);
}
}
/* ** Remember all informations needed to free this CCB.
*/
cp->tag = tag;
cp->target = tn;
cp->lun = ln;
if (DEBUG_FLAGS & DEBUG_TAGS) {
PRINT_ADDR(cmd, "ccb @%p using tag %d.\n", cp, tag);
}
return cp;
}
/*========================================================== ** ** ** Release one control block ** ** **==========================================================
*/
if (DEBUG_FLAGS & DEBUG_TAGS) {
PRINT_ADDR(cp->cmd, "ccb @%p freeing tag %d.\n", cp, cp->tag);
}
/* ** If lun control block available, ** decrement active commands and increment credit, ** free the tag if any and remove the JUMP for reselect.
*/ if (lp) { if (cp->tag != NO_TAG) {
lp->cb_tags[lp->if_tag++] = cp->tag; if (lp->if_tag == MAX_TAGS)
lp->if_tag = 0;
lp->tags_umap &= ~(((tagmap_t) 1) << cp->tag);
lp->tags_smap &= lp->tags_umap;
lp->jump_ccb[cp->tag] =
cpu_to_scr(NCB_SCRIPTH_PHYS(np, bad_i_t_l_q));
} else {
lp->jump_ccb[0] =
cpu_to_scr(NCB_SCRIPTH_PHYS(np, bad_i_t_l));
}
}
/* ** Make this CCB available.
*/
if (lp) { if (cp != np->ccb)
list_move(&cp->link_ccbq, &lp->free_ccbq);
--lp->busyccbs; if (cp->queued) {
--lp->queuedccbs;
}
}
cp -> host_status = HS_IDLE;
cp -> magic = 0; if (cp->queued) {
--np->queuedccbs;
cp->queued = 0;
}
/* ** Allocate memory for this CCB.
*/
cp = m_calloc_dma(sizeof(struct ccb), "CCB"); if (!cp) return;
/* ** Count it and initialyze it.
*/
lp->actccbs++;
np->actccbs++;
memset(cp, 0, sizeof (*cp));
ncr_init_ccb(np, cp);
/* ** Chain into wakeup list and free ccb queue and take it ** into account for tagged commands.
*/
cp->link_ccb = np->ccb->link_ccb;
np->ccb->link_ccb = cp;
list_add(&cp->link_ccbq, &lp->free_ccbq);
}
/*========================================================== ** ** ** Allocation of resources for Targets/Luns/Tags. ** ** **==========================================================
*/
/*------------------------------------------------------------------------ ** Target control block initialisation. **------------------------------------------------------------------------ ** This data structure is fully initialized after a SCSI command ** has been successfully completed for this target. ** It contains a SCRIPT that is called on target reselection. **------------------------------------------------------------------------
*/ staticvoid ncr_init_tcb (struct ncb *np, u_char tn)
{ struct tcb *tp = &np->target[tn];
ncrcmd copy_1 = np->features & FE_PFEN ? SCR_COPY(1) : SCR_COPY_F(1); int th = tn & 3; int i;
/* ** Jump to next tcb if SFBR does not match this target. ** JUMP IF (SFBR != #target#), @(next tcb)
*/
tp->jump_tcb.l_cmd =
cpu_to_scr((SCR_JUMP ^ IFFALSE (DATA (0x80 + tn))));
tp->jump_tcb.l_paddr = np->jump_tcb[th].l_paddr;
/* ** Get the IDENTIFY message and the lun. ** CALL @script(resel_lun)
*/
tp->call_lun.l_cmd = cpu_to_scr(SCR_CALL);
tp->call_lun.l_paddr = cpu_to_scr(NCB_SCRIPT_PHYS (np, resel_lun));
/* ** Look for the lun control block of this nexus. ** For i = 0 to 3 ** JUMP ^ IFTRUE (MASK (i, 3)), @(next_lcb)
*/ for (i = 0 ; i < 4 ; i++) {
tp->jump_lcb[i].l_cmd =
cpu_to_scr((SCR_JUMP ^ IFTRUE (MASK (i, 3))));
tp->jump_lcb[i].l_paddr =
cpu_to_scr(NCB_SCRIPTH_PHYS (np, bad_identify));
}
/* ** Link this target control block to the JUMP chain.
*/
np->jump_tcb[th].l_paddr = cpu_to_scr(vtobus (&tp->jump_tcb));
/* ** Set max CCBs to 1 and use the default 1 entry ** jump table by default.
*/
lp->maxnxs = 1;
lp->jump_ccb = &lp->jump_ccb_0;
lp->p_jump_ccb = cpu_to_scr(vtobus(lp->jump_ccb));
/* ** Initilialyze the reselect script: ** ** Jump to next lcb if SFBR does not match this lun. ** Load TEMP with the CCB direct jump table bus address. ** Get the SIMPLE TAG message and the tag. ** ** JUMP IF (SFBR != #lun#), @(next lcb) ** COPY @(lp->p_jump_ccb), @(temp) ** JUMP @script(resel_notag)
*/
lp->jump_lcb.l_cmd =
cpu_to_scr((SCR_JUMP ^ IFFALSE (MASK (0x80+ln, 0xff))));
lp->jump_lcb.l_paddr = tp->jump_lcb[lh].l_paddr;
/*------------------------------------------------------------------------ ** Lun control block setup on INQUIRY data received. **------------------------------------------------------------------------ ** We only support WIDE, SYNC for targets and CMDQ for logical units. ** This setup is done on each INQUIRY since we are expecting user ** will play with CHANGE DEFINITION commands. :-) **------------------------------------------------------------------------
*/ staticstruct lcb *ncr_setup_lcb (struct ncb *np, struct scsi_device *sdev)
{ unsignedchar tn = sdev->id, ln = sdev->lun; struct tcb *tp = &np->target[tn]; struct lcb *lp = tp->lp[ln];
/* If no lcb, try to allocate it. */ if (!lp && !(lp = ncr_alloc_lcb(np, tn, ln))) goto fail;
/* ** If unit supports tagged commands, allocate the ** CCB JUMP table if not yet.
*/ if (sdev->tagged_supported && lp->jump_ccb == &lp->jump_ccb_0) { int i;
lp->jump_ccb = m_calloc_dma(256, "JUMP_CCB"); if (!lp->jump_ccb) {
lp->jump_ccb = &lp->jump_ccb_0; goto fail;
}
lp->p_jump_ccb = cpu_to_scr(vtobus(lp->jump_ccb)); for (i = 0 ; i < 64 ; i++)
lp->jump_ccb[i] =
cpu_to_scr(NCB_SCRIPTH_PHYS (np, bad_i_t_l_q)); for (i = 0 ; i < MAX_TAGS ; i++)
lp->cb_tags[i] = i;
lp->maxnxs = MAX_TAGS;
lp->tags_stime = jiffies + 3*HZ;
ncr_setup_tags (np, sdev);
}
fail: return lp;
}
/*========================================================== ** ** ** Build Scatter Gather Block ** ** **========================================================== ** ** The transfer area may be scattered among ** several non adjacent physical pages. ** ** We may use MAX_SCATTER blocks. ** **----------------------------------------------------------
*/
/* ** We try to reduce the number of interrupts caused ** by unexpected phase changes due to disconnects. ** A typical harddisk may disconnect before ANY block. ** If we wanted to avoid unexpected phase changes at all ** we had to use a break point every 512 bytes. ** Of course the number of scatter/gather blocks is ** limited. ** Under Linux, the scatter/gatter blocks are provided by ** the generic driver. We just have to copy addresses and ** sizes to the data segment array.
*/
staticint ncr_scatter(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd)
{ int segment = 0; int use_sg = scsi_sg_count(cmd);
/*========================================================== ** ** ** Test the bus snoop logic :-( ** ** Has to be called with interrupts disabled. ** ** **==========================================================
*/
staticint __init ncr_regtest (struct ncb* np)
{ registervolatile u32 data; /* ** ncr registers may NOT be cached. ** write 0xffffffff to a read only register area, ** and try to read it back.
*/
data = 0xffffffff;
OUTL_OFF(offsetof(struct ncr_reg, nc_dstat), data);
data = INL_OFF(offsetof(struct ncr_reg, nc_dstat)); #if 1 if (data == 0xffffffff) { #else if ((data & 0xe2f0fffd) != 0x02000080) { #endif
printk ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n",
(unsigned) data); return (0x10);
} return (0);
}
staticint __init ncr_snooptest (struct ncb* np)
{
u32 ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc; int i, err=0; if (np->reg) {
err |= ncr_regtest (np); if (err) return (err);
}
/* init */
pc = NCB_SCRIPTH_PHYS (np, snooptest);
host_wr = 1;
ncr_wr = 2; /* ** Set memory and register.
*/
np->ncr_cache = cpu_to_scr(host_wr);
OUTL (nc_temp, ncr_wr); /* ** Start script (exchange values)
*/
OUTL_DSP (pc); /* ** Wait 'til done (with timeout)
*/ for (i=0; i<NCR_SNOOP_TIMEOUT; i++) if (INB(nc_istat) & (INTF|SIP|DIP)) break; /* ** Save termination position.
*/
pc = INL (nc_dsp); /* ** Read memory and register.
*/
host_rd = scr_to_cpu(np->ncr_cache);
ncr_rd = INL (nc_scratcha);
ncr_bk = INL (nc_temp); /* ** Reset ncr chip
*/
ncr_chip_reset(np, 100); /* ** check for timeout
*/ if (i>=NCR_SNOOP_TIMEOUT) {
printk ("CACHE TEST FAILED: timeout.\n"); return (0x20);
} /* ** Check termination position.
*/ if (pc != NCB_SCRIPTH_PHYS (np, snoopend)+8) {
printk ("CACHE TEST FAILED: script execution failed.\n");
printk ("start=%08lx, pc=%08lx, end=%08lx\n",
(u_long) NCB_SCRIPTH_PHYS (np, snooptest), (u_long) pc,
(u_long) NCB_SCRIPTH_PHYS (np, snoopend) +8); return (0x40);
} /* ** Show results.
*/ if (host_wr != ncr_rd) {
printk ("CACHE TEST FAILED: host wrote %d, ncr read %d.\n",
(int) host_wr, (int) ncr_rd);
err |= 1;
} if (host_rd != ncr_wr) {
printk ("CACHE TEST FAILED: ncr wrote %d, host read %d.\n",
(int) ncr_wr, (int) host_rd);
err |= 2;
} if (ncr_bk != ncr_wr) {
printk ("CACHE TEST FAILED: ncr wrote %d, read back %d.\n",
(int) ncr_wr, (int) ncr_bk);
err |= 4;
} return (err);
}
/*========================================================== ** ** Determine the ncr's clock frequency. ** This is essential for the negotiation ** of the synchronous transfer rate. ** **========================================================== ** ** Note: we have to return the correct value. ** THERE IS NO SAFE DEFAULT VALUE. ** ** Most NCR/SYMBIOS boards are delivered with a 40 Mhz clock. ** 53C860 and 53C875 rev. 1 support fast20 transfers but ** do not have a clock doubler and so are provided with a ** 80 MHz clock. All other fast20 boards incorporate a doubler ** and so should be delivered with a 40 MHz clock. ** The future fast40 chips (895/895) use a 40 Mhz base clock ** and provide a clock quadrupler (160 Mhz). The code below ** tries to deal as cleverly as possible with all this stuff. ** **----------------------------------------------------------
*/
if (bootverbose >= 2)
printk ("%s: enabling clock multiplier\n", ncr_name(np));
OUTB(nc_stest1, DBLEN); /* Enable clock multiplier */ if (np->multiplier > 2) { /* Poll bit 5 of stest4 for quadrupler */ int i = 20; while (!(INB(nc_stest4) & LCKFRQ) && --i > 0)
udelay(20); if (!i)
printk("%s: the chip cannot lock the frequency\n", ncr_name(np));
} else/* Wait 20 micro-seconds for doubler */
udelay(20);
OUTB(nc_stest3, HSC); /* Halt the scsi clock */
OUTB(nc_scntl3, scntl3);
OUTB(nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */
OUTB(nc_stest3, 0x00); /* Restart scsi clock */
}
/* * calculate NCR SCSI clock frequency (in KHz)
*/ staticunsigned __init ncrgetfreq (struct ncb *np, int gen)
{ unsigned ms = 0; char count = 0;
/* * Measure GEN timer delay in order * to calculate SCSI clock frequency * * This code will never execute too * many loop iterations (if DELAY is * reasonably correct). It could get * too low a delay (too high a freq.) * if the CPU is slow executing the * loop for some reason (an NMI, for * example). For this reason we will * if multiple measurements are to be * performed trust the higher delay * (lower frequency returned).
*/
OUTB (nc_stest1, 0); /* make sure clock doubler is OFF */
OUTW (nc_sien , 0); /* mask all scsi interrupts */
(void) INW (nc_sist); /* clear pending scsi interrupt */
OUTB (nc_dien , 0); /* mask all dma interrupts */
(void) INW (nc_sist); /* another one, just to be sure :) */
OUTB (nc_scntl3, 4); /* set pre-scaler to divide by 3 */
OUTB (nc_stime1, 0); /* disable general purpose timer */
OUTB (nc_stime1, gen); /* set to nominal delay of 1<<gen * 125us */ while (!(INW(nc_sist) & GEN) && ms++ < 100000) { for (count = 0; count < 10; count ++)
udelay(100); /* count ms */
}
OUTB (nc_stime1, 0); /* disable general purpose timer */ /* * set prescaler to divide by whatever 0 means * 0 ought to choose divide by 2, but appears * to set divide by 3.5 mode in my 53c810 ...
*/
OUTB (nc_scntl3, 0);
if (bootverbose >= 2)
printk ("%s: Delay (GEN=%d): %u msec\n", ncr_name(np), gen, ms); /* * adjust for prescaler, and convert into KHz
*/ return ms ? ((1 << gen) * 4340) / ms : 0;
}
/* ** True with 875 or 895 with clock multiplier selected
*/ if (mult > 1 && (stest1 & (DBLEN+DBLSEL)) == DBLEN+DBLSEL) { if (bootverbose >= 2)
printk ("%s: clock multiplier found\n", ncr_name(np));
np->multiplier = mult;
}
/* ** If multiplier not found or scntl3 not 7,5,3, ** reset chip and get frequency from general purpose timer. ** Otherwise trust scntl3 BIOS setting.
*/ if (np->multiplier != mult || (scntl3 & 7) < 3 || !(scntl3 & 1)) { unsigned f2;
ncr_chip_reset(np, 5);
(void) ncrgetfreq (np, 11); /* throw away first result */
f1 = ncrgetfreq (np, 11);
f2 = ncrgetfreq (np, 11);
/* ** Select queue depth from driver setup. ** Donnot use more than configured by user. ** Use at least 2. ** Donnot use more than our maximum.
*/
numtags = device_queue_depth(np->unit, device->id, device->lun); if (numtags > tp->usrtags)
numtags = tp->usrtags; if (!device->tagged_supported)
numtags = 1;
depth_to_use = numtags; if (depth_to_use < 2)
depth_to_use = 2; if (depth_to_use > MAX_TAGS)
depth_to_use = MAX_TAGS;
scsi_change_queue_depth(device, depth_to_use);
/* ** Since the queue depth is not tunable under Linux, ** we need to know this value in order not to ** announce stupid things to user. ** ** XXX(hch): As of Linux 2.6 it certainly _is_ tunable.. ** In fact we just tuned it, or did I miss ** something important? :)
*/ if (lp) {
lp->numtags = lp->maxtags = numtags;
lp->scdev_depth = depth_to_use;
}
ncr_setup_tags (np, device);
/* * If the mid-level driver told us reset is synchronous, it seems * that we must call the done() callback for the involved command, * even if this command was not queued to the low-level driver, * before returning SUCCESS.
*/
/* ** Scsi command waiting list management. ** ** It may happen that we cannot insert a scsi command into the start queue, ** in the following circumstances. ** Too few preallocated ccb(s), ** maxtags < cmd_per_lun of the Linux host control block, ** etc... ** Such scsi commands are inserted into a waiting list. ** When a scsi command complete, we try to requeue the commands of the ** waiting list.
*/
if (device->slot.base_v)
np->vaddr = device->slot.base_v; else
np->vaddr = ioremap(device->slot.base_c, 128);
if (!np->vaddr) {
printk(KERN_ERR "%s: can't map memory mapped IO region\n",ncr_name(np)); goto attach_error;
} else { if (bootverbose > 1)
printk(KERN_INFO "%s: using memory mapped IO at virtual address 0x%lx\n", ncr_name(np), (u_long) np->vaddr);
}
/* Make the controller's registers available. Now the INB INW INL * OUTB OUTW OUTL macros can be used safely.
*/
np->reg = (struct ncr_reg __iomem *)np->vaddr;
/* Do chip dependent initialization. */
ncr_prepare_setting(np);
if (np->paddr2 && sizeof(struct script) > 4096) {
np->paddr2 = 0;
printk(KERN_WARNING "%s: script too large, NOT using on chip RAM.\n",
ncr_name(np));
}
instance->max_channel = 0;
instance->this_id = np->myaddr;
instance->max_id = np->maxwide ? 16 : 8;
instance->max_lun = SCSI_NCR_MAX_LUN;
instance->base = (unsignedlong) np->reg;
instance->irq = device->slot.irq;
instance->unique_id = device->slot.base;
instance->dma_channel = 0;
instance->cmd_per_lun = MAX_TAGS;
instance->can_queue = (MAX_START-4); /* This can happen if you forget to call ncr53c8xx_init from
* your module_init */
BUG_ON(!ncr53c8xx_transport_template);
instance->transportt = ncr53c8xx_transport_template;
/* Patch script to physical addresses */
ncr_script_fill(&script0, &scripth0);
/* * Look for the target control block of this nexus. * For i = 0 to 3 * JUMP ^ IFTRUE (MASK (i, 3)), @(next_lcb)
*/ for (i = 0 ; i < 4 ; i++) {
np->jump_tcb[i].l_cmd =
cpu_to_scr((SCR_JUMP ^ IFTRUE (MASK (i, 3))));
np->jump_tcb[i].l_paddr =
cpu_to_scr(NCB_SCRIPTH_PHYS (np, bad_target));
}
ncr_chip_reset(np, 100);
/* Now check the cache handling of the chipset. */
if (ncr_snooptest(np)) {
printk(KERN_ERR "CACHE INCORRECTLY CONFIGURED.\n"); goto attach_error;
}
/* Install the interrupt handler. */
np->irq = device->slot.irq;
/* Initialize the fixed part of the default ccb. */
ncr_init_ccb(np, np->ccb);
/* * After SCSI devices have been opened, we cannot reset the bus * safely, so we do it here. Interrupt handler does the real work. * Process the reset exception if interrupts are not enabled yet. * Then enable disconnects.
*/
spin_lock_irqsave(&np->smp_lock, flags); if (ncr_reset_scsi_bus(np, 0, driver_setup.settle_delay) != 0) {
printk(KERN_ERR "%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np));
/* * The middle-level SCSI driver does not wait for devices to settle. * Wait synchronously if more than 2 seconds.
*/ if (driver_setup.settle_delay > 2) {
printk(KERN_INFO "%s: waiting %d seconds for scsi devices to settle...\n",
ncr_name(np), driver_setup.settle_delay);
mdelay(1000 * driver_setup.settle_delay);
}
/* start the timeout daemon */
np->lasttime=0;
ncr_timeout (np);
/* use SIMPLE TAG messages by default */ #ifdef SCSI_NCR_ALWAYS_SIMPLE_TAG
np->order = SIMPLE_QUEUE_TAG; #endif
spin_unlock_irqrestore(&np->smp_lock, flags);
return instance;
attach_error: if (!instance) return NULL;
printk(KERN_INFO "%s: detaching...\n", ncr_name(np)); if (!np) goto unregister; if (np->scripth0)
m_free_dma(np->scripth0, sizeof(struct scripth), "SCRIPTH"); if (np->script0)
m_free_dma(np->script0, sizeof(struct script), "SCRIPT"); if (np->ccb)
m_free_dma(np->ccb, sizeof(struct ccb), "CCB");
m_free_dma(np, sizeof(struct ncb), "NCB");
host_data->ncb = NULL;
switch (np->scsi_mode) { case SMODE_SE:
type = SPI_SIGNAL_SE; break; case SMODE_HVD:
type = SPI_SIGNAL_HVD; break; default:
type = SPI_SIGNAL_UNKNOWN; break;
}
spi_signalling(shost) = type;
}
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.214Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-04-26)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.