summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorse <se@FreeBSD.org>1995-09-07 20:53:40 +0000
committerse <se@FreeBSD.org>1995-09-07 20:53:40 +0000
commit13b2c6871dce957361bbd1e96d8e218a6482a799 (patch)
treec26c16e995dab8b1567dd64fa0909f412ff9edb9
parent39322cdbf1346f0f1c2e69cba8622f65063b4988 (diff)
downloadFreeBSD-src-13b2c6871dce957361bbd1e96d8e218a6482a799.zip
FreeBSD-src-13b2c6871dce957361bbd1e96d8e218a6482a799.tar.gz
Add support for 16 targets on WIDE SCSI bus.
This seems to work fine on my 53c810, but really should be tested on a 53c825 with at least one target set to an ID >= 8. The script is now copied to memory mapped using vm_page_alloc_contig(), since it has to be physically contigous. This must be changed, if the driver is converted into a loadable module ! Two of the probe messages are suppressed, unless "bootverbose" is set.
-rw-r--r--sys/pci/ncr.c209
1 files changed, 103 insertions, 106 deletions
diff --git a/sys/pci/ncr.c b/sys/pci/ncr.c
index d5d2470..53ec371 100644
--- a/sys/pci/ncr.c
+++ b/sys/pci/ncr.c
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** $Id: ncr.c,v 1.42 1995/08/23 23:03:25 gibbs Exp $
+** $Id: ncr.c,v 1.43 1995/09/05 22:37:59 se Exp $
**
** Device driver for the NCR 53C810 PCI-SCSI-Controller.
**
@@ -44,7 +44,7 @@
***************************************************************************
*/
-#define __NCR_C__ "pl22 95/07/07"
+#define NCR_DATE "pl23 95/09/07"
#define NCR_VERSION (2)
#define MAX_UNITS (16)
@@ -111,7 +111,7 @@
** #7 .. is myself.
*/
-#define MAX_TARGET (7)
+#define MAX_TARGET (16)
/*
** Number of logic units supported by the driver.
@@ -125,10 +125,11 @@
/*
** The maximum number of jobs scheduled for starting.
** There should be one slot per target, and one slot
-** for each tag of each target.
+** for each tag of each target in use.
+** The calculation below is actually quite silly ...
*/
-#define MAX_START (7 * SCSI_NCR_MAX_TAGS)
+#define MAX_START (MAX_TARGET + 7 * SCSI_NCR_MAX_TAGS)
/*
** The maximum number of segments a transfer is split into.
@@ -170,8 +171,12 @@
#include <sys/kernel.h>
#ifndef __NetBSD__
#include <machine/clock.h>
+#include <machine/cpu.h> /* bootverbose */
+#else
+#define bootverbose 1
#endif
#include <vm/vm.h>
+#include <vm/vm_extern.h>
#endif /* KERNEL */
@@ -1188,7 +1193,7 @@ 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
- (ncb_p np);
+ (struct script * script, ncb_p np);
static void ncr_script_fill (struct script * scr);
static int ncr_scatter (struct dsb* phys,u_long vaddr,u_long datalen);
static void ncr_setmaxtags (tcb_p tp, u_long usrtags);
@@ -1223,13 +1228,13 @@ static void ncr_attach (pcici_t tag, int unit);
static char ident[] =
- "\n$Id: ncr.c,v 1.42 1995/08/23 23:03:25 gibbs Exp $\n";
+ "\n$Id: ncr.c,v 1.43 1995/09/05 22:37:59 se Exp $\n";
-u_long ncr_version = NCR_VERSION
- + (u_long) sizeof (struct ncb)
- * (u_long) sizeof (struct ccb)
- * (u_long) sizeof (struct lcb)
- * (u_long) sizeof (struct tcb);
+u_long ncr_version = NCR_VERSION * 11
+ + (u_long) sizeof (struct ncb) * 7
+ + (u_long) sizeof (struct ccb) * 5
+ + (u_long) sizeof (struct lcb) * 3
+ + (u_long) sizeof (struct tcb) * 2;
#ifdef KERNEL
@@ -2937,57 +2942,26 @@ void ncr_script_fill (struct script * scr)
**==========================================================
*/
-static ncrcmd *src = (ncrcmd *)&script0;
-
-static void ncr_script_copy_and_bind (ncb_p np)
+static void ncr_script_copy_and_bind (struct script *script, ncb_p np)
{
ncrcmd opcode, new, old;
- ncrcmd *dst, *start, *end;
- int relocs;
- u_long p_script;
-
- /*
- * Test whether last byte of script is at the right
- * PHYSICAL address, since the NCR uses phys. addresses only.
- * Assumes that the script fits into two 4KB pages ...
- */
- assert (sizeof(struct script) <= 8192);
-
- while ((p_script = vtophys (src)) + sizeof (struct script) !=
- vtophys ((char *)src + sizeof (struct script))) {
-
- struct script *newsrc = (struct script *)
- malloc (sizeof (struct script), M_DEVBUF, M_WAITOK);
- memcpy (newsrc, src, sizeof(struct script));
- src = (ncrcmd *) newsrc;
-
- printf ("%s: NCR script not physically contigous, retrying\n",
- ncr_name(np));
- }
+ ncrcmd *src, *dst, *start, *end;
+ int relocs;
- np->script = (struct script*) src;
- np->p_script = p_script;
+ np->script = (struct script*) vm_page_alloc_contig
+ (round_page(sizeof (struct script)), 0x100000, 0xffffffff, PAGE_SIZE);
- dst = (ncrcmd *) malloc (sizeof (struct script), M_DEVBUF, M_WAITOK);
-
- /*
- * Copy the script to keep an unmodified version
- * to bind for another NCR chip, if present.
- */
- memcpy (dst, src, sizeof(struct script));
+ np->p_script = vtophys(np->script);
- /*
- * Patch the "src" of the memcpy to become the script to execute.
- * The copy in the malloc()ed memory at "dst" will be the src of
- * the script for the next NCR, if there are multiple chips.
- */
+ src = script->start;
+ dst = np->script->start;
start = src;
- end = src + (sizeof(struct script) / 4);
+ end = src + (sizeof (struct script) / 4);
while (src < end) {
- opcode = *src++;
+ *dst++ = opcode = *src++;
/*
** If we forget to change the length
@@ -3055,7 +3029,7 @@ static void ncr_script_copy_and_bind (ncb_p np)
if (relocs) {
while (relocs--) {
- old = *src;
+ old = *src++;
switch (old & RELOC_MASK) {
case RELOC_REGISTER:
@@ -3079,17 +3053,12 @@ static void ncr_script_copy_and_bind (ncb_p np)
break;
}
- *src++ = new;
+ *dst++ = new;
}
} else
- src++;
+ *dst++ = *src++;
};
-
- /*
- * next time use the (unmodified) copy of the script as "src"
- */
- src = dst;
}
/*==========================================================
@@ -3305,7 +3274,7 @@ static void ncr_attach (pcici_t config_id, int unit)
*/
ncr_script_fill (&script0);
- ncr_script_copy_and_bind (np);
+ ncr_script_copy_and_bind (&script0, np);
/*
** init data structure
@@ -3341,6 +3310,7 @@ static void ncr_attach (pcici_t config_id, int unit)
*/
OUTB (nc_istat, SRST);
+ DELAY (1000);
OUTB (nc_istat, 0 );
#ifdef NCR_DUMP_REG
@@ -3364,6 +3334,7 @@ static void ncr_attach (pcici_t config_id, int unit)
*/
OUTB (nc_istat, SRST);
+ DELAY (1000);
OUTB (nc_istat, 0 );
#endif /* NCR_DUMP_REG */
@@ -3396,16 +3367,13 @@ static void ncr_attach (pcici_t config_id, int unit)
DELAY (1000);
/*
- ** process the reset exception,
+ ** Process the reset exception,
** if interrupts are not enabled yet.
- ** than enable disconnects.
+ ** Then enable disconnects.
*/
ncr_exception (np);
np->disc = 1;
- printf ("%s scanning for targets 0..%d (V%d " __NCR_C__ ")\n",
- ncr_name (np), MAX_TARGET-1, NCR_VERSION);
-
/*
** Now let the generic SCSI driver
** look for the SCSI devices on the bus ..
@@ -3419,6 +3387,8 @@ static void ncr_attach (pcici_t config_id, int unit)
np->sc_link.adapter_targ = np->myaddr;
np->sc_link.adapter = &ncr_switch;
np->sc_link.device = &ncr_dev;
+ np->sc_link.flags = 0;
+ np->sc_link.fordriver = 0;
#ifdef __NetBSD__
config_found(self, &np->sc_link, ncr_print);
@@ -3427,8 +3397,27 @@ static void ncr_attach (pcici_t config_id, int unit)
scbus = scsi_alloc_bus();
if(!scbus)
return;
- /* XXX scbus->maxtarg should be adjusted based on bus width */
scbus->adapter_link = &np->sc_link;
+
+ if(np->maxwide)
+ scbus->maxtarg = 15;
+
+ if (bootverbose) {
+ unsigned t_from = 0;
+ unsigned t_to = scbus->maxtarg;
+ unsigned myaddr = np->myaddr;
+
+ char *txt_and = "";
+ printf ("%s scanning for targets ", ncr_name (np));
+ if (t_from < myaddr) {
+ printf ("%d..%d ", t_from, myaddr -1);
+ txt_and = "and ";
+ }
+ if (myaddr < t_to)
+ printf ("%s%d..%d ", txt_and, myaddr +1, t_to);
+ printf ("(V%d " NCR_DATE ")\n", NCR_VERSION);
+ }
+
scsi_attachdevs (scbus);
scbus = NULL; /* Upper-level SCSI code owns this now */
#else
@@ -4316,7 +4305,8 @@ void ncr_init (ncb_p np, char * msg, u_long code)
** Reset chip.
*/
- OUTB (nc_istat, SRST );
+ OUTB (nc_istat, SRST);
+ DELAY (1000);
/*
** Message.
@@ -4354,18 +4344,18 @@ void ncr_init (ncb_p np, char * msg, u_long code)
burstlen = tbl[pci_max_burst_len];
} else burstlen = 0xc0;
- OUTB (nc_istat, 0 ); /* Remove Reset, abort ... */
+ OUTB (nc_istat, 0 ); /* 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 */
+ OUTB (nc_scntl3, np->rv_scntl3);/* timing prescaler */
OUTB (nc_scid , RRE|np->myaddr);/* host adapter SCSI address */
- OUTW (nc_respid, 1ul<<np->myaddr);/* id to respond to */
- OUTB (nc_istat , SIGP ); /* Signal Process */
+ OUTW (nc_respid, 1ul<<np->myaddr);/* id to respond to */
+ OUTB (nc_istat , SIGP ); /* Signal Process */
OUTB (nc_dmode , burstlen); /* Burst length = 2 .. 16 transfers */
OUTB (nc_dcntl , NOCOM ); /* no single step mode, protect SFBR*/
OUTB (nc_ctest4, 0x08 ); /* enable master parity checking */
OUTB (nc_stest2, EXT ); /* Extended Sreq/Sack filtering */
- OUTB (nc_stest3, TE ); /* TolerANT enable */
+ OUTB (nc_stest3, TE ); /* TolerANT enable */
OUTB (nc_stime0, 0xfb ); /* HTH = 1.6sec STO = 0.1 sec. */
/*
@@ -4775,23 +4765,21 @@ static void ncr_timeout (ncb_p np)
OUTB (nc_istat, SIGP);
};
- if (np->latetime>10) {
+ if (np->latetime>4) {
/*
- ** Although we tried to wakeup it,
- ** the script processor didn't answer.
+ ** Although we tried to wake it up,
+ ** the script processor didn't respond.
**
** May be a target is hanging,
** or another initator lets a tape device
- ** rewind with disabled disconnect :-(
+ ** rewind with disconnect disabled :-(
**
** We won't accept that.
*/
- printf ("%s: reset by timeout.\n", ncr_name (np));
- OUTB (nc_istat, SRST);
- OUTB (nc_istat, 0);
if (INB (nc_sbcl) & CBSY)
OUTB (nc_scntl1, CRST);
- ncr_init (np, NULL, HS_TIMEOUT);
+ DELAY (1000);
+ ncr_init (np, "ncr dead ?", HS_TIMEOUT);
np->heartbeat = thistime;
};
@@ -4921,7 +4909,7 @@ void ncr_exception (ncb_p np)
*/
if (sist & RST) {
- ncr_init (np, "scsi reset", HS_RESET);
+ ncr_init (np, bootverbose ? "scsi reset" : NULL, HS_RESET);
return;
};
@@ -5029,32 +5017,25 @@ void ncr_exception (ncb_p np)
dsp = (unsigned) INL (nc_dsp);
dsa = (unsigned) INL (nc_dsa);
- script_ofs = dsp - (unsigned) np->p_script,
+ script_ofs = dsp - vtophys(np->script);
- printf ("%s targ %d?: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%x:%08x).\n",
- ncr_name (np), INB (nc_ctest0)&7, dstat, sist,
+ 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 (" %x", ((u_char*)np->reg)[i]);
+ printf (" %02x", ((u_char*)np->reg)[i]);
printf (".\n");
- if (script_ofs < sizeof(*np->script))
- {
- u_long vpci;
- u_long vpc = ((u_long) np->script) + script_ofs;
-
- for (vpci = vpc; vpci >= 4; vpci -= 4);
- while (vpci <= vpc) {
- printf ("\tvirt.addr: 0x%08lx instr: 0x%08lx\n",
- vpci, *(ncrcmd *)(vpci));
- vpci += 4;
- }
- }
-
/*----------------------------------------
** clean up the dma fifo
**----------------------------------------
@@ -5070,6 +5051,21 @@ void ncr_exception (ncb_p np)
}
/*----------------------------------------
+ ** handshake timeout
+ **----------------------------------------
+ */
+
+ if (sist & HTH) {
+ printf ("%s: handshake timeout\n", ncr_name(np));
+ OUTB (nc_scntl1, CRST);
+ DELAY (1000);
+ OUTB (nc_scntl1, 0x00);
+ OUTB (nc_scr0, HS_FAIL);
+ OUTL (nc_dsp, vtophys(&np->script->cleanup));
+ return;
+ }
+
+ /*----------------------------------------
** unexpected disconnect
**----------------------------------------
*/
@@ -5107,8 +5103,8 @@ void ncr_exception (ncb_p np)
ncr_name (np));
return;
};
- printf ("%s: target %d? doesn't release the bus.\n",
- ncr_name (np), INB (nc_ctest0)&7);
+ printf ("%s: target %d doesn't release the bus.\n",
+ ncr_name (np), INB (nc_ctest0)&0x0f);
/*
** return without restarting the NCR.
** timeout will do the real work.
@@ -5338,7 +5334,7 @@ static void ncr_int_ma (ncb_p np)
** log the information
*/
if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_PHASE)) {
- printf ("P%d%d ",cmd&7, sbcl&7);
+ printf ("P%x%x ",cmd&7, sbcl&7);
printf ("RL=%d D=%d SS0=%x ",
(unsigned) rest, (unsigned) delta, ss0);
};
@@ -5379,13 +5375,13 @@ static void ncr_int_ma (ncb_p np)
if (cmd != (vdsp[0] >> 24)) {
PRINT_ADDR(cp->xfer);
printf ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n",
- cmd, vdsp[0] >> 24);
+ (unsigned)cmd, (unsigned)vdsp[0] >> 24);
return;
}
if (cmd & 0x06) {
PRINT_ADDR(cp->xfer);
- printf ("phase change %d-%d %d@%x resid=%d.\n",
+ printf ("phase change %x-%x %d@%08x resid=%d.\n",
cmd&7, sbcl&7, (unsigned)olen,
(unsigned)oadr, (unsigned)rest);
@@ -5543,7 +5539,7 @@ void ncr_int_sir (ncb_p np)
if (DEBUG_FLAGS & DEBUG_RESTART) {
PRINT_ADDR(cp->xfer);
printf ("in getcc reselect by t%d.\n",
- INB(nc_ssid)&7);
+ INB(nc_ssid) & 0x0f);
}
/*
@@ -6492,6 +6488,7 @@ static int ncr_snooptest (struct ncb* np)
** Reset ncr chip
*/
OUTB (nc_istat, SRST);
+ DELAY (1000);
OUTB (nc_istat, 0 );
/*
** check for timeout
OpenPOWER on IntegriCloud