-/* $OpenBSD: ncr.c,v 1.25 1997/01/22 21:46:51 deraadt Exp $ */
-/* $NetBSD: ncr.c,v 1.48 1996/10/25 21:33:33 cgd Exp $ */
+/* $OpenBSD: ncr.c,v 1.26 1997/03/03 00:25:03 millert Exp $ */
+/* $NetBSD: ncr.c,v 1.55 1997/01/10 05:57:10 perry Exp $ */
/**************************************************************************
**
** Device driver for the NCR 53C810 PCI-SCSI-Controller.
**
-** FreeBSD / NetBSD
+** FreeBSD / NetBSD / OpenBSD
**
**-------------------------------------------------------------------------
**
**
** Ported to NetBSD by
** Charles M. Hannum <mycroft@gnu.ai.mit.edu>
-** Dave Huang <khym@bga.com>
**
**-------------------------------------------------------------------------
**
***************************************************************************
*/
-#define NCR_DATE "pl23 95/09/07"
+#define NCR_DATE "pl24 96/12/14"
#define NCR_VERSION (2)
#define MAX_UNITS (16)
#define NCR_GETCC_WITHMSG
-#ifdef FAILSAFE
+#ifdef __OpenBSD__
+#define __BROKEN_INDIRECT_CONFIG
+#endif
+
+#if defined (__FreeBSD__) && defined(KERNEL)
+#include "opt_ncr.h"
+#endif /* defined (__FreeBSD__) && defined(KERNEL) */
+
+#ifdef FAILSAFE
+#ifndef SCSI_NCR_DFLT_TAGS
#define SCSI_NCR_DFLT_TAGS (0)
-#define MAX_LUN (1)
-#define CDROM_ASYNC
-#endif /* FAILSAFE */
+#endif /* SCSI_NCR_DFLT_TAGS */
+#define NCR_CDROM_ASYNC
+#endif /* FAILSAFE */
/*==========================================================
**
/*
** Number of logic units supported by the driver.
** n enables logic unit numbers 0..n-1.
+** The common SCSI devices require only
+** one lun, so take 1 as the default.
*/
+#ifndef MAX_LUN
#define MAX_LUN (8)
+#endif /* MAX_LUN */
/*
** The maximum number of jobs scheduled for starting.
#ifndef __alpha__
#define DELAY(x) delay(x)
#endif
-#endif /* __NetBSD__ */
+#endif /* __NetBSD__ || __OpenBSD__ */
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
** Can be changed at runtime too.
*/
-#ifdef SCSI_DEBUG_FLAGS
+#ifdef SCSI_NCR_DEBUG
#define DEBUG_FLAGS ncr_debug
-#else /* SCSI_DEBUG_FLAGS */
- #define SCSI_DEBUG_FLAGS 0
+#else /* SCSI_NCR_DEBUG */
+ #define SCSI_NCR_DEBUG 0
#define DEBUG_FLAGS 0
-#endif /* SCSI_DEBUG_FLAGS */
+#endif /* SCSI_NCR_DEBUG */
#endif
-#else /* !__NetBSD__ */
+#else /* !(__NetBSD__ || __OpenBSD__) */
#ifdef NCR_IOMAPPED
#define INL(r) (np->reg->r)
#define INL_OFF(o) (*((volatile INT32 *)((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 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
#endif
-#endif /* __NetBSD__ */
+#endif /* __NetBSD__ || __OpenBSD__ */
/*==========================================================
**
bus_space_tag_t sc_memt;
pci_chipset_tag_t sc_pc;
bus_space_handle_t sc_bah;
-#else /* !__NetBSD__ */
+#else /* !(__NetBSD__ || __OpenBSD__) */
int unit;
-#endif /* __NetBSD__ */
+#endif /* __NetBSD__ || __OpenBSD__ */
/*-----------------------------------------------
** Scripts ..
/*
** timing parameters
*/
- u_char ns_async;
u_char ns_sync;
+ u_char maxoffs;
+
+ /*
+ ** BIOS supplied PCI bus options
+ */
u_char rv_scntl3;
+ u_char rv_dcntl;
+ u_char rv_dmode;
+ u_char rv_ctest3;
+ u_char rv_ctest5;
/*-----------------------------------------------
** Link to the generic SCSI driver
#else
static void ncr_intr (void *vnp);
static U_INT32 ncr_info (int unit);
-#endif /* !__NetBSD__ */
+#endif /* !(__NetBSD__ || __OpenBSD__) */
static void ncr_int_ma (ncb_p np);
static void ncr_int_sir (ncb_p np);
static void ncr_int_sto (ncb_p np);
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, vm_offset_t vaddr,
+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_wakeup (ncb_p np, u_long code);
#if defined(__NetBSD__) || defined(__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__ */
+#else /* !(__NetBSD__ || __OpenBSD__) */
static char* ncr_probe (pcici_t tag, pcidi_t type);
static void ncr_attach (pcici_t tag, int unit);
-#endif /* __NetBSD__ */
+#endif /* __NetBSD__ || __OpenBSD__ */
#endif /* KERNEL */
#if 0
static char ident[] =
- "\n$NetBSD: ncr.c,v 1.48 1996/10/25 21:33:33 cgd Exp $\n";
+ "\n$OpenBSD: ncr.c,v 1.26 1997/03/03 00:25:03 millert Exp $\n";
#endif
static const u_long ncr_version = NCR_VERSION * 11
#if !(defined(__NetBSD__) || defined(__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__ */
+ncb_p ncrp [MAX_UNITS]; /* XXX to be replaced by SYSCTL */
+#endif /* !(__NetBSD__ || __OpenBSD__) */
-static int ncr_debug = SCSI_DEBUG_FLAGS;
-#if !defined(__NetBSD__) && !defined(__OpenBSD__)
+static int ncr_debug = SCSI_NCR_DEBUG;
+#if !(defined(__NetBSD__) || defined(__OpenBSD__))
SYSCTL_INT(_debug, OID_AUTO, ncr_debug, CTLFLAG_RW, &ncr_debug, 0, "");
-#endif /* !__NetBSD__ */
+#endif /* !(__NetBSD__ || __OpenBSD__) */
static int ncr_cache; /* to be aligned _NOT_ static */
*/
#define NCR_810_ID (0x00011000ul)
-#define NCR_810AP_ID (0x00051000ul)
#define NCR_815_ID (0x00041000ul)
#define NCR_825_ID (0x00031000ul)
#define NCR_860_ID (0x00061000ul)
NULL, "ncr", DV_DULL
};
-#else /* !__NetBSD__ */
+#else /* !(__NetBSD__ || __OpenBSD__) */
static u_long ncr_count;
DATA_SET (pcidevice_set, ncr_device);
-#endif /* !__NetBSD__ */
+#endif /* !(__NetBSD__ || __OpenBSD__) */
static struct scsi_adapter ncr_switch =
{
#if !(defined(__NetBSD__) || defined(__OpenBSD__))
ncr_info,
"ncr",
-#endif /* !__NetBSD__ */
+#endif /* !(__NetBSD__ || __OpenBSD__) */
};
static struct scsi_device ncr_dev =
NULL, /* Use default 'done' routine */
#if !(defined(__NetBSD__) || defined(__OpenBSD__))
"ncr",
-#endif /* !__NetBSD__ */
+#endif /* !(__NetBSD__ || __OpenBSD__) */
};
#if defined(__NetBSD__) || defined(__OpenBSD__)
#define ncr_name(np) (np->sc_dev.dv_xname)
-#else /* !__NetBSD__ */
+#else /* !(__NetBSD__ || __OpenBSD__) */
static char *ncr_name (ncb_p np)
{
int relocs;
#if !(defined(__NetBSD__) || defined(__OpenBSD__))
- np->script = (struct script*) vm_page_alloc_contig
+ np->script = (struct script*) vm_page_alloc_contig
(round_page(sizeof (struct script)), 0x100000, 0xffffffff, PAGE_SIZE);
-#else /* !__NetBSD___ */
+#else /* !(__NetBSD__ || __OpenBSD__) */
np->script = (struct script *)
malloc (sizeof (struct script), M_DEVBUF, M_WAITOK);
-#endif /* __NetBSD__ */
+#endif /* __NetBSD__ || __OpenBSD__ */
np->p_script = vtophys(np->script);
*/
if (opcode == 0) {
- printf ("%s: ERROR0 IN SCRIPT at %d.\n",
- ncr_name(np), src-start-1);
+ printf ("%s: ERROR0 IN SCRIPT at %ld.\n",
+ ncr_name(np), (long)(src-start-1));
DELAY (1000000);
};
if ((tmp2 & RELOC_MASK) == RELOC_KVAR)
tmp2 = 0;
if ((tmp1 ^ tmp2) & 3) {
- printf ("%s: ERROR1 IN SCRIPT at %d.\n",
- ncr_name(np), src-start-1);
+ printf ("%s: ERROR1 IN SCRIPT at %ld.\n",
+ ncr_name(np), (long)(src-start-1));
DELAY (1000000);
};
break;
int
ncr_probe(parent, match, aux)
struct device *parent;
- void *match, *aux;
+#ifdef __BROKEN_INDIRECT_CONFIG
+ void *match;
+#else
+ struct cfdata *match;
+#endif
+ void *aux;
{
struct pci_attach_args *pa = aux;
#if 0
return 0;
#endif
if (pa->pa_id != NCR_810_ID &&
- pa->pa_id != NCR_810AP_ID &&
pa->pa_id != NCR_815_ID &&
pa->pa_id != NCR_825_ID &&
pa->pa_id != NCR_860_ID &&
return 1;
}
-#else /* !__NetBSD__ */
+#else /* !(__NetBSD__ || __OpenBSD__) */
static char* ncr_probe (pcici_t tag, pcidi_t type)
{
+ u_char rev = pci_conf_read (tag, PCI_CLASS_REG) & 0xff;
switch (type) {
case NCR_810_ID:
- return ("ncr 53c810 scsi");
-
- case NCR_810AP_ID:
- return ("ncr 53c810ap scsi");
+ return (rev & 0xf0) == 0x00
+ ? ("ncr 53c810 scsi")
+ : ("ncr 53c810a scsi");
case NCR_815_ID:
return ("ncr 53c815 scsi");
case NCR_825_ID:
- return ("ncr 53c825 wide scsi");
+ return (rev & 0xf0) == 0x00
+ ? ("ncr 53c825 wide scsi")
+ : ("ncr 53c825a wide scsi");
case NCR_860_ID:
return ("ncr 53c860 scsi");
return (NULL);
}
-#endif /* !__NetBSD__ */
+#endif /* !(__NetBSD__ || __OpenBSD__) */
/*==========================================================
#define MIN_SYNC_PD 20
#if defined(__NetBSD__) || defined(__OpenBSD__)
-
void
ncr_attach(parent, self, aux)
struct device *parent, *self;
const char *intrstr;
ncb_p np = (void *)self;
int wide = 0;
+ 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("53c810");
- break;
- case NCR_810AP_ID:
- printf("53c810ap");
+ printf((rev & 0xf0) == 0x00 ? "53c810" : "53c810a");
break;
case NCR_815_ID:
printf("53c815");
break;
case NCR_825_ID:
- printf("53c825 Wide");
+ printf((rev & 0xf0) == 0x00 ? "53c825 Wide" : "53c825a Wide");
wide = 1;
break;
case NCR_860_ID:
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);
if (intrstr != NULL)
if (intrstr != NULL)
printf("%s: interrupting at %s\n", self->dv_xname, intrstr);
-#else /* !__NetBSD__ */
+#else /* !(__NetBSD__ || __OpenBSD__) */
static void ncr_attach (pcici_t config_id, int unit)
{
return;
#endif
-#endif /* !__NetBSD__ */
+#endif /* !(__NetBSD__ || __OpenBSD__) */
/*
- ** Do chip dependent initialization.
+ ** Save some controller register default values
*/
- np->maxwide = 0;
+ 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 */
- np->ns_sync = 25; /* XXX no support for Fast-20, yet */
- np->ns_async = 50;
+
+ /*
+ ** Do chip dependent initialization.
+ */
+
+ np->maxwide = 0;
+ np->ns_sync = 25; /* in units of 4ns */
+ np->maxoffs = 8;
/*
** Get the frequency of the chip's clock.
#if defined(__NetBSD__) || defined(__OpenBSD__)
switch (pa->pa_id) {
-#else /* !__NetBSD__ */
+#else /* !(__NetBSD__ || __OpenBSD__) */
switch (pci_conf_read (config_id, PCI_ID_REG)) {
-#endif /* __NetBSD__ */
+#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;
}
np->myaddr = INB(nc_scid) & 0x07;
if (!np->myaddr) np->myaddr = SCSI_NCR_MYADDR;
- /*
- ** Reset chip.
- */
-
- OUTB (nc_istat, SRST);
- DELAY (1000);
- OUTB (nc_istat, 0 );
-
#ifdef NCR_DUMP_REG
/*
** Log the initial register contents
int reg;
#if defined(__NetBSD__) || defined(__OpenBSD__)
u_long config_id = pa->pa_tag;
-#endif /* __NetBSD__ */
+#endif /* __NetBSD__ || __OpenBSD__ */
for (reg=0; reg<256; reg+=4) {
if (reg%16==0) printf ("reg[%2x]", reg);
printf (" %08x", (int)pci_conf_read (config_id, reg));
if (reg%16==12) printf ("\n");
}
}
+#endif /* NCR_DUMP_REG */
/*
- ** Reset chip, once again.
+ ** Reset chip.
*/
OUTB (nc_istat, SRST);
DELAY (1000);
OUTB (nc_istat, 0 );
-#endif /* NCR_DUMP_REG */
/*
** Now check the cache handling of the pci chipset.
if (!pci_map_int (config_id, ncr_intr, np, &bio_imask))
printf ("\tinterruptless mode: reduced performance.\n");
-#endif /* __NetBSD__ */
+#endif /* __NetBSD__ || __OpenBSD__ */
/*
** After SCSI devices have been opened, we cannot
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
-#else /* !__NetBSD__ */
+#endif /* __OpenBSD__ */
+#else /* !(__NetBSD__ || __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__ */
+#endif /* !(__NetBSD__ || __OpenBSD__) */
np->sc_link.adapter = &ncr_switch;
np->sc_link.device = &ncr_dev;
np->sc_link.flags = 0;
#if defined(__NetBSD__) || defined(__OpenBSD__)
config_found(self, &np->sc_link, scsiprint);
-#else
+#else /* !(__NetBSD__ || __OpenBSD__) */
#if (__FreeBSD__ >= 2)
scbus = scsi_alloc_bus();
if(!scbus)
#else
scsi_attachdevs (&np->sc_link);
#endif /* !__FreeBSD__ >= 2 */
-#endif /* !__NetBSD__ */
+#endif /* !(__NetBSD__ || __OpenBSD__) */
/*
** start the timeout daemon
#if defined(__NetBSD__) || defined(__OpenBSD__)
static int
-#else /* !__NetBSD__ */
+#else /* !(__NetBSD__ || __OpenBSD__) */
static void
-#endif /* __NetBSD__ */
+#endif /* __NetBSD__ || __OpenBSD__ */
ncr_intr(vnp)
void *vnp;
{
if (DEBUG_FLAGS & DEBUG_TINY) {
PRINT_ADDR(xp);
- printf ("CMD=%x F=%p A=%p L=%p ",
- cmd->opcode, xp->flags, xp->data, xp->datalen);
+ printf ("CMD=%x F=%x A=%p L=%x ",
+ cmd->opcode, (unsigned)xp->flags, xp->data,
+ (unsigned)xp->datalen);
}
/*--------------------------------------------
if (!nego && !tp->period) {
if (SCSI_NCR_MAX_SYNC
-#if defined (CDROM_ASYNC) || defined (GENERIC)
+#ifdef NCR_CDROM_ASYNC
&& ((tp->inqdata[0] & 0x1f) != 5)
-#endif
+#endif /* NCR_CDROM_ASYNC */
&& (tp->inqdata[7] & INQ7_SYNC)) {
nego = NS_SYNC;
} else {
**----------------------------------------------------
*/
- 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) {
#if defined(__NetBSD__) || defined(__OpenBSD__)
if (!(flags & SCSI_POLL)) {
-#else /* !__NetBSD__ */
+#else /* !(__NetBSD__ || __OpenBSD__) */
if (!(flags & SCSI_NOMASK)) {
-#endif /* __NetBSD__ */
+#endif /* __NetBSD__ || __OpenBSD__ */
if (np->lasttime) {
if(DEBUG_FLAGS & DEBUG_TINY) printf ("Q");
return(SUCCESSFULLY_QUEUED);
};
#if defined(__NetBSD__) || defined(__OpenBSD__)
if (!(flags & SCSI_POLL))
-#else /* !__NetBSD__ */
+#else /* !(__NetBSD__ || __OpenBSD__) */
if (!(flags & SCSI_NOMASK))
-#endif /* __NetBSD__ */
+#endif /* __NetBSD__ || __OpenBSD__ */
return (SUCCESSFULLY_QUEUED);
switch (xp->error) {
case 0 : return (COMPLETE);
ncb_profile (np, cp);
if (DEBUG_FLAGS & DEBUG_TINY)
- printf ("CCB=%p STAT=%x/%x\n",
- (caddr_t)((vm_offset_t)cp & 0xfff),
+ printf ("CCB=%lx STAT=%x/%x\n", (unsigned long)cp & 0xfff,
cp->host_status,cp->scsi_status);
xp = cp->xfer;
/*
** fallback to asynch transfer.
*/
- tp->usrsync=255;
+ tp->usrsync = 255;
tp->period = 0;
};
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;
};
** Don't override the error value.
*/
} else
-#endif /* __NetBSD__ */
+#endif /* __NetBSD__ || __OpenBSD__ */
if ( (cp->host_status == HS_COMPLETE)
&& (cp->scsi_status == S_GOOD)) {
/*
** On inquire cmd (0x12) save some data.
*/
- if (xp->cmd->opcode == 0x12) {
+ if (xp->cmd->opcode == 0x12 && xp->sc_link->lun == 0) {
bcopy ( xp->data,
&tp->inqdata,
sizeof (tp->inqdata));
** Not correct, but errors expected.
*/
xp->resid = 0;
-#endif /* !__NetBSD__ */
+#endif /* !(__NetBSD__ || __OpenBSD__) */
} else if ((cp->host_status == HS_COMPLETE)
&& (cp->scsi_status == (S_SENSE|S_GOOD))) {
** Init chip.
*/
-#if !(defined(__NetBSD__) || defined(__OpenBSD__))
- if (pci_max_burst_len < 4) {
- static u_char tbl[4]={0,0,0x40,0x80};
- burstlen = tbl[pci_max_burst_len];
- } else burstlen = 0xc0;
-#else /* !__NetBSD__ */
- burstlen = 0xc0;
-#endif /* __NetBSD__ */
-
- OUTB (nc_istat, 0 ); /* Remove Reset, abort ... */
+ 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 */
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 */
- 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_dmode , np->rv_dmode); /* XXX modify burstlen ??? */
+ 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_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));
+ }
+#endif /* __FreeBSD__ */
+
/*
** Reinitialize usrsync.
** Have to renegotiate synch mode.
u_long minsync = tp->usrsync;
- if (minsync < 25) minsync=25;
-
/*
** if not scsi 2
** don't believe FAST!
minsync = 255;
tp->minsync = minsync;
- tp->maxoffs = (minsync<255 ? 8 : 0);
+ tp->maxoffs = (minsync<255 ? np->maxoffs : 0);
/*
** period=0: has to negotiate sync transfer
assert (target == (xp->sc_link->target & 0x0f));
tp = &np->target[target];
- tp->period= sxfer&0xf ? ((sxfer>>5)+4) * np->ns_sync : 0xffff;
+ tp->period= sxfer&0x1f ? ((sxfer>>5)+4) * np->ns_sync : 0xffff;
if (tp->sval == sxfer) return;
tp->sval = sxfer;
** Bells and whistles ;-)
*/
PRINT_ADDR(xp);
- if (sxfer & 0x0f) {
+ if (sxfer & 0x1f) {
+ unsigned f10 = 10000 << (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);
- printf ("%s%dns (%d Mb/sec) offset %d.\n",
- tp->period<200 ? "FAST SCSI-2 ":"",
- tp->period, (1000+tp->period/2)/tp->period,
- sxfer & 0x0f);
+ printf ("%d.%d MB/s (%d ns, offset %d)\n",
+ mb10 / 10, mb10 % 10, tp->period, sxfer & 0x1f);
} else printf ("asynchronous.\n");
/*
** If there are no requests, the script
** processor will sleep on SEL_WAIT_RESEL.
** But we have to check whether it died.
- ** Let's wake it up.
+ ** Let's try to wake it up.
*/
OUTB (nc_istat, SIGP);
};
-#ifdef undef
- if (np->latetime>4) {
- /*
- ** 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 disconnect disabled :-(
- **
- ** We won't accept that.
- */
- if (INB (nc_sbcl) & CBSY)
- OUTB (nc_scntl1, CRST);
- DELAY (1000);
- ncr_init (np, "ncr dead ?", HS_TIMEOUT);
- np->heartbeat = thistime;
- };
-#endif
/*----------------------------------------------------
**
** handle ccb timeouts
** Never test for an error condition you don't know how to handle.
*/
+ sist = (istat & SIP) ? INW (nc_sist) : 0;
dstat = (istat & DIP) ? INB (nc_dstat) : 0;
- sist = (istat & SIP) ? INW (nc_sist) : 0;
np->profile.num_int++;
if (DEBUG_FLAGS & DEBUG_TINY)
!(dstat & DFE)) {
printf ("%s: have to clear fifos.\n", ncr_name (np));
OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */
- OUTB (nc_ctest3, CLF); /* clear dma fifo */
+ OUTB (nc_ctest3, np->rv_ctest3 | CLF);
+ /* clear dma fifo */
}
/*----------------------------------------
** It's an early reconnect.
** Let's continue ...
*/
- OUTB (nc_dcntl, (STD|NOCOM));
+ OUTB (nc_dcntl, np->rv_dcntl | STD);
/*
** info message
*/
if ((dstat & SSI) &&
!(sist & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) &&
!(dstat & (MDPE|BF|ABRT|SIR|IID))) {
- OUTB (nc_dcntl, (STD|NOCOM));
+ OUTB (nc_dcntl, np->rv_dcntl | STD);
return;
};
*/
if (sist & SGE) {
- OUTB (nc_ctest3, CLF); /* clear scsi offsets */
+ /* clear scsi offsets */
+ OUTB (nc_ctest3, np->rv_ctest3 | CLF);
}
/*
if (ss2 & OLF1) rest++;
if (ss2 & ORF1) rest++;
};
- OUTB (nc_ctest3, CLF ); /* clear dma fifo */
- OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */
+ OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */
+ OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */
/*
** locate matching cp
cmd&7, sbcl&7, (unsigned)olen,
(unsigned)oadr, (unsigned)rest);
- OUTB (nc_dcntl, (STD|NOCOM));
+ OUTB (nc_dcntl, np->rv_dcntl | STD);
return;
};
if (DEBUG_FLAGS & DEBUG_PHASE) {
PRINT_ADDR(cp->xfer);
- printf ("newcmd[%d] %x %x %x %x.\n",
- newcmd - cp->patch,
+ printf ("newcmd[%ld] %x %x %x %x.\n",
+ (long)(newcmd - cp->patch),
(unsigned)newcmd[0],
(unsigned)newcmd[1],
(unsigned)newcmd[2],
};
out:
- OUTB (nc_dcntl, (STD|NOCOM));
+ OUTB (nc_dcntl, np->rv_dcntl | STD);
}
/*==========================================================
{
lcb_p lp;
ccb_p cp = (ccb_p) 0;
+ int oldspl;
+ oldspl = splhigh();
/*
** Lun structure available ?
*/
** Look for free CCB
*/
- while (cp && cp->magic) cp = cp->next_ccb;
+ while (cp && cp->magic) {
+ cp = cp->next_ccb;
+ }
}
/*
break;
};
- if (cp->magic)
+ if (cp->magic) {
+ splx(oldspl);
return ((ccb_p) 0);
+ }
cp->magic = 1;
+ splx(oldspl);
return (cp);
}
diff = xp->sc_link->openings;
xp->sc_link->openings -= diff;
-#else /* !__NetBSD__ */
+#else /* !(__NetBSD__ || __OpenBSD__) */
if (diff > xp->sc_link->opennings)
diff = xp->sc_link->opennings;
xp->sc_link->opennings -= diff;
-#endif /* __NetBSD__ */
+#endif /* __NetBSD__ || __OpenBSD__ */
lp->actlink -= diff;
if (DEBUG_FLAGS & DEBUG_TAGS)
printf ("%s: actlink: diff=%d, new=%d, req=%d\n",
#if defined(__NetBSD__) || defined(__OpenBSD__)
xp->sc_link->openings += diff;
-#else /* !__NetBSD__ */
+#else /* !(__NetBSD__ || __OpenBSD__) */
xp->sc_link->opennings += diff;
-#endif /* __NetBSD__ */
+#endif /* __NetBSD__ || __OpenBSD__ */
lp->actlink += diff;
wakeup ((caddr_t) xp->sc_link);
if (DEBUG_FLAGS & DEBUG_TAGS)
*/
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;
*/
if (pc != NCB_SCRIPT_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);
return (0x40);
};
/*
* 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->rv_scntl3 = ((scntl3 & 0x7) << 4) -0x20 + (scntl3 & 0x7);
-
- if (bootverbose) {
- printf ("\tinitial value of SCNTL3 = %02x, final = %02x\n",
- scntl3, np->rv_scntl3);
- }
+ * 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->rv_scntl3 = ((scntl3 & 0x7) << 4) -0x20 + (scntl3 & 0x7);
+
+ if (bootverbose) {
+ printf ("\tinitial value of SCNTL3 = %02x, final = %02x\n",
+ scntl3, np->rv_scntl3);
+ }
+}
+
+/*=========================================================================*/
+
+#ifdef NCR_TEKRAM_EEPROM
+
+struct tekram_eeprom_dev {
+ u_char devmode;
+#define TKR_PARCHK 0x01
+#define TKR_TRYSYNC 0x02
+#define TKR_ENDISC 0x04
+#define TKR_STARTUNIT 0x08
+#define TKR_USETAGS 0x10
+#define TKR_TRYWIDE 0x20
+ u_char syncparam; /* max. sync transfer rate (table ?) */
+ u_char filler1;
+ u_char filler2;
+};
+
+
+struct tekram_eeprom {
+ struct tekram_eeprom_dev
+ dev[16];
+ u_char adaptid;
+ u_char adaptmode;
+#define TKR_ADPT_GT2DRV 0x01
+#define TKR_ADPT_GT1GB 0x02
+#define TKR_ADPT_RSTBUS 0x04
+#define TKR_ADPT_ACTNEG 0x08
+#define TKR_ADPT_NOSEEK 0x10
+#define TKR_ADPT_MORLUN 0x20
+ u_char delay; /* unit ? (table ???) */
+ u_char tags; /* use 4 times as many ... */
+ u_char filler[60];
+};
+
+static void
+tekram_write_bit (ncb_p np, int bit)
+{
+ u_char val = 0x10 + ((bit & 1) << 1);
+
+ DELAY(10);
+ OUTB (nc_gpreg, val);
+ DELAY(10);
+ OUTB (nc_gpreg, val | 0x04);
+ DELAY(10);
+ OUTB (nc_gpreg, val);
+ DELAY(10);
+}
+
+static int
+tekram_read_bit (ncb_p np)
+{
+ OUTB (nc_gpreg, 0x10);
+ DELAY(10);
+ OUTB (nc_gpreg, 0x14);
+ DELAY(10);
+ return INB (nc_gpreg) & 1;
+}
+
+static u_short
+read_tekram_eeprom_reg (ncb_p np, int reg)
+{
+ int bit;
+ u_short result = 0;
+ int cmd = 0x80 | reg;
+
+ OUTB (nc_gpreg, 0x10);
+
+ tekram_write_bit (np, 1);
+ for (bit = 7; bit >= 0; bit--)
+ {
+ tekram_write_bit (np, cmd >> bit);
+ }
+
+ for (bit = 0; bit < 16; bit++)
+ {
+ result <<= 1;
+ result |= tekram_read_bit (np);
+ }
+
+ OUTB (nc_gpreg, 0x00);
+ return result;
+}
+
+static int
+read_tekram_eeprom(ncb_p np, struct tekram_eeprom *buffer)
+{
+ u_short *p = (u_short *) buffer;
+ u_short sum = 0;
+ int i;
+
+ if (INB (nc_gpcntl) != 0x09)
+ {
+ return 0;
+ }
+ for (i = 0; i < 64; i++)
+ {
+ u_short val;
+if((i&0x0f) == 0) printf ("%02x:", i*2);
+ val = read_tekram_eeprom_reg (np, i);
+ if (p)
+ *p++ = val;
+ sum += val;
+if((i&0x01) == 0x00) printf (" ");
+ printf ("%02x%02x", val & 0xff, (val >> 8) & 0xff);
+if((i&0x0f) == 0x0f) printf ("\n");
+ }
+printf ("Sum = %04x\n", sum);
+ return sum == 0x1234;
}
+#endif /* NCR_TEKRAM_EEPROM */
/*=========================================================================*/
#endif /* KERNEL */