mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-29 17:32:43 +00:00
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.
This commit is contained in:
parent
defdcfcfb3
commit
3a5a6263e3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=10605
209
sys/pci/ncr.c
209
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;
|
||||
ncrcmd *src, *dst, *start, *end;
|
||||
int relocs;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
np->script = (struct script*) vm_page_alloc_contig
|
||||
(round_page(sizeof (struct script)), 0x100000, 0xffffffff, PAGE_SIZE);
|
||||
|
||||
while ((p_script = vtophys (src)) + sizeof (struct script) !=
|
||||
vtophys ((char *)src + sizeof (struct script))) {
|
||||
np->p_script = vtophys(np->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));
|
||||
}
|
||||
|
||||
np->script = (struct script*) src;
|
||||
np->p_script = p_script;
|
||||
|
||||
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));
|
||||
|
||||
/*
|
||||
* 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
|
||||
**----------------------------------------
|
||||
@ -5069,6 +5050,21 @@ void ncr_exception (ncb_p np)
|
||||
OUTB (nc_ctest3, CLF); /* clear dma fifo */
|
||||
}
|
||||
|
||||
/*----------------------------------------
|
||||
** 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
|
||||
|
Loading…
Reference in New Issue
Block a user