diff options
author | se <se@FreeBSD.org> | 1996-12-14 13:13:33 +0000 |
---|---|---|
committer | se <se@FreeBSD.org> | 1996-12-14 13:13:33 +0000 |
commit | 0d930771c96111302a7452571de004b04afae4cc (patch) | |
tree | a835e55d8a48184469685f56fbad6ed5a0c1153a /sys/pci | |
parent | e4aef44ea4dac7ffb00e29438eff35a9ada2df49 (diff) | |
download | FreeBSD-src-0d930771c96111302a7452571de004b04afae4cc.zip FreeBSD-src-0d930771c96111302a7452571de004b04afae4cc.tar.gz |
General cleanup and new features for 53c875 based cards, especially the
Tekram DC390W/U/F, whose config EEPROM can now be dumped, if the kernel
is built with option NCR_TEKRAM_EEPROM.
Other changes:
- add brackets to expansion of OUTB/W/L macro arguments.
- remove unused NCB structure element ns_async
- support sync. SCSI offset of 16 (instead of only 8) on 825A and 875
- correctly identify 53c810A and 53c825A chips
- preserve SCSI BIOS settings of PCI performance options
- remove (already disabled) support for NCR reset because of command timeout
- reverse order of reading of SCSI and DMA specific interrupt cause registers
- add definition of Tekram config EEPROM contents (not currently used)
Diffstat (limited to 'sys/pci')
-rw-r--r-- | sys/pci/ncr.c | 291 | ||||
-rw-r--r-- | sys/pci/ncrreg.h | 21 |
2 files changed, 232 insertions, 80 deletions
diff --git a/sys/pci/ncr.c b/sys/pci/ncr.c index 5b4e7b9..f1286d5 100644 --- a/sys/pci/ncr.c +++ b/sys/pci/ncr.c @@ -1,6 +1,6 @@ /************************************************************************** ** -** $Id: ncr.c,v 1.83 1996/11/08 23:46:04 se Exp $ +** $Id: ncr.c,v 1.84 1996/12/13 07:55:11 jkh Exp $ ** ** Device driver for the NCR 53C810 PCI-SCSI-Controller. ** @@ -292,9 +292,9 @@ #define INW(r) (np->reg->r) #define INL(r) (np->reg->r) -#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) #endif @@ -988,14 +988,22 @@ struct ncb { /* ** The SCSI address of the host adapter. */ - u_char myaddr; + u_char myaddr; /* ** 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 @@ -1252,7 +1260,7 @@ static void ncr_attach (pcici_t tag, int unit); static char ident[] = - "\n$Id: ncr.c,v 1.83 1996/11/08 23:46:04 se Exp $\n"; + "\n$Id: ncr.c,v 1.84 1996/12/13 07:55:11 jkh Exp $\n"; static const u_long ncr_version = NCR_VERSION * 11 + (u_long) sizeof (struct ncb) * 7 @@ -1279,7 +1287,6 @@ 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) @@ -3160,7 +3167,6 @@ ncr_probe(parent, match, aux) 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 && @@ -3175,19 +3181,21 @@ ncr_probe(parent, match, aux) 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"); @@ -3308,13 +3316,22 @@ static void ncr_attach (pcici_t config_id, int unit) #endif /* !__NetBSD__ */ /* - ** 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. @@ -3327,13 +3344,32 @@ static void ncr_attach (pcici_t config_id, int unit) switch (pci_conf_read (config_id, PCI_ID_REG)) { #endif /* __NetBSD__ */ case NCR_825_ID: + { +#ifndef __NetBSD__ + u_char rev = pci_conf_read (config_id, PCI_CLASS_REG) & 0xff; + if ((rev & 0xf0) == 0x10) + np->maxoffs = 16; +#endif /* !__NetBSD__ */ 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; } @@ -3360,14 +3396,6 @@ static void ncr_attach (pcici_t config_id, int unit) 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 @@ -3383,16 +3411,16 @@ static void ncr_attach (pcici_t config_id, int unit) 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. @@ -4417,29 +4445,34 @@ void ncr_init (ncb_p np, char * msg, u_long code) ** Init chip. */ -#ifndef __NetBSD__ - 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__ */ + burstlen = 0xc0; /* XXX 53c875 needs code change to */ + /* be able to use larger bursts */ - OUTB (nc_istat, 0 ); /* Remove Reset, abort ... */ + 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. */ + 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)); + } + /* ** Reinitialize usrsync. ** Have to renegotiate synch mode. @@ -4517,8 +4550,6 @@ static void ncr_negotiate (struct ncb* np, struct tcb* tp) u_long minsync = tp->usrsync; - if (minsync < 25) minsync=25; - /* ** if not scsi 2 ** don't believe FAST! @@ -4542,7 +4573,7 @@ static void ncr_negotiate (struct ncb* np, struct tcb* tp) 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 @@ -4578,7 +4609,7 @@ 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&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; @@ -4587,15 +4618,15 @@ static void ncr_setsync (ncb_p np, ccb_p cp, u_char sxfer) ** Bells and whistles ;-) */ PRINT_ADDR(xp); - if (sxfer & 0x0f) { + if (sxfer & 0x1f) { /* ** Disable extended Sreq/Sack filtering */ if (tp->period <= 200) OUTB (nc_stest2, 0); - printf ("%s%dns (%d Mb/sec) offset %d.\n", + printf ("%s%dns (%d MHz) offset %d.\n", tp->period<200 ? "FAST SCSI-2 ":"", tp->period, (1000+tp->period/2)/tp->period, - sxfer & 0x0f); + sxfer & 0x1f); } else printf ("asynchronous.\n"); /* @@ -4844,30 +4875,11 @@ static void ncr_timeout (ncb_p np) ** 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 @@ -4971,8 +4983,8 @@ void ncr_exception (ncb_p np) ** Never test for an error condition you don't know how to handle. */ - dstat = (istat & DIP) ? INB (nc_dstat) : 0; sist = (istat & SIP) ? INW (nc_sist) : 0; + dstat = (istat & DIP) ? INB (nc_dstat) : 0; np->profile.num_int++; if (DEBUG_FLAGS & DEBUG_TINY) @@ -5133,7 +5145,8 @@ void ncr_exception (ncb_p np) !(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 */ } /*---------------------------------------- @@ -5181,7 +5194,7 @@ void ncr_exception (ncb_p np) ** It's an early reconnect. ** Let's continue ... */ - OUTB (nc_dcntl, (STD|NOCOM)); + OUTB (nc_dcntl, np->rv_dcntl | STD); /* ** info message */ @@ -5206,7 +5219,7 @@ void ncr_exception (ncb_p np) 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; }; @@ -5219,7 +5232,8 @@ void ncr_exception (ncb_p np) */ if (sist & SGE) { - OUTB (nc_ctest3, CLF); /* clear scsi offsets */ + /* clear scsi offsets */ + OUTB (nc_ctest3, np->rv_ctest3 | CLF); } /* @@ -5378,8 +5392,8 @@ static void ncr_int_ma (ncb_p np) 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 @@ -5471,7 +5485,7 @@ static void ncr_int_ma (ncb_p np) cmd&7, sbcl&7, (unsigned)olen, (unsigned)oadr, (unsigned)rest); - OUTB (nc_dcntl, (STD|NOCOM)); + OUTB (nc_dcntl, np->rv_dcntl | STD); return; }; @@ -6114,7 +6128,7 @@ void ncr_int_sir (ncb_p np) }; out: - OUTB (nc_dcntl, (STD|NOCOM)); + OUTB (nc_dcntl, np->rv_dcntl | STD); } /*========================================================== @@ -6131,7 +6145,9 @@ static ccb_p ncr_get_ccb { lcb_p lp; ccb_p cp = (ccb_p) 0; + int oldspl; + oldspl = splhigh(); /* ** Lun structure available ? */ @@ -6144,7 +6160,9 @@ static ccb_p ncr_get_ccb ** Look for free CCB */ - while (cp && cp->magic) cp = cp->next_ccb; + while (cp && cp->magic) { + cp = cp->next_ccb; + } } /* @@ -6163,10 +6181,13 @@ static ccb_p ncr_get_ccb break; }; - if (cp->magic) + if (cp->magic) { + splx(oldspl); return ((ccb_p) 0); + } cp->magic = 1; + splx(oldspl); return (cp); } @@ -6608,6 +6629,9 @@ static int ncr_snooptest (struct ncb* np) */ if (pc != NCB_SCRIPT_PHYS (np, snoopend)+8) { printf ("CACHE TEST FAILED: script execution failed.\n"); + printf ("\tstart=%08x, pc=%08x, end=%08x\n", + NCB_SCRIPT_PHYS (np, snooptest), pc, + NCB_SCRIPT_PHYS (np, snoopend) +8); return (0x40); }; /* @@ -6867,4 +6891,115 @@ static void ncr_getclock (ncb_p np) } /*=========================================================================*/ + +#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 */ diff --git a/sys/pci/ncrreg.h b/sys/pci/ncrreg.h index 2f88c42..ba50afb 100644 --- a/sys/pci/ncrreg.h +++ b/sys/pci/ncrreg.h @@ -1,6 +1,6 @@ /************************************************************************** ** -** $Id: ncrreg.h,v 1.3 1995/03/21 22:48:36 se Exp $ +** $Id: ncrreg.h,v 1.4 1996/10/11 19:50:12 se Exp $ ** ** Device driver for the NCR 53C810 PCI-SCSI-Controller. ** @@ -147,12 +147,18 @@ struct ncr_reg { #define CSIGP 0x40 /*1b*/ u_char nc_ctest3; - #define CLF 0x04 /* clear scsi fifo */ + #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_long nc_temp; /* ### Temporary stack */ /*20*/ u_char nc_dfifo; /*21*/ u_char nc_ctest4; + #define BDIS 0x80 /* mod: burst disable */ + #define MPEE 0x08 /* mod: master parity error enable */ + /*22*/ u_char nc_ctest5; /*23*/ u_char nc_ctest6; @@ -163,12 +169,23 @@ struct ncr_reg { /*34*/ u_long nc_scratcha; /* ??? Temporary register a */ /*38*/ u_char 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_char nc_dien; /*3a*/ u_char nc_dwt; /*3b*/ u_char 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_long nc_adder; |