?? ncr.c
字號:
u_char rv_stest2; /*----------------------------------------------- ** Link to the generic SCSI driver **----------------------------------------------- */ struct scsi_link sc_link; /*----------------------------------------------- ** Job control **----------------------------------------------- ** ** Commands from user */ struct usrcmd user; u_char order; /* ** Target data */ struct tcb target[MAX_TARGET]; /* ** Start queue. */ u_int32_t squeue [MAX_START]; u_short squeueput; u_short actccbs; /* ** Timeout handler */ u_long heartbeat; u_short ticks; u_short latetime; u_long lasttime;#ifdef __FreeBSD__ struct callout_handle timeout_ch;#endif /*----------------------------------------------- ** Debug and profiling **----------------------------------------------- ** ** register dump */ struct ncr_reg regdump; struct timeval regtime; /* ** Profiling data */ struct profile profile; u_long disc_phys; u_long disc_ref;#ifdef __OpenBSD__ /* ** The global header. ** Accessible to both the host and the ** script-processor. ** We assume it is cache line size aligned. */ struct head header;#endif /* ** The global control block. ** It's used only during the configuration phase. ** A target control block will be created ** after the first successful transfer. ** It is allocated separately in order to ensure ** cache line size alignment. */ struct ccb *ccb; /* ** message buffers. ** Should be longword aligned, ** because they're written with a ** COPY script command. */ u_char msgout[8]; u_char msgin [8]; u_int32_t lastmsg; /* ** Buffer for STATUS_IN phase. */ u_char scratch; /* ** controller chip dependent maximal transfer width. */ u_char maxwide; /* ** option for M_IDENTIFY message: enables disconnecting */ u_char disc;#if defined(NCR_IOMAPPED) && !defined(__OpenBSD__) /* ** address of the ncr control registers in io space */ u_short port;#endif};#define NCB_SCRIPT_PHYS(np,lbl) (np->p_script + offsetof (struct script, lbl))#define NCB_SCRIPTH_PHYS(np,lbl) (np->p_scripth + offsetof (struct scripth,lbl))/*==========================================================****** 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!****----------------------------------------------------------*//*** Script fragments which are loaded into the on-board RAM** of 825A, 875 and 895 chips.*/struct script { ncrcmd start [ 7]; ncrcmd start0 [ 2]; ncrcmd start1 [ 3]; ncrcmd startpos [ 1]; ncrcmd trysel [ 8]; ncrcmd skip [ 8]; ncrcmd skip2 [ 3]; ncrcmd idle [ 2]; ncrcmd select [ 22]; ncrcmd prepare [ 4]; ncrcmd loadpos [ 14]; ncrcmd prepare2 [ 24]; ncrcmd setmsg [ 5]; ncrcmd clrack [ 2]; ncrcmd dispatch [ 33]; ncrcmd no_data [ 17]; ncrcmd checkatn [ 10]; ncrcmd command [ 15]; ncrcmd status [ 27]; ncrcmd msg_in [ 26]; ncrcmd msg_bad [ 6]; ncrcmd complete [ 13]; ncrcmd cleanup [ 12]; ncrcmd cleanup0 [ 11]; ncrcmd signal [ 10]; ncrcmd save_dp [ 5]; ncrcmd restore_dp [ 5]; ncrcmd disconnect [ 12]; ncrcmd disconnect0 [ 5]; ncrcmd disconnect1 [ 23]; ncrcmd msg_out [ 9]; ncrcmd msg_out_done [ 7]; ncrcmd badgetcc [ 6]; ncrcmd reselect [ 8]; ncrcmd reselect1 [ 8]; ncrcmd reselect2 [ 8]; ncrcmd resel_tmp [ 5]; ncrcmd resel_lun [ 18]; ncrcmd resel_tag [ 24]; ncrcmd data_in [MAX_SCATTER * 4 + 7]; ncrcmd data_out [MAX_SCATTER * 4 + 7];};/*** Script fragments which stay in main memory for all chips.*/struct scripth { ncrcmd tryloop [MAX_START*5+2]; ncrcmd msg_parity [ 6]; ncrcmd msg_reject [ 8]; ncrcmd msg_ign_residue [ 32]; ncrcmd msg_extended [ 18]; ncrcmd msg_ext_2 [ 18]; ncrcmd msg_wdtr [ 27]; ncrcmd msg_ext_3 [ 18]; ncrcmd msg_sdtr [ 27]; ncrcmd msg_out_abort [ 10]; ncrcmd getcc [ 4]; ncrcmd getcc1 [ 5];#ifdef NCR_GETCC_WITHMSG ncrcmd getcc2 [ 33];#else ncrcmd getcc2 [ 14];#endif ncrcmd getcc3 [ 10]; ncrcmd aborttag [ 4]; ncrcmd abort [ 22]; ncrcmd snooptest [ 9]; ncrcmd snoopend [ 2];};/*==========================================================****** Function headers.******==========================================================*/#ifdef KERNELstatic void ncr_alloc_ccb (ncb_p np, u_long target, u_long lun);static void ncr_complete (ncb_p np, ccb_p cp);static int ncr_delta (struct timeval * from, struct timeval * to);static void ncr_exception (ncb_p np);static void ncr_free_ccb (ncb_p np, ccb_p cp, int flags);static void ncr_selectclock (ncb_p np, u_char scntl3);static void ncr_getclock (ncb_p np, u_char multiplier);static ccb_p ncr_get_ccb (ncb_p np, u_long flags, u_long t,u_long l);static void ncr_init (ncb_p np, char * msg, u_long code);#ifdef __OpenBSD__static int ncr_intr (void *vnp);#elsestatic void ncr_intr (void *vnp);static u_int32_t ncr_info (int unit);#endif /* !__OpenBSD__ */ static void ncr_int_ma (ncb_p np, u_char dstat);static void ncr_int_sir (ncb_p np);static void ncr_int_sto (ncb_p np);#ifdef __OpenBSD__static u_long ncr_lookup (char* id);#endif#ifndef PMONstatic void ncr_min_phys (struct buf *bp);#endifstatic void ncr_negotiate (struct ncb* np, struct tcb* tp);static void ncr_opennings (ncb_p np, lcb_p lp, struct scsi_xfer * xp);static void ncb_profile (ncb_p np, ccb_p cp);static 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 *scrh);static int ncr_scatter (ncb_p np, struct dsb* phys, vm_offset_t vaddr, vm_size_t datalen);static void ncr_setmaxtags (tcb_p tp, u_long usrtags);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_settags (tcb_p tp, lcb_p lp, u_long usrtags);static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack);static int ncr_show_msg (u_char * msg);#ifndef PMONstatic int ncr_snooptest (ncb_p np);#endifstatic int32_t ncr_start (struct scsi_xfer *xp);static void ncr_timeout (void *arg);static void ncr_usercmd (ncb_p np);static void ncr_wakeup (ncb_p np, u_long code);#ifdef __OpenBSD__#ifdef __BROKEN_INDIRECT_CONFIGstatic int ncr_probe (struct device *, void *, void *);#elsestatic int ncr_probe (struct device *, struct cfdata *, void *);#endifstatic void ncr_attach (struct device *, struct device *, void *);#else /* !__OpenBSD__ */static char* ncr_probe (pcici_t tag, pcidi_t type);static void ncr_attach (pcici_t tag, int unit);#endif /* __OpenBSD__ */#endif /* KERNEL *//*==========================================================****** Global static data.******==========================================================*/#if 0static char ident[] = "\n$OpenBSD: ncr.c,v 1.46 1999/06/06 23:17:24 deraadt Exp $\n";#endifstatic const u_long ncr_version = NCR_VERSION * 11 + (u_long) sizeof (struct ncb) * 7 + (u_long) sizeof (struct ccb) * 5 + (u_long) sizeof (struct lcb) * 3 + (u_long) sizeof (struct tcb) * 2;#ifdef KERNEL#ifndef __OpenBSD__static const int nncr=MAX_UNITS; /* XXX to be replaced by SYSCTL */ncb_p ncrp [MAX_UNITS]; /* XXX to be replaced by SYSCTL */#endif /* !__OpenBSD__ */static int ncr_debug = SCSI_NCR_DEBUG;#ifndef __OpenBSD__SYSCTL_INT(_debug, OID_AUTO, ncr_debug, CTLFLAG_RW, &ncr_debug, 0, "");#endif /* !__OpenBSD__ */static int ncr_cache; /* to be aligned _NOT_ static *//*==========================================================****** Global static data: auto configure******==========================================================*/#define NCR_810_ID (0x00011000ul)#define NCR_815_ID (0x00041000ul)#define NCR_820_ID (0x00021000ul)#define NCR_825_ID (0x00031000ul)#define NCR_860_ID (0x00061000ul)#define NCR_875_ID (0x000f1000ul)#define NCR_875_ID2 (0x008f1000ul)#define NCR_885_ID (0x000d1000ul)#define NCR_895_ID (0x000c1000ul)#define NCR_895A_ID (0x00121000ul)#define NCR_896_ID (0x000b1000ul)#define NCR_1510_ID (0x00101000ul)#define NCR_1510D_ID (0x000a1000ul)#ifdef __OpenBSD__struct cfattach ncr_ca = { sizeof(struct ncb), ncr_probe, ncr_attach};struct cfdriver ncr_cd = { NULL, "ncr", DV_DULL};#else /* !__OpenBSD__ */static u_long ncr_count;static struct pci_device ncr_device = { "ncr", ncr_probe, ncr_attach, &ncr_count, NULL};DATA_SET (pcidevice_set, ncr_device);#endif /* !__OpenBSD__ */static struct scsi_adapter ncr_switch ={ ncr_start,#ifndef PMON ncr_min_phys,#else NULL,#endif 0, 0,#ifndef __OpenBSD__ ncr_info, "ncr",#endif /* !__OpenBSD__ */};static struct scsi_device ncr_dev ={ NULL, /* Use default error handler */ NULL, /* have a queue, served by this */ NULL, /* have no async handler */ NULL, /* Use default 'done' routine */#ifndef __OpenBSD__ "ncr",#endif /* !__OpenBSD__ */};#ifdef __OpenBSD__#define ncr_name(np) (np->sc_dev.dv_xname)#else /* !__OpenBSD__ */static char *ncr_name (ncb_p np){ static char name[10]; sprintf(name, "ncr%d", np->unit); return (name);}#endif/*==========================================================****** 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#define RELOC_KVAR 0x70000000#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)))#define KVAR(which) (RELOC_KVAR | (which))#define KVAR_TIME_TV_SEC (0)#define KVAR_TIME (1)#define KVAR_NCR_CACHE (2)#define SCRIPT_KVAR_FIRST (0)#define SCRIPT_KVAR_LAST (3)/* * Kernel variables referenced in the scripts. * THESE MUST ALL BE ALIGNED TO A 4-BYTE BOUNDARY. */#ifdef __OpenBSD__static unsigned long script_kvars[] = { (unsigned long)&time.tv_sec, (unsigned long)&time, (unsigned long)&ncr_cache,};#elsestatic void *script_kvars[] = { &time.tv_sec, &time, &ncr_cache };#endifstatic struct script script0 = {/*--------------------------< START >-----------------------*/ { /* ** Claim to be still alive ... */ SCR_COPY (sizeof (((struct ncb *)0)->heartbeat)), KVAR (KVAR_TIME_TV_SEC), NADDR (heartbeat), /* ** Make data structure address invalid. ** clear SIGP. */ SCR_LOAD_REG (dsa, 0xff), 0, SCR_FROM_REG (ctest2), 0,}/*-------------------------< START0 >----------------------*/,{ /* ** Hook for interrupted GetConditionCode. ** Will be patched to ... IFTRUE by ** the interrupt handler. */ SCR_INT ^ IFFALSE (0), SIR_SENSE_RESTART,}/*-------------------------< START1 >----------------------*/,{ /* ** Hook for stalled start queue. ** Will be patched to IFTRUE by the interrupt handler. */ SCR_INT ^ IFFALSE (0), SIR_STALL_RESTART, /* ** 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),}/*-------------------------< TRYSEL >----------------------*/,{ /* ** Now: ** DSA: Address of a Data Structure ** or Address of the IDLE-Label. ** ** TEMP: Address of a script, which tries to ** start the NEXT entry. ** ** Save the TEMP register into the SCRATCHA register. ** Then copy the DSA to TEMP and RETURN. ** This is kind of an indirect jump. ** (The script processor has NO stack, so the ** CALL is actually a jump and link, and the ** RETURN is an indirect jump.) ** ** If the slot was empty, DSA contains the address ** of the IDLE part of this script. The processor ** jumps to IDLE and waits for a reselect. ** It will wake up and try the same slot again ** after the SIGP bit becomes set by the host. ** ** If the slot was not empty, DSA contains ** the address of the phys-part of a ccb. ** The processor jumps to this address. ** phys starts with head, ** head starts with launch, ** so actually the processor jumps to ** the lauch part. ** If the entry is scheduled for execution, ** then launch contains a jump to SELECT. ** If it's not scheduled, it contains a jump to IDLE. */ SCR_COPY (4), RADDR (temp), RADDR (scratcha), SCR_COPY (4), RADDR (dsa), RADDR (temp), SCR_RETURN, 0}/*-------------------------< SKIP >------------------------*/,{ /* ** This entry has been canceled. ** Next time use the next slot. */ SCR_COPY (4), RADDR (scratcha), PADDR (startpos), /* ** patch the launch field. ** should look like an idle process. */ SCR_COPY_F (4), RADDR (dsa), PADDR (skip2), SCR_COPY (8), PADDR (idle),}/*-------------------------< SKIP2 >-----------------------*/,{ 0, SCR_JUMP, PADDR(start),}/*-------------------------< IDLE >------------------------*/,{ /* ** Nothing to do? ** Wait for reselect. */ SCR_JUMP, PADDR(reselect),}/*-------------------------< 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, 0xff), 0,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -