From 19999945980d3554ff5326874707c88a83b15413 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 1 Dec 1997 18:58:50 +0000 Subject: Newer ncr driver from NetBSD minus the scsipi stuff and with changes to make it diff usefully against the FreeBSD driver. Tested on alpha and i386, not tested on powerpc. --- sys/dev/pci/ncr.c | 3213 ++++++++++++++++++++++++++++++-------------------- sys/dev/pci/ncrreg.h | 665 +++++++++++ 2 files changed, 2616 insertions(+), 1262 deletions(-) create mode 100644 sys/dev/pci/ncrreg.h (limited to 'sys/dev/pci') diff --git a/sys/dev/pci/ncr.c b/sys/dev/pci/ncr.c index fb74a3bb21e..b2458859639 100644 --- a/sys/dev/pci/ncr.c +++ b/sys/dev/pci/ncr.c @@ -1,9 +1,11 @@ -/* $OpenBSD: ncr.c,v 1.31 1997/10/11 11:05:27 pefo Exp $ */ -/* $NetBSD: ncr.c,v 1.56 1997/03/04 21:42:34 mycroft Exp $ */ +/* $OpenBSD: ncr.c,v 1.32 1997/12/01 18:58:48 millert Exp $ */ +/* $NetBSD: ncr.c,v 1.63 1997/09/23 02:39:15 perry Exp $ */ /************************************************************************** ** -** Device driver for the NCR 53C810 PCI-SCSI-Controller. +** Id: ncr.c,v 1.112 1997/11/07 09:20:56 phk Exp +** +** Device driver for the NCR 53C8xx PCI-SCSI-Controller. ** ** FreeBSD / NetBSD / OpenBSD ** @@ -55,10 +57,6 @@ #define NCR_GETCC_WITHMSG -#ifdef __OpenBSD__ -#define __BROKEN_INDIRECT_CONFIG -#endif - #if defined (__FreeBSD__) && defined(KERNEL) #include "opt_ncr.h" #endif /* defined (__FreeBSD__) && defined(KERNEL) */ @@ -90,13 +88,35 @@ #endif /* SCSI_NCR_MYADDR */ /* -** The maximal synchronous frequency in kHz. +** The default synchronous period factor ** (0=asynchronous) +** If maximum synchronous frequency is defined, use it instead. +*/ + +#ifndef SCSI_NCR_MAX_SYNC + +#ifndef SCSI_NCR_DFLT_SYNC +#define SCSI_NCR_DFLT_SYNC (12) +#endif /* SCSI_NCR_DFLT_SYNC */ + +#else + +#if SCSI_NCR_MAX_SYNC == 0 +#define SCSI_NCR_DFLT_SYNC 0 +#else +#define SCSI_NCR_DFLT_SYNC (250000 / SCSI_NCR_MAX_SYNC) +#endif + +#endif + +/* +** The minimal asynchronous pre-scaler period (ns) +** Shall be 40. */ -#ifndef SCSI_NCR_MAX_SYNC -#define SCSI_NCR_MAX_SYNC (10000) -#endif /* SCSI_NCR_MAX_SYNC */ +#ifndef SCSI_NCR_MIN_ASYNC +#define SCSI_NCR_MIN_ASYNC (40) +#endif /* SCSI_NCR_MIN_ASYNC */ /* ** The maximal bus with (in log2 byte) @@ -160,10 +180,10 @@ /* ** The maximum transfer length (should be >= 64k). -** MUST NOT be greater than (MAX_SCATTER-1) * NBPG. +** MUST NOT be greater than (MAX_SCATTER-1) * PAGE_SIZE. */ -#define MAX_SIZE ((MAX_SCATTER-1) * (long) NBPG) +#define MAX_SIZE ((MAX_SCATTER-1) * (long) PAGE_SIZE) /* ** other @@ -178,39 +198,35 @@ **========================================================== */ -#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ #ifdef _KERNEL #define KERNEL #endif +#else +#include #endif #define offsetof(type, member) ((size_t)(&((type *)0)->member)) -#include #include #include -#include #ifdef KERNEL #include #include #include #include -#if defined(__NetBSD__) || defined(__OpenBSD__) -#define bootverbose 1 -#endif -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) +#ifndef __OpenBSD__ #include #include #endif #include -#include #include #include #endif /* KERNEL */ -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) +#ifndef __OpenBSD__ #include #include #include @@ -218,18 +234,34 @@ #include #include #include -#include +#include #include #include -#if !defined(__alpha__) && !defined(__powerpc__) +#ifndef __alpha__ #define DELAY(x) delay(x) #endif -#endif /* __NetBSD__ || __OpenBSD__ */ - #include +#endif /* __OpenBSD__ */ + #include -#if (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(__alpha__) +#ifdef __OpenBSD__ /* XXX */ +#define __BROKEN_INDIRECT_CONFIG +#undef PAGE_SIZE +#undef PAGE_MASK +#define PAGE_SIZE NBPG +#define PAGE_MASK (NBPG-1) +#endif + +#ifdef __OpenBSD__ +#ifdef NCR_VERBOSE +#define bootverbose NCR_VERBOSE +#else +#define bootverbose 0 +#endif +#endif + +#if defined(__OpenBSD__) && defined(__alpha__) /* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */ #undef vtophys #define vtophys(va) alpha_XXX_dmamap((vm_offset_t)(va)) @@ -298,58 +330,50 @@ **========================================================== */ -#if defined(__NetBSD__) || defined(__OpenBSD__) - -#ifdef NCR_IOMAPPED +#ifdef __OpenBSD__ #define INB(r) \ INB_OFF(offsetof(struct ncr_reg, r)) #define INB_OFF(o) \ - bus_space_read_1 (np->sc_memt, np->sc_bah, (o)) + bus_space_read_1 (np->sc_st, np->sc_sh, (o)) #define INW(r) \ - bus_space_read_2 (np->sc_memt, np->sc_bah, offsetof(struct ncr_reg, r)) + bus_space_read_2 (np->sc_st, np->sc_sh, offsetof(struct ncr_reg, r)) #define INL(r) \ INL_OFF(offsetof(struct ncr_reg, r)) #define INL_OFF(o) \ - bus_space_read_4 (np->sc_memt, np->sc_bah, (o)) + bus_space_read_4 (np->sc_st, np->sc_sh, (o)) #define OUTB(r, val) \ - bus_space_write_1 (np->sc_memt, np->sc_bah, offsetof(struct ncr_reg, r), (val)) + bus_space_write_1 (np->sc_st, np->sc_sh, offsetof(struct ncr_reg, r), (val)) #define OUTW(r, val) \ - bus_space_write_2 (np->sc_memt, np->sc_bah, offsetof(struct ncr_reg, r), (val)) + bus_space_write_2 (np->sc_st, np->sc_sh, offsetof(struct ncr_reg, r), (val)) #define OUTL(r, val) \ OUTL_OFF(offsetof(struct ncr_reg, r), (val)) #define OUTL_OFF(o, val) \ - bus_space_write_4 (np->sc_memt, np->sc_bah, (o), (val)) + bus_space_write_4 (np->sc_st, np->sc_sh, (o), (val)) -#else +#define READSCRIPT_OFF(base, off) \ + SCR_BO(base ? *((int32_t *)((char *)base + (off))) : \ + bus_space_read_4 (np->ram_tag, np->ram_handle, off)) -#define INB(r) \ - INB_OFF(offsetof(struct ncr_reg, r)) -#define INB_OFF(o) \ - bus_space_read_1 (np->sc_memt, np->sc_bah, (o)) -#define INW(r) \ - bus_space_read_2 (np->sc_memt, np->sc_bah, offsetof(struct ncr_reg, r)) -#define INL(r) \ - INL_OFF(offsetof(struct ncr_reg, r)) -#define INL_OFF(o) \ - bus_space_read_4 (np->sc_memt, np->sc_bah, (o)) +#define WRITESCRIPT_OFF(base, off, val) \ + do { \ + if (base) \ + *((int32_t *)((char *)base + (off))) = (SCR_BO(val)); \ + else \ + bus_space_write_4 (np->ram_tag, np->ram_handle, off, SCR_BO(val)); \ + } while (0) -#define OUTB(r, val) \ - bus_space_write_1 (np->sc_memt, np->sc_bah, offsetof(struct ncr_reg, r), (val)) -#define OUTW(r, val) \ - bus_space_write_2 (np->sc_memt, np->sc_bah, offsetof(struct ncr_reg, r), (val)) -#define OUTL(r, val) \ - OUTL_OFF(offsetof(struct ncr_reg, r), (val)) -#define OUTL_OFF(o, val) \ - bus_space_write_4 (np->sc_memt, np->sc_bah, (o), (val)) +#define READSCRIPT(r) \ + READSCRIPT_OFF(np->script, offsetof(struct script, r)) -#endif +#define WRITESCRIPT(r, val) \ + WRITESCRIPT_OFF(np->script, offsetof(struct script, r), val) -#else /* !(__NetBSD__ || __OpenBSD__) */ +#else /* !__OpenBSD__ */ #ifdef NCR_IOMAPPED - + #define INB(r) inb (np->port + offsetof(struct ncr_reg, r)) #define INB_OFF(o) inb (np->port + (o)) #define INW(r) inw (np->port + offsetof(struct ncr_reg, r)) @@ -364,19 +388,34 @@ #else #define INB(r) (np->reg->r) -#define INB_OFF(o) (*((volatile INT8 *)((char *)np->reg + (o)))) +#define INB_OFF(o) (*((volatile int8_t *)((char *)np->reg + (o)))) #define INW(r) (np->reg->r) #define INL(r) (np->reg->r) -#define INL_OFF(o) (*((volatile INT32 *)((char *)np->reg + (o)))) +#define INL_OFF(o) (*((volatile int32_t *)((char *)np->reg + (o)))) #define OUTB(r, val) np->reg->r = (val) #define OUTW(r, val) np->reg->r = (val) #define OUTL(r, val) np->reg->r = (val) -#define OUTL_OFF(o, val) *((volatile INT32 *)((char *)np->reg + (o))) = val +#define OUTL_OFF(o, val) *((volatile int32_t *)((char *)np->reg + (o))) = val #endif -#endif /* __NetBSD__ || __OpenBSD__ */ +#define READSCRIPT_OFF(base, off) (*((int32_t *)((char *)base + (off)))) +#define READSCRIPT(r) (np->script->r) +#define WRITESCRIPT(r, val) np->script->r = (val) + +#endif /* __OpenBSD__ */ + +/* +** Set bit field ON, OFF +*/ + +#define OUTONB(r, m) OUTB(r, INB(r) | (m)) +#define OUTOFFB(r, m) OUTB(r, INB(r) & ~(m)) +#define OUTONW(r, m) OUTW(r, INW(r) | (m)) +#define OUTOFFW(r, m) OUTW(r, INW(r) & ~(m)) +#define OUTONL(r, m) OUTL(r, INL(r) | (m)) +#define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m)) /*========================================================== ** @@ -485,7 +524,7 @@ ** ** OS dependencies. ** -** Note that various types are defined in ncr_reg.h. +** Note that various types are defined in ncrreg.h. ** **========================================================== */ @@ -626,6 +665,14 @@ struct tcb { ccb_p hold_cp; + /* + ** pointer to ccb used for negotiating. + ** Avoid to start a nego for all queued commands + ** when tagged command queuing is enabled. + */ + + ccb_p nego_cp; + /* ** statistical data */ @@ -766,9 +813,9 @@ struct head { ** the last transfer command. */ - u_long savep; - u_long lastp; - u_long goalp; + u_int32_t savep; + u_int32_t lastp; + u_int32_t goalp; /* ** The virtual address of the ccb @@ -795,7 +842,7 @@ struct head { ** The status bytes are used by the host and the script processor. ** ** The first four byte are copied to the scratchb register -** (declared as scr0..scr3 in ncr_reg.h) just after the select/reselect, +** (declared as scr0..scr3 in ncrreg.h) just after the select/reselect, ** and copied back just after disconnecting. ** Inside the script the XX_REG are used. ** @@ -898,6 +945,12 @@ struct dsb { struct ccb { + /* + ** This filler ensures that the global header is + ** cache line size aligned. + */ + ncrcmd filler[4]; + /* ** during reselection the ncr jumps to this point. ** If a "SIMPLE_TAG" message was received, @@ -1016,15 +1069,24 @@ struct ccb { */ struct ncb { -#if defined(__NetBSD__) || defined(__OpenBSD__) + /* + ** The global header. + ** Accessible to both the host and the + ** script-processor. + ** We assume it is cache line size aligned. + */ + struct head header; + +#ifdef __OpenBSD__ struct device sc_dev; - void *sc_ih; - bus_space_tag_t sc_memt; pci_chipset_tag_t sc_pc; - bus_space_handle_t sc_bah; -#else /* !(__NetBSD__ || __OpenBSD__) */ + void *sc_ih; + bus_space_tag_t sc_st; + bus_space_handle_t sc_sh; + int sc_iomapped; +#else /* !__OpenBSD__ */ int unit; -#endif /* __NetBSD__ || __OpenBSD__ */ +#endif /* __OpenBSD__ */ /*----------------------------------------------- ** Scripts .. @@ -1047,14 +1109,20 @@ struct ncb { ** virtual and physical addresses ** of the 53c810 chip. */ -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) +#ifdef __OpenBSD__ + bus_addr_t paddr; + + bus_space_tag_t ram_tag; + bus_space_handle_t ram_handle; + bus_addr_t paddr2; + int scriptmapped; +#else vm_offset_t vaddr; vm_offset_t paddr; -#else - bus_addr_t paddr; -#endif -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) + vm_offset_t vaddr2; + vm_offset_t paddr2; + /* ** pointer to the chip's registers. */ @@ -1063,25 +1131,34 @@ struct ncb { #endif /* - ** A copy of the script, relocated for this ncb. + ** Scripts instance virtual address. */ struct script *script; + struct scripth *scripth; /* - ** Physical address of this instance of ncb->script + ** Scripts instance physical address. */ u_long p_script; + u_long p_scripth; /* ** The SCSI address of the host adapter. */ - u_char myaddr; + u_char myaddr; /* ** timing parameters */ - u_char ns_sync; - u_char maxoffs; + u_char minsync; /* Minimum sync period factor */ + u_char maxsync; /* Maximum sync period factor */ + u_char maxoffs; /* Max scsi offset */ + u_char clock_divn; /* Number of clock divisors */ + u_long clock_khz; /* SCSI clock frequency in KHz */ + u_long features; /* Chip features map */ + u_char multiplier; /* Clock multiplier (1,2,4) */ + + u_char maxburst; /* log base 2 of dwords burst */ /* ** BIOS supplied PCI bus options @@ -1090,7 +1167,10 @@ struct ncb { u_char rv_dcntl; u_char rv_dmode; u_char rv_ctest3; + u_char rv_ctest4; u_char rv_ctest5; + u_char rv_gpcntl; + u_char rv_stest2; /*----------------------------------------------- ** Link to the generic SCSI driver @@ -1116,7 +1196,7 @@ struct ncb { /* ** Start queue. */ - u_long squeue [MAX_START]; + u_int32_t squeue [MAX_START]; u_short squeueput; u_short actccbs; @@ -1127,6 +1207,9 @@ struct ncb { u_short ticks; u_short latetime; u_long lasttime; +#ifdef __FreeBSD__ + struct callout_handle timeout_ch; +#endif /*----------------------------------------------- ** Debug and profiling @@ -1144,20 +1227,15 @@ struct ncb { u_long disc_phys; u_long disc_ref; - /* - ** The global header. - ** Accessible to both the host and the - ** script-processor. - */ - struct head header; - /* ** 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; + struct ccb *ccb; /* ** message buffers. @@ -1167,7 +1245,7 @@ struct ncb { */ u_char msgout[8]; u_char msgin [8]; - u_long lastmsg; + u_int32_t lastmsg; /* ** Buffer for STATUS_IN phase. @@ -1184,7 +1262,7 @@ struct ncb { */ u_char disc; -#if defined(NCR_IOMAPPED) && !(defined(__NetBSD__) || defined(__OpenBSD__)) +#if defined(NCR_IOMAPPED) && !defined(__OpenBSD__) /* ** address of the ncr control registers in io space */ @@ -1193,6 +1271,7 @@ struct ncb { }; #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)) /*========================================================== ** @@ -1215,12 +1294,15 @@ struct ncb { **---------------------------------------------------------- */ +/* +** 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 tryloop [MAX_START*5+2]; ncrcmd trysel [ 8]; ncrcmd skip [ 8]; ncrcmd skip2 [ 3]; @@ -1238,14 +1320,6 @@ struct script { ncrcmd status [ 27]; ncrcmd msg_in [ 26]; ncrcmd msg_bad [ 6]; - 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 complete [ 13]; ncrcmd cleanup [ 12]; ncrcmd cleanup0 [ 11]; @@ -1257,6 +1331,30 @@ struct script { 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]; @@ -1266,14 +1364,6 @@ struct script { ncrcmd getcc2 [ 14]; #endif ncrcmd getcc3 [ 10]; - ncrcmd badgetcc [ 6]; - ncrcmd reselect [ 12]; - ncrcmd reselect2 [ 6]; - 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]; ncrcmd aborttag [ 4]; ncrcmd abort [ 22]; ncrcmd snooptest [ 9]; @@ -1295,56 +1385,55 @@ 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_getclock (ncb_p np); +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); -#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ static int ncr_intr (void *vnp); #else static void ncr_intr (void *vnp); -static U_INT32 ncr_info (int unit); -#endif /* !(__NetBSD__ || __OpenBSD__) */ -static void ncr_int_ma (ncb_p np); +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); -#ifndef NEW_SCSICONF +#ifdef __OpenBSD__ static u_long ncr_lookup (char* id); -#endif /* NEW_SCSICONF */ -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) -static void ncr_min_phys (struct buf *bp); -#else -static void ncr_minphys (struct buf *bp); #endif +static void ncr_min_phys (struct buf *bp); static 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 - (struct script * script, ncb_p np); -static void ncr_script_fill (struct script * scr); + (ncb_p np, ncrcmd *src, ncrcmd *dst, int len); +static void ncr_script_fill (struct script * scr, struct scripth *scrh); static int ncr_scatter (struct dsb* phys, vm_offset_t vaddr, vm_size_t datalen); static void ncr_setmaxtags (tcb_p tp, u_long usrtags); -static void ncr_setsync (ncb_p np, ccb_p cp, u_char sxfer); -static void ncr_settags (tcb_p tp, lcb_p lp); -static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide); +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); static int ncr_snooptest (ncb_p np); -static INT32 ncr_start (struct scsi_xfer *xp); -static void ncr_timeout (ncb_p np); +static 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); -#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ #ifdef __BROKEN_INDIRECT_CONFIG static int ncr_probe (struct device *, void *, void *); #else static int ncr_probe (struct device *, struct cfdata *, void *); #endif static void ncr_attach (struct device *, struct device *, void *); -#else /* !(__NetBSD__ || __OpenBSD__) */ +#else /* !__OpenBSD__ */ static char* ncr_probe (pcici_t tag, pcidi_t type); static void ncr_attach (pcici_t tag, int unit); -#endif /* __NetBSD__ || __OpenBSD__ */ +#endif /* __OpenBSD__ */ #endif /* KERNEL */ @@ -1360,7 +1449,7 @@ static void ncr_attach (pcici_t tag, int unit); #if 0 static char ident[] = - "\n$OpenBSD: ncr.c,v 1.31 1997/10/11 11:05:27 pefo Exp $\n"; + "\n$OpenBSD: ncr.c,v 1.32 1997/12/01 18:58:48 millert Exp $\n"; #endif static const u_long ncr_version = NCR_VERSION * 11 @@ -1371,15 +1460,15 @@ static const u_long ncr_version = NCR_VERSION * 11 #ifdef KERNEL -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) +#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 /* !(__NetBSD__ || __OpenBSD__) */ +#endif /* !__OpenBSD__ */ static int ncr_debug = SCSI_NCR_DEBUG; -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) +#ifndef __OpenBSD__ SYSCTL_INT(_debug, OID_AUTO, ncr_debug, CTLFLAG_RW, &ncr_debug, 0, ""); -#endif /* !(__NetBSD__ || __OpenBSD__) */ +#endif /* !__OpenBSD__ */ static int ncr_cache; /* to be aligned _NOT_ static */ @@ -1394,11 +1483,16 @@ static int ncr_cache; /* to be aligned _NOT_ static */ #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_896_ID (0x000b1000ul) -#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ struct cfattach ncr_ca = { sizeof(struct ncb), ncr_probe, ncr_attach @@ -1408,7 +1502,7 @@ struct cfdriver ncr_cd = { NULL, "ncr", DV_DULL }; -#else /* !(__NetBSD__ || __OpenBSD__) */ +#else /* !__OpenBSD__ */ static u_long ncr_count; @@ -1422,22 +1516,18 @@ static struct pci_device ncr_device = { DATA_SET (pcidevice_set, ncr_device); -#endif /* !(__NetBSD__ || __OpenBSD__) */ +#endif /* !__OpenBSD__ */ static struct scsi_adapter ncr_switch = { ncr_start, -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) ncr_min_phys, -#else - ncr_minphys, -#endif 0, 0, -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) +#ifndef __OpenBSD__ ncr_info, "ncr", -#endif /* !(__NetBSD__ || __OpenBSD__) */ +#endif /* !__OpenBSD__ */ }; static struct scsi_device ncr_dev = @@ -1446,16 +1536,16 @@ static struct scsi_device ncr_dev = NULL, /* have a queue, served by this */ NULL, /* have no async handler */ NULL, /* Use default 'done' routine */ -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) +#ifndef __OpenBSD__ "ncr", -#endif /* !(__NetBSD__ || __OpenBSD__) */ +#endif /* !__OpenBSD__ */ }; -#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ #define ncr_name(np) (np->sc_dev.dv_xname) -#else /* !(__NetBSD__ || __OpenBSD__) */ +#else /* !__OpenBSD__ */ static char *ncr_name (ncb_p np) { @@ -1488,30 +1578,37 @@ static char *ncr_name (ncb_p np) #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 SCRIPT_KVAR_MONO_TIME_TV_SEC (0) -#define SCRIPT_KVAR_MONO_TIME (SCRIPT_KVAR_MONO_TIME_TV_SEC + 1) -#define SCRIPT_KVAR_NCR_CACHE (SCRIPT_KVAR_MONO_TIME + 1) +#define KVAR_TIME_TV_SEC (0) +#define KVAR_TIME (1) +#define KVAR_NCR_CACHE (2) -#define SCRIPT_KVAR_FIRST SCRIPT_KVAR_MONO_TIME_TV_SEC -#define SCRIPT_KVAR_LAST SCRIPT_KVAR_NCR_CACHE +#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)&mono_time.tv_sec, (unsigned long)&mono_time, (unsigned long)&ncr_cache, }; +#else +static void *script_kvars[] = + { &time.tv_sec, &time, &ncr_cache }; +#endif static struct script script0 = { /*--------------------------< START >-----------------------*/ { @@ -1519,7 +1616,7 @@ static struct script script0 = { ** Claim to be still alive ... */ SCR_COPY (sizeof (((struct ncb *)0)->heartbeat)), - KVAR(SCRIPT_KVAR_MONO_TIME_TV_SEC), + KVAR (KVAR_TIME_TV_SEC), NADDR (heartbeat), /* ** Make data structure address invalid. @@ -1552,32 +1649,7 @@ static struct script script0 = { */ SCR_JUMP, }/*-------------------------< STARTPOS >--------------------*/,{ - PADDR(tryloop), -}/*-------------------------< TRYLOOP >---------------------*/,{ -/* -** Load an entry of the start queue into dsa -** and try to start it by jumping to TRYSEL. -** -** Because the size depends on the -** #define MAX_START parameter, it is filled -** in at runtime. -** -**----------------------------------------------------------- -** -** ##===========< I=0; i=========== -** || SCR_COPY (4), -** || NADDR (squeue[i]), -** || RADDR (dsa), -** || SCR_CALL, -** || PADDR (trysel), -** ##========================================== -** -** SCR_JUMP, -** PADDR(tryloop), -** -**----------------------------------------------------------- -*/ -0 + PADDRH(tryloop), }/*-------------------------< TRYSEL >----------------------*/,{ /* @@ -1633,7 +1705,7 @@ static struct script script0 = { ** patch the launch field. ** should look like an idle process. */ - SCR_COPY (4), + SCR_COPY_F (4), RADDR (dsa), PADDR (skip2), SCR_COPY (8), @@ -1739,7 +1811,7 @@ static struct script script0 = { ** We patch the address part of a ** COPY command with the DSA-register. */ - SCR_COPY (4), + SCR_COPY_F (4), RADDR (dsa), PADDR (loadpos), /* @@ -1763,7 +1835,7 @@ static struct script script0 = { ** Set a time stamp for this selection */ SCR_COPY (sizeof (struct timeval)), - KVAR(SCRIPT_KVAR_MONO_TIME), + KVAR (KVAR_TIME), NADDR (header.stamp.select), /* ** load the savep (saved pointer) into @@ -1816,7 +1888,7 @@ static struct script script0 = { SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)), PADDR (msg_in), SCR_JUMP ^ IFTRUE (DATA (M_REJECT)), - PADDR (msg_reject), + PADDRH (msg_reject), /* ** normal processing */ @@ -1945,7 +2017,7 @@ static struct script script0 = { ** ... set a timestamp ... */ SCR_COPY (sizeof (struct timeval)), - KVAR(SCRIPT_KVAR_MONO_TIME), + KVAR (KVAR_TIME), NADDR (header.stamp.command), /* ** ... and send the command @@ -1967,7 +2039,7 @@ static struct script script0 = { ** set the timestamp. */ SCR_COPY (sizeof (struct timeval)), - KVAR(SCRIPT_KVAR_MONO_TIME), + KVAR (KVAR_TIME), NADDR (header.stamp.status), /* ** If this is a GETCC transfer, @@ -2033,7 +2105,7 @@ static struct script script0 = { SCR_FROM_REG (socl), 0, SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDR (msg_parity), + PADDRH (msg_parity), SCR_FROM_REG (scratcha), 0, /* @@ -2048,13 +2120,13 @@ static struct script script0 = { SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)), PADDR (disconnect), SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)), - PADDR (msg_extended), + PADDRH (msg_extended), SCR_JUMP ^ IFTRUE (DATA (M_NOOP)), PADDR (clrack), SCR_JUMP ^ IFTRUE (DATA (M_REJECT)), - PADDR (msg_reject), + PADDRH (msg_reject), SCR_JUMP ^ IFTRUE (DATA (M_IGN_RESIDUE)), - PADDR (msg_ign_residue), + PADDRH (msg_ign_residue), /* ** Rest of the messages left as ** an exercise ... @@ -2073,63 +2145,587 @@ static struct script script0 = { SCR_JUMP, PADDR (setmsg), -}/*-------------------------< MSG_PARITY >---------------*/,{ +}/*-------------------------< COMPLETE >-----------------*/,{ /* - ** count it + ** Complete message. + ** + ** If it's not the get condition code, + ** copy TEMP register to LASTP in header. */ - SCR_REG_REG (PS_REG, SCR_ADD, 0x01), + SCR_FROM_REG (SS_REG), 0, - /* - ** send a "message parity error" message. +/*<<<*/ SCR_JUMPR ^ IFTRUE (MASK (S_SENSE, S_SENSE)), + 12, + 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_LOAD_REG (scratcha, M_PARITY), + SCR_REG_REG (scntl2, SCR_AND, 0x7f), 0, - SCR_JUMP, - PADDR (setmsg), -}/*-------------------------< MSG_REJECT >---------------*/,{ /* - ** If a negotiation was in progress, - ** negotiation failed. + ** Terminate cycle ... */ - SCR_FROM_REG (HS_REG), + SCR_CLR (SCR_ACK|SCR_ATN), 0, - SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)), - SIR_NEGO_FAILED, /* - ** else make host log this message + ** ... and wait for the disconnect. */ - SCR_INT ^ IFFALSE (DATA (HS_NEGOTIATE)), - SIR_REJECT_RECEIVED, - SCR_JUMP, - PADDR (clrack), - -}/*-------------------------< MSG_IGN_RESIDUE >----------*/,{ + SCR_WAIT_DISC, + 0, +}/*-------------------------< CLEANUP >-------------------*/,{ /* - ** Terminate cycle + ** dsa: Pointer to ccb + ** or xxxxxxFF (no ccb) + ** + ** HS_REG: Host-Status (<>0!) */ - SCR_CLR (SCR_ACK), + SCR_FROM_REG (dsa), 0, - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), + SCR_JUMP ^ IFTRUE (DATA (0xff)), + PADDR (signal), /* - ** get residue size. + ** dsa is valid. + ** save the status registers */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin[1]), + SCR_COPY (4), + RADDR (scr0), + NADDR (header.status), /* - ** Check for message parity error. + ** and copy back the header to the ccb. */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDR (msg_parity), - SCR_FROM_REG (scratcha), + SCR_COPY_F (4), + RADDR (dsa), + PADDR (cleanup0), + SCR_COPY (sizeof (struct head)), + NADDR (header), +}/*-------------------------< CLEANUP0 >--------------------*/,{ 0, + /* - ** Size is 0 .. ignore message. - */ + ** If command resulted in "check condition" + ** status and is not yet completed, + ** try to get the condition code. + */ + SCR_FROM_REG (HS_REG), + 0, +/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (0, HS_DONEMASK)), + 16, + SCR_FROM_REG (SS_REG), + 0, + SCR_JUMP ^ IFTRUE (DATA (S_CHECK_COND)), + PADDRH(getcc2), + /* + ** And make the DSA register invalid. + */ +/*>>>*/ SCR_LOAD_REG (dsa, 0xff), /* invalid */ + 0, +}/*-------------------------< SIGNAL >----------------------*/,{ + /* + ** if status = queue full, + ** reinsert in startqueue and stall queue. + */ + SCR_FROM_REG (SS_REG), + 0, + SCR_INT ^ IFTRUE (DATA (S_QUEUE_FULL)), + SIR_STALL_QUEUE, + /* + ** if job completed ... + */ + SCR_FROM_REG (HS_REG), + 0, + /* + ** ... signal completion to the host + */ + SCR_INT_FLY ^ IFFALSE (MASK (0, HS_DONEMASK)), + 0, + /* + ** Auf zu neuen Schandtaten! + */ + SCR_JUMP, + PADDR(start), + +}/*-------------------------< SAVE_DP >------------------*/,{ + /* + ** SAVE_DP message: + ** Copy TEMP register to SAVEP in header. + */ + SCR_COPY (4), + RADDR (temp), + NADDR (header.savep), + SCR_JUMP, + PADDR (clrack), +}/*-------------------------< RESTORE_DP >---------------*/,{ + /* + ** RESTORE_DP message: + ** Copy SAVEP in header to TEMP register. + */ + SCR_COPY (4), + NADDR (header.savep), + RADDR (temp), + SCR_JUMP, + PADDR (clrack), + +}/*-------------------------< DISCONNECT >---------------*/,{ + /* + ** If QUIRK_AUTOSAVE is set, + ** do an "save pointer" operation. + */ + SCR_FROM_REG (QU_REG), + 0, +/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (QUIRK_AUTOSAVE, QUIRK_AUTOSAVE)), + 12, + /* + ** like SAVE_DP message: + ** Copy TEMP register to SAVEP in header. + */ + SCR_COPY (4), + RADDR (temp), + NADDR (header.savep), +/*>>>*/ /* + ** Check if temp==savep or temp==goalp: + ** if not, log a missing save pointer message. + ** In fact, it's a comparison mod 256. + ** + ** Hmmm, I hadn't thought that I would be urged to + ** write this kind of ugly self modifying code. + ** + ** It's unbelievable, but the ncr53c8xx isn't able + ** to subtract one register from another. + */ + SCR_FROM_REG (temp), + 0, + /* + ** You are not expected to understand this .. + ** + ** CAUTION: only little endian architectures supported! XXX + */ + SCR_COPY_F (1), + NADDR (header.savep), + PADDR (disconnect0), +}/*-------------------------< DISCONNECT0 >--------------*/,{ +/*<<<*/ SCR_JUMPR ^ IFTRUE (DATA (1)), + 20, + /* + ** neither this + */ + SCR_COPY_F (1), + NADDR (header.goalp), + PADDR (disconnect1), +}/*-------------------------< DISCONNECT1 >--------------*/,{ + SCR_INT ^ IFFALSE (DATA (1)), + SIR_MISSING_SAVE, +/*>>>*/ + + /* + ** 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, + /* + ** Profiling: + ** Set a time stamp, + ** and count the disconnects. + */ + SCR_COPY (sizeof (struct timeval)), + KVAR (KVAR_TIME), + NADDR (header.stamp.disconnect), + SCR_COPY (4), + NADDR (disc_phys), + RADDR (temp), + SCR_REG_REG (temp, SCR_ADD, 0x01), + 0, + SCR_COPY (4), + RADDR (temp), + NADDR (disc_phys), + /* + ** Status is: DISCONNECTED. + */ + SCR_LOAD_REG (HS_REG, HS_DISCONNECT), + 0, + SCR_JUMP, + PADDR (cleanup), + +}/*-------------------------< MSG_OUT >-------------------*/,{ + /* + ** The target requests a message. + */ + SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, + NADDR (msgout), + SCR_COPY (1), + RADDR (sfbr), + NADDR (lastmsg), + /* + ** If it was no ABORT message ... + */ + SCR_JUMP ^ IFTRUE (DATA (M_ABORT)), + 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, M_NOOP), + 0, + SCR_COPY (4), + RADDR (scratcha), + NADDR (msgout), + /* + ** ... and process the next phase + */ + SCR_JUMP, + PADDR (dispatch), + +}/*------------------------< BADGETCC >---------------------*/,{ + /* + ** If SIGP was set, clear it and try again. + */ + SCR_FROM_REG (ctest2), + 0, + SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)), + PADDRH (getcc2), + SCR_INT, + SIR_SENSE_FAILED, +}/*-------------------------< RESELECT >--------------------*/,{ + /* + ** This NOP will be patched with LED OFF + ** SCR_REG_REG (gpreg, SCR_OR, 0x01) + */ + SCR_NO_OP, + 0, + + /* + ** make the DSA invalid. + */ + SCR_LOAD_REG (dsa, 0xff), + 0, + SCR_CLR (SCR_TRG), + 0, + /* + ** Sleep waiting for a reselection. + ** If SIGP is set, special treatment. + ** + ** Zu allem bereit .. + */ + SCR_WAIT_RESEL, + PADDR(reselect2), +}/*-------------------------< RESELECT1 >--------------------*/,{ + /* + ** 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 (ctest0), + 0, + SCR_JUMP, + NADDR (jump_tcb), +}/*-------------------------< RESELECT2 >-------------------*/,{ + /* + ** This NOP will be patched with LED ON + ** SCR_REG_REG (gpreg, SCR_AND, 0xfe) + */ + SCR_NO_OP, + 0, + /* + ** If it's not connected :( + ** -> interrupted by SIGP bit. + ** Jump to start. + */ + SCR_FROM_REG (ctest2), + 0, + SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)), + PADDR (start), + SCR_JUMP, + PADDR (reselect), + +}/*-------------------------< RESEL_TMP >-------------------*/,{ + /* + ** The return address in TEMP + ** is in fact the data structure address, + ** so copy it to the DSA register. + */ + SCR_COPY (4), + RADDR (temp), + RADDR (dsa), + SCR_JUMP, + PADDR (prepare), + +}/*-------------------------< RESEL_LUN >-------------------*/,{ + /* + ** come back to this point + ** to get an IDENTIFY message + ** Wait for a msg_in phase. + */ +/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), + 48, + /* + ** message phase + ** It's not a sony, it's a trick: + ** read the data without acknowledging it. + */ + SCR_FROM_REG (sbdl), + 0, +/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (M_IDENTIFY, 0x98)), + 32, + /* + ** It WAS an Identify message. + ** get it and ack it! + */ + SCR_MOVE_ABS (1) ^ SCR_MSG_IN, + NADDR (msgin), + SCR_CLR (SCR_ACK), + 0, + /* + ** Mask out the lun. + */ + SCR_REG_REG (sfbr, SCR_AND, 0x07), + 0, + SCR_RETURN, + 0, + /* + ** No message phase or no IDENTIFY message: + ** return 0. + */ +/*>>>*/ SCR_LOAD_SFBR (0), + 0, + SCR_RETURN, + 0, + +}/*-------------------------< RESEL_TAG >-------------------*/,{ + /* + ** come back to this point + ** to get a SIMPLE_TAG message + ** Wait for a MSG_IN phase. + */ +/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), + 64, + /* + ** message phase + ** It's a trick - read the data + ** without acknowledging it. + */ + SCR_FROM_REG (sbdl), + 0, +/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (M_SIMPLE_TAG)), + 48, + /* + ** It WAS a SIMPLE_TAG message. + ** get it and ack it! + */ + SCR_MOVE_ABS (1) ^ SCR_MSG_IN, + NADDR (msgin), + SCR_CLR (SCR_ACK), + 0, + /* + ** Wait for the second byte (the tag) + */ +/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), + 24, + /* + ** Get it and ack it! + */ + SCR_MOVE_ABS (1) ^ SCR_MSG_IN, + NADDR (msgin), + SCR_CLR (SCR_ACK|SCR_CARRY), + 0, + SCR_RETURN, + 0, + /* + ** No message phase or no SIMPLE_TAG message + ** or no second byte: return 0. + */ +/*>>>*/ SCR_LOAD_SFBR (0), + 0, + SCR_SET (SCR_CARRY), + 0, + SCR_RETURN, + 0, + +}/*-------------------------< DATA_IN >--------------------*/,{ +/* +** Because the size depends on the +** #define MAX_SCATTER parameter, +** it is filled in at runtime. +** +** SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), +** PADDR (no_data), +** SCR_COPY (sizeof (struct timeval)), +** KVAR (KVAR_TIME), +** NADDR (header.stamp.data), +** SCR_MOVE_TBL ^ SCR_DATA_IN, +** offsetof (struct dsb, data[ 0]), +** +** ##===========< i=1; i========= +** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)), +** || PADDR (checkatn), +** || SCR_MOVE_TBL ^ SCR_DATA_IN, +** || offsetof (struct dsb, data[ i]), +** ##========================================== +** +** SCR_CALL, +** PADDR (checkatn), +** SCR_JUMP, +** PADDR (no_data), +*/ +0 +}/*-------------------------< DATA_OUT >-------------------*/,{ +/* +** Because the size depends on the +** #define MAX_SCATTER parameter, +** it is filled in at runtime. +** +** SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_OUT)), +** PADDR (no_data), +** SCR_COPY (sizeof (struct timeval)), +** KVAR (KVAR_TIME), +** NADDR (header.stamp.data), +** SCR_MOVE_TBL ^ SCR_DATA_OUT, +** offsetof (struct dsb, data[ 0]), +** +** ##===========< i=1; i========= +** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)), +** || PADDR (dispatch), +** || SCR_MOVE_TBL ^ SCR_DATA_OUT, +** || offsetof (struct dsb, data[ i]), +** ##========================================== +** +** SCR_CALL, +** PADDR (dispatch), +** SCR_JUMP, +** PADDR (no_data), +** +**--------------------------------------------------------- +*/ +#ifdef __OpenBSD__ +0 +#else +(u_long)&ident +#endif + +}/*--------------------------------------------------------*/ +}; + + +static struct scripth scripth0 = { +/*-------------------------< TRYLOOP >---------------------*/{ +/* +** Load an entry of the start queue into dsa +** and try to start it by jumping to TRYSEL. +** +** Because the size depends on the +** #define MAX_START parameter, it is filled +** in at runtime. +** +**----------------------------------------------------------- +** +** ##===========< I=0; i=========== +** || SCR_COPY (4), +** || NADDR (squeue[i]), +** || RADDR (dsa), +** || SCR_CALL, +** || PADDR (trysel), +** ##========================================== +** +** SCR_JUMP, +** PADDRH(tryloop), +** +**----------------------------------------------------------- +*/ +0 +}/*-------------------------< MSG_PARITY >---------------*/,{ + /* + ** count it + */ + SCR_REG_REG (PS_REG, SCR_ADD, 0x01), + 0, + /* + ** send a "message parity error" message. + */ + SCR_LOAD_REG (scratcha, M_PARITY), + 0, + SCR_JUMP, + PADDR (setmsg), +}/*-------------------------< MSG_REJECT >---------------*/,{ + /* + ** If a negotiation was in progress, + ** negotiation failed. + */ + SCR_FROM_REG (HS_REG), + 0, + SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)), + SIR_NEGO_FAILED, + /* + ** else make host log this message + */ + SCR_INT ^ IFFALSE (DATA (HS_NEGOTIATE)), + SIR_REJECT_RECEIVED, + 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]), + /* + ** Check for message parity error. + */ + SCR_TO_REG (scratcha), + 0, + SCR_FROM_REG (socl), + 0, + SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), + PADDRH (msg_parity), + SCR_FROM_REG (scratcha), + 0, + /* + ** Size is 0 .. ignore message. + */ SCR_JUMP ^ IFTRUE (DATA (0)), PADDR (clrack), /* @@ -2183,13 +2779,13 @@ static struct script script0 = { SCR_FROM_REG (socl), 0, SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDR (msg_parity), + PADDRH (msg_parity), SCR_FROM_REG (scratcha), 0, /* */ SCR_JUMP ^ IFTRUE (DATA (3)), - PADDR (msg_ext_3), + PADDRH (msg_ext_3), SCR_JUMP ^ IFFALSE (DATA (2)), PADDR (msg_bad), }/*-------------------------< MSG_EXT_2 >----------------*/,{ @@ -2210,11 +2806,11 @@ static struct script script0 = { SCR_FROM_REG (socl), 0, SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDR (msg_parity), + PADDRH (msg_parity), SCR_FROM_REG (scratcha), 0, SCR_JUMP ^ IFTRUE (DATA (M_X_WIDE_REQ)), - PADDR (msg_wdtr), + PADDRH (msg_wdtr), /* ** unknown extended message */ @@ -2233,7 +2829,7 @@ static struct script script0 = { SCR_FROM_REG (socl), 0, SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDR (msg_parity), + PADDRH (msg_parity), /* ** let the host do the real work. */ @@ -2272,318 +2868,67 @@ static struct script script0 = { */ SCR_MOVE_ABS (1) ^ SCR_MSG_IN, NADDR (msgin[2]), - /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDR (msg_parity), - SCR_FROM_REG (scratcha), - 0, - SCR_JUMP ^ IFTRUE (DATA (M_X_SYNC_REQ)), - PADDR (msg_sdtr), - /* - ** unknown extended message - */ - SCR_JUMP, - PADDR (msg_bad) - -}/*-------------------------< MSG_SDTR >-----------------*/,{ - SCR_CLR (SCR_ACK), - 0, - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** get period and offset - */ - SCR_MOVE_ABS (2) ^ SCR_MSG_IN, - NADDR (msgin[3]), - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDR (msg_parity), - /* - ** let the host do the real work. - */ - SCR_INT, - SIR_NEGO_SYNC, - /* - ** let the target fetch our answer. - */ - SCR_SET (SCR_ATN), - 0, - SCR_CLR (SCR_ACK), - 0, - - SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), - SIR_NEGO_PROTO, - /* - ** Send the M_X_SYNC_REQ - */ - SCR_MOVE_ABS (5) ^ SCR_MSG_OUT, - NADDR (msgout), - SCR_CLR (SCR_ATN), - 0, - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), - SCR_JUMP, - PADDR (msg_out_done), - -}/*-------------------------< COMPLETE >-----------------*/,{ - /* - ** Complete message. - ** - ** If it's not the get condition code, - ** copy TEMP register to LASTP in header. - */ - SCR_FROM_REG (SS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFTRUE (MASK (S_SENSE, S_SENSE)), - 12, - 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 >-------------------*/,{ - /* - ** dsa: Pointer to ccb - ** or xxxxxxFF (no ccb) - ** - ** HS_REG: Host-Status (<>0!) - */ - SCR_FROM_REG (dsa), - 0, - SCR_JUMP ^ IFTRUE (DATA (0xff)), - PADDR (signal), - /* - ** dsa is valid. - ** save the status registers - */ - SCR_COPY (4), - RADDR (scr0), - NADDR (header.status), - /* - ** and copy back the header to the ccb. - */ - SCR_COPY (4), - RADDR (dsa), - PADDR (cleanup0), - SCR_COPY (sizeof (struct head)), - NADDR (header), -}/*-------------------------< CLEANUP0 >--------------------*/,{ - 0, - - /* - ** If command resulted in "check condition" - ** status and is not yet completed, - ** try to get the condition code. - */ - SCR_FROM_REG (HS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (0, HS_DONEMASK)), - 16, - SCR_FROM_REG (SS_REG), - 0, - SCR_JUMP ^ IFTRUE (DATA (S_CHECK_COND)), - PADDR(getcc2), - /* - ** And make the DSA register invalid. - */ -/*>>>*/ SCR_LOAD_REG (dsa, 0xff), /* invalid */ - 0, -}/*-------------------------< SIGNAL >----------------------*/,{ - /* - ** if status = queue full, - ** reinsert in startqueue and stall queue. - */ - SCR_FROM_REG (SS_REG), - 0, - SCR_INT ^ IFTRUE (DATA (S_QUEUE_FULL)), - SIR_STALL_QUEUE, - /* - ** if job completed ... - */ - SCR_FROM_REG (HS_REG), - 0, - /* - ** ... signal completion to the host - */ - SCR_INT_FLY ^ IFFALSE (MASK (0, HS_DONEMASK)), - 0, - /* - ** Auf zu neuen Schandtaten! - */ - SCR_JUMP, - PADDR(start), - -}/*-------------------------< SAVE_DP >------------------*/,{ - /* - ** SAVE_DP message: - ** Copy TEMP register to SAVEP in header. - */ - SCR_COPY (4), - RADDR (temp), - NADDR (header.savep), - SCR_JUMP, - PADDR (clrack), -}/*-------------------------< RESTORE_DP >---------------*/,{ - /* - ** RESTORE_DP message: - ** Copy SAVEP in header to TEMP register. - */ - SCR_COPY (4), - NADDR (header.savep), - RADDR (temp), - SCR_JUMP, - PADDR (clrack), - -}/*-------------------------< DISCONNECT >---------------*/,{ - /* - ** If QUIRK_AUTOSAVE is set, - ** do an "save pointer" operation. - */ - SCR_FROM_REG (QU_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (QUIRK_AUTOSAVE, QUIRK_AUTOSAVE)), - 12, - /* - ** like SAVE_DP message: - ** Copy TEMP register to SAVEP in header. - */ - SCR_COPY (4), - RADDR (temp), - NADDR (header.savep), -/*>>>*/ /* - ** Check if temp==savep or temp==goalp: - ** if not, log a missing save pointer message. - ** In fact, it's a comparison mod 256. - ** - ** Hmmm, I hadn't thought that I would be urged to - ** write this kind of ugly self modifying code. - ** - ** It's unbelievable, but the ncr53c8xx isn't able - ** to subtract one register from another. - */ - SCR_FROM_REG (temp), - 0, - /* - ** You are not expected to understand this .. - ** - ** CAUTION: only little endian architectures supported! XXX - */ - SCR_COPY (1), - NADDR (header.savep), - PADDR (disconnect0), -}/*-------------------------< DISCONNECT0 >--------------*/,{ -/*<<<*/ SCR_JUMPR ^ IFTRUE (DATA (1)), - 20, - /* - ** neither this - */ - SCR_COPY (1), - NADDR (header.goalp), - PADDR (disconnect1), -}/*-------------------------< DISCONNECT1 >--------------*/,{ - SCR_INT ^ IFFALSE (DATA (1)), - SIR_MISSING_SAVE, -/*>>>*/ - - /* - ** DISCONNECTing ... - ** - ** disable the "unexpected disconnect" feature, - ** and remove the ACK signal. + /* + ** Check for message parity error. */ - SCR_REG_REG (scntl2, SCR_AND, 0x7f), + SCR_TO_REG (scratcha), 0, - SCR_CLR (SCR_ACK|SCR_ATN), + SCR_FROM_REG (socl), + 0, + SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), + PADDRH (msg_parity), + SCR_FROM_REG (scratcha), 0, + SCR_JUMP ^ IFTRUE (DATA (M_X_SYNC_REQ)), + PADDRH (msg_sdtr), /* - ** Wait for the disconnect. + ** unknown extended message */ - SCR_WAIT_DISC, + SCR_JUMP, + PADDR (msg_bad) + +}/*-------------------------< MSG_SDTR >-----------------*/,{ + SCR_CLR (SCR_ACK), 0, + SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), + PADDR (dispatch), /* - ** Profiling: - ** Set a time stamp, - ** and count the disconnects. + ** get period and offset */ - SCR_COPY (sizeof (struct timeval)), - KVAR(SCRIPT_KVAR_MONO_TIME), - NADDR (header.stamp.disconnect), - SCR_COPY (4), - NADDR (disc_phys), - RADDR (temp), - SCR_REG_REG (temp, SCR_ADD, 0x01), + SCR_MOVE_ABS (2) ^ SCR_MSG_IN, + NADDR (msgin[3]), + SCR_FROM_REG (socl), 0, - SCR_COPY (4), - RADDR (temp), - NADDR (disc_phys), + SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), + PADDRH (msg_parity), /* - ** Status is: DISCONNECTED. + ** let the host do the real work. */ - SCR_LOAD_REG (HS_REG, HS_DISCONNECT), + SCR_INT, + SIR_NEGO_SYNC, + /* + ** let the target fetch our answer. + */ + SCR_SET (SCR_ATN), + 0, + SCR_CLR (SCR_ACK), 0, - SCR_JUMP, - PADDR (cleanup), -}/*-------------------------< MSG_OUT >-------------------*/,{ + SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), + SIR_NEGO_PROTO, /* - ** The target requests a message. + ** Send the M_X_SYNC_REQ */ - SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, + SCR_MOVE_ABS (5) ^ SCR_MSG_OUT, NADDR (msgout), + SCR_CLR (SCR_ATN), + 0, SCR_COPY (1), RADDR (sfbr), NADDR (lastmsg), - /* - ** If it was no ABORT message ... - */ - SCR_JUMP ^ IFTRUE (DATA (M_ABORT)), - PADDR (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, M_NOOP), - 0, - SCR_COPY (4), - RADDR (scratcha), - NADDR (msgout), - /* - ** ... and process the next phase - */ SCR_JUMP, - PADDR (dispatch), + PADDR (msg_out_done), + }/*-------------------------< MSG_OUT_ABORT >-------------*/,{ /* ** After ABORT message, @@ -2614,9 +2959,9 @@ static struct script script0 = { ** We patch the address part of a COPY command ** with the address of the dsa register ... */ - SCR_COPY (4), + SCR_COPY_F (4), RADDR (dsa), - PADDR (getcc1), + PADDRH (getcc1), /* ** ... then we do the actual copy. */ @@ -2682,7 +3027,7 @@ static struct script script0 = { SCR_FROM_REG (QU_REG), 0, SCR_JUMP ^ IFTRUE (MASK (QUIRK_NOMSG, QUIRK_NOMSG)), - PADDR(getcc3), + PADDRH(getcc3), /* ** Then try to connect to the target. ** If we are reselected, special treatment @@ -2710,259 +3055,41 @@ static struct script script0 = { ** save the first byte of the message. */ SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), - SCR_JUMP, - PADDR (prepare2), - -#endif -}/*-------------------------< GETCC3 >----------------------*/,{ - /* - ** Try to connect to the target. - ** If we are reselected, special treatment - ** of the current job is required before - ** accepting the reselection. - ** - ** Silly target won't accept a message. - ** Select without ATN. - */ - SCR_SEL_TBL ^ offsetof (struct dsb, select), - PADDR(badgetcc), - /* - ** save target id. - */ - SCR_FROM_REG (sdid), - 0, - SCR_TO_REG (ctest0), - 0, - /* - ** Force error if selection timeout - */ - SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_IN)), - 0, - /* - ** don't negotiate. - */ - SCR_JUMP, - PADDR (prepare2), - -}/*------------------------< BADGETCC >---------------------*/,{ - /* - ** If SIGP was set, clear it and try again. - */ - SCR_FROM_REG (ctest2), - 0, - SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)), - PADDR (getcc2), - SCR_INT, - SIR_SENSE_FAILED, -}/*-------------------------< RESELECT >--------------------*/,{ - /* - ** make the DSA invalid. - */ - SCR_LOAD_REG (dsa, 0xff), - 0, - SCR_CLR (SCR_TRG), - 0, - /* - ** Sleep waiting for a reselection. - ** If SIGP is set, special treatment. - ** - ** Zu allem bereit .. - */ - SCR_WAIT_RESEL, - PADDR(reselect2), - /* - ** ... 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 (ctest0), - 0, - SCR_JUMP, - NADDR (jump_tcb), -}/*-------------------------< RESELECT2 >-------------------*/,{ - /* - ** If it's not connected :( - ** -> interrupted by SIGP bit. - ** Jump to start. - */ - SCR_FROM_REG (ctest2), - 0, - SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)), - PADDR (start), - SCR_JUMP, - PADDR (reselect), - -}/*-------------------------< RESEL_TMP >-------------------*/,{ - /* - ** The return address in TEMP - ** is in fact the data structure address, - ** so copy it to the DSA register. - */ - SCR_COPY (4), - RADDR (temp), - RADDR (dsa), - SCR_JUMP, - PADDR (prepare), - -}/*-------------------------< RESEL_LUN >-------------------*/,{ - /* - ** come back to this point - ** to get an IDENTIFY message - ** Wait for a msg_in phase. - */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), - 48, - /* - ** message phase - ** It's not a sony, it's a trick: - ** read the data without acknowledging it. - */ - SCR_FROM_REG (sbdl), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (M_IDENTIFY, 0x98)), - 32, - /* - ** It WAS an Identify message. - ** get it and ack it! - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), - SCR_CLR (SCR_ACK), - 0, - /* - ** Mask out the lun. - */ - SCR_REG_REG (sfbr, SCR_AND, 0x07), - 0, - SCR_RETURN, - 0, - /* - ** No message phase or no IDENTIFY message: - ** return 0. - */ -/*>>>*/ SCR_LOAD_SFBR (0), - 0, - SCR_RETURN, - 0, - -}/*-------------------------< RESEL_TAG >-------------------*/,{ - /* - ** come back to this point - ** to get a SIMPLE_TAG message - ** Wait for a MSG_IN phase. - */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), - 64, - /* - ** message phase - ** It's a trick - read the data - ** without acknowledging it. - */ - SCR_FROM_REG (sbdl), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (M_SIMPLE_TAG)), - 48, - /* - ** It WAS a SIMPLE_TAG message. - ** get it and ack it! - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), - SCR_CLR (SCR_ACK), - 0, + RADDR (sfbr), + NADDR (lastmsg), + SCR_JUMP, + PADDR (prepare2), + +#endif +}/*-------------------------< GETCC3 >----------------------*/,{ /* - ** Wait for the second byte (the tag) + ** Try to connect to the target. + ** If we are reselected, special treatment + ** of the current job is required before + ** accepting the reselection. + ** + ** Silly target won't accept a message. + ** Select without ATN. */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), - 24, + SCR_SEL_TBL ^ offsetof (struct dsb, select), + PADDR(badgetcc), /* - ** Get it and ack it! + ** save target id. */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), - SCR_CLR (SCR_ACK|SCR_CARRY), + SCR_FROM_REG (sdid), 0, - SCR_RETURN, + SCR_TO_REG (ctest0), 0, /* - ** No message phase or no SIMPLE_TAG message - ** or no second byte: return 0. + ** Force error if selection timeout */ -/*>>>*/ SCR_LOAD_SFBR (0), - 0, - SCR_SET (SCR_CARRY), - 0, - SCR_RETURN, + SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_IN)), 0, - -}/*-------------------------< DATA_IN >--------------------*/,{ -/* -** Because the size depends on the -** #define MAX_SCATTER parameter, -** it is filled in at runtime. -** -** SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), -** PADDR (no_data), -** SCR_COPY (sizeof (struct timeval)), -** KVAR(SCRIPT_KVAR_MONO_TIME), -** NADDR (header.stamp.data), -** SCR_MOVE_TBL ^ SCR_DATA_IN, -** offsetof (struct dsb, data[ 0]), -** -** ##===========< i=1; i========= -** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)), -** || PADDR (checkatn), -** || SCR_MOVE_TBL ^ SCR_DATA_IN, -** || offsetof (struct dsb, data[ i]), -** ##========================================== -** -** SCR_CALL, -** PADDR (checkatn), -** SCR_JUMP, -** PADDR (no_data), -*/ -0 -}/*-------------------------< DATA_OUT >-------------------*/,{ -/* -** Because the size depends on the -** #define MAX_SCATTER parameter, -** it is filled in at runtime. -** -** SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), -** PADDR (no_data), -** SCR_COPY (sizeof (struct timeval)), -** KVAR(SCRIPT_KVAR_MONO_TIME), -** NADDR (header.stamp.data), -** SCR_MOVE_TBL ^ SCR_DATA_OUT, -** offsetof (struct dsb, data[ 0]), -** -** ##===========< i=1; i========= -** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)), -** || PADDR (dispatch), -** || SCR_MOVE_TBL ^ SCR_DATA_OUT, -** || offsetof (struct dsb, data[ i]), -** ##========================================== -** -** SCR_CALL, -** PADDR (dispatch), -** SCR_JUMP, -** PADDR (no_data), -** -**--------------------------------------------------------- -*/ -0 + /* + ** don't negotiate. + */ + SCR_JUMP, + PADDR (prepare2), }/*-------------------------< ABORTTAG >-------------------*/,{ /* ** Abort a bad reselection. @@ -3004,19 +3131,19 @@ static struct script script0 = { ** Read the variable. */ SCR_COPY (4), - KVAR(SCRIPT_KVAR_NCR_CACHE), + KVAR (KVAR_NCR_CACHE), RADDR (scratcha), /* ** Write the variable. */ SCR_COPY (4), RADDR (temp), - KVAR(SCRIPT_KVAR_NCR_CACHE), + KVAR (KVAR_NCR_CACHE), /* ** Read back the variable. */ SCR_COPY (4), - KVAR(SCRIPT_KVAR_NCR_CACHE), + KVAR (KVAR_NCR_CACHE), RADDR (temp), }/*-------------------------< SNOOPEND >-------------------*/,{ /* @@ -3027,6 +3154,7 @@ static struct script script0 = { }/*--------------------------------------------------------*/ }; + /*========================================================== ** ** @@ -3036,12 +3164,12 @@ static struct script script0 = { **========================================================== */ -void ncr_script_fill (struct script * scr) +void ncr_script_fill (struct script * scr, struct scripth * scrh) { int i; ncrcmd *p; - p = scr->tryloop; + p = scrh->tryloop; for (i=0; itryloop + sizeof (scr->tryloop)); + assert ((u_long)p == (u_long)&scrh->tryloop + sizeof (scrh->tryloop)); p = scr->data_in; *p++ =SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)); *p++ =PADDR (no_data); *p++ =SCR_COPY (sizeof (struct timeval)); - *p++ =KVAR(SCRIPT_KVAR_MONO_TIME); + *p++ =(ncrcmd) KVAR (KVAR_TIME); *p++ =NADDR (header.stamp.data); *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN; *p++ =offsetof (struct dsb, data[ 0]); @@ -3083,7 +3211,7 @@ void ncr_script_fill (struct script * scr) *p++ =SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_OUT)); *p++ =PADDR (no_data); *p++ =SCR_COPY (sizeof (struct timeval)); - *p++ =KVAR(SCRIPT_KVAR_MONO_TIME); + *p++ =(ncrcmd) KVAR (KVAR_TIME); *p++ =NADDR (header.stamp.data); *p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT; *p++ =offsetof (struct dsb, data[ 0]); @@ -3112,32 +3240,21 @@ void ncr_script_fill (struct script * scr) **========================================================== */ -static void ncr_script_copy_and_bind (struct script *script, ncb_p np) +static void ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len) { ncrcmd opcode, new, old, tmp1, tmp2; - ncrcmd *src, *dst, *start, *end; - int relocs; - -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) - np->script = (struct script*) vm_page_alloc_contig - (round_page(sizeof (struct script)), 0x100000, 0xffffffff, PAGE_SIZE); -#else /* !(__NetBSD__ || __OpenBSD__) */ - np->script = (struct script *) - malloc (sizeof (struct script), M_DEVBUF, M_WAITOK); -#endif /* __NetBSD__ || __OpenBSD__ */ - - np->p_script = vtophys(np->script); - - src = script->start; - dst = np->script->start; + ncrcmd *start, *end; + int relocs, offset; start = src; - end = src + (sizeof (struct script) / 4); + end = src + len/4; + offset = 0; while (src < end) { opcode = *src++; - *dst++ = SCR_BO(opcode); + WRITESCRIPT_OFF(dst, offset, opcode); + offset += 4; /* ** If we forget to change the length @@ -3153,7 +3270,8 @@ static void ncr_script_copy_and_bind (struct script *script, ncb_p np) }; if (DEBUG_FLAGS & DEBUG_SCRIPT) - printf ("%p: <%x>\n", (src-1), (unsigned)opcode); + printf ("%p: <%x>\n", + (src-1), (unsigned)opcode); /* ** We don't have to decode ALL commands @@ -3175,7 +3293,14 @@ static void ncr_script_copy_and_bind (struct script *script, ncb_p np) printf ("%s: ERROR1 IN SCRIPT at %ld.\n", ncr_name(np), (long)(src-start-1)); DELAY (1000000); - }; + } + /* + ** If PREFETCH feature not enabled, remove + ** the NO FLUSH bit if present. + */ + if ((opcode & SCR_NO_FLUSH) && !(np->features&FE_PFEN)) + WRITESCRIPT_OFF(dst, offset - 4, + (opcode & ~SCR_NO_FLUSH)); break; case 0x0: @@ -3219,6 +3344,9 @@ static void ncr_script_copy_and_bind (struct script *script, ncb_p np) case RELOC_LABEL: new = (old & ~RELOC_MASK) + np->p_script; break; + case RELOC_LABELH: + new = (old & ~RELOC_MASK) + np->p_scripth; + break; case RELOC_SOFTC: new = (old & ~RELOC_MASK) + vtophys(np); break; @@ -3239,17 +3367,18 @@ static void ncr_script_copy_and_bind (struct script *script, ncb_p np) } /* fall through */ default: - panic("ncr_script_copy_and_bind: weird relocation %x\n", old); + panic("ncr_script_copy_and_bind: weird relocation %x @ %ld\n", old, (long)(src - start)); break; } - *dst++ = SCR_BO(new); + WRITESCRIPT_OFF(dst, offset, new); + offset += 4; } + } else { + WRITESCRIPT_OFF(dst, offset, *src++); + offset += 4; } - else { - *dst++ = SCR_BO(*src); - src++; - } + }; } @@ -3277,15 +3406,15 @@ static void ncr_script_copy_and_bind (struct script *script, ncb_p np) **---------------------------------------------------------- */ -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) +#ifndef __OpenBSD__ void ncr_min_phys (struct buf *bp) { if ((unsigned long)bp->b_bcount > MAX_SIZE) bp->b_bcount = MAX_SIZE; } #else -void ncr_minphys (struct buf *bp) +void ncr_min_phys (struct buf *bp) { - if(bp->b_bcount > MAX_SIZE) + if (bp->b_bcount > MAX_SIZE) bp->b_bcount = MAX_SIZE; minphys(bp); } @@ -3298,13 +3427,90 @@ void ncr_minphys (struct buf *bp) **---------------------------------------------------------- */ -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) -U_INT32 ncr_info (int unit) +#ifndef __OpenBSD__ +u_int32_t ncr_info (int unit) { return (1); /* may be changed later */ } #endif +/*---------------------------------------------------------- +** +** NCR chip devices table and chip look up function. +** Features bit are defined in ncrreg.h. Is it the +** right place? +** +**---------------------------------------------------------- +*/ +typedef struct { + unsigned long device_id; + unsigned short minrevid; + char *name; + unsigned char maxburst; + unsigned char maxoffs; + unsigned char clock_divn; + unsigned int features; +} ncr_chip; + +static ncr_chip ncr_chip_table[] = { + {NCR_810_ID, 0x00, "ncr 53c810 fast10 scsi", 4, 8, 4, + FE_ERL} + , + {NCR_810_ID, 0x10, "ncr 53c810a fast10 scsi", 4, 8, 4, + FE_ERL|FE_LDSTR|FE_PFEN|FE_BOF} + , + {NCR_815_ID, 0x00, "ncr 53c815 fast10 scsi", 4, 8, 4, + FE_ERL|FE_BOF} + , + {NCR_820_ID, 0x00, "ncr 53c820 fast10 wide scsi", 4, 8, 4, + FE_WIDE|FE_ERL} + , + {NCR_825_ID, 0x00, "ncr 53c825 fast10 wide scsi", 4, 8, 4, + FE_WIDE|FE_ERL|FE_BOF} + , + {NCR_825_ID, 0x10, "ncr 53c825a fast10 wide scsi", 7, 8, 4, + FE_WIDE|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} + , + {NCR_860_ID, 0x00, "ncr 53c860 fast20 scsi", 4, 8, 5, + FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_LDSTR|FE_PFEN} + , + {NCR_875_ID, 0x00, "ncr 53c875 fast20 wide scsi", 7, 16, 5, + FE_WIDE|FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} + , + {NCR_875_ID, 0x02, "ncr 53c875 fast20 wide scsi", 7, 16, 5, + FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} + , + {NCR_875_ID2, 0x00, "ncr 53c875j fast20 wide scsi", 7, 16, 5, + FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} + , + {NCR_885_ID, 0x00, "ncr 53c885 fast20 wide scsi", 7, 16, 5, + FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} + , + {NCR_895_ID, 0x00, "ncr 53c895 fast40 wide scsi", 7, 31, 7, + FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} + , + {NCR_896_ID, 0x00, "ncr 53c896 fast40 wide scsi", 7, 31, 7, + FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} +}; + +static int ncr_chip_lookup(u_long device_id, u_char revision_id) +{ + int i, found; + + found = -1; + for (i = 0; i < sizeof(ncr_chip_table)/sizeof(ncr_chip_table[0]); i++) { + if (device_id == ncr_chip_table[i].device_id && + ncr_chip_table[i].minrevid <= revision_id) { + if (found < 0 || + ncr_chip_table[found].minrevid + < ncr_chip_table[i].minrevid) { + found = i; + } + } + } + return found; +} + /*---------------------------------------------------------- ** ** Probe the hostadapter. @@ -3312,7 +3518,7 @@ U_INT32 ncr_info (int unit) **---------------------------------------------------------- */ -#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ int ncr_probe(parent, match, aux) @@ -3325,54 +3531,89 @@ ncr_probe(parent, match, aux) void *aux; { struct pci_attach_args *pa = aux; + u_char rev = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_CLASS_REG) & 0xff; #if 0 struct cfdata *cf = match; if (!pci_targmatch(cf, pa)) return 0; #endif - if (pa->pa_id != NCR_810_ID && - pa->pa_id != NCR_815_ID && - pa->pa_id != NCR_825_ID && - pa->pa_id != NCR_860_ID && - pa->pa_id != NCR_875_ID) + if (ncr_chip_lookup(pa->pa_id, rev) < 0) return 0; return 1; } -#else /* !(__NetBSD__ || __OpenBSD__) */ +#else /* !__OpenBSD__ */ static char* ncr_probe (pcici_t tag, pcidi_t type) { u_char rev = pci_conf_read (tag, PCI_CLASS_REG) & 0xff; - switch (type) { + int i; - case NCR_810_ID: - return (rev & 0xf0) == 0x00 - ? ("ncr 53c810 scsi") - : ("ncr 53c810a scsi"); + i = ncr_chip_lookup(type, rev); + if (i >= 0) + return ncr_chip_table[i].name; - case NCR_815_ID: - return ("ncr 53c815 scsi"); + return (NULL); +} - case NCR_825_ID: - return (rev & 0xf0) == 0x00 - ? ("ncr 53c825 wide scsi") - : ("ncr 53c825a wide scsi"); +#endif /* !__OpenBSD__ */ - case NCR_860_ID: - return ("ncr 53c860 scsi"); - case NCR_875_ID: - return ("ncr 53c875 wide scsi"); - } - return (NULL); -} +/*========================================================== +** +** NCR chip clock divisor table. +** Divisors are multiplied by 10,000,000 in order to make +** calculations more simple. +** +**========================================================== +*/ + +#define _5M 5000000 +static u_long div_10M[] = + {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M}; + +/*=============================================================== +** +** 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". +** +**=============================================================== +*/ + +/* + * Burst length from burst code. + */ +#define burst_length(bc) (!(bc))? 0 : 1 << (bc) + +/* + * Burst code from io register bits. + */ +#define burst_code(dmode, ctest4, ctest5) \ + (ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ((ctest5) & 0x04) + 1 -#endif /* !(__NetBSD__ || __OpenBSD__) */ +/* + * Set initial io register bits from burst code. + */ +static void ncr_init_burst(ncb_p np, u_char bc) +{ + np->rv_ctest4 &= ~0x80; + np->rv_dmode &= ~(0x3 << 6); + np->rv_ctest5 &= ~0x4; + if (!bc) { + np->rv_ctest4 |= 0x80; + } + else { + --bc; + np->rv_dmode |= ((bc & 0x3) << 6); + np->rv_ctest5 |= (bc & 0x4); + } +} /*========================================================== ** @@ -3383,10 +3624,7 @@ static char* ncr_probe (pcici_t tag, pcidi_t type) **========================================================== */ -#define MIN_ASYNC_PD 40 -#define MIN_SYNC_PD 20 - -#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ void ncr_attach(parent, self, aux) struct device *parent, *self; @@ -3400,33 +3638,15 @@ ncr_attach(parent, self, aux) pci_intr_handle_t intrhandle; const char *intrstr; ncb_p np = (void *)self; - int wide = 0; + u_long period; + int i; u_char rev = pci_conf_read(pc, pa->pa_tag, PCI_CLASS_REG) & 0xff; - printf(": NCR "); - switch (pa->pa_id) { - case NCR_810_ID: - printf((rev & 0xf0) == 0x00 ? "53c810" : "53c810a"); - break; - case NCR_815_ID: - printf("53c815"); - break; - case NCR_825_ID: - printf((rev & 0xf0) == 0x00 ? "53c825 Wide" : "53c825a Wide"); - wide = 1; - break; - case NCR_860_ID: - printf("53c860"); - break; - case NCR_875_ID: - printf("53c875 Wide"); - wide = 1; - break; - } - printf(" SCSI\n"); - - np->sc_memt = memt; + np->sc_st = memt; np->sc_pc = pc; + np->ccb = (ccb_p) malloc (sizeof (struct ccb), M_DEVBUF, M_WAITOK); + if (!np->ccb) return; + bzero (np->ccb, sizeof (*np->ccb)); /* ** Try to map the controller chip to @@ -3436,15 +3656,14 @@ ncr_attach(parent, self, aux) retval = pci_mem_find(pc, pa->pa_tag, 0x14, &np->paddr, &memsize, &cacheable); if (retval) { - printf("%s: couldn't find memory region\n", self->dv_xname); + printf("\n%s: couldn't find memory region\n", self->dv_xname); return; } /* Map the memory. Note that we never want it to be cacheable. */ - retval = bus_space_map(pa->pa_memt, np->paddr, memsize, 0, - &np->sc_bah); + retval = bus_space_map(pa->pa_memt, np->paddr, memsize, 0, &np->sc_sh); if (retval) { - printf("%s: couldn't map memory region\n", self->dv_xname); + printf("\n%s: couldn't map memory region\n", self->dv_xname); return; } @@ -3454,28 +3673,27 @@ ncr_attach(parent, self, aux) retval = pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin, pa->pa_intrline, &intrhandle); if (retval) { - printf("%s: couldn't map interrupt\n", self->dv_xname); + printf("\n%s: couldn't map interrupt\n", self->dv_xname); return; } intrstr = pci_intr_string(pc, intrhandle); -#ifndef __OpenBSD__ - np->sc_ih = pci_intr_establish(pc, intrhandle, IPL_BIO, - ncr_intr, np); -#else /* !__OpenBSD__ */ np->sc_ih = pci_intr_establish(pc, intrhandle, IPL_BIO, ncr_intr, np, self->dv_xname); -#endif /* __OpenBSD__ */ if (np->sc_ih == NULL) { - printf("%s: couldn't establish interrupt", self->dv_xname); + printf("\n%s: couldn't establish interrupt", self->dv_xname); if (intrstr != NULL) printf(" at %s", intrstr); printf("\n"); return; } + + i = ncr_chip_lookup(pa->pa_id, rev); if (intrstr != NULL) - printf("%s: interrupting at %s\n", self->dv_xname, intrstr); + printf(": %s, %s\n", ncr_chip_table[i].name, intrstr); + else + printf(": %s\n", ncr_chip_table[i].name); -#else /* !(__NetBSD__ || __OpenBSD__) */ +#else /* !__OpenBSD__ */ static void ncr_attach (pcici_t config_id, int unit) { @@ -3487,9 +3705,12 @@ static void ncr_attach (pcici_t config_id, int unit) #if (__FreeBSD__ >= 2) struct scsibus_data *scbus; #endif + u_char rev = 0; + u_long period; + int i; /* - ** allocate structure + ** allocate and initialize structures. */ if (!np) { @@ -3497,12 +3718,12 @@ static void ncr_attach (pcici_t config_id, int unit) if (!np) return; ncrp[unit]=np; } + bzero (np, sizeof (*np)); - /* - ** initialize structure. - */ + np->ccb = (ccb_p) malloc (sizeof (struct ccb), M_DEVBUF, M_WAITOK); + if (!np->ccb) return; + bzero (np->ccb, sizeof (*np->ccb)); - bzero (np, sizeof (*np)); np->unit = unit; /* @@ -3519,92 +3740,315 @@ static void ncr_attach (pcici_t config_id, int unit) ** can be used safely. */ - np->reg = (struct ncr_reg*) np->vaddr; + np->reg = (struct ncr_reg*) np->vaddr; + +#ifdef NCR_IOMAPPED + /* + ** Try to map the controller chip into iospace. + */ + + if (!pci_map_port (config_id, 0x10, &np->port)) + return; +#endif + +#endif /* !__OpenBSD__ */ + + /* + ** Save some controller register default values + */ + + np->rv_scntl3 = INB(nc_scntl3) & 0x77; + np->rv_dmode = INB(nc_dmode) & 0xce; + np->rv_dcntl = INB(nc_dcntl) & 0xa9; + np->rv_ctest3 = INB(nc_ctest3) & 0x01; + np->rv_ctest4 = INB(nc_ctest4) & 0x88; + np->rv_ctest5 = INB(nc_ctest5) & 0x24; + np->rv_gpcntl = INB(nc_gpcntl); + np->rv_stest2 = INB(nc_stest2) & 0x20; + + if (bootverbose >= 2) { + printf ("\tBIOS values: SCNTL3:%02x DMODE:%02x DCNTL:%02x\n", + np->rv_scntl3, np->rv_dmode, np->rv_dcntl); + printf ("\t CTEST3:%02x CTEST4:%02x CTEST5:%02x\n", + np->rv_ctest3, np->rv_ctest4, np->rv_ctest5); + } + + np->rv_dcntl |= NOCOM; + + /* + ** Do chip dependent initialization. + */ + +#ifndef __OpenBSD__ + rev = pci_conf_read (config_id, PCI_CLASS_REG) & 0xff; +#endif /* !__OpenBSD__ */ + + /* + ** Get chip features from chips table. + */ +#ifndef __OpenBSD__ + i = ncr_chip_lookup(pci_conf_read(config_id, PCI_ID_REG), rev); +#endif /* !__OpenBSD__ */ + + if (i >= 0) { + np->maxburst = ncr_chip_table[i].maxburst; + np->maxoffs = ncr_chip_table[i].maxoffs; + np->clock_divn = ncr_chip_table[i].clock_divn; + np->features = ncr_chip_table[i].features; + } else { /* Should'nt happen if probe() is ok */ + np->maxburst = 4; + np->maxoffs = 8; + np->clock_divn = 4; + np->features = FE_ERL; + } + + np->maxwide = np->features & FE_WIDE ? 1 : 0; + np->clock_khz = np->features & FE_CLK80 ? 80000 : 40000; + if (np->features & FE_QUAD) np->multiplier = 4; + else if (np->features & FE_DBLR) np->multiplier = 2; + else np->multiplier = 1; + + /* + ** Get the frequency of the chip's clock. + ** Find the right value for scntl3. + */ + if (np->features & (FE_ULTRA|FE_ULTRA2)) + ncr_getclock(np, np->multiplier); + +#ifdef NCR_TEKRAM_EEPROM + if (bootverbose) { + printf ("%s: Tekram EEPROM read %s\n", + ncr_name(np), + read_tekram_eeprom (np, NULL) ? + "succeeded" : "failed"); + } +#endif /* NCR_TEKRAM_EEPROM */ + + /* + * If scntl3 != 0, we assume BIOS is present. + */ + if (np->rv_scntl3) + np->features |= FE_BIOS; + + /* + * Divisor to be used for async (timer pre-scaler). + */ + i = np->clock_divn - 1; + while (i >= 0) { + --i; + if (10ul * SCSI_NCR_MIN_ASYNC * np->clock_khz > div_10M[i]) { + ++i; + break; + } + } + np->rv_scntl3 = i+1; + + /* + * Minimum synchronous period factor supported by the chip. + * Btw, 'period' is in tenths of nanoseconds. + */ + + period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz; + if (period <= 250) np->minsync = 10; + else if (period <= 303) np->minsync = 11; + else if (period <= 500) np->minsync = 12; + else np->minsync = (period + 40 - 1) / 40; + + /* + * Check against chip SCSI standard support (SCSI-2,ULTRA,ULTRA2). + */ + + if (np->minsync < 25 && !(np->features & (FE_ULTRA|FE_ULTRA2))) + np->minsync = 25; + else if (np->minsync < 12 && !(np->features & FE_ULTRA2)) + np->minsync = 12; + + /* + * Maximum synchronous period factor supported by the chip. + */ + + period = (11 * div_10M[np->clock_divn - 1]) / (4 * np->clock_khz); + np->maxsync = period > 2540 ? 254 : period / 10; + + /* + * Now, some features available with Symbios compatible boards. + * LED support through GPIO0 and DIFF support. + */ + +#ifdef SCSI_NCR_SYMBIOS_COMPAT + if (!(np->rv_gpcntl & 0x01)) + np->features |= FE_LED0; +#if 0 /* Not safe enough without NVRAM support or user settable option */ + if (!(INB(nc_gpreg) & 0x08)) + np->features |= FE_DIFF; +#endif +#endif /* SCSI_NCR_SYMBIOS_COMPAT */ + + /* + * Prepare initial IO registers settings. + * Trust BIOS only if we believe we have one and if we want to. + */ +#ifdef SCSI_NCR_TRUST_BIOS + if (!(np->features & FE_BIOS)) { +#else + if (1) { +#endif + np->rv_dmode = 0; + np->rv_dcntl = NOCOM; + np->rv_ctest3 = 0; + np->rv_ctest4 = MPEE; + np->rv_ctest5 = 0; + np->rv_stest2 = 0; + + 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_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_PFEN) + np->rv_dcntl |= PFEN; /* Prefetch Enable */ + if (np->features & FE_DFS) + np->rv_ctest5 |= DFS; /* Dma Fifo Size */ + if (np->features & FE_DIFF) + np->rv_stest2 |= 0x20; /* Differential mode */ + ncr_init_burst(np, np->maxburst); /* Max dwords burst length */ + } else { + np->maxburst = + burst_code(np->rv_dmode, np->rv_ctest4, np->rv_ctest5); + } + +#ifndef NCR_IOMAPPED + /* + ** Get on-chip SRAM address, if supported + */ +#ifndef __OpenBSD__ + if ((np->features & FE_RAM) && sizeof(struct script) <= 4096) + (void)(!pci_map_mem (config_id,0x18, &np->vaddr2, &np->paddr2)); +#endif /* __OpenBSD__ */ +#endif /* !NCR_IOMAPPED */ + + /* + ** Allocate structure for script relocation. + */ +#ifdef __FreeBSD__ + if (np->vaddr2 != NULL) { + np->script = (struct script *) np->vaddr2; + np->p_script = np->paddr2; + } else if (sizeof (struct script) > PAGE_SIZE) { + np->script = (struct script*) vm_page_alloc_contig + (round_page(sizeof (struct script)), + 0x100000, 0xffffffff, PAGE_SIZE); +#else + if (ISSCRIPTRAMMAPPED(np)) { + /* + * A NULL value means that the script is in the chip's + * on-board RAM and has no virtual address. + */ + np->script = NULL; + np->p_script = np->paddr2; +#endif /* __FreeBSD__ */ + } else { + np->script = (struct script *) + malloc (sizeof (struct script), M_DEVBUF, M_WAITOK); + } + +#ifdef __FreeBSD__ + if (sizeof (struct scripth) > PAGE_SIZE) { + np->scripth = (struct scripth*) vm_page_alloc_contig + (round_page(sizeof (struct scripth)), + 0x100000, 0xffffffff, PAGE_SIZE); + } else +#endif /* __FreeBSD__ */ + { + np->scripth = (struct scripth *) + malloc (sizeof (struct scripth), M_DEVBUF, M_WAITOK); + } -#ifdef NCR_IOMAPPED +#ifdef SCSI_NCR_PCI_CONFIG_FIXUP /* - ** Try to map the controller chip into iospace. + ** If cache line size is enabled, check PCI config space and + ** try to fix it up if necessary. */ +#ifdef PCIR_CACHELNSZ /* To be sure that new PCI stuff is present */ + { + u_char cachelnsz = pci_cfgread(config_id, PCIR_CACHELNSZ, 1); + u_short command = pci_cfgread(config_id, PCIR_COMMAND, 2); + + if (!cachelnsz) { + cachelnsz = 8; + printf("%s: setting PCI cache line size register to %d.\n", + ncr_name(np), (int)cachelnsz); + pci_cfgwrite(config_id, PCIR_CACHELNSZ, cachelnsz, 1); + } - if (!pci_map_port (config_id, 0x10, &np->port)) - return; -#endif + if (!(command & (1<<4))) { + command |= (1<<4); + printf("%s: setting PCI command write and invalidate.\n", + ncr_name(np)); + pci_cfgwrite(config_id, PCIR_COMMAND, command, 2); + } + } +#endif /* PCIR_CACHELNSZ */ -#endif /* !(__NetBSD__ || __OpenBSD__) */ +#endif /* SCSI_NCR_PCI_CONFIG_FIXUP */ /* - ** Save some controller register default values + ** Bells and whistles ;-) */ - - np->rv_dmode = INB (nc_dmode); - np->rv_dcntl = INB (nc_dcntl) | CLSE | PFEN | NOCOM; - np->rv_ctest3 = INB (nc_ctest3); - np->rv_ctest5 = 0; - np->rv_scntl3 = 0x13; /* default: 40MHz clock */ + if (bootverbose) + printf("%s: minsync=%d, maxsync=%d, maxoffs=%d, %d dwords burst, %s dma fifo\n", + ncr_name(np), np->minsync, np->maxsync, np->maxoffs, + burst_length(np->maxburst), + (np->rv_ctest5 & DFS) ? "large" : "normal"); /* - ** Do chip dependent initialization. + ** Print some complementary information that can be helpfull. */ - - np->maxwide = 0; - np->ns_sync = 25; /* in units of 4ns */ - np->maxoffs = 8; - + if (bootverbose) + printf("%s: %s, %s IRQ driver%s\n", + ncr_name(np), + np->rv_stest2 & 0x20 ? "differential" : "single-ended", + np->rv_dcntl & IRQM ? "totem pole" : "open drain", + ISSCRIPTRAMMAPPED(np) ? ", using on-chip SRAM" : ""); + /* - ** Get the frequency of the chip's clock. - ** Find the right value for scntl3. + ** Patch scripts to physical addresses */ + ncr_script_fill (&script0, &scripth0); -#if defined(__NetBSD__) || defined(__OpenBSD__) - switch (pa->pa_id) { -#else /* !(__NetBSD__ || __OpenBSD__) */ - switch (pci_conf_read (config_id, PCI_ID_REG)) { -#endif /* __NetBSD__ || __OpenBSD__ */ - case NCR_825_ID: - { -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) - u_char rev = pci_conf_read (config_id, PCI_CLASS_REG) & 0xff; -#endif /* !(__NetBSD__ || __OpenBSD__) */ - if ((rev & 0xf0) == 0x10) - np->maxoffs = 16; - np->maxwide = 1; - break; - } - case NCR_860_ID: - np->rv_scntl3 = 0x35; /* always assume 80MHz clock for 860 */ - /*np->ns_sync = 12;*/ /* in units of 4ns */ - break; - case NCR_875_ID: - np->maxwide = 1; - /*np->ns_sync = 12;*/ /* in units of 4ns */ - np->maxoffs = 16; -#ifdef NCR_TEKRAM_EEPROM - if (bootverbose) - { - printf ("%s: Tekram EEPROM read %s\n", - ncr_name(np), - read_tekram_eeprom (np, NULL) ? - "succeeded" : "failed"); - } -#endif /* NCR_TEKRAM_EEPROM */ - ncr_getclock(np); - break; - } + if (np->script) + np->p_script = vtophys(np->script); + np->p_scripth = vtophys(np->scripth); + + ncr_script_copy_and_bind (np, (ncrcmd *) &script0, + (ncrcmd *) np->script, sizeof(struct script)); + + ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, + (ncrcmd *) np->scripth, sizeof(struct scripth)); + + np->ccb->p_ccb = vtophys (np->ccb); /* - ** Patch script to physical addresses + ** Patch the script for LED support. */ - ncr_script_fill (&script0); - ncr_script_copy_and_bind (&script0, np); - np->ccb.p_ccb = vtophys (&np->ccb); + if (np->features & FE_LED0) { + WRITESCRIPT(reselect[0], SCR_REG_REG(gpreg, SCR_OR, 0x01)); + WRITESCRIPT(reselect1[0], SCR_REG_REG(gpreg, SCR_AND, 0xfe)); + WRITESCRIPT(reselect2[0], SCR_REG_REG(gpreg, SCR_AND, 0xfe)); + } /* ** init data structure */ np->jump_tcb.l_cmd = SCR_BO(SCR_JUMP); - np->jump_tcb.l_paddr = SCR_BO(NCB_SCRIPT_PHYS (np, abort)); + np->jump_tcb.l_paddr = SCR_BO(NCB_SCRIPTH_PHYS (np, abort)); /* ** Get SCSI addr of host adapter (set by bios?). @@ -3619,12 +4063,12 @@ static void ncr_attach (pcici_t config_id, int unit) */ { int reg; -#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ u_long config_id = pa->pa_tag; -#endif /* __NetBSD__ || __OpenBSD__ */ +#endif /* __OpenBSD__ */ for (reg=0; reg<256; reg+=4) { if (reg%16==0) printf ("reg[%2x]", reg); - printf (" %08x", (int)pci_conf_read (pc, config_id, reg)); + printf (" %08x", (int)pci_conf_read (config_id, reg)); if (reg%16==12) printf ("\n"); } } @@ -3648,14 +4092,14 @@ static void ncr_attach (pcici_t config_id, int unit) return; }; -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) +#ifndef __OpenBSD__ /* ** Install the interrupt handler. */ if (!pci_map_int (config_id, ncr_intr, np, &bio_imask)) printf ("\tinterruptless mode: reduced performance.\n"); -#endif /* __NetBSD__ || __OpenBSD__ */ +#endif /* !__OpenBSD__ */ /* ** After SCSI devices have been opened, we cannot @@ -3679,30 +4123,25 @@ static void ncr_attach (pcici_t config_id, int unit) ** look for the SCSI devices on the bus .. */ -#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ np->sc_link.adapter_softc = np; np->sc_link.adapter_target = np->myaddr; np->sc_link.openings = 1; -#ifndef __OpenBSD__ - np->sc_link.channel = SCSI_CHANNEL_ONLY_ONE; - np->sc_link.max_target = wide ? 15 : 7; -#else if (np->maxwide) np->sc_link.adapter_buswidth = MAX_TARGET; -#endif /* __OpenBSD__ */ -#else /* !(__NetBSD__ || __OpenBSD__) */ +#else /* !__OpenBSD__ */ np->sc_link.adapter_unit = unit; np->sc_link.adapter_softc = np; np->sc_link.adapter_targ = np->myaddr; np->sc_link.fordriver = 0; -#endif /* !(__NetBSD__ || __OpenBSD__) */ +#endif /* !__OpenBSD__ */ np->sc_link.adapter = &ncr_switch; np->sc_link.device = &ncr_dev; np->sc_link.flags = 0; -#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ config_found(self, &np->sc_link, scsiprint); -#else /* !(__NetBSD__ || __OpenBSD__) */ +#else /* !__OpenBSD__ */ #if (__FreeBSD__ >= 2) scbus = scsi_alloc_bus(); if(!scbus) @@ -3733,7 +4172,7 @@ static void ncr_attach (pcici_t config_id, int unit) #else scsi_attachdevs (&np->sc_link); #endif /* !__FreeBSD__ >= 2 */ -#endif /* !(__NetBSD__ || __OpenBSD__) */ +#endif /* !__OpenBSD__ */ /* ** start the timeout daemon @@ -3746,6 +4185,7 @@ static void ncr_attach (pcici_t config_id, int unit) */ np->order = M_SIMPLE_TAG; + /* ** Done. */ @@ -3762,15 +4202,15 @@ static void ncr_attach (pcici_t config_id, int unit) **========================================================== */ -#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ static int -#else /* !(__NetBSD__ || __OpenBSD__) */ +#else /* !__OpenBSD__ */ static void -#endif /* __NetBSD__ || __OpenBSD__ */ +#endif /* __OpenBSD__ */ ncr_intr(vnp) void *vnp; { -#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ int n = 0; #endif ncb_p np = vnp; @@ -3786,8 +4226,8 @@ ncr_intr(vnp) ncr_exception (np); } while (INB(nc_istat) & (INTF|SIP|DIP)); -#if defined(__NetBSD__) || defined(__OpenBSD__) - n = 1; +#ifdef __OpenBSD__ + n=1; #endif np->ticks = 100; }; @@ -3795,7 +4235,7 @@ ncr_intr(vnp) if (DEBUG_FLAGS & DEBUG_TINY) printf ("]\n"); splx (oldspl); -#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ return (n); #endif } @@ -3810,11 +4250,11 @@ ncr_intr(vnp) **========================================================== */ -static INT32 ncr_start (struct scsi_xfer * xp) +static int32_t ncr_start (struct scsi_xfer * xp) { - ncb_p np = (ncb_p) xp->sc_link->adapter_softc; + ncb_p np = (ncb_p) xp->sc_link->adapter_softc; - struct scsi_generic * cmd = xp->cmd; + struct scsi_generic * cmd = (struct scsi_generic *)xp->cmd; ccb_p cp; lcb_p lp; tcb_p tp = &np->target[xp->sc_link->target]; @@ -3875,21 +4315,21 @@ static INT32 ncr_start (struct scsi_xfer * xp) if ((unsigned)xp->datalen > 128*1024*1024) { PRINT_ADDR(xp); - printf ("trying to transfer %8x bytes, mem addr = %p\n", + printf ("trying to transfer %8x bytes, mem addr = %p\n", xp->datalen, xp->data); { - int i; + int j; PRINT_ADDR(xp); printf ("command: %2x (", cmd->opcode); - for (i = 0; i<11; i++) - printf (" %2x", cmd->bytes[i]); + for (j = 0; j<11; j++) + printf (" %2x", cmd->bytes[j]); printf (")\n"); } } if (DEBUG_FLAGS & DEBUG_TINY) { PRINT_ADDR(xp); - printf ("CMD=%x F=%x A=%p L=%x ", + printf ("CMD=%x F=%x A=%p L=%x ", cmd->opcode, (unsigned)xp->flags, xp->data, (unsigned)xp->datalen); } @@ -3925,7 +4365,8 @@ static INT32 ncr_start (struct scsi_xfer * xp) oldspl = splbio(); - if (!(cp=ncr_get_ccb (np, flags, xp->sc_link->target, xp->sc_link->lun))) { + if (!(cp=ncr_get_ccb (np, flags, xp->sc_link->target, + xp->sc_link->lun))) { printf ("%s: no ccb.\n", ncr_name (np)); xp->error = XS_DRIVER_STUFFUP; splx(oldspl); @@ -3941,7 +4382,11 @@ static INT32 ncr_start (struct scsi_xfer * xp) */ bzero (&cp->phys.header.stamp, sizeof (struct tstamp)); +#ifdef __OpenBSD__ cp->phys.header.stamp.start = mono_time; +#else + gettime(&cp->phys.header.stamp.start); +#endif /*---------------------------------------------------- ** @@ -3955,15 +4400,26 @@ static INT32 ncr_start (struct scsi_xfer * xp) */ if (tp->quirks & QUIRK_UPDATE) { -#ifdef NEW_SCSICONF - tp->quirks = xp->sc_link->quirks; -#else +#ifdef __OpenBSD__ tp->quirks = ncr_lookup ((char*) &tp->inqdata[0]); +#else + int q = xp->sc_link->quirks; + tp->quirks = QUIRK_NOMSG; + if (q & SD_Q_NO_TAGS) + tp->quirks |= QUIRK_NOTAGS; + if (q & SD_Q_NO_SYNC) + tp->quirks |= QUIRK_NOSYNC; + if (q & SD_Q_NO_WIDE) + tp->quirks |= QUIRK_NOWIDE16; #endif - if (tp->quirks & ~QUIRK_NOMSG) { + if (bootverbose && (tp->quirks & ~QUIRK_NOMSG)) { PRINT_ADDR(xp); - printf ("quirks=%x.\n", tp->quirks); + printf ("NCR quirks=0x%x\n", tp->quirks); }; + /* + ** set number of tags + */ + ncr_setmaxtags (tp, tp->usrtags); }; /*--------------------------------------------------- @@ -3975,7 +4431,7 @@ static INT32 ncr_start (struct scsi_xfer * xp) nego = 0; - if (tp->inqdata[7]) { + if (!tp->nego_cp && tp->inqdata[7]) { /* ** negotiate wide transfers ? */ @@ -3992,7 +4448,7 @@ static INT32 ncr_start (struct scsi_xfer * xp) */ if (!nego && !tp->period) { - if (SCSI_NCR_MAX_SYNC + if (SCSI_NCR_DFLT_SYNC #ifdef NCR_CDROM_ASYNC && ((tp->inqdata[0] & 0x1f) != 5) #endif /* NCR_CDROM_ASYNC */ @@ -4005,6 +4461,15 @@ static INT32 ncr_start (struct scsi_xfer * xp) printf ("asynchronous.\n"); }; }; + + /* + ** remember nego is pending for the target. + ** Avoid to start a nego for all queued commands + ** when tagged command queuing is enabled. + */ + + if (nego) + tp->nego_cp = cp; }; /*--------------------------------------------------- @@ -4042,7 +4507,7 @@ static INT32 ncr_start (struct scsi_xfer * xp) */ idmsg = M_IDENTIFY | xp->sc_link->lun; - if ((cp!=&np->ccb) && (np->disc)) + if ((cp!=np->ccb) && (np->disc)) idmsg |= 0x40; msgptr = cp->scsi_smsg; @@ -4228,7 +4693,11 @@ static INT32 ncr_start (struct scsi_xfer * xp) */ cp->jump_ccb.l_cmd = SCR_BO((SCR_JUMP ^ IFFALSE (DATA (cp->tag)))); +#ifdef __OpenBSD__ cp->tlimit = mono_time.tv_sec + xp->timeout / 1000 + 2; +#else + cp->tlimit = time.tv_sec + xp->timeout / 1000 + 2; +#endif cp->magic = CCB_MAGIC; /* @@ -4244,8 +4713,8 @@ static INT32 ncr_start (struct scsi_xfer * xp) if(DEBUG_FLAGS & DEBUG_QUEUE) printf ("%s: queuepos=%d tryoffset=%d.\n", ncr_name (np), np->squeueput, - SCR_BO((unsigned)(np->script->startpos[0]))- - (NCB_SCRIPT_PHYS (np, tryloop))); + (unsigned)(READSCRIPT(startpos[0])- + (NCB_SCRIPTH_PHYS (np, tryloop)))); /* ** Script processor may be waiting for reselect. @@ -4263,11 +4732,11 @@ static INT32 ncr_start (struct scsi_xfer * xp) ** Command is successfully queued. */ -#if defined(__NetBSD__) || defined(__OpenBSD__) - if (!(flags & SCSI_POLL)) { -#else /* !(__NetBSD__ || __OpenBSD__) */ +#ifdef __OpenBSD__ + if (!(flags & SCSI_POLL)) { +#else /* !__OpenBSD__ */ if (!(flags & SCSI_NOMASK)) { -#endif /* __NetBSD__ || __OpenBSD__ */ +#endif /* __OpenBSD__ */ if (np->lasttime) { if(DEBUG_FLAGS & DEBUG_TINY) printf ("Q"); return(SUCCESSFULLY_QUEUED); @@ -4316,11 +4785,11 @@ static INT32 ncr_start (struct scsi_xfer * xp) printf ("%s: result: %x %x.\n", ncr_name (np), cp->host_status, cp->scsi_status); }; -#if defined(__NetBSD__) || defined(__OpenBSD__) - if (!(flags & SCSI_POLL)) -#else /* !(__NetBSD__ || __OpenBSD__) */ +#ifdef __OpenBSD__ + if (!(flags & SCSI_POLL)) +#else /* !__OpenBSD__ */ if (!(flags & SCSI_NOMASK)) -#endif /* __NetBSD__ || __OpenBSD__ */ +#endif /* __OpenBSD__ */ return (SUCCESSFULLY_QUEUED); switch (xp->error) { case 0 : return (COMPLETE); @@ -4369,7 +4838,7 @@ void ncr_complete (ncb_p np, ccb_p cp) ncb_profile (np, cp); if (DEBUG_FLAGS & DEBUG_TINY) - printf ("CCB=%lx STAT=%x/%x\n", (unsigned long)cp, + printf ("CCB=%lx STAT=%x/%x\n", (unsigned long)cp & 0xfff, cp->host_status,cp->scsi_status); xp = cp->xfer; @@ -4377,6 +4846,15 @@ void ncr_complete (ncb_p np, ccb_p cp) tp = &np->target[xp->sc_link->target]; lp = tp->lp[xp->sc_link->lun]; + /* + ** 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 = 0; + /* ** Check for parity errors. */ @@ -4387,7 +4865,7 @@ void ncr_complete (ncb_p np, ccb_p cp) /* ** fallback to asynch transfer. */ - tp->usrsync = 255; + tp->usrsync=255; tp->period = 0; }; @@ -4408,21 +4886,21 @@ void ncr_complete (ncb_p np, ccb_p cp) printf ("extended error %d.\n", cp->xerr_status); break; }; - if (cp->host_status == HS_COMPLETE) + if (cp->host_status==HS_COMPLETE) cp->host_status = HS_FAIL; }; /* ** Check the status. */ -#if defined(__NetBSD__) || defined(__OpenBSD__) - if (xp->error != XS_NOERROR) { - - /* +#ifdef __OpenBSD__ + if (xp->error != XS_NOERROR) { + + /* ** Don't override the error value. */ - } else -#endif /* __NetBSD__ || __OpenBSD__ */ + } else +#endif /* __OpenBSD__ */ if ( (cp->host_status == HS_COMPLETE) && (cp->scsi_status == S_GOOD)) { @@ -4454,12 +4932,6 @@ void ncr_complete (ncb_p np, ccb_p cp) bcopy ( xp->data, &tp->inqdata, sizeof (tp->inqdata)); - - /* - ** set number of tags - */ - ncr_setmaxtags (tp, tp->usrtags); - /* ** prepare negotiation of synch and wide. */ @@ -4475,21 +4947,20 @@ void ncr_complete (ncb_p np, ccb_p cp) ** Announce changes to the generic driver */ if (lp) { - ncr_settags (tp, lp); if (lp->reqlink != lp->actlink) ncr_opennings (np, lp, xp); }; tp->bytes += xp->datalen; tp->transfers ++; -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) +#ifndef __OpenBSD__ } else if (xp->flags & SCSI_ERR_OK) { /* ** Not correct, but errors expected. */ xp->resid = 0; -#endif /* !(__NetBSD__ || __OpenBSD__) */ +#endif /* !__OpenBSD__ */ } else if ((cp->host_status == HS_COMPLETE) && (cp->scsi_status == (S_SENSE|S_GOOD))) { @@ -4507,10 +4978,11 @@ void ncr_complete (ncb_p np, ccb_p cp) }; } else if ((cp->host_status == HS_COMPLETE) - && (cp->scsi_status == S_BUSY)) { + && ((cp->scsi_status == S_BUSY) + || (cp->scsi_status == S_CONFLICT))) { /* - ** Target is busy. + ** Target is busy, or reservation conflict */ xp->error = XS_BUSY; @@ -4520,6 +4992,7 @@ void ncr_complete (ncb_p np, ccb_p cp) ** Device failed selection */ xp->error = XS_SELTIMEOUT; + } else if(cp->host_status == HS_TIMEOUT) { /* @@ -4603,7 +5076,7 @@ void ncr_wakeup (ncb_p np, u_long code) ** complete all jobs that are not IDLE. */ - ccb_p cp = &np->ccb; + ccb_p cp = np->ccb; while (cp) { switch (cp->host_status) { @@ -4643,7 +5116,6 @@ void ncr_init (ncb_p np, char * msg, u_long code) int i; u_long usrsync; u_char usrwide; - u_char burstlen; /* ** Reset chip. @@ -4651,6 +5123,7 @@ void ncr_init (ncb_p np, char * msg, u_long code) OUTB (nc_istat, SRST); DELAY (1000); + OUTB (nc_istat, 0); /* ** Message. @@ -4670,8 +5143,8 @@ void ncr_init (ncb_p np, char * msg, u_long code) */ np->squeueput = 0; - np->script->startpos[0] = SCR_BO(NCB_SCRIPT_PHYS (np, tryloop)); - np->script->start0 [0] = SCR_BO(SCR_INT ^ IFFALSE (0)); + WRITESCRIPT(startpos[0], NCB_SCRIPTH_PHYS (np, tryloop)); + WRITESCRIPT(start0 [0], SCR_INT ^ IFFALSE (0)); /* ** Wakeup all pending jobs. @@ -4683,13 +5156,10 @@ void ncr_init (ncb_p np, char * msg, u_long code) ** Init chip. */ - burstlen = 0xc0; /* XXX 53c875 needs code change to */ - /* be able to use larger bursts */ - OUTB (nc_istat, 0x00 ); /* Remove Reset, abort ... */ OUTB (nc_scntl0, 0xca ); /* full arb., ena parity, par->ATN */ OUTB (nc_scntl1, 0x00 ); /* odd parity, and remove CRST!! */ - OUTB (nc_scntl3, np->rv_scntl3);/* timing prescaler */ + ncr_selectclock(np, np->rv_scntl3); /* Select SCSI clock */ OUTB (nc_scid , RRE|np->myaddr);/* host adapter SCSI address */ OUTW (nc_respid, 1ul<myaddr);/* id to respond to */ OUTB (nc_istat , SIGP ); /* Signal Process */ @@ -4697,21 +5167,25 @@ void ncr_init (ncb_p np, char * msg, u_long code) OUTB (nc_dcntl , np->rv_dcntl); OUTB (nc_ctest3, np->rv_ctest3); OUTB (nc_ctest5, np->rv_ctest5); - OUTB (nc_ctest4, MPEE ); /* enable master parity checking */ - OUTB (nc_stest2, EXT ); /* Extended Sreq/Sack filtering */ + OUTB (nc_ctest4, np->rv_ctest4);/* enable master parity checking */ + OUTB (nc_stest2, np->rv_stest2|EXT); /* Extended Sreq/Sack filtering */ OUTB (nc_stest3, TE ); /* TolerANT enable */ OUTB (nc_stime0, 0x0b ); /* HTH = disabled, STO = 0.1 sec. */ -#ifdef __FreeBSD__ - if (bootverbose) { - printf ("\tBIOS values: dmode: %02x, dcntl: %02x, ctest3: %02x\n", - np->rv_dmode, np->rv_dcntl, np->rv_ctest3); - printf ("\tdmode: %02x/%02x, dcntl: %02x/%02x, ctest3: %02x/%02x\n", - burstlen | ERL | ERMP | BOF, INB (nc_dmode), - CLSE | PFEN | NOCOM, INB (nc_dcntl), - WRIE, INB (nc_ctest3)); + if (bootverbose >= 2) { + printf ("\tACTUAL values:SCNTL3:%02x DMODE:%02x DCNTL:%02x\n", + np->rv_scntl3, np->rv_dmode, np->rv_dcntl); + printf ("\t CTEST3:%02x CTEST4:%02x CTEST5:%02x\n", + np->rv_ctest3, np->rv_ctest4, np->rv_ctest5); + } + + /* + ** Enable GPIO0 pin for writing if LED support. + */ + + if (np->features & FE_LED0) { + OUTOFFB (nc_gpcntl, 0x01); } -#endif /* __FreeBSD__ */ /* ** Reinitialize usrsync. @@ -4719,15 +5193,12 @@ void ncr_init (ncb_p np, char * msg, u_long code) */ usrsync = 255; - if (SCSI_NCR_MAX_SYNC) { - u_long period; - period =1000000/SCSI_NCR_MAX_SYNC; /* ns = 10e6 / kHz */ - if (period <= 11 * np->ns_sync) { - if (period < 4 * np->ns_sync) - usrsync = np->ns_sync; - else - usrsync = period / 4; - }; + if (SCSI_NCR_DFLT_SYNC) { + usrsync = SCSI_NCR_DFLT_SYNC; + if (usrsync > np->maxsync) + usrsync = np->maxsync; + if (usrsync < np->minsync) + usrsync = np->minsync; }; /* @@ -4802,14 +5273,14 @@ static void ncr_negotiate (struct ncb* np, struct tcb* tp) ** our limit .. */ - if (minsync < np->ns_sync) - minsync = np->ns_sync; + if (minsync < np->minsync) + minsync = np->minsync; /* ** divider limit */ - if (minsync > (np->ns_sync * 11) / 4) + if (minsync > np->maxsync) minsync = 255; tp->minsync = minsync; @@ -4827,6 +5298,76 @@ static void ncr_negotiate (struct ncb* np, struct tcb* tp) 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. +** +**========================================================== +*/ + +static void ncr_getsync(ncb_p 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; + else if (sfac == 11) per = 303; + else if (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] * 4)) break; + + /* + ** Calculate the lowest clock factor that allows an output + ** speed not faster than the period. + */ + fak = (kpc - 1) / div_10M[div] + 1; + +#if 0 /* You can #if 1 if you think this optimization is usefull */ + + per = (fak * div_10M[div]) / clk; + + /* + ** Why not to try the immediate lower divisor and to choose + ** the one that allows the fastest output speed ? + ** We dont want input speed too much greater than output speed. + */ + if (div >= 1 && fak < 6) { + u_long fak2, per2; + fak2 = (kpc - 1) / div_10M[div-1] + 1; + per2 = (fak2 * div_10M[div-1]) / clk; + if (per2 < per && fak2 <= 6) { + fak = fak2; + per = per2; + --div; + } + } +#endif + + 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); +} + /*========================================================== ** ** Switch sync mode for current job and it's target @@ -4834,10 +5375,11 @@ static void ncr_negotiate (struct ncb* np, struct tcb* tp) **========================================================== */ -static void ncr_setsync (ncb_p np, ccb_p cp, u_char sxfer) +static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer) { struct scsi_xfer *xp; tcb_p tp; + int div; u_char target = INB (nc_ctest0) & 0x0f; assert (cp); @@ -4849,24 +5391,43 @@ static void ncr_setsync (ncb_p np, ccb_p cp, u_char sxfer) assert (target == (xp->sc_link->target & 0x0f)); tp = &np->target[target]; - tp->period= sxfer&0x1f ? ((sxfer>>5)+4) * np->ns_sync : 0xffff; - if (tp->sval == sxfer) return; + if (!scntl3 || !(sxfer & 0x1f)) + scntl3 = np->rv_scntl3; + scntl3 = (scntl3 & 0xf0) | (tp->wval & EWS) | (np->rv_scntl3 & 0x07); + + /* + ** Deduce the value of controller sync period from scntl3. + ** period is in tenths of nano-seconds. + */ + + div = ((scntl3 >> 4) & 0x7); + if ((sxfer & 0x1f) && div) + tp->period = (((sxfer>>5)+4)*div_10M[div-1])/np->clock_khz; + else + tp->period = 0xffff; + + /* + ** Stop there if sync parameters are unchanged + */ + + if (tp->sval == sxfer && tp->wval == scntl3) return; tp->sval = sxfer; + tp->wval = scntl3; /* ** Bells and whistles ;-) */ PRINT_ADDR(xp); if (sxfer & 0x1f) { - unsigned f10 = 10000 << (tp->widedone ? tp->widedone -1 : 0); + unsigned f10 = 100000 << (tp->widedone ? tp->widedone -1 : 0); unsigned mb10 = (f10 + tp->period/2) / tp->period; /* ** Disable extended Sreq/Sack filtering */ - if (tp->period <= 200) OUTB (nc_stest2, 0); + if (tp->period <= 2000) OUTOFFB (nc_stest2, EXT); printf ("%d.%d MB/s (%d ns, offset %d)\n", - mb10 / 10, mb10 % 10, tp->period, sxfer & 0x1f); + mb10 / 10, mb10 % 10, tp->period / 10, sxfer & 0x1f); } else printf ("asynchronous.\n"); /* @@ -4874,30 +5435,37 @@ static void ncr_setsync (ncb_p np, ccb_p cp, u_char sxfer) */ OUTB (nc_sxfer, sxfer); np->sync_st = sxfer; + OUTB (nc_scntl3, scntl3); + np->wide_st = scntl3; /* ** patch ALL ccbs of this target. */ - for (cp = &np->ccb; cp; cp = cp->link_ccb) { + for (cp = np->ccb; cp; cp = cp->link_ccb) { if (!cp->xfer) continue; if (cp->xfer->sc_link->target != target) continue; cp->sync_status = sxfer; + cp->wide_status = scntl3; }; } /*========================================================== ** ** 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. ** **========================================================== */ -static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide) +static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack) { struct scsi_xfer *xp; u_short target = INB (nc_ctest0) & 0x0f; tcb_p tp; - u_char scntl3 = np->rv_scntl3 | (wide ? EWS : 0); + u_char scntl3; + u_char sxfer; assert (cp); if (!cp) return; @@ -4909,28 +5477,41 @@ static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide) tp = &np->target[target]; tp->widedone = wide+1; - if (tp->wval == scntl3) return; + scntl3 = (tp->wval & (~EWS)) | (wide ? EWS : 0); + + sxfer = ack ? 0 : tp->sval; + + /* + ** Stop there if sync/wide parameters are unchanged + */ + if (tp->sval == sxfer && tp->wval == scntl3) return; + tp->sval = sxfer; tp->wval = scntl3; /* ** Bells and whistles ;-) */ PRINT_ADDR(xp); - printf ("WIDE SCSI %sabled\n", - (scntl3 & EWS) ? "(16 bit) en" : "dis"); + if (scntl3 & EWS) + printf ("WIDE SCSI (16 bit) enabled\n"); + else + printf ("WIDE SCSI disabled\n"); /* ** set actual value and sync_status */ + OUTB (nc_sxfer, sxfer); + np->sync_st = sxfer; OUTB (nc_scntl3, scntl3); np->wide_st = scntl3; /* ** patch ALL ccbs of this target. */ - for (cp = &np->ccb; cp; cp = cp->link_ccb) { + for (cp = np->ccb; cp; cp = cp->link_ccb) { if (!cp->xfer) continue; if (cp->xfer->sc_link->target != target) continue; + cp->sync_status = sxfer; cp->wide_status = scntl3; }; } @@ -4945,17 +5526,16 @@ static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide) static void ncr_setmaxtags (tcb_p tp, u_long usrtags) { int l; - tp->usrtags = usrtags; for (l=0; llp[l]; if (!lp) continue; - ncr_settags (tp, lp); + ncr_settags (tp, lp, usrtags); }; } -static void ncr_settags (tcb_p tp, lcb_p lp) +static void ncr_settags (tcb_p tp, lcb_p lp, u_long usrtags) { u_char reqtags, tmp; @@ -4966,14 +5546,13 @@ static void ncr_settags (tcb_p tp, lcb_p lp) ** only disk devices ** only if enabled by user .. */ - if ((tp->inqdata[7] & INQ7_QUEUE) == 0) { - tp->usrtags=0; + if ((tp->inqdata[0] & 0x1f) != 0x00 + || (tp->inqdata[7] & INQ7_QUEUE) == 0 + || (tp->quirks & QUIRK_NOTAGS) != 0) { + usrtags=0; } - if (tp->quirks & QUIRK_NOTAGS) { - tp->usrtags = 0; - } - if (tp->usrtags && ((tp->inqdata[0] & 0x1f) == 0x00)) { - reqtags = tp->usrtags; + if (usrtags) { + reqtags = usrtags; if (lp->actlink <= 1) lp->usetags=reqtags; } else { @@ -4995,6 +5574,8 @@ static void ncr_settags (tcb_p tp, lcb_p lp) tmp = lp->actlink; if (tmp < reqtags) tmp = reqtags; lp->reqccbs = tmp; + if (lp->reqlink < lp->reqccbs) + lp->reqlink = lp->reqccbs; } /*---------------------------------------------------- @@ -5027,7 +5608,9 @@ static void ncr_usercmd (ncb_p np) break; for (t=0; tuser.target>>t)&1)) continue; - ncr_setmaxtags (&np->target[t], np->user.data); + tp = &np->target[t]; + tp->usrtags = np->user.data; + ncr_setmaxtags (tp, tp->usrtags); }; break; @@ -5079,9 +5662,14 @@ static void ncr_usercmd (ncb_p np) **---------------------------------------------------------- */ -static void ncr_timeout (ncb_p np) +static void ncr_timeout (void *arg) { + ncb_p np = arg; +#ifdef __OpenBSD__ u_long thistime = mono_time.tv_sec; +#else + u_long thistime = time.tv_sec; +#endif u_long step = np->ticks; u_long count = 0; long signed t; @@ -5128,7 +5716,7 @@ static void ncr_timeout (ncb_p np) **---------------------------------------------------- */ - for (cp=&np->ccb; cp; cp=cp->link_ccb) { + for (cp=np->ccb; cp; cp=cp->link_ccb) { /* ** look for timed out ccbs. */ @@ -5174,7 +5762,11 @@ static void ncr_timeout (ncb_p np) splx (oldspl); } - timeout (TIMEOUT ncr_timeout, (caddr_t) np, step ? step : 1); +#ifdef __FreeBSD__ + np->timeout_ch = timeout (ncr_timeout, (caddr_t) np, step ? step : 1); +#else + timeout (ncr_timeout, (caddr_t) np, step ? step : 1); +#endif if (INB(nc_istat) & (INTF|SIP|DIP)) { @@ -5190,6 +5782,85 @@ static void ncr_timeout (ncb_p np) }; } +/*========================================================== +** +** 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 adress (relative to start of script). +** dbc: first word of script command. +** +** First 16 register of the chip: +** r0..rf +** +**========================================================== +*/ + +static void ncr_log_hard_error(ncb_p np, u_short sist, u_char dstat) +{ + u_int32_t dsp; + int script_ofs; + int script_size; + char *script_name; + u_char *script_base; + int i; + + dsp = INL (nc_dsp); + + if (np->p_script < dsp && + dsp <= np->p_script + sizeof(struct script)) { + script_ofs = dsp - np->p_script; + script_size = sizeof(struct script); + script_base = (u_char *) np->script; + script_name = "script"; + } + else if (np->p_scripth < dsp && + dsp <= np->p_scripth + sizeof(struct scripth)) { + script_ofs = dsp - np->p_scripth; + script_size = sizeof(struct scripth); + script_base = (u_char *) np->scripth; + script_name = "scripth"; + } else { + script_ofs = dsp; + script_size = 0; + script_base = 0; + script_name = "mem"; + } + + printf ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%s %x:%08x).\n", + ncr_name (np), (unsigned)INB (nc_ctest0)&0x0f, dstat, sist, + (unsigned)INB (nc_socl), (unsigned)INB (nc_sbcl), (unsigned)INB (nc_sbdl), + (unsigned)INB (nc_sxfer),(unsigned)INB (nc_scntl3), script_name, script_ofs, + (unsigned)INL (nc_dbc)); + + if (((script_ofs & 3) == 0) && + (unsigned)script_ofs < script_size) { + printf ("%s: script cmd = %08x\n", ncr_name(np), + (int)READSCRIPT_OFF(script_base, script_ofs)); + } + + printf ("%s: regdump:", ncr_name(np)); + for (i=0; i<16;i++) + printf (" %02x", (unsigned)INB_OFF(i)); + printf (".\n"); +} + /*========================================================== ** ** @@ -5201,10 +5872,8 @@ static void ncr_timeout (ncb_p np) void ncr_exception (ncb_p np) { - U_INT8 istat, dstat; - U_INT16 sist; - U_INT32 dsp, dsa; - int i, script_ofs; + u_int8_t istat, dstat; + u_int16_t sist; /* ** interrupt on the fly ? @@ -5224,7 +5893,7 @@ void ncr_exception (ncb_p np) ** Never test for an error condition you don't know how to handle. */ - sist = (istat & SIP) ? INW (nc_sist) : 0; + sist = (istat & SIP) ? INW (nc_sist) : 0; dstat = (istat & DIP) ? INB (nc_dstat) : 0; np->profile.num_int++; @@ -5275,7 +5944,7 @@ void ncr_exception (ncb_p np) if ((sist & MA) && !(sist & (STO|GEN|HTH|SGE|UDC|RST|PAR)) && !(dstat & (MDPE|BF|ABRT|SIR|IID))) { - ncr_int_ma (np); + ncr_int_ma (np, dstat); return; }; @@ -5309,71 +5978,33 @@ void ncr_exception (ncb_p np) return; }; + /*======================================== + ** log message for real hard errors + **======================================== + */ + + ncr_log_hard_error(np, sist, dstat); + /*======================================== ** do the register dump **======================================== */ +#ifdef __OpenBSD__ if (mono_time.tv_sec - np->regtime.tv_sec>10) { int i; np->regtime = mono_time; +#else + if (time.tv_sec - np->regtime.tv_sec>10) { + int i; + gettime(&np->regtime); +#endif for (i=0; iregdump); i++) ((char*)&np->regdump)[i] = INB_OFF(i); np->regdump.nc_dstat = dstat; np->regdump.nc_sist = sist; }; - /*========================================= - ** log message for real hard errors - **========================================= - - "ncr0 targ 0?: ERROR (ds:si) (so-si-sd) (sxfer/scntl3) @ (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 adress (relative to start of script). - dbc: first word of script command. - - First 16 register of the chip: - r0..rf - - ============================================= - */ - - dsp = (unsigned) INL (nc_dsp); - dsa = (unsigned) INL (nc_dsa); - - script_ofs = dsp - np->p_script; - - printf ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%x:%08x).\n", - ncr_name (np), INB (nc_ctest0)&0x0f, dstat, sist, - INB (nc_socl), INB (nc_sbcl), INB (nc_sbdl), - INB (nc_sxfer),INB (nc_scntl3), script_ofs, - (unsigned) INL (nc_dbc)); - - if (((script_ofs & 3) == 0) && - (unsigned)script_ofs < sizeof(struct script)) { - printf ("\tscript cmd = %08x\n", - *(ncrcmd *)((char*)np->script +script_ofs)); - } - - printf ("\treg:\t"); - for (i=0; i<16;i++) - printf (" %02x", INB_OFF(i)); - printf (".\n"); /*---------------------------------------- ** clean up the dma fifo @@ -5468,7 +6099,7 @@ void ncr_exception (ncb_p np) ** @RECOVER@ HTH, SGE, ABRT. ** ** We should try to recover from these interrupts. -** They may occur if there are problems with synch transfers, or +** They may occur if there are problems with synch transfers, or ** if targets are switched on or off while the driver is running. */ @@ -5502,7 +6133,11 @@ void ncr_exception (ncb_p np) if (i%16==15) printf (".\n"); }; - untimeout (TIMEOUT ncr_timeout, (caddr_t) np); +#ifdef __FreeBSD__ + untimeout (ncr_timeout, (caddr_t) np, np->timeout_ch); +#else + untimeout (ncr_timeout, (caddr_t) np); +#endif printf ("%s: halted!\n", ncr_name(np)); /* @@ -5555,7 +6190,7 @@ void ncr_int_sto (ncb_p np) */ dsa = INL (nc_dsa); - cp = &np->ccb; + cp = np->ccb; while (cp && (CCB_PHYS (cp, phys) != dsa)) cp = cp->link_ccb; @@ -5569,12 +6204,12 @@ void ncr_int_sto (ncb_p np) */ scratcha = INL (nc_scratcha); - diff = scratcha - NCB_SCRIPT_PHYS (np, tryloop); + diff = scratcha - NCB_SCRIPTH_PHYS (np, tryloop); /* assert ((diff <= MAX_START * 20) && !(diff % 20));*/ if ((diff <= MAX_START * 20) && !(diff % 20)) { - np->script->startpos[0] = SCR_BO(scratcha); + WRITESCRIPT(startpos[0], scratcha); OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start)); return; }; @@ -5595,18 +6230,19 @@ void ncr_int_sto (ncb_p np) **---------------------------------------------------------- */ -static void ncr_int_ma (ncb_p np) +static void ncr_int_ma (ncb_p np, u_char dstat) { - U_INT32 dbc; - U_INT32 rest; - U_INT32 dsa; - U_INT32 dsp; - U_INT32 nxtdsp; - U_INT32 *vdsp; - U_INT32 oadr, olen; - U_INT32 *tblp; + u_int32_t dbc; + u_int32_t rest; + u_int32_t dsa; + u_int32_t dsp; + u_int32_t nxtdsp; + void *vdsp_base; + size_t vdsp_off; + u_int32_t oadr, olen; + u_int32_t *tblp; ncrcmd *newcmd; - U_INT32 cmd, sbcl, delta, ss0, ss2; + u_int32_t cmd, sbcl, delta, ss0, ss2, ctest5; ccb_p cp; dsp = INL (nc_dsp); @@ -5618,7 +6254,13 @@ static void ncr_int_ma (ncb_p np) cmd = dbc >> 24; rest= dbc & 0xffffff; - delta=(INB (nc_dfifo) - rest) & 0x7f; + + ctest5 = (np->rv_ctest5 & DFS) ? INB (nc_ctest5) : 0; + if (ctest5 & DFS) + delta=(((ctest5<<8) | (INB (nc_dfifo) & 0xff)) - rest) & 0x3ff; + else + delta=(INB (nc_dfifo) - rest) & 0x7f; + /* ** The data in the dma fifo has not been transfered to @@ -5627,7 +6269,7 @@ static void ncr_int_ma (ncb_p np) ** Check the sstat2 register in case of wide transfer. */ - if (! (INB(nc_dstat) & DFE)) rest += delta; + if (!(dstat & DFE)) rest += delta; if (ss0 & OLF) rest++; if (ss0 & ORF) rest++; if (INB(nc_scntl3) & EWS) { @@ -5641,18 +6283,18 @@ static void ncr_int_ma (ncb_p np) ** locate matching cp */ dsa = INL (nc_dsa); - cp = &np->ccb; + cp = np->ccb; while (cp && (CCB_PHYS (cp, phys) != dsa)) cp = cp->link_ccb; if (!cp) { - printf ("%s: SCSI phase error fixup: CCB already dequeued (0x%08lx)\n", - ncr_name (np), (u_long) np->header.cp); + printf ("%s: SCSI phase error fixup: CCB already dequeued (%p)\n", + ncr_name (np), np->header.cp); return; } if (cp != np->header.cp) { - printf ("%s: SCSI phase error fixup: CCB address mismatch (0x%08lx != 0x%08lx) np.ccb = %p\n", - ncr_name (np), (u_long) cp, (u_long) np->header.cp, &np->ccb); + printf ("%s: SCSI phase error fixup: CCB address mismatch (0x%08lx != 0x%08lx) np->ccb = %p\n", + ncr_name (np), (u_long) cp, (u_long) np->header.cp, np->ccb); /* return;*/ } @@ -5662,13 +6304,21 @@ static void ncr_int_ma (ncb_p np) */ if (dsp == vtophys (&cp->patch[2])) { - vdsp = &cp->patch[0]; - nxtdsp = SCR_BO(vdsp[3]); + vdsp_base = cp; + vdsp_off = offsetof(struct ccb, patch[0]); + nxtdsp = READSCRIPT_OFF(vdsp_base, vdsp_off + 3*4); } else if (dsp == vtophys (&cp->patch[6])) { - vdsp = &cp->patch[4]; - nxtdsp = SCR_BO(vdsp[3]); + vdsp_base = cp; + vdsp_off = offsetof(struct ccb, patch[4]); + nxtdsp = READSCRIPT_OFF(vdsp_base, vdsp_off + 3*4); + } else if (dsp > np->p_script && + dsp <= np->p_script + sizeof(struct script)) { + vdsp_base = np->script; + vdsp_off = dsp - np->p_script - 8; + nxtdsp = dsp; } else { - vdsp = (U_INT32 *) ((char*)np->script - np->p_script + dsp -8); + vdsp_base = np->scripth; + vdsp_off = dsp - np->p_scripth - 8; nxtdsp = dsp; }; @@ -5681,29 +6331,29 @@ static void ncr_int_ma (ncb_p np) (unsigned) rest, (unsigned) delta, ss0); }; if (DEBUG_FLAGS & DEBUG_PHASE) { - printf ("\nCP=%p CP2=%p DSP=%x NXT=%x VDSP=%p CMD=%x ", + printf ("\nCP=%p CP2=%p DSP=%x NXT=%x VDSP_BASE=%p VDSP_OFF=0x%x CMD=%x ", cp, np->header.cp, (unsigned)dsp, - (unsigned)nxtdsp, vdsp, cmd); + (unsigned)nxtdsp, vdsp_base, (unsigned)vdsp_off, cmd); }; /* ** get old startaddress and old length. */ - oadr = SCR_BO(vdsp[1]); + oadr = READSCRIPT_OFF(vdsp_base, vdsp_off + 1*4); if (cmd & 0x10) { /* Table indirect */ - tblp = (U_INT32 *) ((char*) &cp->phys + oadr); + tblp = (u_int32_t *) ((char*) &cp->phys + oadr); olen = SCR_BO(tblp[0]); oadr = SCR_BO(tblp[1]); } else { - tblp = (U_INT32 *) 0; - olen = SCR_BO(vdsp[0]) & 0xffffff; + tblp = (u_int32_t *) 0; + olen = READSCRIPT_OFF(vdsp_base, vdsp_off) & 0xffffff; }; if (DEBUG_FLAGS & DEBUG_PHASE) { printf ("OCMD=%x\nTBLP=%p OLEN=%x OADR=%x\n", - (unsigned) (SCR_BO(vdsp[0]) >> 24), + (unsigned) (READSCRIPT_OFF(vdsp_base, vdsp_off) >> 24), tblp, (unsigned) olen, (unsigned) oadr); @@ -5713,10 +6363,11 @@ static void ncr_int_ma (ncb_p np) ** if old phase not dataphase, leave here. */ - if (cmd != (SCR_BO(vdsp[0]) >> 24)) { + if (cmd != (READSCRIPT_OFF(vdsp_base, vdsp_off) >> 24)) { PRINT_ADDR(cp->xfer); printf ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n", - (unsigned)cmd, (unsigned)SCR_BO(vdsp[0]) >> 24); + (unsigned)cmd, + (unsigned)READSCRIPT_OFF(vdsp_base, vdsp_off) >> 24); return; } @@ -5762,7 +6413,10 @@ static void ncr_int_ma (ncb_p np) */ np->profile.num_break++; OUTL (nc_temp, vtophys (newcmd)); - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch)); + if ((cmd & 7) == 0) + OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch)); + else + OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, checkatn)); } /*========================================================== @@ -5793,6 +6447,7 @@ static int ncr_show_msg (u_char * msg) void ncr_int_sir (ncb_p np) { + u_char scntl3; u_char chg, ofs, per, fak, wide; u_char num = INB (nc_dsps); ccb_p cp=0; @@ -5812,7 +6467,7 @@ void ncr_int_sir (ncb_p np) ** lookup the ccb */ dsa = INL (nc_dsa); - cp = &np->ccb; + cp = np->ccb; while (cp && (CCB_PHYS (cp, phys) != dsa)) cp = cp->link_ccb; @@ -5861,7 +6516,7 @@ void ncr_int_sir (ncb_p np) if (DEBUG_FLAGS & DEBUG_RESTART) printf ("+ restart job ..\n"); OUTL (nc_dsa, CCB_PHYS (cp, phys)); - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, getcc)); + OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, getcc)); return; }; @@ -5869,7 +6524,7 @@ void ncr_int_sir (ncb_p np) ** no job, resume normal processing */ if (DEBUG_FLAGS & DEBUG_RESTART) printf (" -- remove trap\n"); - np->script->start0[0] = SCR_INT ^ IFFALSE (0); + WRITESCRIPT(start0[0], SCR_INT ^ IFFALSE (0)); break; case SIR_SENSE_FAILED: @@ -5895,7 +6550,7 @@ void ncr_int_sir (ncb_p np) /* ** And patch code to restart it. */ - np->script->start0[0] = SCR_INT; + WRITESCRIPT(start0[0], SCR_INT); break; /*----------------------------------------------------------------------------- @@ -5925,14 +6580,14 @@ void ncr_int_sir (ncb_p np) ** ** 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 +** (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 +** 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. ** @@ -5992,11 +6647,11 @@ void ncr_int_sir (ncb_p np) switch (cp->nego_status) { case NS_SYNC: - ncr_setsync (np, cp, 0xe0); + ncr_setsync (np, cp, 0, 0xe0); break; case NS_WIDE: - ncr_setwide (np, cp, 0); + ncr_setwide (np, cp, 0, 0); break; }; @@ -6039,8 +6694,8 @@ void ncr_int_sir (ncb_p np) ** check values against driver limits. */ - if (per < np->ns_sync) - {chg = 1; per = np->ns_sync;} + if (per < np->minsync) + {chg = 1; per = np->minsync;} if (per < tp->minsync) {chg = 1; per = tp->minsync;} if (ofs > tp->maxoffs) @@ -6049,23 +6704,27 @@ void ncr_int_sir (ncb_p np) /* ** Check against controller limits. */ + + fak = 7; + scntl3 = 0; if (ofs != 0) { - fak = (4ul * per - 1) / np->ns_sync - 3; - if (fak>7) { + ncr_getsync(np, per, &fak, &scntl3); + if (fak > 7) { chg = 1; ofs = 0; } } if (ofs == 0) { - fak = 7; - per = 0; + fak = 7; + per = 0; + scntl3 = 0; tp->minsync = 0; } if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->xfer); - printf ("sync: per=%d ofs=%d fak=%d chg=%d.\n", - per, ofs, fak, chg); + printf ("sync: per=%d scntl3=0x%x ofs=%d fak=%d chg=%d.\n", + per, scntl3, ofs, fak, chg); } if (INB (HS_PRT) == HS_NEGOTIATE) { @@ -6080,19 +6739,19 @@ void ncr_int_sir (ncb_p np) /* ** Answer wasn't acceptable. */ - ncr_setsync (np, cp, 0xe0); + ncr_setsync (np, cp, 0, 0xe0); OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad)); } else { /* ** Answer is ok. */ - ncr_setsync (np, cp, (fak<<5)|ofs); + ncr_setsync (np,cp,scntl3,(fak<<5)|ofs); OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack)); }; return; case NS_WIDE: - ncr_setwide (np, cp, 0); + ncr_setwide (np, cp, 0, 0); break; }; }; @@ -6102,7 +6761,7 @@ void ncr_int_sir (ncb_p np) ** prepare an answer message */ - ncr_setsync (np, cp, (fak<<5)|ofs); + ncr_setsync (np, cp, scntl3, (fak<<5)|ofs); np->msgout[0] = M_EXTENDED; np->msgout[1] = 3; @@ -6177,19 +6836,19 @@ void ncr_int_sir (ncb_p np) /* ** Answer wasn't acceptable. */ - ncr_setwide (np, cp, 0); + ncr_setwide (np, cp, 0, 1); OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad)); } else { /* ** Answer is ok. */ - ncr_setwide (np, cp, wide); + ncr_setwide (np, cp, wide, 1); OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack)); }; return; case NS_SYNC: - ncr_setsync (np, cp, 0xe0); + ncr_setsync (np, cp, 0, 0xe0); break; }; }; @@ -6199,7 +6858,7 @@ void ncr_int_sir (ncb_p np) ** prepare an answer message */ - ncr_setwide (np, cp, wide); + ncr_setwide (np, cp, wide, 1); np->msgout[0] = M_EXTENDED; np->msgout[1] = 2; @@ -6316,7 +6975,7 @@ void ncr_int_sir (ncb_p np) PRINT_ADDR(cp->xfer); printf ("queue full.\n"); - np->script->start1[0] = SCR_INT; + WRITESCRIPT(start1[0], SCR_INT); /* ** Try to disable tagged transfers. @@ -6344,7 +7003,7 @@ void ncr_int_sir (ncb_p np) /* ** Look for a disconnected job. */ - cp = &np->ccb; + cp = np->ccb; while (cp && cp->host_status != HS_DISCONNECT) cp = cp->link_ccb; @@ -6364,7 +7023,7 @@ void ncr_int_sir (ncb_p np) */ printf ("%s: queue empty.\n", ncr_name (np)); - np->script->start1[0] = SCR_INT ^ IFFALSE (0); + WRITESCRIPT(start1[0], SCR_INT ^ IFFALSE (0)); break; }; @@ -6387,6 +7046,7 @@ static ccb_p ncr_get_ccb lcb_p lp; ccb_p cp = (ccb_p) 0; int oldspl; + oldspl = splbio(); /* ** Lun structure available ? @@ -6409,7 +7069,7 @@ static ccb_p ncr_get_ccb ** if nothing available, take the default. */ - if (!cp) cp = &np->ccb; + if (!cp) cp = np->ccb; /* ** Wait until available. @@ -6450,7 +7110,7 @@ void ncr_free_ccb (ncb_p np, ccb_p cp, int flags) cp -> host_status = HS_IDLE; cp -> magic = 0; - if (cp == &np->ccb) + if (cp == np->ccb) wakeup ((caddr_t) cp); } @@ -6484,10 +7144,11 @@ static void ncr_alloc_ccb (ncb_p np, u_long target, u_long lun) tp->jump_tcb.l_cmd = SCR_BO((SCR_JUMP^IFFALSE (DATA (0x80 + target)))); tp->jump_tcb.l_paddr = np->jump_tcb.l_paddr; - tp->getscr[0] = SCR_BO(SCR_COPY (1)); + tp->getscr[0] = + (np->features & FE_PFEN)? SCR_BO(SCR_COPY(1)) : SCR_BO(SCR_COPY_F(1)); tp->getscr[1] = SCR_BO(vtophys (&tp->sval)); tp->getscr[2] = SCR_BO(np->paddr + offsetof (struct ncr_reg, nc_sxfer)); - tp->getscr[3] = SCR_BO(SCR_COPY (1)); + tp->getscr[3] = tp->getscr[0]; tp->getscr[4] = SCR_BO(vtophys (&tp->wval)); tp->getscr[5] = SCR_BO(np->paddr + offsetof (struct ncr_reg, nc_scntl3)); @@ -6500,10 +7161,11 @@ static void ncr_alloc_ccb (ncb_p np, u_long target, u_long lun) tp->call_lun.l_paddr = SCR_BO(NCB_SCRIPT_PHYS (np, resel_lun)); tp->jump_lcb.l_cmd = SCR_BO((SCR_JUMP)); - tp->jump_lcb.l_paddr = SCR_BO(NCB_SCRIPT_PHYS (np, abort)); + tp->jump_lcb.l_paddr = SCR_BO(NCB_SCRIPTH_PHYS (np, abort)); np->jump_tcb.l_paddr = SCR_BO(vtophys (&tp->jump_tcb)); - ncr_setmaxtags (tp, SCSI_NCR_DFLT_TAGS); + tp->usrtags = SCSI_NCR_DFLT_TAGS; + ncr_setmaxtags (tp, tp->usrtags); } /* @@ -6528,7 +7190,7 @@ static void ncr_alloc_ccb (ncb_p np, u_long target, u_long lun) lp->call_tag.l_paddr = SCR_BO(NCB_SCRIPT_PHYS (np, resel_tag)); lp->jump_ccb.l_cmd = SCR_BO((SCR_JUMP)); - lp->jump_ccb.l_paddr = SCR_BO(NCB_SCRIPT_PHYS (np, aborttag)); + lp->jump_ccb.l_paddr = SCR_BO(NCB_SCRIPTH_PHYS (np, aborttag)); lp->actlink = 1; @@ -6592,8 +7254,8 @@ static void ncr_alloc_ccb (ncb_p np, u_long target, u_long lun) /* ** Chain into wakeup list */ - cp->link_ccb = np->ccb.link_ccb; - np->ccb.link_ccb = cp; + cp->link_ccb = np->ccb->link_ccb; + np->ccb->link_ccb = cp; /* ** Chain into CCB list @@ -6626,17 +7288,17 @@ static void ncr_opennings (ncb_p np, lcb_p lp, struct scsi_xfer * xp) if (!diff) return; -#if defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef __OpenBSD__ if (diff > xp->sc_link->openings) diff = xp->sc_link->openings; xp->sc_link->openings -= diff; -#else /* !(__NetBSD__ || __OpenBSD__) */ +#else if (diff > xp->sc_link->opennings) diff = xp->sc_link->opennings; xp->sc_link->opennings -= diff; -#endif /* __NetBSD__ || __OpenBSD__ */ +#endif lp->actlink -= diff; if (DEBUG_FLAGS & DEBUG_TAGS) printf ("%s: actlink: diff=%d, new=%d, req=%d\n", @@ -6650,11 +7312,7 @@ static void ncr_opennings (ncb_p np, lcb_p lp, struct scsi_xfer * xp) if (lp->reqlink > lp->actlink) { u_char diff = lp->reqlink - lp->actlink; -#if defined(__NetBSD__) || defined(__OpenBSD__) xp->sc_link->openings += diff; -#else /* !(__NetBSD__ || __OpenBSD__) */ - xp->sc_link->opennings += diff; -#endif /* __NetBSD__ || __OpenBSD__ */ lp->actlink += diff; wakeup ((caddr_t) xp->sc_link); if (DEBUG_FLAGS & DEBUG_TAGS) @@ -6693,7 +7351,7 @@ static int ncr_scatter bzero (&phys->data, sizeof (phys->data)); if (!datalen) return (0); - paddr = vtophys ((void *)vaddr); + paddr = vtophys (vaddr); /* ** insert extra break points at a distance of chunk. @@ -6708,7 +7366,7 @@ static int ncr_scatter free = MAX_SCATTER - 1; - if (vaddr & (NBPG-1)) free -= datalen / NBPG; + if (vaddr & PAGE_MASK) free -= datalen / PAGE_SIZE; if (free>1) while ((chunk * free >= 2 * datalen) && (chunk>=1024)) @@ -6737,7 +7395,7 @@ static int ncr_scatter /* ** continue this segment */ - pnext = (paddr & (~(NBPG - 1))) + NBPG; + pnext = (paddr & (~PAGE_MASK)) + PAGE_SIZE; /* ** Compute max size @@ -6751,7 +7409,7 @@ static int ncr_scatter vaddr += size; csize -= size; datalen -= size; - paddr = vtophys ((void *)vaddr); + paddr = vtophys (vaddr); }; if(DEBUG_FLAGS & DEBUG_SCATTER) @@ -6786,10 +7444,10 @@ static int ncr_scatter **========================================================== */ -#ifndef NCR_IOMAPPED +#if !defined(NCR_IOMAPPED) || defined(__OpenBSD__) static int ncr_regtest (struct ncb* np) { - register volatile u_long data; + register volatile u_int32_t data; /* ** ncr registers may NOT be cached. ** write 0xffffffff to a read only register area, @@ -6813,16 +7471,21 @@ static int ncr_regtest (struct ncb* np) static int ncr_snooptest (struct ncb* np) { - u_long ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc, err=0; - int i; -#ifndef NCR_IOMAPPED - err |= ncr_regtest (np); - if (err) return (err); + u_int32_t ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc; + int i, err=0; +#if !defined(NCR_IOMAPPED) || defined(__OpenBSD__) +#ifdef __OpenBSD__ + if (!np->sc_iomapped) +#endif + { + err |= ncr_regtest (np); + if (err) return (err); + } #endif /* ** init */ - pc = NCB_SCRIPT_PHYS (np, snooptest); + pc = NCB_SCRIPTH_PHYS (np, snooptest); host_wr = 1; ncr_wr = 2; /* @@ -6866,11 +7529,11 @@ static int ncr_snooptest (struct ncb* np) /* ** Check termination position. */ - if (pc != NCB_SCRIPT_PHYS (np, snoopend)+8) { + if (pc != NCB_SCRIPTH_PHYS (np, snoopend)+8) { printf ("CACHE TEST FAILED: script execution failed.\n"); - printf ("\tstart=%08lx, pc=%08lx, end=%08lx\n", - NCB_SCRIPT_PHYS (np, snooptest), pc, - NCB_SCRIPT_PHYS (np, snoopend) +8); + printf ("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); }; /* @@ -6921,7 +7584,11 @@ static void ncb_profile (ncb_p np, ccb_p cp) int co, da, st, en, di, se, post,work,disc; u_long diff; +#ifdef __OpenBSD__ PROFILE.end = mono_time; +#else + gettime(&PROFILE.end); +#endif st = ncr_delta (&PROFILE.start,&PROFILE.status); if (st<0) return; /* status not reached */ @@ -6959,6 +7626,7 @@ static void ncb_profile (ncb_p np, ccb_p cp) } #undef PROFILE +#ifdef __OpenBSD__ /*========================================================== ** ** @@ -6970,8 +7638,6 @@ static void ncb_profile (ncb_p np, ccb_p cp) **========================================================== */ -#ifndef NEW_SCSICONF - struct table_entry { char * manufacturer; char * model; @@ -7017,12 +7683,12 @@ static u_long ncr_lookup(char * id) return (p->info); } } -#endif +#endif /* __OpenBSD__ */ /*========================================================== ** ** Determine the ncr's clock frequency. -** This is important for the negotiation +** This is essential for the negotiation ** of the synchronous transfer rate. ** **========================================================== @@ -7030,18 +7696,45 @@ static u_long ncr_lookup(char * id) ** Note: we have to return the correct value. ** THERE IS NO SAVE DEFAULT VALUE. ** -** We assume that all NCR based boards are delivered -** with a 40Mhz clock. Because we have to divide -** by an integer value greater than 3, only clock -** frequencies of 40Mhz (/4) or 50MHz (/5) permit -** the FAST-SCSI rate of 10MHz. +** 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. ** **---------------------------------------------------------- */ -#ifndef NCR_CLOCK -# define NCR_CLOCK 40 -#endif /* NCR_CLOCK */ +/* + * Select NCR SCSI clock frequency + */ +static void ncr_selectclock(ncb_p np, u_char scntl3) +{ + if (np->multiplier < 2) { + OUTB(nc_scntl3, scntl3); + return; + } + + if (bootverbose >= 2) + printf ("%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) + DELAY(20); + if (!i) + printf("%s: the chip cannot lock the frequency\n", ncr_name(np)); + } else /* Wait 20 micro-seconds for doubler */ + DELAY(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) @@ -7051,18 +7744,18 @@ ncrgetfreq (ncb_p np, int gen) { int ms = 0; /* - * Measure GEN timer delay in order + * Measure GEN timer delay in order * to calculate SCSI clock frequency * * This code will never execute too - * many loop iterations (if DELAY is + * 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 + * 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 + * if multiple measurements are to be + * performed trust the higher delay * (lower frequency returned). */ OUTB (nc_stest1, 0); /* make sure clock doubler is OFF */ @@ -7084,25 +7777,26 @@ ncrgetfreq (ncb_p np, int gen) */ OUTB (nc_scntl3, 0); - if (bootverbose) + if (bootverbose >= 2) printf ("\tDelay (GEN=%d): %u msec\n", gen, ms); /* - * adjust for prescaler, and convert into KHz + * adjust for prescaler, and convert into KHz */ return ms ? ((1 << gen) * 4440) / ms : 0; } -static void ncr_getclock (ncb_p np) +static void ncr_getclock (ncb_p np, u_char multiplier) { unsigned char scntl3; unsigned char stest1; scntl3 = INB(nc_scntl3); stest1 = INB(nc_stest1); - + + np->multiplier = 1; /* always false, except for 875 with clock doubler selected */ if ((stest1 & (DBLEN+DBLSEL)) == DBLEN+DBLSEL) { - OUTB(nc_stest1, 0); - scntl3 = 3; + np->multiplier = multiplier; + np->clock_khz = 40000 * multiplier; } else { if ((scntl3 & 7) == 0) { unsigned f1, f2; @@ -7111,7 +7805,7 @@ static void ncr_getclock (ncb_p np) f1 = ncrgetfreq (np, 11); f2 = ncrgetfreq (np, 11); - if (bootverbose) + if (bootverbose >= 2) printf ("\tNCR clock is %uKHz, %uKHz\n", f1, f2); if (f1 > f2) f1 = f2; /* trust lower result */ if (f1 > 45000) { @@ -7120,13 +7814,8 @@ static void ncr_getclock (ncb_p np) scntl3 = 3; /* <45Mhz: assume 40MHz */ } } - } - - np->rv_scntl3 = ((scntl3 & 0x7) << 4) -0x20 + (scntl3 & 0x7); - - if (bootverbose) { - printf ("\tinitial value of SCNTL3 = %02x, final = %02x\n", - scntl3, np->rv_scntl3); + else if ((scntl3 & 7) == 5) + np->clock_khz = 80000; /* Probably a 875 rev. 1 ? */ } } @@ -7149,7 +7838,7 @@ struct tekram_eeprom_dev { struct tekram_eeprom { - struct tekram_eeprom_dev + struct tekram_eeprom_dev dev[16]; u_char adaptid; u_char adaptmode; @@ -7213,7 +7902,7 @@ read_tekram_eeprom_reg (ncb_p np, int reg) return result; } -static int +static int read_tekram_eeprom(ncb_p np, struct tekram_eeprom *buffer) { u_short *p = (u_short *) buffer; diff --git a/sys/dev/pci/ncrreg.h b/sys/dev/pci/ncrreg.h new file mode 100644 index 00000000000..e25ac4af03e --- /dev/null +++ b/sys/dev/pci/ncrreg.h @@ -0,0 +1,665 @@ +/* $OpenBSD: ncrreg.h,v 1.1 1997/12/01 18:58:49 millert Exp $ */ +/* $NetBSD: ncrreg.h,v 1.14 1997/09/23 02:27:46 perry Exp $ */ + +/************************************************************************** +** +** Id: ncrreg.h,v 1.11 1997/08/31 19:42:31 se Exp +** +** Device driver for the NCR 53C810 PCI-SCSI-Controller. +** +** FreeBSD / NetBSD / OpenBSD +** +**------------------------------------------------------------------------- +** +** Written for 386bsd and FreeBSD by +** wolf@cologne.de Wolfgang Stanglmeier +** se@mi.Uni-Koeln.de Stefan Esser +** +** Ported to NetBSD by +** mycroft@gnu.ai.mit.edu +** +**------------------------------------------------------------------------- +** +** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +*************************************************************************** +*/ + +#ifndef __NCR_REG_H__ +#define __NCR_REG_H__ + +/*========================================================== +** +** OS dependencies. +** +**========================================================== +*/ + +#ifdef __OpenBSD__ +#define ISSCRIPTRAMMAPPED(np) (np->scriptmapped) +#else /*__OpenBSD__*/ +#define ISSCRIPTRAMMAPPED(np) (np->vaddr2) +#endif /*__OpenBSD__*/ + +/*----------------------------------------------------------------- +** +** The ncr 53c810 register structure. +** +**----------------------------------------------------------------- +*/ + +struct ncr_reg { +/*00*/ u_int8_t nc_scntl0; /* full arb., ena parity, par->ATN */ + +/*01*/ u_int8_t nc_scntl1; /* no reset */ + #define ISCON 0x10 /* connected to scsi */ + #define CRST 0x08 /* force reset */ + +/*02*/ u_int8_t nc_scntl2; /* no disconnect expected */ + #define SDU 0x80 /* cmd: disconnect will raise error */ + #define CHM 0x40 /* sta: chained mode */ + #define WSS 0x08 /* sta: wide scsi send [W]*/ + #define WSR 0x01 /* sta: wide scsi received [W]*/ + +/*03*/ u_int8_t nc_scntl3; /* cnf system clock dependent */ + #define EWS 0x08 /* cmd: enable wide scsi [W]*/ + +/*04*/ u_int8_t nc_scid; /* cnf host adapter scsi address */ + #define RRE 0x40 /* r/w:e enable response to resel. */ + #define SRE 0x20 /* r/w:e enable response to select */ + +/*05*/ u_int8_t nc_sxfer; /* ### Sync speed and count */ + +/*06*/ u_int8_t nc_sdid; /* ### Destination-ID */ + +/*07*/ u_int8_t nc_gpreg; /* ??? IO-Pins */ + +/*08*/ u_int8_t nc_sfbr; /* ### First byte in phase */ + +/*09*/ u_int8_t nc_socl; + #define CREQ 0x80 /* r/w: SCSI-REQ */ + #define CACK 0x40 /* r/w: SCSI-ACK */ + #define CBSY 0x20 /* r/w: SCSI-BSY */ + #define CSEL 0x10 /* r/w: SCSI-SEL */ + #define CATN 0x08 /* r/w: SCSI-ATN */ + #define CMSG 0x04 /* r/w: SCSI-MSG */ + #define CC_D 0x02 /* r/w: SCSI-C_D */ + #define CI_O 0x01 /* r/w: SCSI-I_O */ + +/*0a*/ u_int8_t nc_ssid; + +/*0b*/ u_int8_t nc_sbcl; + +/*0c*/ u_int8_t nc_dstat; + #define DFE 0x80 /* sta: dma fifo empty */ + #define MDPE 0x40 /* int: master data parity error */ + #define BF 0x20 /* int: script: bus fault */ + #define ABRT 0x10 /* int: script: command aborted */ + #define SSI 0x08 /* int: script: single step */ + #define SIR 0x04 /* int: script: interrupt instruct. */ + #define IID 0x01 /* int: script: illegal instruct. */ + +/*0d*/ u_int8_t nc_sstat0; + #define ILF 0x80 /* sta: data in SIDL register lsb */ + #define ORF 0x40 /* sta: data in SODR register lsb */ + #define OLF 0x20 /* sta: data in SODL register lsb */ + #define AIP 0x10 /* sta: arbitration in progress */ + #define LOA 0x08 /* sta: arbitration lost */ + #define WOA 0x04 /* sta: arbitration won */ + #define IRST 0x02 /* sta: scsi reset signal */ + #define SDP 0x01 /* sta: scsi parity signal */ + +/*0e*/ u_int8_t nc_sstat1; + #define FF3210 0xf0 /* sta: bytes in the scsi fifo */ + +/*0f*/ u_int8_t nc_sstat2; + #define ILF1 0x80 /* sta: data in SIDL register msb[W]*/ + #define ORF1 0x40 /* sta: data in SODR register msb[W]*/ + #define OLF1 0x20 /* sta: data in SODL register msb[W]*/ + #define LDSC 0x02 /* sta: disconnect & reconnect */ + +/*10*/ u_int32_t nc_dsa; /* --> Base page */ + +/*14*/ u_int8_t nc_istat; /* --> Main Command and status */ + #define CABRT 0x80 /* cmd: abort current operation */ + #define SRST 0x40 /* mod: reset chip */ + #define SIGP 0x20 /* r/w: message from host to ncr */ + #define SEM 0x10 /* r/w: message between host + ncr */ + #define CON 0x08 /* sta: connected to scsi */ + #define INTF 0x04 /* sta: int on the fly (reset by wr)*/ + #define SIP 0x02 /* sta: scsi-interrupt */ + #define DIP 0x01 /* sta: host/script interrupt */ + +/*15*/ u_int8_t nc_15_; +/*16*/ u_int8_t nc_16_; +/*17*/ u_int8_t nc_17_; + +/*18*/ u_int8_t nc_ctest0; +/*19*/ u_int8_t nc_ctest1; + +/*1a*/ u_int8_t nc_ctest2; + #define CSIGP 0x40 + +/*1b*/ u_int8_t nc_ctest3; + #define FLF 0x08 /* cmd: flush dma fifo */ + #define CLF 0x04 /* cmd: clear dma fifo */ + #define FM 0x02 /* mod: fetch pin mode */ + #define WRIE 0x01 /* mod: write and invalidate enable */ + +/*1c*/ u_int32_t nc_temp; /* ### Temporary stack */ + +/*20*/ u_int8_t nc_dfifo; +/*21*/ u_int8_t nc_ctest4; + #define BDIS 0x80 /* mod: burst disable */ + #define MPEE 0x08 /* mod: master parity error enable */ + +/*22*/ u_int8_t nc_ctest5; + #define DFS 0x20 /* mod: dma fifo size */ +/*23*/ u_int8_t nc_ctest6; + +/*24*/ u_int32_t nc_dbc; /* ### Byte count and command */ +/*28*/ u_int32_t nc_dnad; /* ### Next command register */ +/*2c*/ u_int32_t nc_dsp; /* --> Script Pointer */ +/*30*/ u_int32_t nc_dsps; /* --> Script pointer save/opcode#2 */ +/*34*/ u_int32_t nc_scratcha; /* ??? Temporary register a */ + +/*38*/ u_int8_t nc_dmode; + #define BL_2 0x80 /* mod: burst length shift value +2 */ + #define BL_1 0x40 /* mod: burst length shift value +1 */ + #define ERL 0x08 /* mod: enable read line */ + #define ERMP 0x04 /* mod: enable read multiple */ + #define BOF 0x02 /* mod: burst op code fetch */ + +/*39*/ u_int8_t nc_dien; +/*3a*/ u_int8_t nc_dwt; + +/*3b*/ u_int8_t nc_dcntl; /* --> Script execution control */ + #define CLSE 0x80 /* mod: cache line size enable */ + #define PFF 0x40 /* cmd: pre-fetch flush */ + #define PFEN 0x20 /* mod: pre-fetch enable */ + #define SSM 0x10 /* mod: single step mode */ + #define IRQM 0x08 /* mod: irq mode (1 = totem pole !) */ + #define STD 0x04 /* cmd: start dma mode */ + #define IRQD 0x02 /* mod: irq disable */ + #define NOCOM 0x01 /* cmd: protect sfbr while reselect */ + +/*3c*/ u_int32_t nc_adder; + +/*40*/ u_int16_t nc_sien; /* -->: interrupt enable */ +/*42*/ u_int16_t nc_sist; /* <--: interrupt status */ + #define STO 0x0400/* sta: timeout (select) */ + #define GEN 0x0200/* sta: timeout (general) */ + #define HTH 0x0100/* sta: timeout (handshake) */ + #define MA 0x80 /* sta: phase mismatch */ + #define CMP 0x40 /* sta: arbitration complete */ + #define SEL 0x20 /* sta: selected by another device */ + #define RSL 0x10 /* sta: reselected by another device*/ + #define SGE 0x08 /* sta: gross error (over/underflow)*/ + #define UDC 0x04 /* sta: unexpected disconnect */ + #define RST 0x02 /* sta: scsi bus reset detected */ + #define PAR 0x01 /* sta: scsi parity error */ + +/*44*/ u_int8_t nc_slpar; +/*45*/ u_int8_t nc_swide; +/*46*/ u_int8_t nc_macntl; +/*47*/ u_int8_t nc_gpcntl; +/*48*/ u_int8_t nc_stime0; /* cmd: timeout for select&handshake*/ +/*49*/ u_int8_t nc_stime1; /* cmd: timeout user defined */ +/*4a*/ u_int16_t nc_respid; /* sta: Reselect-IDs */ + +/*4c*/ u_int8_t nc_stest0; + +/*4d*/ u_int8_t nc_stest1; + #define DBLEN 0x08 /* clock doubler running */ + #define DBLSEL 0x04 /* clock doubler selected */ + +/*4e*/ u_int8_t nc_stest2; + #define ROF 0x40 /* reset scsi offset (after gross error!) */ + #define EXT 0x02 /* extended filtering */ + +/*4f*/ u_int8_t nc_stest3; + #define TE 0x80 /* c: tolerAnt enable */ + #define HSC 0x20 /* c: Halt SCSI Clock */ + #define CSF 0x02 /* c: clear scsi fifo */ + +/*50*/ u_int16_t nc_sidl; /* Lowlevel: latched from scsi data */ +/*52*/ u_int8_t nc_stest4; + #define SMODE 0xc0 /* SCSI bus mode (895/6 only) */ + #define SMODE_HVD 0x40 /* High Voltage Differential */ + #define SMODE_SE 0x80 /* Single Ended */ + #define SMODE_LVD 0xc0 /* Low Voltage Differential */ + #define LCKFRQ 0x20 /* Frequency Lock (895/6 only) */ + +/*53*/ u_int8_t nc_53_; +/*54*/ u_int16_t nc_sodl; /* Lowlevel: data out to scsi data */ +/*56*/ u_int16_t nc_56_; +/*58*/ u_int16_t nc_sbdl; /* Lowlevel: data from scsi data */ +/*5a*/ u_int16_t nc_5a_; +/*5c*/ u_int8_t nc_scr0; /* Working register B */ +/*5d*/ u_int8_t nc_scr1; /* */ +/*5e*/ u_int8_t nc_scr2; /* */ +/*5f*/ u_int8_t nc_scr3; /* */ +/*60*/ +}; + +/*----------------------------------------------------------- +** +** Utility macros for the script. +** +**----------------------------------------------------------- +*/ + +#define REGJ(p,r) (offsetof(struct ncr_reg, p ## r)) +#define REG(r) REGJ (nc_, r) + +#ifndef TARGET_MODE +#define TARGET_MODE 0 +#endif + +typedef u_int32_t ncrcmd; + +#if BYTE_ORDER == BIG_ENDIAN +#define SCR_BO(x) (((x) >> 24) | (((x) >> 8) & 0xff00) | \ + ((x) << 24) | (((x) & 0xff00) << 8)) +#else +#define SCR_BO(x) (x) +#endif + +/*----------------------------------------------------------- +** +** SCSI phases +** +**----------------------------------------------------------- +*/ + +#define SCR_DATA_OUT 0x00000000 +#define SCR_DATA_IN 0x01000000 +#define SCR_COMMAND 0x02000000 +#define SCR_STATUS 0x03000000 +#define SCR_ILG_OUT 0x04000000 +#define SCR_ILG_IN 0x05000000 +#define SCR_MSG_OUT 0x06000000 +#define SCR_MSG_IN 0x07000000 + +/*----------------------------------------------------------- +** +** Data transfer via SCSI. +** +**----------------------------------------------------------- +** +** MOVE_ABS (LEN) +** <> +** +** MOVE_IND (LEN) +** <> +** +** MOVE_TBL +** <> +** +**----------------------------------------------------------- +*/ + +#define SCR_MOVE_ABS(l) ((0x08000000 ^ (TARGET_MODE << 1ul)) | (l)) +#define SCR_MOVE_IND(l) ((0x28000000 ^ (TARGET_MODE << 1ul)) | (l)) +#define SCR_MOVE_TBL (0x18000000 ^ (TARGET_MODE << 1ul)) + +struct scr_tblmove { + u_int32_t size; + u_int32_t addr; +}; + +/*----------------------------------------------------------- +** +** Selection +** +**----------------------------------------------------------- +** +** SEL_ABS | SCR_ID (0..7) [ | REL_JMP] +** <> +** +** SEL_TBL | << dnad_offset>> [ | REL_JMP] +** <> +** +**----------------------------------------------------------- +*/ + +#define SCR_SEL_ABS 0x40000000 +#define SCR_SEL_ABS_ATN 0x41000000 +#define SCR_SEL_TBL 0x42000000 +#define SCR_SEL_TBL_ATN 0x43000000 + +struct scr_tblsel { + u_int8_t sel_0; + u_int8_t sel_sxfer; + u_int8_t sel_id; + u_int8_t sel_scntl3; +}; + +#define SCR_JMP_REL 0x04000000 +#define SCR_ID(id) (((u_int32_t)(id)) << 16) + +/*----------------------------------------------------------- +** +** Waiting for Disconnect or Reselect +** +**----------------------------------------------------------- +** +** WAIT_DISC +** dummy: <> +** +** WAIT_RESEL +** <> +** +**----------------------------------------------------------- +*/ + +#define SCR_WAIT_DISC 0x48000000 +#define SCR_WAIT_RESEL 0x50000000 + +/*----------------------------------------------------------- +** +** Bit Set / Reset +** +**----------------------------------------------------------- +** +** SET (flags {|.. }) +** +** CLR (flags {|.. }) +** +**----------------------------------------------------------- +*/ + +#define SCR_SET(f) (0x58000000 | (f)) +#define SCR_CLR(f) (0x60000000 | (f)) + +#define SCR_CARRY 0x00000400 +#define SCR_TRG 0x00000200 +#define SCR_ACK 0x00000040 +#define SCR_ATN 0x00000008 + + +/*----------------------------------------------------------- +** +** Memory to memory move +** +**----------------------------------------------------------- +** +** COPY (bytecount) +** << source_address >> +** << destination_address >> +** +** SCR_COPY sets the NO FLUSH option by default. +** SCR_COPY_F does not set this option. +** +** For chips which do not support this option, +** ncr_copy_and_bind() will remove this bit. +**----------------------------------------------------------- +*/ + +#define SCR_NO_FLUSH 0x01000000 + +#define SCR_COPY(n) (0xc0000000 | SCR_NO_FLUSH | (n)) +#define SCR_COPY_F(n) (0xc0000000 | (n)) + + +/*----------------------------------------------------------- +** +** Register move and binary operations +** +**----------------------------------------------------------- +** +** SFBR_REG (reg, op, data) reg = SFBR op data +** << 0 >> +** +** REG_SFBR (reg, op, data) SFBR = reg op data +** << 0 >> +** +** REG_REG (reg, op, data) reg = reg op data +** << 0 >> +** +**----------------------------------------------------------- +*/ + +#define SCR_REG_OFS(ofs) ((ofs) << 16ul) + +#define SCR_SFBR_REG(reg,op,data) \ + (0x68000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul)) + +#define SCR_REG_SFBR(reg,op,data) \ + (0x70000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul)) + +#define SCR_REG_REG(reg,op,data) \ + (0x78000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul)) + + +#define SCR_LOAD 0x00000000 +#define SCR_SHL 0x01000000 +#define SCR_OR 0x02000000 +#define SCR_XOR 0x03000000 +#define SCR_AND 0x04000000 +#define SCR_SHR 0x05000000 +#define SCR_ADD 0x06000000 +#define SCR_ADDC 0x07000000 + +/*----------------------------------------------------------- +** +** FROM_REG (reg) reg = SFBR +** << 0 >> +** +** TO_REG (reg) SFBR = reg +** << 0 >> +** +** LOAD_REG (reg, data) reg = +** << 0 >> +** +** LOAD_SFBR(data) SFBR = +** << 0 >> +** +**----------------------------------------------------------- +*/ + +#define SCR_FROM_REG(reg) \ + SCR_REG_SFBR(reg,SCR_OR,0) + +#define SCR_TO_REG(reg) \ + SCR_SFBR_REG(reg,SCR_OR,0) + +#define SCR_LOAD_REG(reg,data) \ + SCR_REG_REG(reg,SCR_LOAD,data) + +#define SCR_LOAD_SFBR(data) \ + (SCR_REG_SFBR (gpreg, SCR_LOAD, data)) + +/*----------------------------------------------------------- +** +** Waiting for Disconnect or Reselect +** +**----------------------------------------------------------- +** +** JUMP [ | IFTRUE/IFFALSE ( ... ) ] +** <
> +** +** JUMPR [ | IFTRUE/IFFALSE ( ... ) ] +** <> +** +** CALL [ | IFTRUE/IFFALSE ( ... ) ] +** <
> +** +** CALLR [ | IFTRUE/IFFALSE ( ... ) ] +** <> +** +** RETURN [ | IFTRUE/IFFALSE ( ... ) ] +** <> +** +** INT [ | IFTRUE/IFFALSE ( ... ) ] +** <> +** +** INT_FLY [ | IFTRUE/IFFALSE ( ... ) ] +** <> +** +** Conditions: +** WHEN (phase) +** IF (phase) +** CARRY +** DATA (data, mask) +** +**----------------------------------------------------------- +*/ + +#define SCR_NO_OP 0x80000000 +#define SCR_JUMP 0x80080000 +#define SCR_JUMPR 0x80880000 +#define SCR_CALL 0x88080000 +#define SCR_CALLR 0x88880000 +#define SCR_RETURN 0x90080000 +#define SCR_INT 0x98080000 +#define SCR_INT_FLY 0x98180000 + +#define IFFALSE(arg) (0x00080000 | (arg)) +#define IFTRUE(arg) (0x00000000 | (arg)) + +#define WHEN(phase) (0x00030000 | (phase)) +#define IF(phase) (0x00020000 | (phase)) + +#define DATA(D) (0x00040000 | ((D) & 0xff)) +#define MASK(D,M) (0x00040000 | (((M ^ 0xff) & 0xff) << 8ul)|((D) & 0xff)) + +#define CARRYSET (0x00200000) + +/*----------------------------------------------------------- +** +** SCSI constants. +** +**----------------------------------------------------------- +*/ + +/* +** Messages +*/ +#ifdef __OpenBSD__ +#include + +#define M_COMPLETE MSG_CMDCOMPLETE +#define M_EXTENDED MSG_EXTENDED +#define M_SAVE_DP MSG_SAVEDATAPOINTER +#define M_RESTORE_DP MSG_RESTOREPOINTERS +#define M_DISCONNECT MSG_DISCONNECT +#define M_ID_ERROR MSG_INITIATOR_DET_ERR +#define M_ABORT MSG_ABORT +#define M_REJECT MSG_MESSAGE_REJECT +#define M_NOOP MSG_NOOP +#define M_PARITY MSG_PARITY_ERROR +#define M_LCOMPLETE MSG_LINK_CMD_COMPLETE +#define M_FCOMPLETE MSG_LINK_CMD_COMPLETEF +#define M_RESET MSG_BUS_DEV_RESET +#define M_ABORT_TAG MSG_ABORT_TAG +#define M_CLEAR_QUEUE MSG_CLEAR_QUEUE +#define M_INIT_REC MSG_INIT_RECOVERY +#define M_REL_REC MSG_REL_RECOVERY +#define M_TERMINATE MSG_TERM_IO_PROC +#define M_SIMPLE_TAG MSG_SIMPLE_Q_TAG +#define M_HEAD_TAG MSG_HEAD_OF_Q_TAG +#define M_ORDERED_TAG MSG_ORDERED_Q_TAG +#define M_IGN_RESIDUE MSG_IGN_WIDE_RESIDUE +#define M_IDENTIFY MSG_IDENTIFY(0, 0) + +/* #define M_X_MODIFY_DP (0x00) */ /* XXX what is this? */ +#define M_X_SYNC_REQ MSG_EXT_SDTR +#define M_X_WIDE_REQ MSG_EXT_WDTR +#else +#define M_COMPLETE (0x00) +#define M_EXTENDED (0x01) +#define M_SAVE_DP (0x02) +#define M_RESTORE_DP (0x03) +#define M_DISCONNECT (0x04) +#define M_ID_ERROR (0x05) +#define M_ABORT (0x06) +#define M_REJECT (0x07) +#define M_NOOP (0x08) +#define M_PARITY (0x09) +#define M_LCOMPLETE (0x0a) +#define M_FCOMPLETE (0x0b) +#define M_RESET (0x0c) +#define M_ABORT_TAG (0x0d) +#define M_CLEAR_QUEUE (0x0e) +#define M_INIT_REC (0x0f) +#define M_REL_REC (0x10) +#define M_TERMINATE (0x11) +#define M_SIMPLE_TAG (0x20) +#define M_HEAD_TAG (0x21) +#define M_ORDERED_TAG (0x22) +#define M_IGN_RESIDUE (0x23) +#define M_IDENTIFY (0x80) + +#define M_X_MODIFY_DP (0x00) +#define M_X_SYNC_REQ (0x01) +#define M_X_WIDE_REQ (0x03) +#endif + + +/* +** Status +*/ + +#define S_GOOD (0x00) +#define S_CHECK_COND (0x02) +#define S_COND_MET (0x04) +#define S_BUSY (0x08) +#define S_INT (0x10) +#define S_INT_COND_MET (0x14) +#define S_CONFLICT (0x18) +#define S_TERMINATED (0x20) +#define S_QUEUE_FULL (0x28) +#define S_ILLEGAL (0xff) +#define S_SENSE (0x80) + +/* +** Bits defining chip features. +** For now only some of them are used, since we explicitely +** deal with PCI device id and revision id. +*/ +#define FE_LED0 (1<<0) +#define FE_WIDE (1<<1) +#define FE_ULTRA (1<<2) +#define FE_ULTRA2 (1<<3) +#define FE_DBLR (1<<4) +#define FE_QUAD (1<<5) +#define FE_ERL (1<<6) +#define FE_CLSE (1<<7) +#define FE_WRIE (1<<8) +#define FE_ERMP (1<<9) +#define FE_BOF (1<<10) +#define FE_DFS (1<<11) +#define FE_PFEN (1<<12) +#define FE_LDSTR (1<<13) +#define FE_RAM (1<<14) +#define FE_CLK80 (1<<15) +#define FE_DIFF (1<<16) +#define FE_BIOS (1<<17) +#define FE_CACHE_SET (FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP) +#define FE_SCSI_SET (FE_WIDE|FE_ULTRA|FE_ULTRA2|FE_DBLR|FE_QUAD|F_CLK80) +#define FE_SPECIAL_SET (FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM) + +#endif /*__NCR_REG_H__*/ -- cgit v1.2.3