ncr53c8xx.c
来自「linux 内核源代码」· C语言 代码 · 共 2,376 行 · 第 1/5 页
C
2,376 行
/*** Asynchronous pre-scaler (ns). Shall be 40*/ #ifndef SCSI_NCR_MIN_ASYNC#define SCSI_NCR_MIN_ASYNC (40)#endif/*** 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 ...*/#ifdef SCSI_NCR_CAN_QUEUE#define MAX_START (SCSI_NCR_CAN_QUEUE + 4)#else#define MAX_START (MAX_TARGET + 7 * MAX_TAGS)#endif/*** 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.*/#define MAX_SCATTER (SCSI_NCR_MAX_SCATTER)#if (MAX_SCATTER > 80)#define MAX_SCATTERL 80#define MAX_SCATTERH (MAX_SCATTER - MAX_SCATTERL)#else#define MAX_SCATTERL (MAX_SCATTER-1)#define MAX_SCATTERH 1#endif/*** other*/#define NCR_SNOOP_TIMEOUT (1000000)/*** Other definitions*/#define ScsiResult(host_code, scsi_code) (((host_code) << 16) + ((scsi_code) & 0x7f))#define initverbose (driver_setup.verbose)#define bootverbose (np->verbose)/*==========================================================**** Command control block states.****==========================================================*/#define HS_IDLE (0)#define HS_BUSY (1)#define HS_NEGOTIATE (2) /* sync/wide data transfer*/#define HS_DISCONNECT (3) /* Disconnected by target */#define HS_DONEMASK (0x80)#define HS_COMPLETE (4|HS_DONEMASK)#define HS_SEL_TIMEOUT (5|HS_DONEMASK) /* Selection timeout */#define HS_RESET (6|HS_DONEMASK) /* SCSI reset */#define HS_ABORTED (7|HS_DONEMASK) /* Transfer aborted */#define HS_TIMEOUT (8|HS_DONEMASK) /* Software timeout */#define HS_FAIL (9|HS_DONEMASK) /* SCSI or PCI bus errors */#define HS_UNEXPECTED (10|HS_DONEMASK)/* Unexpected disconnect *//*** Invalid host status values used by the SCRIPTS processor ** when the nexus is not fully identified.** Shall never appear in a CCB.*/#define HS_INVALMASK (0x40)#define HS_SELECTING (0|HS_INVALMASK)#define HS_IN_RESELECT (1|HS_INVALMASK)#define HS_STARTING (2|HS_INVALMASK)/*** Flags set by the SCRIPT processor for commands ** that have been skipped.*/#define HS_SKIPMASK (0x20)/*==========================================================**** Software Interrupt Codes****==========================================================*/#define SIR_BAD_STATUS (1)#define SIR_XXXXXXXXXX (2)#define SIR_NEGO_SYNC (3)#define SIR_NEGO_WIDE (4)#define SIR_NEGO_FAILED (5)#define SIR_NEGO_PROTO (6)#define SIR_REJECT_RECEIVED (7)#define SIR_REJECT_SENT (8)#define SIR_IGN_RESIDUE (9)#define SIR_MISSING_SAVE (10)#define SIR_RESEL_NO_MSG_IN (11)#define SIR_RESEL_NO_IDENTIFY (12)#define SIR_RESEL_BAD_LUN (13)#define SIR_RESEL_BAD_TARGET (14)#define SIR_RESEL_BAD_I_T_L (15)#define SIR_RESEL_BAD_I_T_L_Q (16)#define SIR_DONE_OVERFLOW (17)#define SIR_INTFLY (18)#define SIR_MAX (18)/*==========================================================**** Extended error codes.** xerr_status field of struct ccb.****==========================================================*/#define XE_OK (0)#define XE_EXTRA_DATA (1) /* unexpected data phase */#define XE_BAD_PHASE (2) /* illegal phase (4/5) *//*==========================================================**** Negotiation status.** nego_status field of struct ccb.****==========================================================*/#define NS_NOCHANGE (0)#define NS_SYNC (1)#define NS_WIDE (2)#define NS_PPR (4)/*==========================================================**** Misc.****==========================================================*/#define CCB_MAGIC (0xf2691ad2)/*==========================================================**** Declaration of structs.****==========================================================*/static struct scsi_transport_template *ncr53c8xx_transport_template = NULL;struct tcb;struct lcb;struct ccb;struct ncb;struct script;struct link { ncrcmd l_cmd; ncrcmd l_paddr;};struct usrcmd { u_long target; u_long lun; u_long data; u_long cmd;};#define UC_SETSYNC 10#define UC_SETTAGS 11#define UC_SETDEBUG 12#define UC_SETORDER 13#define UC_SETWIDE 14#define UC_SETFLAG 15#define UC_SETVERBOSE 17#define UF_TRACE (0x01)#define UF_NODISC (0x02)#define UF_NOSCAN (0x04)/*========================================================================**** 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; /*---------------------------------------------------------------- ** negotiation of wide and synch transfer and device quirks. **---------------------------------------------------------------- */#ifdef SCSI_NCR_BIG_ENDIAN/*0*/ u16 period;/*2*/ u_char sval;/*3*/ u_char minsync;/*0*/ u_char wval;/*1*/ u_char widedone;/*2*/ u_char quirks;/*3*/ u_char maxoffs;#else/*0*/ u_char minsync;/*1*/ u_char sval;/*2*/ u16 period;/*0*/ u_char maxoffs;/*1*/ u_char quirks;/*2*/ u_char widedone;/*3*/ u_char wval;#endif /* 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*//*** Last four bytes (script)*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?