📄 ncr53c8xx.c
字号:
static void ncr_int_sto (ncb_p np);static u_long ncr_lookup (char* id);static void ncr_negotiate (struct ncb* np, struct tcb* tp);static int ncr_prepare_nego(ncb_p np, ccb_p cp, u_char *msgptr);#ifdef SCSI_NCR_INTEGRITY_CHECKINGstatic int ncr_ic_nego(ncb_p np, ccb_p cp, Scsi_Cmnd *cmd, u_char *msgptr);#endif#ifdef SCSI_NCR_PROFILE_SUPPORTstatic void ncb_profile (ncb_p np, ccb_p cp);#endifstatic void ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len);static void ncr_script_fill (struct script * scr, struct scripth * scripth);static int ncr_scatter (ncb_p np, ccb_p cp, Scsi_Cmnd *cmd);static void ncr_getsync (ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p);static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer);static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln);static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack);static int ncr_show_msg (u_char * msg);static void ncr_print_msg (ccb_p cp, char *label, u_char *msg);static int ncr_snooptest (ncb_p np);static void ncr_timeout (ncb_p np);static void ncr_wakeup (ncb_p np, u_long code);static void ncr_wakeup_done (ncb_p np);static void ncr_start_next_ccb (ncb_p np, lcb_p lp, int maxn);static void ncr_put_start_queue(ncb_p np, ccb_p cp);static void ncr_start_reset (ncb_p np);static int ncr_reset_scsi_bus (ncb_p np, int enab_int, int settle_delay);#ifdef SCSI_NCR_USER_COMMAND_SUPPORTstatic void ncr_usercmd (ncb_p np);#endifstatic int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device);static void insert_into_waiting_list(ncb_p np, Scsi_Cmnd *cmd);static Scsi_Cmnd *retrieve_from_waiting_list(int to_remove, ncb_p np, Scsi_Cmnd *cmd);static void process_waiting_list(ncb_p np, int sts);#define remove_from_waiting_list(np, cmd) \ retrieve_from_waiting_list(1, (np), (cmd))#define requeue_waiting_list(np) process_waiting_list((np), DID_OK)#define reset_waiting_list(np) process_waiting_list((np), DID_RESET)static inline char *ncr_name (ncb_p np){ return np->inst_name;}/*==========================================================****** 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.****----------------------------------------------------------*/#define RELOC_SOFTC 0x40000000#define RELOC_LABEL 0x50000000#define RELOC_REGISTER 0x60000000#if 0#define RELOC_KVAR 0x70000000#endif#define RELOC_LABELH 0x80000000#define RELOC_MASK 0xf0000000#define NADDR(label) (RELOC_SOFTC | offsetof(struct ncb, label))#define PADDR(label) (RELOC_LABEL | offsetof(struct script, label))#define PADDRH(label) (RELOC_LABELH | offsetof(struct scripth, label))#define RADDR(label) (RELOC_REGISTER | REG(label))#define FADDR(label,ofs)(RELOC_REGISTER | ((REG(label))+(ofs)))#if 0#define KVAR(which) (RELOC_KVAR | (which))#endif#if 0#define SCRIPT_KVAR_JIFFIES (0)#define SCRIPT_KVAR_FIRST SCRIPT_KVAR_JIFFIES#define SCRIPT_KVAR_LAST SCRIPT_KVAR_JIFFIES/* * Kernel variables referenced in the scripts. * THESE MUST ALL BE ALIGNED TO A 4-BYTE BOUNDARY. */static void *script_kvars[] __initdata = { (void *)&jiffies };#endifstatic struct 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) */ SCR_CLR (SCR_TRG), 0, SCR_LOAD_REG (HS_REG, HS_SELECTING), 0, /* ** 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 looses 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 M_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), /* ** 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 M_X_SYNC_REQ 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, M_NOOP), 0, SCR_COPY (1), RADDR (scratcha), NADDR (msgout),#if 0 SCR_COPY (1), RADDR (scratcha), NADDR (msgin),#endif /* ** Anticipate the COMMAND phase. ** This is the normal case for initial selection. */ SCR_JUMP ^ IFFALSE (WHEN (SCR_COMMAND)), PADDR (dispatch),}/*-------------------------< COMMAND >--------------------*/,{#ifdef SCSI_NCR_PROFILE_SUPPORT /* ** ... set a timestamp ... */ SCR_COPY (sizeof (u_long)), NADDR (ktime), NADDR (header.stamp.command),#endif /* ** ... 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 README.ncr53c8xx 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),}/*-------------------------< CLRACK >----------------------*/,{ /* ** Terminate possible pending message phase. */ SCR_CLR (SCR_ACK), 0, 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 >--------------------*/,{#ifdef SCSI_NCR_PROFILE_SUPPORT /* ** set the timestamp. */ SCR_COPY (sizeof (u_long)), NADDR (ktime), NADDR (header.stamp.status),#endif /* ** 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 (M_COMPLETE)), PADDR (complete), SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)), PADDR (disconnect), SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)), PADDR (save_dp), SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)), PADDR (restore_dp), SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)), PADDRH (msg_extended), SCR_JUMP ^ IFTRUE (DATA (M_NOOP)), PADDR (clrack), SCR_JUMP ^ IFTRUE (DATA (M_REJECT)), PADDRH (msg_reject), SCR_JUMP ^ IFTRUE (DATA (M_IGN_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, M_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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -