diff options
author | Jason Downs <downsj@cvs.openbsd.org> | 1996-10-13 20:36:17 +0000 |
---|---|---|
committer | Jason Downs <downsj@cvs.openbsd.org> | 1996-10-13 20:36:17 +0000 |
commit | ceb0b36530a0cabb0fc6023eddc2327618b5356c (patch) | |
tree | b0cd3f0b8039085f7fc0a223cf9ec148c97daef1 /sys/dev/pci | |
parent | 9b73af68344ca1498c0ae9990cd700441db92f22 (diff) |
Updated driver to match FreeBSD, from Dave Huang <khym@bga.com>.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/ncr.c | 461 | ||||
-rw-r--r-- | sys/dev/pci/ncr_reg.h | 4 |
2 files changed, 263 insertions, 202 deletions
diff --git a/sys/dev/pci/ncr.c b/sys/dev/pci/ncr.c index 8cf1591d3f5..247e96b529d 100644 --- a/sys/dev/pci/ncr.c +++ b/sys/dev/pci/ncr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ncr.c,v 1.14 1996/10/12 01:08:13 downsj Exp $ */ +/* $OpenBSD: ncr.c,v 1.15 1996/10/13 20:36:14 downsj Exp $ */ /* $NetBSD: ncr.c,v 1.35.4.1 1996/06/03 20:32:17 cgd Exp $ */ /************************************************************************** @@ -15,6 +15,7 @@ ** ** Ported to NetBSD by ** Charles M. Hannum <mycroft@gnu.ai.mit.edu> +** Dave Huang <khym@bga.com> ** **------------------------------------------------------------------------- ** @@ -52,6 +53,12 @@ #define NCR_GETCC_WITHMSG +#ifdef FAILSAFE +#define SCSI_NCR_DFLT_TAGS (0) +#define MAX_LUN (1) +#define CDROM_ASYNC +#endif /* FAILSAFE */ + /*========================================================== ** ** Configuration and Debugging @@ -94,9 +101,9 @@ ** Used only for disk devices that support tags. */ -#ifndef SCSI_NCR_MAX_TAGS -#define SCSI_NCR_MAX_TAGS (4) -#endif /* SCSI_NCR_MAX_TAGS */ +#ifndef SCSI_NCR_DFLT_TAGS +#define SCSI_NCR_DFLT_TAGS (4) +#endif /* SCSI_NCR_DFLT_TAGS */ /*========================================================== ** @@ -128,7 +135,7 @@ ** The calculation below is actually quite silly ... */ -#define MAX_START (MAX_TARGET + 7 * SCSI_NCR_MAX_TAGS) +#define MAX_START (MAX_TARGET + 7 * SCSI_NCR_DFLT_TAGS) /* ** The maximum number of segments a transfer is split into. @@ -173,23 +180,24 @@ #include <sys/malloc.h> #include <sys/buf.h> #include <sys/kernel.h> +#if defined(__NetBSD__) || defined(__OpenBSD__) +#define bootverbose 1 +#endif #if !(defined(__NetBSD__) || defined(__OpenBSD__)) +#include <sys/sysctl.h> #include <machine/clock.h> -#include <machine/cpu.h> /* bootverbose */ -#else -#define bootverbose 1 #endif #include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> #include <vm/vm_extern.h> #endif /* KERNEL */ #if !(defined(__NetBSD__) || defined(__OpenBSD__)) -#include <sys/devconf.h> #include <pci/pcivar.h> #include <pci/pcireg.h> #include <pci/ncrreg.h> -extern PRINT_ADDR(); #else #include <sys/device.h> #include <machine/bus.h> @@ -204,9 +212,6 @@ extern PRINT_ADDR(); #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) -#include <machine/clock.h> -#endif /* __NetBSD__ */ #if (defined(__NetBSD__) || defined(__OpenBSD__)) && defined(__alpha__) /* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */ @@ -1197,7 +1202,7 @@ struct script { ncrcmd skip [ 8]; ncrcmd skip2 [ 3]; ncrcmd idle [ 2]; - ncrcmd select [ 24]; + ncrcmd select [ 22]; ncrcmd prepare [ 4]; ncrcmd loadpos [ 14]; ncrcmd prepare2 [ 24]; @@ -1262,20 +1267,20 @@ struct script { */ #ifdef KERNEL -static void ncr_alloc_ccb (ncb_p np, struct scsi_xfer * xp); +static void ncr_alloc_ccb (ncb_p np, u_long target, u_long lun); static void ncr_complete (ncb_p np, ccb_p cp); static int ncr_delta (struct timeval * from, struct timeval * to); static void ncr_exception (ncb_p np); static void ncr_free_ccb (ncb_p np, ccb_p cp, int flags); -static void ncr_getclock (ncb_p np, u_char scntl3); +static void ncr_getclock (ncb_p np); 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__) -static int ncr_intr (void *); -#else /* !__NetBSD__ */ -static int ncr_intr (ncb_p np); +static int ncr_intr (void *vnp); +#else +static void ncr_intr (void *vnp); static U_INT32 ncr_info (int unit); -#endif /* __NetBSD__ */ +#endif /* !__NetBSD__ */ static void ncr_int_ma (ncb_p np); static void ncr_int_sir (ncb_p np); static void ncr_int_sto (ncb_p np); @@ -1293,8 +1298,8 @@ 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); -static int ncr_scatter (ncb_p np, struct dsb* phys,u_long vaddr, - u_long datalen); +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); @@ -1309,7 +1314,7 @@ static void ncr_wakeup (ncb_p np, u_long code); #if defined(__NetBSD__) || defined(__OpenBSD__) static int ncr_probe (struct device *, void *, void *); static void ncr_attach (struct device *, struct device *, void *); -#else /* !__NetBSD */ +#else /* !__NetBSD__ */ static char* ncr_probe (pcici_t tag, pcidi_t type); static void ncr_attach (pcici_t tag, int unit); #endif /* __NetBSD__ */ @@ -1331,7 +1336,7 @@ static char ident[] = "\n$NetBSD: ncr.c,v 1.35.4.1 1996/06/03 20:32:17 cgd Exp $\n"; #endif -u_long ncr_version = NCR_VERSION * 11 +static const u_long ncr_version = NCR_VERSION * 11 + (u_long) sizeof (struct ncb) * 7 + (u_long) sizeof (struct ccb) * 5 + (u_long) sizeof (struct lcb) * 3 @@ -1340,13 +1345,16 @@ u_long ncr_version = NCR_VERSION * 11 #ifdef KERNEL #if !(defined(__NetBSD__) || defined(__OpenBSD__)) -u_long nncr=MAX_UNITS; -ncb_p ncrp [MAX_UNITS]; +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__ */ static int ncr_debug = SCSI_DEBUG_FLAGS; +#if !defined(__NetBSD__) && !defined(__OpenBSD__) +SYSCTL_INT(_debug, OID_AUTO, ncr_debug, CTLFLAG_RW, &ncr_debug, 0, ""); +#endif /* !__NetBSD__ */ -int ncr_cache; /* to be aligned _NOT_ static */ +static int ncr_cache; /* to be aligned _NOT_ static */ /*========================================================== ** @@ -1378,7 +1386,7 @@ struct cfdriver ncr_cd = { static u_long ncr_count; -struct pci_device ncr_device = { +static struct pci_device ncr_device = { "ncr", ncr_probe, ncr_attach, @@ -1390,7 +1398,7 @@ DATA_SET (pcidevice_set, ncr_device); #endif /* !__NetBSD__ */ -struct scsi_adapter ncr_switch = +static struct scsi_adapter ncr_switch = { ncr_start, #if !(defined(__NetBSD__) || defined(__OpenBSD__)) @@ -1406,7 +1414,7 @@ struct scsi_adapter ncr_switch = #endif /* !__NetBSD__ */ }; -struct scsi_device ncr_dev = +static struct scsi_device ncr_dev = { NULL, /* Use default error handler */ NULL, /* have a queue, served by this */ @@ -1676,8 +1684,10 @@ static struct script script0 = { */ SCR_MOVE_TBL ^ SCR_MSG_OUT, offsetof (struct dsb, smsg), +#ifdef undef /* XXX better fail than try to deal with this ... */ SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_OUT)), -16, +#endif SCR_CLR (SCR_ATN), 0, SCR_COPY (1), @@ -2746,7 +2756,7 @@ static struct script script0 = { ** - struct ccb ** to understand what's going on. */ - SCR_REG_SFBR (ssid, SCR_AND, 0x87), + SCR_REG_SFBR (ssid, SCR_AND, 0x8F), 0, SCR_TO_REG (ctest0), 0, @@ -3472,6 +3482,14 @@ static void ncr_attach (pcici_t config_id, int unit) if (!pci_map_mem (config_id, 0x14, &np->vaddr, &np->paddr)) return; + /* + ** Make the controller's registers available. + ** Now the INB INW INL OUTB OUTW OUTL macros + ** can be used safely. + */ + + np->reg = (struct ncr_reg*) np->vaddr; + #ifdef NCR_IOMAPPED /* ** Try to map the controller chip into iospace. @@ -3487,17 +3505,30 @@ static void ncr_attach (pcici_t config_id, int unit) ** Do chip dependent initialization. */ + np->maxwide = 0; + np->rv_scntl3 = 0x13; /* default: 40MHz clock */ + np->ns_sync = 25; + np->ns_async = 50; + + /* + ** Get the frequency of the chip's clock. + ** Find the right value for scntl3. + */ + #if defined(__NetBSD__) || defined(__OpenBSD__) switch (pa->pa_id) { #else /* !__NetBSD__ */ switch (pci_conf_read (config_id, PCI_ID_REG)) { #endif /* __NetBSD__ */ case NCR_825_ID: - case NCR_875_ID: np->maxwide = 1; break; - default: - np->maxwide = 0; + case NCR_860_ID: + np->rv_scntl3 = 0x35; /* always assume 80MHz clock for 860 */ + break; + case NCR_875_ID: + np->maxwide = 1; + ncr_getclock(np); break; } @@ -3516,16 +3547,6 @@ static void ncr_attach (pcici_t config_id, int unit) np->jump_tcb.l_cmd = SCR_JUMP; np->jump_tcb.l_paddr = NCB_SCRIPT_PHYS (np, abort); -#if !(defined(__NetBSD__) || defined(__OpenBSD__)) - /* - ** Make the controller's registers available. - ** Now the INB INW INL OUTB OUTW OUTL macros - ** can be used safely. - */ - - np->reg = (struct ncr_reg*) np->vaddr; -#endif - /* ** Get SCSI addr of host adapter (set by bios?). */ @@ -3534,13 +3555,6 @@ static void ncr_attach (pcici_t config_id, int unit) if (!np->myaddr) np->myaddr = SCSI_NCR_MYADDR; /* - ** Get the value of the chip's clock. - ** Find the right value for scntl3. - */ - - ncr_getclock (np, INB(nc_scntl3)); - - /* ** Reset chip. */ @@ -3620,6 +3634,7 @@ static void ncr_attach (pcici_t config_id, int unit) np->sc_link.openings = 1; #else /* !__NetBSD__ */ 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__ */ @@ -3669,6 +3684,11 @@ static void ncr_attach (pcici_t config_id, int unit) np->lasttime=0; /* + ** use SIMPLE TAG messages by default + */ + + np->order = M_SIMPLE_TAG; + /* ** Done. */ @@ -3685,18 +3705,17 @@ static void ncr_attach (pcici_t config_id, int unit) */ #if defined(__NetBSD__) || defined(__OpenBSD__) -int -ncr_intr(arg) - void *arg; -{ - ncb_p np = arg; +static int #else /* !__NetBSD__ */ -int -ncr_intr(np) - ncb_p np; -{ +static void #endif /* __NetBSD__ */ +ncr_intr(vnp) + void *vnp; +{ +#if defined(__NetBSD__) || defined(__OpenBSD__) int n = 0; +#endif + ncb_p np = vnp; int oldspl = splbio(); if (DEBUG_FLAGS & DEBUG_TINY) printf ("["); @@ -3709,14 +3728,18 @@ ncr_intr(np) ncr_exception (np); } while (INB(nc_istat) & (INTF|SIP|DIP)); - n=1; +#if defined(__NetBSD__) || defined(__OpenBSD__) + n = 1; +#endif np->ticks = 100; }; if (DEBUG_FLAGS & DEBUG_TINY) printf ("]\n"); splx (oldspl); +#if defined(__NetBSD__) || defined(__OpenBSD__) return (n); +#endif } /*========================================================== @@ -3731,11 +3754,7 @@ ncr_intr(np) static INT32 ncr_start (struct scsi_xfer * xp) { -#if defined(__NetBSD__) || defined(__OpenBSD__) - ncb_p np = xp->sc_link->adapter_softc; -#else /*__NetBSD__*/ - ncb_p np = ncrp[xp->sc_link->adapter_unit]; -#endif/*__NetBSD__*/ + ncb_p np = (ncb_p) xp->sc_link->adapter_softc; struct scsi_generic * cmd = xp->cmd; ccb_p cp; @@ -3743,11 +3762,9 @@ static INT32 ncr_start (struct scsi_xfer * xp) tcb_p tp = &np->target[xp->sc_link->target]; int i, oldspl, segments, flags = xp->flags; - u_char ptr, nego, idmsg; + u_char qidx, nego, idmsg, *msgptr; u_long msglen, msglen2; - - /*--------------------------------------------- ** ** Reset SCSI bus @@ -3798,10 +3815,25 @@ 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", + xp->datalen, xp->data); + { + int i; + PRINT_ADDR(xp); + printf ("command: %2x (", cmd->opcode); + for (i = 0; i<11; i++) + printf (" %2x", cmd->bytes[i]); + printf (")\n"); + } + } + if (DEBUG_FLAGS & DEBUG_TINY) { PRINT_ADDR(xp); - printf ("CMD=%x F=%x L=%x ", cmd->opcode, - (unsigned)xp->flags, (unsigned) xp->datalen); + printf ("CMD=%x F=%x A=%x L=%x ", + cmd->opcode, (unsigned)xp->flags, + (unsigned) xp->data, (unsigned) xp->datalen); } /*-------------------------------------------- @@ -3889,10 +3921,21 @@ static INT32 ncr_start (struct scsi_xfer * xp) if (tp->inqdata[7]) { /* + ** negotiate wide transfers ? + */ + + if (!tp->widedone) { + if (tp->inqdata[7] & INQ7_WIDE16) { + nego = NS_WIDE; + } else + tp->widedone=1; + }; + + /* ** negotiate synchronous transfers? */ - if (!tp->period) { + if (!nego && !tp->period) { if (SCSI_NCR_MAX_SYNC #if defined (CDROM_ASYNC) || defined (GENERIC) && ((tp->inqdata[0] & 0x1f) != 5) @@ -3906,17 +3949,6 @@ static INT32 ncr_start (struct scsi_xfer * xp) printf ("asynchronous.\n"); }; }; - - /* - ** negotiate wide transfers ? - */ - - if (!tp->widedone) { - if (tp->inqdata[7] & INQ7_WIDE16) { - if (!nego) nego = NS_WIDE; - } else - tp->widedone=1; - }; }; /*--------------------------------------------------- @@ -3954,25 +3986,18 @@ static INT32 ncr_start (struct scsi_xfer * xp) */ idmsg = M_IDENTIFY | xp->sc_link->lun; -#ifndef NCR_NO_DISCONNECT - /*--------------------------------------------------------------------- - ** Some users have problems with this driver. - ** I assume that the current problems relate to a conflict between - ** a disconnect and an immediately following reconnect operation. - ** With this option one can prevent the driver from using disconnects. - ** Without disconnects the performance will be severely degraded. - ** But it may help to trace down the core problem. - **--------------------------------------------------------------------- - */ if ((cp!=&np->ccb) && (np->disc)) idmsg |= 0x40; -#endif - cp -> scsi_smsg [0] = idmsg; - msglen=1; + msgptr = cp->scsi_smsg; + msglen = 0; + msgptr[msglen++] = idmsg; if (cp->tag) { + char tag; + tag = np->order; + if (tag == 0) { /* ** Ordered write ops, unordered read ops. */ @@ -3980,31 +4005,23 @@ static INT32 ncr_start (struct scsi_xfer * xp) case 0x08: /* READ_SMALL (6) */ case 0x28: /* READ_BIG (10) */ case 0xa8: /* READ_HUGE (12) */ - cp -> scsi_smsg [msglen] = M_SIMPLE_TAG; - break; + tag = M_SIMPLE_TAG; + break; default: - cp -> scsi_smsg [msglen] = M_ORDERED_TAG; + tag = M_ORDERED_TAG; } - - /* - ** can be overwritten by ncrcontrol - */ - switch (np->order) { - case M_SIMPLE_TAG: - case M_ORDERED_TAG: - cp -> scsi_smsg [msglen] = np->order; - }; - msglen++; - cp -> scsi_smsg [msglen++] = cp -> tag; + } + msgptr[msglen++] = tag; + msgptr[msglen++] = cp -> tag; } switch (nego) { case NS_SYNC: - cp -> scsi_smsg [msglen++] = M_EXTENDED; - cp -> scsi_smsg [msglen++] = 3; - cp -> scsi_smsg [msglen++] = M_X_SYNC_REQ; - cp -> scsi_smsg [msglen++] = tp->minsync; - cp -> scsi_smsg [msglen++] = tp->maxoffs; + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 3; + msgptr[msglen++] = M_X_SYNC_REQ; + msgptr[msglen++] = tp->minsync; + msgptr[msglen++] = tp->maxoffs; if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->xfer); printf ("sync msgout: "); @@ -4013,10 +4030,10 @@ static INT32 ncr_start (struct scsi_xfer * xp) }; break; case NS_WIDE: - cp -> scsi_smsg [msglen++] = M_EXTENDED; - cp -> scsi_smsg [msglen++] = 2; - cp -> scsi_smsg [msglen++] = M_X_WIDE_REQ; - cp -> scsi_smsg [msglen++] = tp->usrwide; + msgptr[msglen++] = M_EXTENDED; + msgptr[msglen++] = 2; + msgptr[msglen++] = M_X_WIDE_REQ; + msgptr[msglen++] = tp->usrwide; if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->xfer); printf ("wide msgout: "); @@ -4043,7 +4060,7 @@ static INT32 ncr_start (struct scsi_xfer * xp) **---------------------------------------------------- */ - segments = ncr_scatter (np, &cp->phys, (vm_offset_t) xp->data, + segments = ncr_scatter (&cp->phys, (vm_offset_t) xp->data, (vm_size_t) xp->datalen); if (segments < 0) { @@ -4098,11 +4115,9 @@ static INT32 ncr_start (struct scsi_xfer * xp) /* ** message */ -/* cp->phys.smsg.addr = cp->p_scsi_smsg;*/ cp->phys.smsg.addr = CCB_PHYS (cp, scsi_smsg); cp->phys.smsg.size = msglen; -/* cp->phys.smsg2.addr = cp->p_scsi_smsg2;*/ cp->phys.smsg2.addr = CCB_PHYS (cp, scsi_smsg2); cp->phys.smsg2.size = msglen2; /* @@ -4113,7 +4128,6 @@ static INT32 ncr_start (struct scsi_xfer * xp) /* ** sense command */ -/* cp->phys.scmd.addr = cp->p_sensecmd;*/ cp->phys.scmd.addr = CCB_PHYS (cp, sensecmd); cp->phys.scmd.size = 6; /* @@ -4161,11 +4175,11 @@ static INT32 ncr_start (struct scsi_xfer * xp) ** insert into start queue. */ - ptr = np->squeueput + 1; - if (ptr >= MAX_START) ptr=0; - np->squeue [ptr ] = NCB_SCRIPT_PHYS (np, idle); + qidx = np->squeueput + 1; + if (qidx >= MAX_START) qidx=0; + np->squeue [qidx ] = NCB_SCRIPT_PHYS (np, idle); np->squeue [np->squeueput] = CCB_PHYS (cp, phys); - np->squeueput = ptr; + np->squeueput = qidx; if(DEBUG_FLAGS & DEBUG_QUEUE) printf ("%s: queuepos=%d tryoffset=%d.\n", ncr_name (np), @@ -4295,7 +4309,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 & 0xfff, + printf ("CCB=%x STAT=%x/%x\n", (unsigned)cp & 0xfff, cp->host_status,cp->scsi_status); xp = cp->xfer; @@ -4371,7 +4385,7 @@ void ncr_complete (ncb_p np, ccb_p cp) /* ** Try to assign a ccb to this nexus */ - ncr_alloc_ccb (np, xp); + ncr_alloc_ccb (np, xp->sc_link->target, xp->sc_link->lun); /* ** On inquire cmd (0x12) save some data. @@ -4440,8 +4454,13 @@ void ncr_complete (ncb_p np, ccb_p cp) */ xp->error = XS_BUSY; - } else if ((cp->host_status == HS_SEL_TIMEOUT) - || (cp->host_status == HS_TIMEOUT)) { + } else if (cp->host_status == HS_SEL_TIMEOUT) { + + /* + ** Device failed selection + */ + xp->error = XS_SELTIMEOUT; + } else if(cp->host_status == HS_TIMEOUT) { /* ** No response @@ -4625,7 +4644,7 @@ void ncr_init (ncb_p np, char * msg, u_long code) OUTB (nc_ctest4, 0x08 ); /* enable master parity checking */ OUTB (nc_stest2, EXT ); /* Extended Sreq/Sack filtering */ OUTB (nc_stest3, TE ); /* TolerANT enable */ - OUTB (nc_stime0, 0xfb ); /* HTH = 1.6sec STO = 0.1 sec. */ + OUTB (nc_stime0, 0x0b ); /* HTH = disabled, STO = 0.1 sec. */ /* ** Reinitialize usrsync. @@ -4754,7 +4773,7 @@ static void ncr_setsync (ncb_p np, ccb_p cp, u_char sxfer) { struct scsi_xfer *xp; tcb_p tp; - u_char target = INB (nc_ctest0)&7; + u_char target = INB (nc_ctest0) & 0x0f; assert (cp); if (!cp) return; @@ -4762,7 +4781,7 @@ static void ncr_setsync (ncb_p np, ccb_p cp, u_char sxfer) xp = cp->xfer; assert (xp); if (!xp) return; - assert (target == (xp->sc_link->target & 7)); + assert (target == (xp->sc_link->target & 0x0f)); tp = &np->target[target]; tp->period= sxfer&0xf ? ((sxfer>>5)+4) * np->ns_sync : 0xffff; @@ -4811,7 +4830,7 @@ static void ncr_setsync (ncb_p np, ccb_p cp, u_char sxfer) static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide) { struct scsi_xfer *xp; - u_short target = INB (nc_ctest0)&7; + u_short target = INB (nc_ctest0) & 0x0f; tcb_p tp; u_char scntl3 = np->rv_scntl3 | (wide ? EWS : 0); @@ -4821,7 +4840,7 @@ static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide) xp = cp->xfer; assert (xp); if (!xp) return; - assert (target == (xp->sc_link->target & 7)); + assert (target == (xp->sc_link->target & 0x0f)); tp = &np->target[target]; tp->widedone = wide+1; @@ -4884,8 +4903,10 @@ static void ncr_settags (tcb_p tp, lcb_p lp) ** only disk devices ** only if enabled by user .. */ - if (( tp->inqdata[7] & INQ7_QUEUE) && ((tp->inqdata[0] & 0x1f)==0x00) - && tp->usrtags) { + if ((tp->inqdata[7] & INQ7_QUEUE) == 0) { + tp->usrtags=0; + } + if (tp->usrtags && ((tp->inqdata[0] & 0x1f) == 0x00)) { reqtags = tp->usrtags; if (lp->actlink <= 1) lp->usetags=reqtags; @@ -5034,6 +5055,7 @@ static void ncr_timeout (ncb_p np) OUTB (nc_istat, SIGP); }; +#ifdef undef if (np->latetime>4) { /* ** Although we tried to wake it up, @@ -5051,7 +5073,7 @@ static void ncr_timeout (ncb_p np) ncr_init (np, "ncr dead ?", HS_TIMEOUT); np->heartbeat = thistime; }; - +#endif /*---------------------------------------------------- ** ** handle ccb timeouts @@ -5141,13 +5163,14 @@ void ncr_exception (ncb_p np) ** interrupt on the fly ? */ while ((istat = INB (nc_istat)) & INTF) { - if (DEBUG_FLAGS & DEBUG_TINY) printf ("F"); + if (DEBUG_FLAGS & DEBUG_TINY) printf ("F "); OUTB (nc_istat, INTF); np->profile.num_fly++; ncr_wakeup (np, 0); }; - - if (!(istat & (SIP|DIP))) return; + if (!(istat & (SIP|DIP))) { + return; + } /* ** Steinbach's Guideline for Systems Programming: @@ -5579,9 +5602,9 @@ static void ncr_int_ma (ncb_p np) return; } if (cp != np->header.cp) { - printf ("%s: SCSI phase error fixup: CCB address mismatch (0x%08lx != 0x%08lx)\n", - ncr_name (np), (u_long) cp, (u_long) np->header.cp); - return; + 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;*/ } /* @@ -5725,7 +5748,7 @@ void ncr_int_sir (ncb_p np) u_char num = INB (nc_dsps); ccb_p cp=0; u_long dsa; - u_char target = INB (nc_ctest0) & 7; + u_char target = INB (nc_ctest0) & 0x0f; tcb_p tp = &np->target[target]; int i; if (DEBUG_FLAGS & DEBUG_TINY) printf ("I#%d", num); @@ -6043,7 +6066,7 @@ void ncr_int_sir (ncb_p np) if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->xfer); printf ("sync msgout: "); - (void) ncr_show_msg (np->msgin); + (void) ncr_show_msg (np->msgout); printf (".\n"); } @@ -6141,7 +6164,7 @@ void ncr_int_sir (ncb_p np) if (DEBUG_FLAGS & DEBUG_NEGO) { PRINT_ADDR(cp->xfer); printf ("wide msgout: "); - (void) ncr_show_msg (np->msgin); + (void) ncr_show_msg (np->msgout); printf (".\n"); } break; @@ -6385,20 +6408,13 @@ void ncr_free_ccb (ncb_p np, ccb_p cp, int flags) **========================================================== */ -static void ncr_alloc_ccb (ncb_p np, struct scsi_xfer * xp) +static void ncr_alloc_ccb (ncb_p np, u_long target, u_long lun) { tcb_p tp; lcb_p lp; ccb_p cp; - u_long target; - u_long lun; - assert (np != NULL); - assert (xp != NULL); - - target = xp->sc_link->target; - lun = xp->sc_link->lun; if (target>=MAX_TARGET) return; if (lun >=MAX_LUN ) return; @@ -6432,7 +6448,7 @@ static void ncr_alloc_ccb (ncb_p np, struct scsi_xfer * xp) tp->jump_lcb.l_paddr = NCB_SCRIPT_PHYS (np, abort); np->jump_tcb.l_paddr = vtophys (&tp->jump_tcb); - ncr_setmaxtags (tp, SCSI_NCR_MAX_TAGS); + ncr_setmaxtags (tp, SCSI_NCR_DFLT_TAGS); } /* @@ -6489,7 +6505,6 @@ static void ncr_alloc_ccb (ncb_p np, struct scsi_xfer * xp) return; if (DEBUG_FLAGS & DEBUG_ALLOC) { - PRINT_ADDR(xp); printf ("new ccb @%p.\n", cp); } @@ -6610,7 +6625,7 @@ static void ncr_opennings (ncb_p np, lcb_p lp, struct scsi_xfer * xp) */ static int ncr_scatter - (ncb_p np, struct dsb* phys, vm_offset_t vaddr, vm_size_t datalen) + (struct dsb* phys, vm_offset_t vaddr, vm_size_t datalen) { u_long paddr, pnext; @@ -6969,49 +6984,93 @@ static u_long ncr_lookup(char * id) # define NCR_CLOCK 40 #endif /* NCR_CLOCK */ - -static void ncr_getclock (ncb_p np, u_char scntl3) -{ - u_char tbl[6] = {6,2,3,4,6,8}; - u_char f; - u_char ns_clock = (1000/NCR_CLOCK); - - /* - ** Compute the best value for scntl3. - */ /* - f = (2 * MIN_SYNC_PD - 1) / ns_clock; - if (!f ) f=1; - if (f>4) f=4; - np -> ns_sync = (ns_clock * tbl[f]) / 2; - np -> rv_scntl3 = f<<4; - - f = (2 * MIN_ASYNC_PD - 1) / ns_clock; - if (!f ) f=1; - if (f>4) f=4; - np -> ns_async = (ns_clock * tbl[f]) / 2; - np -> rv_scntl3 |= f; - if (DEBUG_FLAGS & DEBUG_TIMING) - printf ("%s: sclk=%d async=%d sync=%d (ns) scntl3=0x%x\n", - ncr_name (np), ns_clock, np->ns_async, np->ns_sync, np->rv_scntl3); -*/ - - /* - * For now just preserve the BIOS setting ... - */ - - if ((scntl3 & 7) == 0) { - scntl3 = 3; /* assume 40MHz if no value supplied by BIOS */ - } - - np->ns_sync = 25; - np->ns_async = 50; - np->rv_scntl3 = ((scntl3 & 0x7) << 4) -0x20 + (scntl3 & 0x7); - - if (bootverbose) { - printf ("\tinitial value of SCNTL3 = %02x, final = %02x\n", - scntl3, np->rv_scntl3); - } + * calculate NCR SCSI clock frequency (in KHz) + */ +static unsigned +ncrgetfreq (ncb_p np, int gen) +{ + int ms = 0; + /* + * Measure GEN timer delay in order + * to calculate SCSI clock frequency + * + * This code will never execute too + * many loop iterations (if DELAY is + * reasonably correct). It could get + * too low a delay (too high a freq.) + * if the CPU is slow executing the + * loop for some reason (an NMI, for + * example). For this reason we will + * if multiple measurements are to be + * performed trust the higher delay + * (lower frequency returned). + */ + OUTB (nc_stest1, 0); /* make sure clock doubler is OFF */ + OUTW (nc_sien , 0); /* mask all scsi interrupts */ + (void) INW (nc_sist); /* clear pending scsi interrupt */ + OUTB (nc_dien , 0); /* mask all dma interrupts */ + (void) INW (nc_sist); /* another one, just to be sure :) */ + OUTB (nc_scntl3, 4); /* set pre-scaler to divide by 3 */ + OUTB (nc_stime1, 0); /* disable general purpose timer */ + OUTB (nc_stime1, gen); /* set to nominal delay of (1<<gen) * 125us */ + while (!(INW(nc_sist) & GEN) && ms++ < 1000) + DELAY(1000); /* count ms */ + OUTB (nc_stime1, 0); /* disable general purpose timer */ + OUTB (nc_scntl3, 0); + /* + * Set prescaler to divide by whatever "0" means. + * "0" ought to choose divide by 2, but appears + * to set divide by 3.5 mode in my 53c810 ... + */ + OUTB (nc_scntl3, 0); + + if (bootverbose) + printf ("\tDelay (GEN=%d): %u msec\n", gen, ms); + /* + * adjust for prescaler, and convert into KHz + */ + return ms ? ((1 << gen) * 4440) / ms : 0; + } + + static void ncr_getclock (ncb_p np) + { + unsigned char scntl3; + unsigned char stest1; + scntl3 = INB(nc_scntl3); + stest1 = INB(nc_stest1); + + /* always false, except for 875 with clock doubler selected */ + if ((stest1 & (DBLEN+DBLSEL)) == DBLEN+DBLSEL) { + OUTB(nc_stest1, 0); + scntl3 = 3; + } else { + if ((scntl3 & 7) == 0) { + unsigned f1, f2; + /* throw away first result */ + (void) ncrgetfreq (np, 11); + f1 = ncrgetfreq (np, 11); + f2 = ncrgetfreq (np, 11); + + if (bootverbose) + printf ("\tNCR clock is %uKHz, %uKHz\n", f1, f2); + if (f1 > f2) f1 = f2; /* trust lower result */ + if (f1 > 45000) { + scntl3 = 5; /* >45Mhz: assume 80MHz */ + } else { + scntl3 = 3; /* <45Mhz: assume 40MHz */ + } + } + } + + np->ns_sync = 25; + np->ns_async = 50; + np->rv_scntl3 = ((scntl3 & 0x7) << 4) -0x20 + (scntl3 & 0x7); + + if (bootverbose) { + printf ("\tinitial value of SCNTL3 = %02x, final = %02x\n", + scntl3, np->rv_scntl3); + } } /*=========================================================================*/ diff --git a/sys/dev/pci/ncr_reg.h b/sys/dev/pci/ncr_reg.h index e465d8f7e78..a5d62688ff8 100644 --- a/sys/dev/pci/ncr_reg.h +++ b/sys/dev/pci/ncr_reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ncr_reg.h,v 1.3 1996/04/18 23:48:01 niklas Exp $ */ +/* $OpenBSD: ncr_reg.h,v 1.4 1996/10/13 20:36:16 downsj Exp $ */ /* $NetBSD: ncr_reg.h,v 1.8 1996/03/11 23:06:04 cgd Exp $ */ /************************************************************************** @@ -224,6 +224,8 @@ struct ncr_reg { /*4c*/ U_INT8 nc_stest0; /*4d*/ U_INT8 nc_stest1; + #define DBLEN 0x08 /* clock doubler running */ + #define DBLSEL 0x04 /* clock doubler selected */ /*4e*/ U_INT8 nc_stest2; #define ROF 0x40 /* reset scsi offset (after gross error!) */ |