From 6a1867824926d71ada354d5f18694d82097e21a8 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Mon, 22 Oct 2018 02:36:18 +0000 Subject: [PATCH] Remove the ncr(4) drive. This driver has been obsolete since the FreeBSD 4.x. It should have been removed then since the sym(4) driver had subsumed it. The driver was commented out of GENERIC in 2000. RelNotes: Yes --- share/man/man4/Makefile | 1 - share/man/man4/ncr.4 | 82 - share/man/man4/sym.4 | 48 - sys/amd64/conf/GENERIC | 3 +- sys/conf/NOTES | 13 - sys/conf/files | 1 - sys/conf/options | 6 - sys/dev/ncr/locate.pl | 45 - sys/dev/ncr/ncr.c | 7118 -------------------------------------- sys/dev/ncr/ncrreg.h | 574 --- sys/i386/conf/GENERIC | 3 +- sys/i386/conf/PAE | 3 +- sys/modules/Makefile | 2 - sys/modules/ncr/Makefile | 9 - 14 files changed, 3 insertions(+), 7905 deletions(-) delete mode 100644 share/man/man4/ncr.4 delete mode 100755 sys/dev/ncr/locate.pl delete mode 100644 sys/dev/ncr/ncr.c delete mode 100644 sys/dev/ncr/ncrreg.h delete mode 100644 sys/modules/ncr/Makefile diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 2e5facf8b309..6582966a3d52 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -304,7 +304,6 @@ MAN= aac.4 \ my.4 \ nand.4 \ nandsim.4 \ - ncr.4 \ ${_ndis.4} \ net80211.4 \ netdump.4 \ diff --git a/share/man/man4/ncr.4 b/share/man/man4/ncr.4 deleted file mode 100644 index a20418cbfdd4..000000000000 --- a/share/man/man4/ncr.4 +++ /dev/null @@ -1,82 +0,0 @@ -.\" -.\" Copyright (c) 1994 James A. Jegers -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd August 19, 2004 -.Dt NCR 4 -.Os -.Sh NAME -.Nm ncr -.Nd NCR 53C8xx SCSI driver -.Sh SYNOPSIS -To compile this driver into the kernel, -place the following lines in your -kernel configuration file: -.Bd -ragged -offset indent -.Cd "device pci" -.Cd "device scbus" -.Cd "device ncr" -.Ed -.Sh HARDWARE -The -.Nm -driver provides support for the following NCR/Symbios SCSI controller -chips: -.Pp -.Bl -bullet -compact -.It -.Tn 53C810 -.It -.Tn 53C810A -.It -.Tn 53C815 -.It -.Tn 53C820 -.It -.Tn 53C825A -.It -.Tn 53C860 -.It -.Tn 53C875 -.It -.Tn 53C875J -.It -.Tn 53C885 -.It -.Tn 53C895 -.It -.Tn 53C895A -.It -.Tn 53C896 -.It -.Tn 53C1510D -.El -.Sh SEE ALSO -.Xr cd 4 , -.Xr ch 4 , -.Xr da 4 , -.Xr intro 4 , -.Xr sa 4 , -.Xr scsi 4 , -.Xr sym 4 diff --git a/share/man/man4/sym.4 b/share/man/man4/sym.4 index dd92eff75bda..bb043b48e0ed 100644 --- a/share/man/man4/sym.4 +++ b/share/man/man4/sym.4 @@ -159,53 +159,6 @@ permanent PCI parity errors detected. This option is supplied for convenience but it is neither recommended nor supported. .Pp -The generic -.Xr ncr 4 -driver also supports SYM53C8XX based PCI SCSI controllers, -except for the SYM53C1010, which is only supported by the -.Nm -driver. -.Pp -By default, when both the -.Xr ncr 4 -and -.Nm -drivers are configured, the -.Nm -driver takes precedence over the -.Xr ncr 4 -driver. -The user can indicate a balancing of chip types between the two drivers -by defining the -.Ar SYM_SETUP_LP_PROBE_MAP -kernel configuration option as follows: -.Bl -column "0x40" -.It Em "Bit Devices to be attached by ncr instead" -.It "0x01 53C810a, 53C860" -.It "0x02 53C825a, 53C875, 53C876, 53C885, 53C895" -.It "0x04 53C895a, 53C896, 53C897, 53C1510d" -.It "0x40 53C810, 53C815, 53C825" -.El -.Pp -For example, if -.Ar SYM_SETUP_LP_PROBE_MAP -is supplied with the value 0x41, the -.Xr ncr 4 -driver will attach to 53C810, 53C815, 53C825, 53C810a, and 53C860 based -controllers, -and the -.Nm -driver will attach to all other 53C8XX based controllers. -.Pp -When only the -.Nm -driver is configured, the -.Ar SYM_SETUP_LP_PROBE_MAP -option has no effect. -Thus, in this case, the -.Nm -driver will attach all 53C8XX based controllers present in the system. -.Pp This driver offers other options that are not currently exported to the user. They are defined and documented in the @@ -342,7 +295,6 @@ The DEC KZPCA-AA is a rebadged SYM8952U. .Sh SEE ALSO .Xr cd 4 , .Xr da 4 , -.Xr ncr 4 , .Xr sa 4 , .Xr scsi 4 , .Xr camcontrol 8 diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index 7f59214f1039..d3cdef23bbc9 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -139,8 +139,7 @@ device isp # Qlogic family device mpt # LSI-Logic MPT-Fusion device mps # LSI-Logic MPT-Fusion 2 device mpr # LSI-Logic MPT-Fusion 3 -#device ncr # NCR/Symbios Logic -device sym # NCR/Symbios Logic (newer chipsets + those of `ncr') +device sym # NCR/Symbios Logic device trm # Tekram DC395U/UW/F DC315U adapters device isci # Intel C600 SAS controller device ocs_fc # Emulex FC adapters diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 820308a4b53f..848681dd21b2 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1563,7 +1563,6 @@ options TERMINAL_KERN_ATTR=(FG_LIGHTRED|BG_BLACK) # ispfw: Firmware module for Qlogic host adapters # mpt: LSI-Logic MPT/Fusion 53c1020 or 53c1030 Ultra4 # or FC9x9 Fibre Channel host adapters. -# ncr: NCR 53C810, 53C825 self-contained SCSI host adapters. # sym: Symbios/Logic 53C8XX family of PCI-SCSI I/O processors: # 53C810, 53C810A, 53C815, 53C825, 53C825A, 53C860, 53C875, # 53C876, 53C885, 53C895, 53C895A, 53C896, 53C897, 53C1510D, @@ -1592,7 +1591,6 @@ hint.isp.0.portwnn="w50000000aaaa0000" hint.isp.0.nodewnn="w50000000aaaa0001" device ispfw device mpt -device ncr device sym device trm @@ -1650,12 +1648,6 @@ options ISP_TARGET_MODE=1 # options ISP_DEFAULT_ROLES=0 -# Options used in dev/sym/ (Symbios SCSI driver). -#options SYM_SETUP_LP_PROBE_MAP #-Low Priority Probe Map (bits) - # Allows the ncr to take precedence - # 1 (1<<0) -> 810a, 860 - # 2 (1<<1) -> 825a, 875, 885, 895 - # 4 (1<<2) -> 895a, 896, 1510d #options SYM_SETUP_SCSI_DIFF #-HVD support for 825a, 875, 885 # disabled:0 (default), enabled:1 #options SYM_SETUP_PCI_PARITY #-PCI parity checking @@ -2923,11 +2915,6 @@ options MSGTQL=41 # Max number of messages in system options NBUF=512 # Number of buffer headers -options SCSI_NCR_DEBUG -options SCSI_NCR_MAX_SYNC=10000 -options SCSI_NCR_MAX_WIDE=1 -options SCSI_NCR_MYADDR=7 - options SC_DEBUG_LEVEL=5 # Syscons debug level options SC_RENDER_DEBUG # syscons rendering debugging diff --git a/sys/conf/files b/sys/conf/files index 71a5341769fb..ca196b599ffd 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2509,7 +2509,6 @@ dev/nand/nandsim_ctrl.c optional nandsim nand dev/nand/nandsim_log.c optional nandsim nand dev/nand/nandsim_swap.c optional nandsim nand dev/nand/nfc_if.m optional nand -dev/ncr/ncr.c optional ncr pci dev/netmap/if_ptnet.c optional netmap inet dev/netmap/netmap.c optional netmap dev/netmap/netmap_freebsd.c optional netmap diff --git a/sys/conf/options b/sys/conf/options index 5e89f3931e10..5e3f99fd52c7 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -386,12 +386,6 @@ SYM_SETUP_PCI_PARITY opt_sym.h #-PCI parity checking SYM_SETUP_MAX_LUN opt_sym.h #-Number of LUNs supported # default:8, range:[1..64] -# Options used only in dev/ncr/* -SCSI_NCR_DEBUG opt_ncr.h -SCSI_NCR_MAX_SYNC opt_ncr.h -SCSI_NCR_MAX_WIDE opt_ncr.h -SCSI_NCR_MYADDR opt_ncr.h - # Options used only in dev/isp/* ISP_TARGET_MODE opt_isp.h ISP_FW_CRASH_DUMP opt_isp.h diff --git a/sys/dev/ncr/locate.pl b/sys/dev/ncr/locate.pl deleted file mode 100755 index 89688e1c6af2..000000000000 --- a/sys/dev/ncr/locate.pl +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/perl -w -# $FreeBSD$ - -use strict; - -if (!defined($ARGV[0])) { - print( -" -Perl script to convert NCR script address into label+offset. -Useful to find the failed NCR instruction ... - -usage: $0
-"); - exit(1); -} - -my $errpos = hex($ARGV[0])/4; -my $ofs=0; - -open (INPUT, "cc -E ncr.c 2>/dev/null |"); - -while ($_ = ) -{ - last if /^struct script \{/; -} - -while ($_ = ) -{ - last if /^\}\;/; - my ($label, $size) = /ncrcmd\s+(\S+)\s+\[([^]]+)/; - $size = eval($size); - if (defined($label) && $label) { - if ($errpos) { - if ($ofs + $size > $errpos) { - printf ("%4x: %s\n", $ofs * 4, $label); - printf ("%4x: %s + %d\n", $errpos * 4, $label, $errpos - $ofs); - last; - } - $ofs += $size; - } else { - printf ("%4x: %s\n", $ofs * 4, $label); - } - } -} - diff --git a/sys/dev/ncr/ncr.c b/sys/dev/ncr/ncr.c deleted file mode 100644 index b7cf433b138f..000000000000 --- a/sys/dev/ncr/ncr.c +++ /dev/null @@ -1,7118 +0,0 @@ -/************************************************************************** -** -** -** Device driver for the NCR 53C8XX PCI-SCSI-Controller Family. -** -**------------------------------------------------------------------------- -** -** Written for 386bsd and FreeBSD by -** Wolfgang Stanglmeier -** Stefan Esser -** -**------------------------------------------------------------------------- -*/ -/*- -** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -*************************************************************************** -*/ - -#include -__FBSDID("$FreeBSD$"); - - -#define NCR_GETCC_WITHMSG - -#if defined (__FreeBSD__) && defined(_KERNEL) -#include "opt_ncr.h" -#endif - -/*========================================================== -** -** Configuration and Debugging -** -** May be overwritten in -** -**========================================================== -*/ - -/* -** SCSI address of this device. -** The boot routines should have set it. -** If not, use this. -*/ - -#ifndef SCSI_NCR_MYADDR -#define SCSI_NCR_MYADDR (7) -#endif /* SCSI_NCR_MYADDR */ - -/* -** The default synchronous period factor -** (0=asynchronous) -** If maximum synchronous frequency is defined, use it instead. -*/ - -#ifndef SCSI_NCR_MAX_SYNC - -#ifndef SCSI_NCR_DFLT_SYNC -#define SCSI_NCR_DFLT_SYNC (12) -#endif /* SCSI_NCR_DFLT_SYNC */ - -#else - -#if SCSI_NCR_MAX_SYNC == 0 -#define SCSI_NCR_DFLT_SYNC 0 -#else -#define SCSI_NCR_DFLT_SYNC (250000 / SCSI_NCR_MAX_SYNC) -#endif - -#endif - -/* -** The minimal asynchronous pre-scaler period (ns) -** Shall be 40. -*/ - -#ifndef SCSI_NCR_MIN_ASYNC -#define SCSI_NCR_MIN_ASYNC (40) -#endif /* SCSI_NCR_MIN_ASYNC */ - -/* -** The maximal bus with (in log2 byte) -** (0=8 bit, 1=16 bit) -*/ - -#ifndef SCSI_NCR_MAX_WIDE -#define SCSI_NCR_MAX_WIDE (1) -#endif /* SCSI_NCR_MAX_WIDE */ - -/*========================================================== -** -** Configuration and Debugging -** -**========================================================== -*/ - -/* -** Number of targets supported by the driver. -** n permits target numbers 0..n-1. -** Default is 7, meaning targets #0..#6. -** #7 .. is myself. -*/ - -#define MAX_TARGET (16) - -/* -** 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. -** There should be one slot per target, and one slot -** for each tag of each target in use. -*/ - -#define MAX_START (256) - -/* -** The maximum number of segments a transfer is split into. -*/ - -#define MAX_SCATTER (33) - -/* -** The maximum transfer length (should be >= 64k). -** MUST NOT be greater than (MAX_SCATTER-1) * PAGE_SIZE. -*/ - -#define MAX_SIZE ((MAX_SCATTER-1) * (long) PAGE_SIZE) - -/* -** other -*/ - -#define NCR_SNOOP_TIMEOUT (1000000) - -/*========================================================== -** -** Include files -** -**========================================================== -*/ - -#include -#include - -#ifdef _KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -/*========================================================== -** -** Debugging tags -** -**========================================================== -*/ - -#define DEBUG_ALLOC (0x0001) -#define DEBUG_PHASE (0x0002) -#define DEBUG_POLL (0x0004) -#define DEBUG_QUEUE (0x0008) -#define DEBUG_RESULT (0x0010) -#define DEBUG_SCATTER (0x0020) -#define DEBUG_SCRIPT (0x0040) -#define DEBUG_TINY (0x0080) -#define DEBUG_TIMING (0x0100) -#define DEBUG_NEGO (0x0200) -#define DEBUG_TAGS (0x0400) -#define DEBUG_FREEZE (0x0800) -#define DEBUG_RESTART (0x1000) - -/* -** Enable/Disable debug messages. -** Can be changed at runtime too. -*/ -#ifdef SCSI_NCR_DEBUG - #define DEBUG_FLAGS ncr_debug -#else /* SCSI_NCR_DEBUG */ - #define SCSI_NCR_DEBUG 0 - #define DEBUG_FLAGS 0 -#endif /* SCSI_NCR_DEBUG */ - - - -/*========================================================== -** -** assert () -** -**========================================================== -** -** modified copy from 386bsd:/usr/include/sys/assert.h -** -**---------------------------------------------------------- -*/ - -#ifdef DIAGNOSTIC -#define assert(expression) { \ - KASSERT(expression, ("%s", #expression)); \ -} -#else -#define assert(expression) { \ - if (!(expression)) { \ - (void)printf("assertion \"%s\" failed: " \ - "file \"%s\", line %d\n", \ - #expression, __FILE__, __LINE__); \ - } \ -} -#endif - -/*========================================================== -** -** Access to the controller chip. -** -**========================================================== -*/ - -#define INB(r) bus_read_1(np->reg_res, offsetof(struct ncr_reg, r)) -#define INW(r) bus_read_2(np->reg_res, offsetof(struct ncr_reg, r)) -#define INL(r) bus_read_4(np->reg_res, offsetof(struct ncr_reg, r)) - -#define OUTB(r, val) bus_write_1(np->reg_res, offsetof(struct ncr_reg, r), val) -#define OUTW(r, val) bus_write_2(np->reg_res, offsetof(struct ncr_reg, r), val) -#define OUTL(r, val) bus_write_4(np->reg_res, offsetof(struct ncr_reg, r), val) -#define OUTL_OFF(o, val) bus_write_4(np->reg_res, o, val) - -#define INB_OFF(o) bus_read_1(np->reg_res, o) -#define INW_OFF(o) bus_read_2(np->reg_res, o) -#define INL_OFF(o) bus_read_4(np->reg_res, o) - -#define READSCRIPT_OFF(base, off) \ - (base ? *((volatile u_int32_t *)((volatile char *)base + (off))) : \ - bus_read_4(np->sram_res, off)) - -#define WRITESCRIPT_OFF(base, off, val) \ - do { \ - if (base) \ - *((volatile u_int32_t *) \ - ((volatile char *)base + (off))) = (val); \ - else \ - bus_write_4(np->sram_res, off, val); \ - } while (0) - -#define READSCRIPT(r) \ - READSCRIPT_OFF(np->script, offsetof(struct script, r)) - -#define WRITESCRIPT(r, val) \ - WRITESCRIPT_OFF(np->script, offsetof(struct script, r), val) - -/* -** Set bit field ON, OFF -*/ - -#define OUTONB(r, m) OUTB(r, INB(r) | (m)) -#define OUTOFFB(r, m) OUTB(r, INB(r) & ~(m)) -#define OUTONW(r, m) OUTW(r, INW(r) | (m)) -#define OUTOFFW(r, m) OUTW(r, INW(r) & ~(m)) -#define OUTONL(r, m) OUTL(r, INL(r) | (m)) -#define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m)) - -/*========================================================== -** -** Command control block states. -** -**========================================================== -*/ - -#define HS_IDLE (0) -#define HS_BUSY (1) -#define HS_NEGOTIATE (2) /* sync/wide data transfer*/ -#define HS_DISCONNECT (3) /* Disconnected by target */ - -#define HS_COMPLETE (4) -#define HS_SEL_TIMEOUT (5) /* Selection timeout */ -#define HS_RESET (6) /* SCSI reset */ -#define HS_ABORTED (7) /* Transfer aborted */ -#define HS_TIMEOUT (8) /* Software timeout */ -#define HS_FAIL (9) /* SCSI or PCI bus errors */ -#define HS_UNEXPECTED (10) /* Unexpected disconnect */ -#define HS_STALL (11) /* QUEUE FULL or BUSY */ - -#define HS_DONEMASK (0xfc) - -/*========================================================== -** -** Software Interrupt Codes -** -**========================================================== -*/ - -#define SIR_SENSE_RESTART (1) -#define SIR_SENSE_FAILED (2) -#define SIR_STALL_RESTART (3) -#define SIR_STALL_QUEUE (4) -#define SIR_NEGO_SYNC (5) -#define SIR_NEGO_WIDE (6) -#define SIR_NEGO_FAILED (7) -#define SIR_NEGO_PROTO (8) -#define SIR_REJECT_RECEIVED (9) -#define SIR_REJECT_SENT (10) -#define SIR_IGN_RESIDUE (11) -#define SIR_MISSING_SAVE (12) -#define SIR_MAX (12) - -/*========================================================== -** -** Extended error codes. -** xerr_status field of struct nccb. -** -**========================================================== -*/ - -#define XE_OK (0) -#define XE_EXTRA_DATA (1) /* unexpected data phase */ -#define XE_BAD_PHASE (2) /* illegal phase (4/5) */ - -/*========================================================== -** -** Negotiation status. -** nego_status field of struct nccb. -** -**========================================================== -*/ - -#define NS_SYNC (1) -#define NS_WIDE (2) - -/*========================================================== -** -** XXX These are no longer used. Remove once the -** script is updated. -** "Special features" of targets. -** quirks field of struct tcb. -** actualquirks field of struct nccb. -** -**========================================================== -*/ - -#define QUIRK_AUTOSAVE (0x01) -#define QUIRK_NOMSG (0x02) -#define QUIRK_NOSYNC (0x10) -#define QUIRK_NOWIDE16 (0x20) -#define QUIRK_NOTAGS (0x40) -#define QUIRK_UPDATE (0x80) - -/*========================================================== -** -** Misc. -** -**========================================================== -*/ - -#define CCB_MAGIC (0xf2691ad2) -#define MAX_TAGS (32) /* hard limit */ - -/*========================================================== -** -** OS dependencies. -** -**========================================================== -*/ - -#define PRINT_ADDR(ccb) xpt_print_path((ccb)->ccb_h.path) - -/*========================================================== -** -** Declaration of structs. -** -**========================================================== -*/ - -struct tcb; -struct lcb; -struct nccb; -struct ncb; -struct script; - -typedef struct ncb * ncb_p; -typedef struct tcb * tcb_p; -typedef struct lcb * lcb_p; -typedef struct nccb * nccb_p; - -struct link { - ncrcmd l_cmd; - ncrcmd l_paddr; -}; - -struct usrcmd { - u_long target; - u_long lun; - u_long data; - u_long cmd; -}; - -#define UC_SETSYNC 10 -#define UC_SETTAGS 11 -#define UC_SETDEBUG 12 -#define UC_SETORDER 13 -#define UC_SETWIDE 14 -#define UC_SETFLAG 15 - -#define UF_TRACE (0x01) - -/*--------------------------------------- -** -** Timestamps for profiling -** -**--------------------------------------- -*/ - -/* Type of the kernel variable `ticks'. XXX should be declared with the var. */ -typedef int ticks_t; - -struct tstamp { - ticks_t start; - ticks_t end; - ticks_t select; - ticks_t command; - ticks_t data; - ticks_t status; - ticks_t disconnect; -}; - -/* -** profiling data (per device) -*/ - -struct profile { - u_long num_trans; - u_long num_bytes; - u_long num_disc; - u_long num_break; - u_long num_int; - u_long num_fly; - u_long ms_setup; - u_long ms_data; - u_long ms_disc; - u_long ms_post; -}; - -/*========================================================== -** -** Declaration of structs: target control block -** -**========================================================== -*/ - -#define NCR_TRANS_CUR 0x01 /* Modify current neogtiation status */ -#define NCR_TRANS_ACTIVE 0x03 /* Assume this is the active target */ -#define NCR_TRANS_GOAL 0x04 /* Modify negotiation goal */ -#define NCR_TRANS_USER 0x08 /* Modify user negotiation settings */ - -struct ncr_transinfo { - u_int8_t width; - u_int8_t period; - u_int8_t offset; -}; - -struct ncr_target_tinfo { - /* Hardware version of our sync settings */ - u_int8_t disc_tag; -#define NCR_CUR_DISCENB 0x01 -#define NCR_CUR_TAGENB 0x02 -#define NCR_USR_DISCENB 0x04 -#define NCR_USR_TAGENB 0x08 - u_int8_t sval; - struct ncr_transinfo current; - struct ncr_transinfo goal; - struct ncr_transinfo user; - /* Hardware version of our wide settings */ - u_int8_t wval; -}; - -struct tcb { - /* - ** during reselection the ncr jumps to this point - ** with SFBR set to the encoded target number - ** with bit 7 set. - ** if it's not this target, jump to the next. - ** - ** JUMP IF (SFBR != #target#) - ** @(next tcb) - */ - - struct link jump_tcb; - - /* - ** load the actual values for the sxfer and the scntl3 - ** register (sync/wide mode). - ** - ** SCR_COPY (1); - ** @(sval field of this tcb) - ** @(sxfer register) - ** SCR_COPY (1); - ** @(wval field of this tcb) - ** @(scntl3 register) - */ - - ncrcmd getscr[6]; - - /* - ** if next message is "identify" - ** then load the message to SFBR, - ** else load 0 to SFBR. - ** - ** CALL - ** - */ - - struct link call_lun; - - /* - ** now look for the right lun. - ** - ** JUMP - ** @(first nccb of this lun) - */ - - struct link jump_lcb; - - /* - ** pointer to interrupted getcc nccb - */ - - nccb_p hold_cp; - - /* - ** pointer to nccb used for negotiating. - ** Avoid to start a nego for all queued commands - ** when tagged command queuing is enabled. - */ - - nccb_p nego_cp; - - /* - ** statistical data - */ - - u_long transfers; - u_long bytes; - - /* - ** user settable limits for sync transfer - ** and tagged commands. - */ - - struct ncr_target_tinfo tinfo; - - /* - ** the lcb's of this tcb - */ - - lcb_p lp[MAX_LUN]; -}; - -/*========================================================== -** -** Declaration of structs: lun control block -** -**========================================================== -*/ - -struct lcb { - /* - ** during reselection the ncr jumps to this point - ** with SFBR set to the "Identify" message. - ** if it's not this lun, jump to the next. - ** - ** JUMP IF (SFBR != #lun#) - ** @(next lcb of this target) - */ - - struct link jump_lcb; - - /* - ** if next message is "simple tag", - ** then load the tag to SFBR, - ** else load 0 to SFBR. - ** - ** CALL - ** - */ - - struct link call_tag; - - /* - ** now look for the right nccb. - ** - ** JUMP - ** @(first nccb of this lun) - */ - - struct link jump_nccb; - - /* - ** start of the nccb chain - */ - - nccb_p next_nccb; - - /* - ** Control of tagged queueing - */ - - u_char reqnccbs; - u_char reqlink; - u_char actlink; - u_char usetags; - u_char lasttag; -}; - -/*========================================================== -** -** Declaration of structs: COMMAND control block -** -**========================================================== -** -** This substructure is copied from the nccb to a -** global address after selection (or reselection) -** and copied back before disconnect. -** -** These fields are accessible to the script processor. -** -**---------------------------------------------------------- -*/ - -struct head { - /* - ** Execution of a nccb starts at this point. - ** It's a jump to the "SELECT" label - ** of the script. - ** - ** After successful selection the script - ** processor overwrites it with a jump to - ** the IDLE label of the script. - */ - - struct link launch; - - /* - ** Saved data pointer. - ** Points to the position in the script - ** responsible for the actual transfer - ** of data. - ** It's written after reception of a - ** "SAVE_DATA_POINTER" message. - ** The goalpointer points after - ** the last transfer command. - */ - - u_int32_t savep; - u_int32_t lastp; - u_int32_t goalp; - - /* - ** The virtual address of the nccb - ** containing this header. - */ - - nccb_p cp; - - /* - ** space for some timestamps to gather - ** profiling data about devices and this driver. - */ - - struct tstamp stamp; - - /* - ** status fields. - */ - - u_char status[8]; -}; - -/* -** The status bytes are used by the host and the script processor. -** -** The first four byte are copied to the scratchb register -** (declared as scr0..scr3 in ncr_reg.h) just after the select/reselect, -** and copied back just after disconnecting. -** Inside the script the XX_REG are used. -** -** The last four bytes are used inside the script by "COPY" commands. -** Because source and destination must have the same alignment -** in a longword, the fields HAVE to be at the chosen offsets. -** xerr_st (4) 0 (0x34) scratcha -** sync_st (5) 1 (0x05) sxfer -** wide_st (7) 3 (0x03) scntl3 -*/ - -/* -** First four bytes (script) -*/ -#define QU_REG scr0 -#define HS_REG scr1 -#define HS_PRT nc_scr1 -#define SS_REG scr2 -#define PS_REG scr3 - -/* -** First four bytes (host) -*/ -#define actualquirks phys.header.status[0] -#define host_status phys.header.status[1] -#define s_status phys.header.status[2] -#define parity_status phys.header.status[3] - -/* -** Last four bytes (script) -*/ -#define xerr_st header.status[4] /* MUST be ==0 mod 4 */ -#define sync_st header.status[5] /* MUST be ==1 mod 4 */ -#define nego_st header.status[6] -#define wide_st header.status[7] /* MUST be ==3 mod 4 */ - -/* -** Last four bytes (host) -*/ -#define xerr_status phys.xerr_st -#define sync_status phys.sync_st -#define nego_status phys.nego_st -#define wide_status phys.wide_st - -/*========================================================== -** -** Declaration of structs: Data structure block -** -**========================================================== -** -** During execution of a nccb by the script processor, -** the DSA (data structure address) register points -** to this substructure of the nccb. -** This substructure contains the header with -** the script-processor-changable data and -** data blocks for the indirect move commands. -** -**---------------------------------------------------------- -*/ - -struct dsb { - - /* - ** Header. - ** Has to be the first entry, - ** because it's jumped to by the - ** script processor - */ - - struct head header; - - /* - ** Table data for Script - */ - - struct scr_tblsel select; - struct scr_tblmove smsg ; - struct scr_tblmove smsg2 ; - struct scr_tblmove cmd ; - struct scr_tblmove scmd ; - struct scr_tblmove sense ; - struct scr_tblmove data [MAX_SCATTER]; -}; - -/*========================================================== -** -** Declaration of structs: Command control block. -** -**========================================================== -** -** During execution of a nccb by the script processor, -** the DSA (data structure address) register points -** to this substructure of the nccb. -** This substructure contains the header with -** the script-processor-changable data and then -** data blocks for the indirect move commands. -** -**---------------------------------------------------------- -*/ - - -struct nccb { - /* - ** This filler ensures that the global header is - ** cache line size aligned. - */ - ncrcmd filler[4]; - - /* - ** during reselection the ncr jumps to this point. - ** If a "SIMPLE_TAG" message was received, - ** then SFBR is set to the tag. - ** else SFBR is set to 0 - ** If looking for another tag, jump to the next nccb. - ** - ** JUMP IF (SFBR != #TAG#) - ** @(next nccb of this lun) - */ - - struct link jump_nccb; - - /* - ** After execution of this call, the return address - ** (in the TEMP register) points to the following - ** data structure block. - ** So copy it to the DSA register, and start - ** processing of this data structure. - ** - ** CALL - ** - */ - - struct link call_tmp; - - /* - ** This is the data structure which is - ** to be executed by the script processor. - */ - - struct dsb phys; - - /* - ** If a data transfer phase is terminated too early - ** (after reception of a message (i.e. DISCONNECT)), - ** we have to prepare a mini script to transfer - ** the rest of the data. - */ - - ncrcmd patch[8]; - - /* - ** The general SCSI driver provides a - ** pointer to a control block. - */ - - union ccb *ccb; - - /* - ** We prepare a message to be sent after selection, - ** and a second one to be sent after getcc selection. - ** Contents are IDENTIFY and SIMPLE_TAG. - ** While negotiating sync or wide transfer, - ** a SDTM or WDTM message is appended. - */ - - u_char scsi_smsg [8]; - u_char scsi_smsg2[8]; - - /* - ** Lock this nccb. - ** Flag is used while looking for a free nccb. - */ - - u_long magic; - - /* - ** Physical address of this instance of nccb - */ - - u_long p_nccb; - - /* - ** Completion time out for this job. - ** It's set to time of start + allowed number of seconds. - */ - - time_t tlimit; - - /* - ** All nccbs of one hostadapter are chained. - */ - - nccb_p link_nccb; - - /* - ** All nccbs of one target/lun are chained. - */ - - nccb_p next_nccb; - - /* - ** Sense command - */ - - u_char sensecmd[6]; - - /* - ** Tag for this transfer. - ** It's patched into jump_nccb. - ** If it's not zero, a SIMPLE_TAG - ** message is included in smsg. - */ - - u_char tag; -}; - -#define CCB_PHYS(cp,lbl) (cp->p_nccb + offsetof(struct nccb, lbl)) - -/*========================================================== -** -** Declaration of structs: NCR device descriptor -** -**========================================================== -*/ - -struct ncb { - /* - ** The global header. - ** Accessible to both the host and the - ** script-processor. - ** We assume it is cache line size aligned. - */ - struct head header; - - device_t dev; - - /*----------------------------------------------- - ** Scripts .. - **----------------------------------------------- - ** - ** During reselection the ncr jumps to this point. - ** The SFBR register is loaded with the encoded target id. - ** - ** Jump to the first target. - ** - ** JUMP - ** @(next tcb) - */ - struct link jump_tcb; - - /*----------------------------------------------- - ** Configuration .. - **----------------------------------------------- - ** - ** virtual and physical addresses - ** of the 53c810 chip. - */ - int reg_rid; - struct resource *reg_res; - - int sram_rid; - struct resource *sram_res; - - struct resource *irq_res; - void *irq_handle; - - /* - ** Scripts instance virtual address. - */ - struct script *script; - struct scripth *scripth; - - /* - ** Scripts instance physical address. - */ - u_long p_script; - u_long p_scripth; - - /* - ** The SCSI address of the host adapter. - */ - u_char myaddr; - - /* - ** timing parameters - */ - u_char minsync; /* Minimum sync period factor */ - u_char maxsync; /* Maximum sync period factor */ - u_char maxoffs; /* Max scsi offset */ - u_char clock_divn; /* Number of clock divisors */ - u_long clock_khz; /* SCSI clock frequency in KHz */ - u_long features; /* Chip features map */ - u_char multiplier; /* Clock multiplier (1,2,4) */ - - u_char maxburst; /* log base 2 of dwords burst */ - - /* - ** BIOS supplied PCI bus options - */ - u_char rv_scntl3; - u_char rv_dcntl; - u_char rv_dmode; - u_char rv_ctest3; - u_char rv_ctest4; - u_char rv_ctest5; - u_char rv_gpcntl; - u_char rv_stest2; - - /*----------------------------------------------- - ** CAM SIM information for this instance - **----------------------------------------------- - */ - - struct cam_sim *sim; - struct cam_path *path; - - /*----------------------------------------------- - ** Job control - **----------------------------------------------- - ** - ** Commands from user - */ - struct usrcmd user; - - /* - ** Target data - */ - struct tcb target[MAX_TARGET]; - - /* - ** Start queue. - */ - u_int32_t squeue [MAX_START]; - u_short squeueput; - - /* - ** Timeout handler - */ - time_t heartbeat; - u_short ticks; - u_short latetime; - time_t lasttime; - struct callout timer; - - /*----------------------------------------------- - ** Debug and profiling - **----------------------------------------------- - ** - ** register dump - */ - struct ncr_reg regdump; - time_t regtime; - - /* - ** Profiling data - */ - struct profile profile; - u_long disc_phys; - u_long disc_ref; - - /* - ** Head of list of all nccbs for this controller. - */ - nccb_p link_nccb; - - /* - ** message buffers. - ** Should be longword aligned, - ** because they're written with a - ** COPY script command. - */ - u_char msgout[8]; - u_char msgin [8]; - u_int32_t lastmsg; - - /* - ** Buffer for STATUS_IN phase. - */ - u_char scratch; - - /* - ** controller chip dependent maximal transfer width. - */ - u_char maxwide; - - struct mtx lock; -#ifdef NCR_IOMAPPED - /* - ** address of the ncr control registers in io space - */ - pci_port_t port; -#endif -}; - -#define NCB_SCRIPT_PHYS(np,lbl) (np->p_script + offsetof (struct script, lbl)) -#define NCB_SCRIPTH_PHYS(np,lbl) (np->p_scripth + offsetof (struct scripth,lbl)) - -/*========================================================== -** -** -** Script for NCR-Processor. -** -** Use ncr_script_fill() to create the variable parts. -** Use ncr_script_copy_and_bind() to make a copy and -** bind to physical addresses. -** -** -**========================================================== -** -** We have to know the offsets of all labels before -** we reach them (for forward jumps). -** Therefore we declare a struct here. -** If you make changes inside the script, -** DONT FORGET TO CHANGE THE LENGTHS HERE! -** -**---------------------------------------------------------- -*/ - -/* -** Script fragments which are loaded into the on-board RAM -** of 825A, 875 and 895 chips. -*/ -struct script { - ncrcmd start [ 7]; - ncrcmd start0 [ 2]; - ncrcmd start1 [ 3]; - ncrcmd startpos [ 1]; - ncrcmd trysel [ 8]; - ncrcmd skip [ 8]; - ncrcmd skip2 [ 3]; - ncrcmd idle [ 2]; - ncrcmd select [ 18]; - ncrcmd prepare [ 4]; - ncrcmd loadpos [ 14]; - ncrcmd prepare2 [ 24]; - ncrcmd setmsg [ 5]; - ncrcmd clrack [ 2]; - ncrcmd dispatch [ 33]; - ncrcmd no_data [ 17]; - ncrcmd checkatn [ 10]; - ncrcmd command [ 15]; - ncrcmd status [ 27]; - ncrcmd msg_in [ 26]; - ncrcmd msg_bad [ 6]; - ncrcmd complete [ 13]; - ncrcmd cleanup [ 12]; - ncrcmd cleanup0 [ 9]; - ncrcmd signal [ 12]; - ncrcmd save_dp [ 5]; - ncrcmd restore_dp [ 5]; - ncrcmd disconnect [ 12]; - ncrcmd disconnect0 [ 5]; - ncrcmd disconnect1 [ 23]; - ncrcmd msg_out [ 9]; - ncrcmd msg_out_done [ 7]; - ncrcmd badgetcc [ 6]; - ncrcmd reselect [ 8]; - ncrcmd reselect1 [ 8]; - ncrcmd reselect2 [ 8]; - ncrcmd resel_tmp [ 5]; - ncrcmd resel_lun [ 18]; - ncrcmd resel_tag [ 24]; - ncrcmd data_in [MAX_SCATTER * 4 + 7]; - ncrcmd data_out [MAX_SCATTER * 4 + 7]; -}; - -/* -** Script fragments which stay in main memory for all chips. -*/ -struct scripth { - ncrcmd tryloop [MAX_START*5+2]; - ncrcmd msg_parity [ 6]; - ncrcmd msg_reject [ 8]; - ncrcmd msg_ign_residue [ 32]; - ncrcmd msg_extended [ 18]; - ncrcmd msg_ext_2 [ 18]; - ncrcmd msg_wdtr [ 27]; - ncrcmd msg_ext_3 [ 18]; - ncrcmd msg_sdtr [ 27]; - ncrcmd msg_out_abort [ 10]; - ncrcmd getcc [ 4]; - ncrcmd getcc1 [ 5]; -#ifdef NCR_GETCC_WITHMSG - ncrcmd getcc2 [ 29]; -#else - ncrcmd getcc2 [ 14]; -#endif - ncrcmd getcc3 [ 6]; - ncrcmd aborttag [ 4]; - ncrcmd abort [ 22]; - ncrcmd snooptest [ 9]; - ncrcmd snoopend [ 2]; -}; - -/*========================================================== -** -** -** Function headers. -** -** -**========================================================== -*/ - -#ifdef _KERNEL -static nccb_p ncr_alloc_nccb(ncb_p np, u_long target, u_long lun); -static void ncr_complete(ncb_p np, nccb_p cp); -static int ncr_delta(int * from, int * to); -static void ncr_exception(ncb_p np); -static void ncr_free_nccb(ncb_p np, nccb_p cp); -static void ncr_freeze_devq(ncb_p np, struct cam_path *path); -static void ncr_selectclock(ncb_p np, u_char scntl3); -static void ncr_getclock(ncb_p np, u_char multiplier); -static nccb_p ncr_get_nccb(ncb_p np, u_long t,u_long l); -#if 0 -static u_int32_t ncr_info(int unit); -#endif -static void ncr_init(ncb_p np, char * msg, u_long code); -static void ncr_intr(void *vnp); -static void ncr_intr_locked(ncb_p np); -static void ncr_int_ma(ncb_p np, u_char dstat); -static void ncr_int_sir(ncb_p np); -static void ncr_int_sto(ncb_p np); -#if 0 -static void ncr_min_phys(struct buf *bp); -#endif -static void ncr_poll(struct cam_sim *sim); -static void ncb_profile(ncb_p np, nccb_p cp); -static void ncr_script_copy_and_bind(ncb_p np, ncrcmd *src, ncrcmd *dst, - int len); -static void ncr_script_fill(struct script * scr, struct scripth *scrh); -static int ncr_scatter(struct dsb* phys, vm_offset_t vaddr, - vm_size_t datalen); -static void ncr_getsync(ncb_p np, u_char sfac, u_char *fakp, - u_char *scntl3p); -static void ncr_setsync(ncb_p np, nccb_p cp,u_char scntl3,u_char sxfer, - u_char period); -static void ncr_setwide(ncb_p np, nccb_p cp, u_char wide, u_char ack); -static int ncr_show_msg(u_char * msg); -static int ncr_snooptest(ncb_p np); -static void ncr_action(struct cam_sim *sim, union ccb *ccb); -static void ncr_timeout(void *arg); -static void ncr_wakeup(ncb_p np, u_long code); - -static int ncr_probe(device_t dev); -static int ncr_attach(device_t dev); - -#endif /* _KERNEL */ - -/*========================================================== -** -** -** Global static data. -** -** -**========================================================== -*/ - -#ifdef _KERNEL - -static int ncr_debug = SCSI_NCR_DEBUG; -SYSCTL_INT(_debug, OID_AUTO, ncr_debug, CTLFLAG_RW, &ncr_debug, 0, ""); - -static int ncr_cache; /* to be aligned _NOT_ static */ - -/*========================================================== -** -** -** Global static data: auto configure -** -** -**========================================================== -*/ - -#define NCR_810_ID (0x00011000ul) -#define NCR_815_ID (0x00041000ul) -#define NCR_820_ID (0x00021000ul) -#define NCR_825_ID (0x00031000ul) -#define NCR_860_ID (0x00061000ul) -#define NCR_875_ID (0x000f1000ul) -#define NCR_875_ID2 (0x008f1000ul) -#define NCR_885_ID (0x000d1000ul) -#define NCR_895_ID (0x000c1000ul) -#define NCR_896_ID (0x000b1000ul) -#define NCR_895A_ID (0x00121000ul) -#define NCR_1510D_ID (0x000a1000ul) - - -/*========================================================== -** -** -** Scripts for NCR-Processor. -** -** Use ncr_script_bind for binding to physical addresses. -** -** -**========================================================== -** -** NADDR generates a reference to a field of the controller data. -** PADDR generates a reference to another part of the script. -** RADDR generates a reference to a script processor register. -** FADDR generates a reference to a script processor register -** with offset. -** -**---------------------------------------------------------- -*/ - -#define RELOC_SOFTC 0x40000000 -#define RELOC_LABEL 0x50000000 -#define RELOC_REGISTER 0x60000000 -#define RELOC_KVAR 0x70000000 -#define RELOC_LABELH 0x80000000 -#define RELOC_MASK 0xf0000000 - -#define NADDR(label) (RELOC_SOFTC | offsetof(struct ncb, label)) -#define PADDR(label) (RELOC_LABEL | offsetof(struct script, label)) -#define PADDRH(label) (RELOC_LABELH | offsetof(struct scripth, label)) -#define RADDR(label) (RELOC_REGISTER | REG(label)) -#define FADDR(label,ofs)(RELOC_REGISTER | ((REG(label))+(ofs))) -#define KVAR(which) (RELOC_KVAR | (which)) - -#define KVAR_SECOND (0) -#define KVAR_TICKS (1) -#define KVAR_NCR_CACHE (2) - -#define SCRIPT_KVAR_FIRST (0) -#define SCRIPT_KVAR_LAST (3) - -/* - * Kernel variables referenced in the scripts. - * THESE MUST ALL BE ALIGNED TO A 4-BYTE BOUNDARY. - */ -static volatile void *script_kvars[] = - { &time_second, &ticks, &ncr_cache }; - -static struct script script0 = { -/*--------------------------< START >-----------------------*/ { - /* - ** Claim to be still alive ... - */ - SCR_COPY (sizeof (((struct ncb *)0)->heartbeat)), - KVAR (KVAR_SECOND), - NADDR (heartbeat), - /* - ** Make data structure address invalid. - ** clear SIGP. - */ - SCR_LOAD_REG (dsa, 0xff), - 0, - SCR_FROM_REG (ctest2), - 0, -}/*-------------------------< START0 >----------------------*/,{ - /* - ** Hook for interrupted GetConditionCode. - ** Will be patched to ... IFTRUE by - ** the interrupt handler. - */ - SCR_INT ^ IFFALSE (0), - SIR_SENSE_RESTART, - -}/*-------------------------< START1 >----------------------*/,{ - /* - ** Hook for stalled start queue. - ** Will be patched to IFTRUE by the interrupt handler. - */ - SCR_INT ^ IFFALSE (0), - SIR_STALL_RESTART, - /* - ** Then jump to a certain point in tryloop. - ** Due to the lack of indirect addressing the code - ** is self modifying here. - */ - SCR_JUMP, -}/*-------------------------< STARTPOS >--------------------*/,{ - PADDRH(tryloop), - -}/*-------------------------< TRYSEL >----------------------*/,{ - /* - ** Now: - ** DSA: Address of a Data Structure - ** or Address of the IDLE-Label. - ** - ** TEMP: Address of a script, which tries to - ** start the NEXT entry. - ** - ** Save the TEMP register into the SCRATCHA register. - ** Then copy the DSA to TEMP and RETURN. - ** This is kind of an indirect jump. - ** (The script processor has NO stack, so the - ** CALL is actually a jump and link, and the - ** RETURN is an indirect jump.) - ** - ** If the slot was empty, DSA contains the address - ** of the IDLE part of this script. The processor - ** jumps to IDLE and waits for a reselect. - ** It will wake up and try the same slot again - ** after the SIGP bit becomes set by the host. - ** - ** If the slot was not empty, DSA contains - ** the address of the phys-part of a nccb. - ** The processor jumps to this address. - ** phys starts with head, - ** head starts with launch, - ** so actually the processor jumps to - ** the lauch part. - ** If the entry is scheduled for execution, - ** then launch contains a jump to SELECT. - ** If it's not scheduled, it contains a jump to IDLE. - */ - SCR_COPY (4), - RADDR (temp), - RADDR (scratcha), - SCR_COPY (4), - RADDR (dsa), - RADDR (temp), - SCR_RETURN, - 0 - -}/*-------------------------< SKIP >------------------------*/,{ - /* - ** This entry has been canceled. - ** Next time use the next slot. - */ - SCR_COPY (4), - RADDR (scratcha), - PADDR (startpos), - /* - ** patch the launch field. - ** should look like an idle process. - */ - SCR_COPY_F (4), - RADDR (dsa), - PADDR (skip2), - SCR_COPY (8), - PADDR (idle), -}/*-------------------------< SKIP2 >-----------------------*/,{ - 0, - SCR_JUMP, - PADDR(start), -}/*-------------------------< IDLE >------------------------*/,{ - /* - ** Nothing to do? - ** Wait for reselect. - */ - SCR_JUMP, - PADDR(reselect), - -}/*-------------------------< SELECT >----------------------*/,{ - /* - ** DSA contains the address of a scheduled - ** data structure. - ** - ** SCRATCHA contains the address of the script, - ** which starts the next entry. - ** - ** Set Initiator mode. - ** - ** (Target mode is left as an exercise for the reader) - */ - - SCR_CLR (SCR_TRG), - 0, - SCR_LOAD_REG (HS_REG, 0xff), - 0, - - /* - ** And try to select this target. - */ - SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select), - PADDR (reselect), - - /* - ** Now there are 4 possibilities: - ** - ** (1) The ncr loses arbitration. - ** This is ok, because it will try again, - ** when the bus becomes idle. - ** (But beware of the timeout function!) - ** - ** (2) The ncr is reselected. - ** Then the script processor takes the jump - ** to the RESELECT label. - ** - ** (3) The ncr completes the selection. - ** Then it will execute the next statement. - ** - ** (4) There is a selection timeout. - ** Then the ncr should interrupt the host and stop. - ** Unfortunately, it seems to continue execution - ** of the script. But it will fail with an - ** IID-interrupt on the next WHEN. - */ - - SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_IN)), - 0, - - /* - ** Send the IDENTIFY and SIMPLE_TAG messages - ** (and the MSG_EXT_SDTR message) - */ - 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), - RADDR (sfbr), - NADDR (lastmsg), - /* - ** Selection complete. - ** Next time use the next slot. - */ - SCR_COPY (4), - RADDR (scratcha), - PADDR (startpos), -}/*-------------------------< PREPARE >----------------------*/,{ - /* - ** The ncr doesn't have an indirect load - ** or store command. So we have to - ** copy part of the control block to a - ** fixed place, where we can access it. - ** - ** We patch the address part of a - ** COPY command with the DSA-register. - */ - SCR_COPY_F (4), - RADDR (dsa), - PADDR (loadpos), - /* - ** then we do the actual copy. - */ - SCR_COPY (sizeof (struct head)), - /* - ** continued after the next label ... - */ - -}/*-------------------------< LOADPOS >---------------------*/,{ - 0, - NADDR (header), - /* - ** Mark this nccb as not scheduled. - */ - SCR_COPY (8), - PADDR (idle), - NADDR (header.launch), - /* - ** Set a time stamp for this selection - */ - SCR_COPY (sizeof (ticks)), - KVAR (KVAR_TICKS), - NADDR (header.stamp.select), - /* - ** load the savep (saved pointer) into - ** the TEMP register (actual pointer) - */ - SCR_COPY (4), - NADDR (header.savep), - RADDR (temp), - /* - ** Initialize the status registers - */ - SCR_COPY (4), - NADDR (header.status), - RADDR (scr0), - -}/*-------------------------< PREPARE2 >---------------------*/,{ - /* - ** Load the synchronous mode register - */ - SCR_COPY (1), - NADDR (sync_st), - RADDR (sxfer), - /* - ** Load the wide mode and timing register - */ - SCR_COPY (1), - NADDR (wide_st), - RADDR (scntl3), - /* - ** Initialize the msgout buffer with a NOOP message. - */ - SCR_LOAD_REG (scratcha, MSG_NOOP), - 0, - SCR_COPY (1), - RADDR (scratcha), - NADDR (msgout), - SCR_COPY (1), - RADDR (scratcha), - NADDR (msgin), - /* - ** Message in phase ? - */ - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** Extended or reject message ? - */ - SCR_FROM_REG (sbdl), - 0, - SCR_JUMP ^ IFTRUE (DATA (MSG_EXTENDED)), - PADDR (msg_in), - SCR_JUMP ^ IFTRUE (DATA (MSG_MESSAGE_REJECT)), - PADDRH (msg_reject), - /* - ** normal processing - */ - SCR_JUMP, - PADDR (dispatch), -}/*-------------------------< SETMSG >----------------------*/,{ - SCR_COPY (1), - RADDR (scratcha), - NADDR (msgout), - SCR_SET (SCR_ATN), - 0, -}/*-------------------------< CLRACK >----------------------*/,{ - /* - ** Terminate possible pending message phase. - */ - SCR_CLR (SCR_ACK), - 0, - -}/*-----------------------< DISPATCH >----------------------*/,{ - SCR_FROM_REG (HS_REG), - 0, - SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)), - SIR_NEGO_FAILED, - /* - ** remove bogus output signals - */ - SCR_REG_REG (socl, SCR_AND, CACK|CATN), - 0, - SCR_RETURN ^ IFTRUE (WHEN (SCR_DATA_OUT)), - 0, - SCR_RETURN ^ IFTRUE (IF (SCR_DATA_IN)), - 0, - SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)), - PADDR (msg_out), - SCR_JUMP ^ IFTRUE (IF (SCR_MSG_IN)), - PADDR (msg_in), - SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)), - PADDR (command), - SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)), - PADDR (status), - /* - ** Discard one illegal phase byte, if required. - */ - SCR_LOAD_REG (scratcha, XE_BAD_PHASE), - 0, - SCR_COPY (1), - RADDR (scratcha), - NADDR (xerr_st), - SCR_JUMPR ^ IFFALSE (IF (SCR_ILG_OUT)), - 8, - SCR_MOVE_ABS (1) ^ SCR_ILG_OUT, - NADDR (scratch), - SCR_JUMPR ^ IFFALSE (IF (SCR_ILG_IN)), - 8, - SCR_MOVE_ABS (1) ^ SCR_ILG_IN, - NADDR (scratch), - SCR_JUMP, - PADDR (dispatch), - -}/*-------------------------< NO_DATA >--------------------*/,{ - /* - ** The target wants to transfer too much data - ** or in the wrong direction. - ** Remember that in extended error. - */ - SCR_LOAD_REG (scratcha, XE_EXTRA_DATA), - 0, - SCR_COPY (1), - RADDR (scratcha), - NADDR (xerr_st), - /* - ** Discard one data byte, if required. - */ - SCR_JUMPR ^ IFFALSE (WHEN (SCR_DATA_OUT)), - 8, - SCR_MOVE_ABS (1) ^ SCR_DATA_OUT, - NADDR (scratch), - SCR_JUMPR ^ IFFALSE (IF (SCR_DATA_IN)), - 8, - SCR_MOVE_ABS (1) ^ SCR_DATA_IN, - NADDR (scratch), - /* - ** .. and repeat as required. - */ - SCR_CALL, - PADDR (dispatch), - SCR_JUMP, - PADDR (no_data), -}/*-------------------------< CHECKATN >--------------------*/,{ - /* - ** If AAP (bit 1 of scntl0 register) is set - ** and a parity error is detected, - ** the script processor asserts ATN. - ** - ** The target should switch to a MSG_OUT phase - ** to get the message. - */ - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFFALSE (MASK (CATN, CATN)), - PADDR (dispatch), - /* - ** count it - */ - SCR_REG_REG (PS_REG, SCR_ADD, 1), - 0, - /* - ** Prepare a MSG_INITIATOR_DET_ERR message - ** (initiator detected error). - ** The target should retry the transfer. - */ - SCR_LOAD_REG (scratcha, MSG_INITIATOR_DET_ERR), - 0, - SCR_JUMP, - PADDR (setmsg), - -}/*-------------------------< COMMAND >--------------------*/,{ - /* - ** If this is not a GETCC transfer ... - */ - SCR_FROM_REG (SS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFTRUE (DATA (SCSI_STATUS_CHECK_COND)), - 28, - /* - ** ... set a timestamp ... - */ - SCR_COPY (sizeof (ticks)), - KVAR (KVAR_TICKS), - NADDR (header.stamp.command), - /* - ** ... and send the command - */ - SCR_MOVE_TBL ^ SCR_COMMAND, - offsetof (struct dsb, cmd), - SCR_JUMP, - PADDR (dispatch), - /* - ** Send the GETCC command - */ -/*>>>*/ SCR_MOVE_TBL ^ SCR_COMMAND, - offsetof (struct dsb, scmd), - SCR_JUMP, - PADDR (dispatch), - -}/*-------------------------< STATUS >--------------------*/,{ - /* - ** set the timestamp. - */ - SCR_COPY (sizeof (ticks)), - KVAR (KVAR_TICKS), - NADDR (header.stamp.status), - /* - ** If this is a GETCC transfer, - */ - SCR_FROM_REG (SS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (SCSI_STATUS_CHECK_COND)), - 40, - /* - ** get the status - */ - SCR_MOVE_ABS (1) ^ SCR_STATUS, - NADDR (scratch), - /* - ** Save status to scsi_status. - ** Mark as complete. - ** And wait for disconnect. - */ - SCR_TO_REG (SS_REG), - 0, - SCR_REG_REG (SS_REG, SCR_OR, SCSI_STATUS_SENSE), - 0, - SCR_LOAD_REG (HS_REG, HS_COMPLETE), - 0, - SCR_JUMP, - PADDR (checkatn), - /* - ** If it was no GETCC transfer, - ** save the status to scsi_status. - */ -/*>>>*/ SCR_MOVE_ABS (1) ^ SCR_STATUS, - NADDR (scratch), - SCR_TO_REG (SS_REG), - 0, - /* - ** if it was no check condition ... - */ - SCR_JUMP ^ IFTRUE (DATA (SCSI_STATUS_CHECK_COND)), - PADDR (checkatn), - /* - ** ... mark as complete. - */ - SCR_LOAD_REG (HS_REG, HS_COMPLETE), - 0, - SCR_JUMP, - PADDR (checkatn), - -}/*-------------------------< MSG_IN >--------------------*/,{ - /* - ** Get the first byte of the message - ** and save it to SCRATCHA. - ** - ** The script processor doesn't negate the - ** ACK signal after this transfer. - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin[0]), - /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDRH (msg_parity), - SCR_FROM_REG (scratcha), - 0, - /* - ** Parity was ok, handle this message. - */ - SCR_JUMP ^ IFTRUE (DATA (MSG_CMDCOMPLETE)), - PADDR (complete), - SCR_JUMP ^ IFTRUE (DATA (MSG_SAVEDATAPOINTER)), - PADDR (save_dp), - SCR_JUMP ^ IFTRUE (DATA (MSG_RESTOREPOINTERS)), - PADDR (restore_dp), - SCR_JUMP ^ IFTRUE (DATA (MSG_DISCONNECT)), - PADDR (disconnect), - SCR_JUMP ^ IFTRUE (DATA (MSG_EXTENDED)), - PADDRH (msg_extended), - SCR_JUMP ^ IFTRUE (DATA (MSG_NOOP)), - PADDR (clrack), - SCR_JUMP ^ IFTRUE (DATA (MSG_MESSAGE_REJECT)), - PADDRH (msg_reject), - SCR_JUMP ^ IFTRUE (DATA (MSG_IGN_WIDE_RESIDUE)), - PADDRH (msg_ign_residue), - /* - ** Rest of the messages left as - ** an exercise ... - ** - ** Unimplemented messages: - ** fall through to MSG_BAD. - */ -}/*-------------------------< MSG_BAD >------------------*/,{ - /* - ** unimplemented message - reject it. - */ - SCR_INT, - SIR_REJECT_SENT, - SCR_LOAD_REG (scratcha, MSG_MESSAGE_REJECT), - 0, - SCR_JUMP, - PADDR (setmsg), - -}/*-------------------------< COMPLETE >-----------------*/,{ - /* - ** Complete message. - ** - ** If it's not the get condition code, - ** copy TEMP register to LASTP in header. - */ - SCR_FROM_REG (SS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFTRUE (MASK (SCSI_STATUS_SENSE, SCSI_STATUS_SENSE)), - 12, - SCR_COPY (4), - RADDR (temp), - NADDR (header.lastp), -/*>>>*/ /* - ** When we terminate the cycle by clearing ACK, - ** the target may disconnect immediately. - ** - ** We don't want to be told of an - ** "unexpected disconnect", - ** so we disable this feature. - */ - SCR_REG_REG (scntl2, SCR_AND, 0x7f), - 0, - /* - ** Terminate cycle ... - */ - SCR_CLR (SCR_ACK|SCR_ATN), - 0, - /* - ** ... and wait for the disconnect. - */ - SCR_WAIT_DISC, - 0, -}/*-------------------------< CLEANUP >-------------------*/,{ - /* - ** dsa: Pointer to nccb - ** or xxxxxxFF (no nccb) - ** - ** HS_REG: Host-Status (<>0!) - */ - SCR_FROM_REG (dsa), - 0, - SCR_JUMP ^ IFTRUE (DATA (0xff)), - PADDR (signal), - /* - ** dsa is valid. - ** save the status registers - */ - SCR_COPY (4), - RADDR (scr0), - NADDR (header.status), - /* - ** and copy back the header to the nccb. - */ - SCR_COPY_F (4), - RADDR (dsa), - PADDR (cleanup0), - SCR_COPY (sizeof (struct head)), - NADDR (header), -}/*-------------------------< CLEANUP0 >--------------------*/,{ - 0, - - /* - ** If command resulted in "check condition" - ** status and is not yet completed, - ** try to get the condition code. - */ - SCR_FROM_REG (HS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (0, HS_DONEMASK)), - 16, - SCR_FROM_REG (SS_REG), - 0, - SCR_JUMP ^ IFTRUE (DATA (SCSI_STATUS_CHECK_COND)), - PADDRH(getcc2), -}/*-------------------------< SIGNAL >----------------------*/,{ - /* - ** if status = queue full, - ** reinsert in startqueue and stall queue. - */ -/*>>>*/ SCR_FROM_REG (SS_REG), - 0, - SCR_INT ^ IFTRUE (DATA (SCSI_STATUS_QUEUE_FULL)), - SIR_STALL_QUEUE, - /* - ** And make the DSA register invalid. - */ - SCR_LOAD_REG (dsa, 0xff), /* invalid */ - 0, - /* - ** if job completed ... - */ - SCR_FROM_REG (HS_REG), - 0, - /* - ** ... signal completion to the host - */ - SCR_INT_FLY ^ IFFALSE (MASK (0, HS_DONEMASK)), - 0, - /* - ** Auf zu neuen Schandtaten! - */ - SCR_JUMP, - PADDR(start), - -}/*-------------------------< SAVE_DP >------------------*/,{ - /* - ** SAVE_DP message: - ** Copy TEMP register to SAVEP in header. - */ - SCR_COPY (4), - RADDR (temp), - NADDR (header.savep), - SCR_JUMP, - PADDR (clrack), -}/*-------------------------< RESTORE_DP >---------------*/,{ - /* - ** RESTORE_DP message: - ** Copy SAVEP in header to TEMP register. - */ - SCR_COPY (4), - NADDR (header.savep), - RADDR (temp), - SCR_JUMP, - PADDR (clrack), - -}/*-------------------------< DISCONNECT >---------------*/,{ - /* - ** If QUIRK_AUTOSAVE is set, - ** do a "save pointer" operation. - */ - SCR_FROM_REG (QU_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (QUIRK_AUTOSAVE, QUIRK_AUTOSAVE)), - 12, - /* - ** like SAVE_DP message: - ** Copy TEMP register to SAVEP in header. - */ - SCR_COPY (4), - RADDR (temp), - NADDR (header.savep), -/*>>>*/ /* - ** Check if temp==savep or temp==goalp: - ** if not, log a missing save pointer message. - ** In fact, it's a comparison mod 256. - ** - ** Hmmm, I hadn't thought that I would be urged to - ** write this kind of ugly self modifying code. - ** - ** It's unbelievable, but the ncr53c8xx isn't able - ** to subtract one register from another. - */ - SCR_FROM_REG (temp), - 0, - /* - ** You are not expected to understand this .. - ** - ** CAUTION: only little endian architectures supported! XXX - */ - SCR_COPY_F (1), - NADDR (header.savep), - PADDR (disconnect0), -}/*-------------------------< DISCONNECT0 >--------------*/,{ -/*<<<*/ SCR_JUMPR ^ IFTRUE (DATA (1)), - 20, - /* - ** neither this - */ - SCR_COPY_F (1), - NADDR (header.goalp), - PADDR (disconnect1), -}/*-------------------------< DISCONNECT1 >--------------*/,{ - SCR_INT ^ IFFALSE (DATA (1)), - SIR_MISSING_SAVE, -/*>>>*/ - - /* - ** DISCONNECTing ... - ** - ** disable the "unexpected disconnect" feature, - ** and remove the ACK signal. - */ - SCR_REG_REG (scntl2, SCR_AND, 0x7f), - 0, - SCR_CLR (SCR_ACK|SCR_ATN), - 0, - /* - ** Wait for the disconnect. - */ - SCR_WAIT_DISC, - 0, - /* - ** Profiling: - ** Set a time stamp, - ** and count the disconnects. - */ - SCR_COPY (sizeof (ticks)), - KVAR (KVAR_TICKS), - NADDR (header.stamp.disconnect), - SCR_COPY (4), - NADDR (disc_phys), - RADDR (temp), - SCR_REG_REG (temp, SCR_ADD, 0x01), - 0, - SCR_COPY (4), - RADDR (temp), - NADDR (disc_phys), - /* - ** Status is: DISCONNECTED. - */ - SCR_LOAD_REG (HS_REG, HS_DISCONNECT), - 0, - SCR_JUMP, - PADDR (cleanup), - -}/*-------------------------< MSG_OUT >-------------------*/,{ - /* - ** The target requests a message. - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, - NADDR (msgout), - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), - /* - ** If it was no ABORT message ... - */ - SCR_JUMP ^ IFTRUE (DATA (MSG_ABORT)), - PADDRH (msg_out_abort), - /* - ** ... wait for the next phase - ** if it's a message out, send it again, ... - */ - SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_OUT)), - PADDR (msg_out), -}/*-------------------------< MSG_OUT_DONE >--------------*/,{ - /* - ** ... else clear the message ... - */ - SCR_LOAD_REG (scratcha, MSG_NOOP), - 0, - SCR_COPY (4), - RADDR (scratcha), - NADDR (msgout), - /* - ** ... and process the next phase - */ - SCR_JUMP, - PADDR (dispatch), - -}/*------------------------< BADGETCC >---------------------*/,{ - /* - ** If SIGP was set, clear it and try again. - */ - SCR_FROM_REG (ctest2), - 0, - SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)), - PADDRH (getcc2), - SCR_INT, - SIR_SENSE_FAILED, -}/*-------------------------< RESELECT >--------------------*/,{ - /* - ** This NOP will be patched with LED OFF - ** SCR_REG_REG (gpreg, SCR_OR, 0x01) - */ - SCR_NO_OP, - 0, - - /* - ** make the DSA invalid. - */ - SCR_LOAD_REG (dsa, 0xff), - 0, - SCR_CLR (SCR_TRG), - 0, - /* - ** Sleep waiting for a reselection. - ** If SIGP is set, special treatment. - ** - ** Zu allem bereit .. - */ - SCR_WAIT_RESEL, - PADDR(reselect2), -}/*-------------------------< RESELECT1 >--------------------*/,{ - /* - ** This NOP will be patched with LED ON - ** SCR_REG_REG (gpreg, SCR_AND, 0xfe) - */ - SCR_NO_OP, - 0, - /* - ** ... zu nichts zu gebrauchen ? - ** - ** load the target id into the SFBR - ** and jump to the control block. - ** - ** Look at the declarations of - ** - struct ncb - ** - struct tcb - ** - struct lcb - ** - struct nccb - ** to understand what's going on. - */ - SCR_REG_SFBR (ssid, SCR_AND, 0x8F), - 0, - SCR_TO_REG (sdid), - 0, - SCR_JUMP, - NADDR (jump_tcb), -}/*-------------------------< RESELECT2 >-------------------*/,{ - /* - ** This NOP will be patched with LED ON - ** SCR_REG_REG (gpreg, SCR_AND, 0xfe) - */ - SCR_NO_OP, - 0, - /* - ** If it's not connected :( - ** -> interrupted by SIGP bit. - ** Jump to start. - */ - SCR_FROM_REG (ctest2), - 0, - SCR_JUMP ^ IFTRUE (MASK (CSIGP,CSIGP)), - PADDR (start), - SCR_JUMP, - PADDR (reselect), - -}/*-------------------------< RESEL_TMP >-------------------*/,{ - /* - ** The return address in TEMP - ** is in fact the data structure address, - ** so copy it to the DSA register. - */ - SCR_COPY (4), - RADDR (temp), - RADDR (dsa), - SCR_JUMP, - PADDR (prepare), - -}/*-------------------------< RESEL_LUN >-------------------*/,{ - /* - ** come back to this point - ** to get an IDENTIFY message - ** Wait for a msg_in phase. - */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), - 48, - /* - ** message phase - ** It's not a sony, it's a trick: - ** read the data without acknowledging it. - */ - SCR_FROM_REG (sbdl), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (MSG_IDENTIFYFLAG, 0x98)), - 32, - /* - ** It WAS an Identify message. - ** get it and ack it! - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), - SCR_CLR (SCR_ACK), - 0, - /* - ** Mask out the lun. - */ - SCR_REG_REG (sfbr, SCR_AND, 0x07), - 0, - SCR_RETURN, - 0, - /* - ** No message phase or no IDENTIFY message: - ** return 0. - */ -/*>>>*/ SCR_LOAD_SFBR (0), - 0, - SCR_RETURN, - 0, - -}/*-------------------------< RESEL_TAG >-------------------*/,{ - /* - ** come back to this point - ** to get a SIMPLE_TAG message - ** Wait for a MSG_IN phase. - */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), - 64, - /* - ** message phase - ** It's a trick - read the data - ** without acknowledging it. - */ - SCR_FROM_REG (sbdl), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (MSG_SIMPLE_Q_TAG)), - 48, - /* - ** It WAS a SIMPLE_TAG message. - ** get it and ack it! - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), - SCR_CLR (SCR_ACK), - 0, - /* - ** Wait for the second byte (the tag) - */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (WHEN (SCR_MSG_IN)), - 24, - /* - ** Get it and ack it! - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin), - SCR_CLR (SCR_ACK|SCR_CARRY), - 0, - SCR_RETURN, - 0, - /* - ** No message phase or no SIMPLE_TAG message - ** or no second byte: return 0. - */ -/*>>>*/ SCR_LOAD_SFBR (0), - 0, - SCR_SET (SCR_CARRY), - 0, - SCR_RETURN, - 0, - -}/*-------------------------< DATA_IN >--------------------*/,{ -/* -** Because the size depends on the -** #define MAX_SCATTER parameter, -** it is filled in at runtime. -** -** SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)), -** PADDR (no_data), -** SCR_COPY (sizeof (ticks)), -** KVAR (KVAR_TICKS), -** NADDR (header.stamp.data), -** SCR_MOVE_TBL ^ SCR_DATA_IN, -** offsetof (struct dsb, data[ 0]), -** -** ##===========< i=1; i========= -** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)), -** || PADDR (checkatn), -** || SCR_MOVE_TBL ^ SCR_DATA_IN, -** || offsetof (struct dsb, data[ i]), -** ##========================================== -** -** SCR_CALL, -** PADDR (checkatn), -** SCR_JUMP, -** PADDR (no_data), -*/ -0 -}/*-------------------------< DATA_OUT >-------------------*/,{ -/* -** Because the size depends on the -** #define MAX_SCATTER parameter, -** it is filled in at runtime. -** -** SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_OUT)), -** PADDR (no_data), -** SCR_COPY (sizeof (ticks)), -** KVAR (KVAR_TICKS), -** NADDR (header.stamp.data), -** SCR_MOVE_TBL ^ SCR_DATA_OUT, -** offsetof (struct dsb, data[ 0]), -** -** ##===========< i=1; i========= -** || SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)), -** || PADDR (dispatch), -** || SCR_MOVE_TBL ^ SCR_DATA_OUT, -** || offsetof (struct dsb, data[ i]), -** ##========================================== -** -** SCR_CALL, -** PADDR (dispatch), -** SCR_JUMP, -** PADDR (no_data), -** -**--------------------------------------------------------- -*/ -(u_long)0 - -}/*--------------------------------------------------------*/ -}; - - -static struct scripth scripth0 = { -/*-------------------------< TRYLOOP >---------------------*/{ -/* -** Load an entry of the start queue into dsa -** and try to start it by jumping to TRYSEL. -** -** Because the size depends on the -** #define MAX_START parameter, it is filled -** in at runtime. -** -**----------------------------------------------------------- -** -** ##===========< I=0; i=========== -** || SCR_COPY (4), -** || NADDR (squeue[i]), -** || RADDR (dsa), -** || SCR_CALL, -** || PADDR (trysel), -** ##========================================== -** -** SCR_JUMP, -** PADDRH(tryloop), -** -**----------------------------------------------------------- -*/ -0 -}/*-------------------------< MSG_PARITY >---------------*/,{ - /* - ** count it - */ - SCR_REG_REG (PS_REG, SCR_ADD, 0x01), - 0, - /* - ** send a "message parity error" message. - */ - SCR_LOAD_REG (scratcha, MSG_PARITY_ERROR), - 0, - SCR_JUMP, - PADDR (setmsg), -}/*-------------------------< MSG_MESSAGE_REJECT >---------------*/,{ - /* - ** If a negotiation was in progress, - ** negotiation failed. - */ - SCR_FROM_REG (HS_REG), - 0, - SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)), - SIR_NEGO_FAILED, - /* - ** else make host log this message - */ - SCR_INT ^ IFFALSE (DATA (HS_NEGOTIATE)), - SIR_REJECT_RECEIVED, - SCR_JUMP, - PADDR (clrack), - -}/*-------------------------< MSG_IGN_RESIDUE >----------*/,{ - /* - ** Terminate cycle - */ - SCR_CLR (SCR_ACK), - 0, - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** get residue size. - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin[1]), - /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDRH (msg_parity), - SCR_FROM_REG (scratcha), - 0, - /* - ** Size is 0 .. ignore message. - */ - SCR_JUMP ^ IFTRUE (DATA (0)), - PADDR (clrack), - /* - ** Size is not 1 .. have to interrupt. - */ -/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (1)), - 40, - /* - ** Check for residue byte in swide register - */ - SCR_FROM_REG (scntl2), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (MASK (WSR, WSR)), - 16, - /* - ** There IS data in the swide register. - ** Discard it. - */ - SCR_REG_REG (scntl2, SCR_OR, WSR), - 0, - SCR_JUMP, - PADDR (clrack), - /* - ** Load again the size to the sfbr register. - */ -/*>>>*/ SCR_FROM_REG (scratcha), - 0, -/*>>>*/ SCR_INT, - SIR_IGN_RESIDUE, - SCR_JUMP, - PADDR (clrack), - -}/*-------------------------< MSG_EXTENDED >-------------*/,{ - /* - ** Terminate cycle - */ - SCR_CLR (SCR_ACK), - 0, - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** get length. - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin[1]), - /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDRH (msg_parity), - SCR_FROM_REG (scratcha), - 0, - /* - */ - SCR_JUMP ^ IFTRUE (DATA (3)), - PADDRH (msg_ext_3), - SCR_JUMP ^ IFFALSE (DATA (2)), - PADDR (msg_bad), -}/*-------------------------< MSG_EXT_2 >----------------*/,{ - SCR_CLR (SCR_ACK), - 0, - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** get extended message code. - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin[2]), - /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDRH (msg_parity), - SCR_FROM_REG (scratcha), - 0, - SCR_JUMP ^ IFTRUE (DATA (MSG_EXT_WDTR)), - PADDRH (msg_wdtr), - /* - ** unknown extended message - */ - SCR_JUMP, - PADDR (msg_bad) -}/*-------------------------< MSG_WDTR >-----------------*/,{ - SCR_CLR (SCR_ACK), - 0, - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** get data bus width - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin[3]), - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDRH (msg_parity), - /* - ** let the host do the real work. - */ - SCR_INT, - SIR_NEGO_WIDE, - /* - ** let the target fetch our answer. - */ - SCR_SET (SCR_ATN), - 0, - SCR_CLR (SCR_ACK), - 0, - - SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), - SIR_NEGO_PROTO, - /* - ** Send the MSG_EXT_WDTR - */ - SCR_MOVE_ABS (4) ^ SCR_MSG_OUT, - NADDR (msgout), - SCR_CLR (SCR_ATN), - 0, - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), - SCR_JUMP, - PADDR (msg_out_done), - -}/*-------------------------< MSG_EXT_3 >----------------*/,{ - SCR_CLR (SCR_ACK), - 0, - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** get extended message code. - */ - SCR_MOVE_ABS (1) ^ SCR_MSG_IN, - NADDR (msgin[2]), - /* - ** Check for message parity error. - */ - SCR_TO_REG (scratcha), - 0, - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDRH (msg_parity), - SCR_FROM_REG (scratcha), - 0, - SCR_JUMP ^ IFTRUE (DATA (MSG_EXT_SDTR)), - PADDRH (msg_sdtr), - /* - ** unknown extended message - */ - SCR_JUMP, - PADDR (msg_bad) - -}/*-------------------------< MSG_SDTR >-----------------*/,{ - SCR_CLR (SCR_ACK), - 0, - SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_IN)), - PADDR (dispatch), - /* - ** get period and offset - */ - SCR_MOVE_ABS (2) ^ SCR_MSG_IN, - NADDR (msgin[3]), - SCR_FROM_REG (socl), - 0, - SCR_JUMP ^ IFTRUE (MASK (CATN, CATN)), - PADDRH (msg_parity), - /* - ** let the host do the real work. - */ - SCR_INT, - SIR_NEGO_SYNC, - /* - ** let the target fetch our answer. - */ - SCR_SET (SCR_ATN), - 0, - SCR_CLR (SCR_ACK), - 0, - - SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)), - SIR_NEGO_PROTO, - /* - ** Send the MSG_EXT_SDTR - */ - SCR_MOVE_ABS (5) ^ SCR_MSG_OUT, - NADDR (msgout), - SCR_CLR (SCR_ATN), - 0, - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), - SCR_JUMP, - PADDR (msg_out_done), - -}/*-------------------------< MSG_OUT_ABORT >-------------*/,{ - /* - ** After ABORT message, - ** - ** expect an immediate disconnect, ... - */ - SCR_REG_REG (scntl2, SCR_AND, 0x7f), - 0, - SCR_CLR (SCR_ACK|SCR_ATN), - 0, - SCR_WAIT_DISC, - 0, - /* - ** ... and set the status to "ABORTED" - */ - SCR_LOAD_REG (HS_REG, HS_ABORTED), - 0, - SCR_JUMP, - PADDR (cleanup), - -}/*-------------------------< GETCC >-----------------------*/,{ - /* - ** The ncr doesn't have an indirect load - ** or store command. So we have to - ** copy part of the control block to a - ** fixed place, where we can modify it. - ** - ** We patch the address part of a COPY command - ** with the address of the dsa register ... - */ - SCR_COPY_F (4), - RADDR (dsa), - PADDRH (getcc1), - /* - ** ... then we do the actual copy. - */ - SCR_COPY (sizeof (struct head)), -}/*-------------------------< GETCC1 >----------------------*/,{ - 0, - NADDR (header), - /* - ** Initialize the status registers - */ - SCR_COPY (4), - NADDR (header.status), - RADDR (scr0), -}/*-------------------------< GETCC2 >----------------------*/,{ - /* - ** Get the condition code from a target. - ** - ** DSA points to a data structure. - ** Set TEMP to the script location - ** that receives the condition code. - ** - ** Because there is no script command - ** to load a longword into a register, - ** we use a CALL command. - */ -/*<<<*/ SCR_CALLR, - 24, - /* - ** Get the condition code. - */ - SCR_MOVE_TBL ^ SCR_DATA_IN, - offsetof (struct dsb, sense), - /* - ** No data phase may follow! - */ - SCR_CALL, - PADDR (checkatn), - SCR_JUMP, - PADDR (no_data), -/*>>>*/ - - /* - ** The CALL jumps to this point. - ** Prepare for a RESTORE_POINTER message. - ** Save the TEMP register into the saved pointer. - */ - SCR_COPY (4), - RADDR (temp), - NADDR (header.savep), - /* - ** Load scratcha, because in case of a selection timeout, - ** the host will expect a new value for startpos in - ** the scratcha register. - */ - SCR_COPY (4), - PADDR (startpos), - RADDR (scratcha), -#ifdef NCR_GETCC_WITHMSG - /* - ** If QUIRK_NOMSG is set, select without ATN. - ** and don't send a message. - */ - SCR_FROM_REG (QU_REG), - 0, - SCR_JUMP ^ IFTRUE (MASK (QUIRK_NOMSG, QUIRK_NOMSG)), - PADDRH(getcc3), - /* - ** Then try to connect to the target. - ** If we are reselected, special treatment - ** of the current job is required before - ** accepting the reselection. - */ - SCR_SEL_TBL_ATN ^ offsetof (struct dsb, select), - PADDR(badgetcc), - /* - ** Send the IDENTIFY message. - ** In case of short transfer, remove ATN. - */ - SCR_MOVE_TBL ^ SCR_MSG_OUT, - offsetof (struct dsb, smsg2), - SCR_CLR (SCR_ATN), - 0, - /* - ** save the first byte of the message. - */ - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), - SCR_JUMP, - PADDR (prepare2), - -#endif -}/*-------------------------< GETCC3 >----------------------*/,{ - /* - ** Try to connect to the target. - ** If we are reselected, special treatment - ** of the current job is required before - ** accepting the reselection. - ** - ** Silly target won't accept a message. - ** Select without ATN. - */ - SCR_SEL_TBL ^ offsetof (struct dsb, select), - PADDR(badgetcc), - /* - ** Force error if selection timeout - */ - SCR_JUMPR ^ IFTRUE (WHEN (SCR_MSG_IN)), - 0, - /* - ** don't negotiate. - */ - SCR_JUMP, - PADDR (prepare2), -}/*-------------------------< ABORTTAG >-------------------*/,{ - /* - ** Abort a bad reselection. - ** Set the message to ABORT vs. ABORT_TAG - */ - SCR_LOAD_REG (scratcha, MSG_ABORT_TAG), - 0, - SCR_JUMPR ^ IFFALSE (CARRYSET), - 8, -}/*-------------------------< ABORT >----------------------*/,{ - SCR_LOAD_REG (scratcha, MSG_ABORT), - 0, - SCR_COPY (1), - RADDR (scratcha), - NADDR (msgout), - SCR_SET (SCR_ATN), - 0, - SCR_CLR (SCR_ACK), - 0, - /* - ** and send it. - ** we expect an immediate disconnect - */ - SCR_REG_REG (scntl2, SCR_AND, 0x7f), - 0, - SCR_MOVE_ABS (1) ^ SCR_MSG_OUT, - NADDR (msgout), - SCR_COPY (1), - RADDR (sfbr), - NADDR (lastmsg), - SCR_CLR (SCR_ACK|SCR_ATN), - 0, - SCR_WAIT_DISC, - 0, - SCR_JUMP, - PADDR (start), -}/*-------------------------< SNOOPTEST >-------------------*/,{ - /* - ** Read the variable. - */ - SCR_COPY (4), - KVAR (KVAR_NCR_CACHE), - RADDR (scratcha), - /* - ** Write the variable. - */ - SCR_COPY (4), - RADDR (temp), - KVAR (KVAR_NCR_CACHE), - /* - ** Read back the variable. - */ - SCR_COPY (4), - KVAR (KVAR_NCR_CACHE), - RADDR (temp), -}/*-------------------------< SNOOPEND >-------------------*/,{ - /* - ** And stop. - */ - SCR_INT, - 99, -}/*--------------------------------------------------------*/ -}; - - -/*========================================================== -** -** -** Fill in #define dependent parts of the script -** -** -**========================================================== -*/ - -static void ncr_script_fill (struct script * scr, struct scripth * scrh) -{ - int i; - ncrcmd *p; - - p = scrh->tryloop; - for (i=0; itryloop + sizeof (scrh->tryloop)); - - p = scr->data_in; - - *p++ =SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)); - *p++ =PADDR (no_data); - *p++ =SCR_COPY (sizeof (ticks)); - *p++ =(ncrcmd) KVAR (KVAR_TICKS); - *p++ =NADDR (header.stamp.data); - *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN; - *p++ =offsetof (struct dsb, data[ 0]); - - for (i=1; idata_in + sizeof (scr->data_in)); - - p = scr->data_out; - - *p++ =SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_OUT)); - *p++ =PADDR (no_data); - *p++ =SCR_COPY (sizeof (ticks)); - *p++ =(ncrcmd) KVAR (KVAR_TICKS); - *p++ =NADDR (header.stamp.data); - *p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT; - *p++ =offsetof (struct dsb, data[ 0]); - - for (i=1; idata_out + sizeof (scr->data_out)); -} - -/*========================================================== -** -** -** Copy and rebind a script. -** -** -**========================================================== -*/ - -static void ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int len) -{ - ncrcmd opcode, new, old, tmp1, tmp2; - ncrcmd *start, *end; - int relocs, offset; - - start = src; - end = src + len/4; - offset = 0; - - while (src < end) { - - opcode = *src++; - WRITESCRIPT_OFF(dst, offset, opcode); - offset += 4; - - /* - ** If we forget to change the length - ** in struct script, a field will be - ** padded with 0. This is an illegal - ** command. - */ - - if (opcode == 0) { - device_printf(np->dev, "ERROR0 IN SCRIPT at %d.\n", - (int)(src - start - 1)); - DELAY (1000000); - } - - if (DEBUG_FLAGS & DEBUG_SCRIPT) - printf ("%p: <%x>\n", - (src-1), (unsigned)opcode); - - /* - ** We don't have to decode ALL commands - */ - switch (opcode >> 28) { - - case 0xc: - /* - ** COPY has TWO arguments. - */ - relocs = 2; - tmp1 = src[0]; - if ((tmp1 & RELOC_MASK) == RELOC_KVAR) - tmp1 = 0; - tmp2 = src[1]; - if ((tmp2 & RELOC_MASK) == RELOC_KVAR) - tmp2 = 0; - if ((tmp1 ^ tmp2) & 3) { - device_printf(np->dev, - "ERROR1 IN SCRIPT at %d.\n", - (int)(src - start - 1)); - DELAY (1000000); - } - /* - ** If PREFETCH feature not enabled, remove - ** the NO FLUSH bit if present. - */ - if ((opcode & SCR_NO_FLUSH) && !(np->features&FE_PFEN)) - WRITESCRIPT_OFF(dst, offset - 4, - (opcode & ~SCR_NO_FLUSH)); - break; - - case 0x0: - /* - ** MOVE (absolute address) - */ - relocs = 1; - break; - - case 0x8: - /* - ** JUMP / CALL - ** dont't relocate if relative :-) - */ - if (opcode & 0x00800000) - relocs = 0; - else - relocs = 1; - break; - - case 0x4: - case 0x5: - case 0x6: - case 0x7: - relocs = 1; - break; - - default: - relocs = 0; - break; - } - - if (relocs) { - while (relocs--) { - old = *src++; - - switch (old & RELOC_MASK) { - case RELOC_REGISTER: - new = (old & ~RELOC_MASK) + rman_get_start(np->reg_res); - break; - case RELOC_LABEL: - new = (old & ~RELOC_MASK) + np->p_script; - break; - case RELOC_LABELH: - new = (old & ~RELOC_MASK) + np->p_scripth; - break; - case RELOC_SOFTC: - new = (old & ~RELOC_MASK) + vtophys(np); - break; - case RELOC_KVAR: - if (((old & ~RELOC_MASK) < - SCRIPT_KVAR_FIRST) || - ((old & ~RELOC_MASK) > - SCRIPT_KVAR_LAST)) - panic("ncr KVAR out of range"); - new = vtophys(script_kvars[old & - ~RELOC_MASK]); - break; - case 0: - /* Don't relocate a 0 address. */ - if (old == 0) { - new = old; - break; - } - /* FALLTHROUGH */ - default: - panic("ncr_script_copy_and_bind: weird relocation %x @ %d\n", old, (int)(src - start)); - break; - } - - WRITESCRIPT_OFF(dst, offset, new); - offset += 4; - } - } else { - WRITESCRIPT_OFF(dst, offset, *src++); - offset += 4; - } - - } -} - -/*========================================================== -** -** -** Auto configuration. -** -** -**========================================================== -*/ - -#if 0 -/*---------------------------------------------------------- -** -** Reduce the transfer length to the max value -** we can transfer safely. -** -** Reading a block greater then MAX_SIZE from the -** raw (character) device exercises a memory leak -** in the vm subsystem. This is common to ALL devices. -** We have submitted a description of this bug to -** . -** It should be fixed in the current release. -** -**---------------------------------------------------------- -*/ - -void ncr_min_phys (struct buf *bp) -{ - if ((unsigned long)bp->b_bcount > MAX_SIZE) bp->b_bcount = MAX_SIZE; -} - -#endif - -#if 0 -/*---------------------------------------------------------- -** -** Maximal number of outstanding requests per target. -** -**---------------------------------------------------------- -*/ - -u_int32_t ncr_info (int unit) -{ - return (1); /* may be changed later */ -} - -#endif - -/*---------------------------------------------------------- -** -** NCR chip devices table and chip look up function. -** Features bit are defined in ncrreg.h. Is it the -** right place? -** -**---------------------------------------------------------- -*/ -typedef struct { - uint32_t device_id; - uint16_t minrevid; - char *name; - unsigned char maxburst; - unsigned char maxoffs; - unsigned char clock_divn; - unsigned int features; -} ncr_chip; - -static ncr_chip ncr_chip_table[] = { - {NCR_810_ID, 0x00, "ncr 53c810 fast10 scsi", 4, 8, 4, - FE_ERL} - , - {NCR_810_ID, 0x10, "ncr 53c810a fast10 scsi", 4, 8, 4, - FE_ERL|FE_LDSTR|FE_PFEN|FE_BOF} - , - {NCR_815_ID, 0x00, "ncr 53c815 fast10 scsi", 4, 8, 4, - FE_ERL|FE_BOF} - , - {NCR_820_ID, 0x00, "ncr 53c820 fast10 wide scsi", 4, 8, 4, - FE_WIDE|FE_ERL} - , - {NCR_825_ID, 0x00, "ncr 53c825 fast10 wide scsi", 4, 8, 4, - FE_WIDE|FE_ERL|FE_BOF} - , - {NCR_825_ID, 0x10, "ncr 53c825a fast10 wide scsi", 7, 8, 4, - FE_WIDE|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_860_ID, 0x00, "ncr 53c860 fast20 scsi", 4, 8, 5, - FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_LDSTR|FE_PFEN} - , - {NCR_875_ID, 0x00, "ncr 53c875 fast20 wide scsi", 7, 16, 5, - FE_WIDE|FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_875_ID, 0x02, "ncr 53c875 fast20 wide scsi", 7, 16, 5, - FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_875_ID2, 0x00, "ncr 53c875j fast20 wide scsi", 7, 16, 5, - FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_885_ID, 0x00, "ncr 53c885 fast20 wide scsi", 7, 16, 5, - FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_895_ID, 0x00, "ncr 53c895 fast40 wide scsi", 7, 31, 7, - FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_896_ID, 0x00, "ncr 53c896 fast40 wide scsi", 7, 31, 7, - FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_895A_ID, 0x00, "ncr 53c895a fast40 wide scsi", 7, 31, 7, - FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_1510D_ID, 0x00, "ncr 53c1510d fast40 wide scsi", 7, 31, 7, - FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} -}; - -static int ncr_chip_lookup(uint32_t device_id, u_char revision_id) -{ - int i, found; - - found = -1; - for (i = 0; i < nitems(ncr_chip_table); i++) { - if (device_id == ncr_chip_table[i].device_id && - ncr_chip_table[i].minrevid <= revision_id) { - if (found < 0 || - ncr_chip_table[found].minrevid - < ncr_chip_table[i].minrevid) { - found = i; - } - } - } - return found; -} - -/*---------------------------------------------------------- -** -** Probe the hostadapter. -** -**---------------------------------------------------------- -*/ - - - -static int ncr_probe (device_t dev) -{ - int i; - - i = ncr_chip_lookup(pci_get_devid(dev), pci_get_revid(dev)); - if (i >= 0) { - device_set_desc(dev, ncr_chip_table[i].name); - return (BUS_PROBE_DEFAULT); - } - - return (ENXIO); -} - - - -/*========================================================== -** -** NCR chip clock divisor table. -** Divisors are multiplied by 10,000,000 in order to make -** calculations more simple. -** -**========================================================== -*/ - -#define _5M 5000000 -static u_long div_10M[] = - {2*_5M, 3*_5M, 4*_5M, 6*_5M, 8*_5M, 12*_5M, 16*_5M}; - -/*=============================================================== -** -** NCR chips allow burst lengths of 2, 4, 8, 16, 32, 64, 128 -** transfers. 32,64,128 are only supported by 875 and 895 chips. -** We use log base 2 (burst length) as internal code, with -** value 0 meaning "burst disabled". -** -**=============================================================== -*/ - -/* - * Burst length from burst code. - */ -#define burst_length(bc) (!(bc))? 0 : 1 << (bc) - -/* - * Burst code from io register bits. - */ -#define burst_code(dmode, ctest4, ctest5) \ - (ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ((ctest5) & 0x04) + 1 - -/* - * Set initial io register bits from burst code. - */ -static void -ncr_init_burst(ncb_p np, u_char bc) -{ - np->rv_ctest4 &= ~0x80; - np->rv_dmode &= ~(0x3 << 6); - np->rv_ctest5 &= ~0x4; - - if (!bc) { - np->rv_ctest4 |= 0x80; - } - else { - --bc; - np->rv_dmode |= ((bc & 0x3) << 6); - np->rv_ctest5 |= (bc & 0x4); - } -} - -/*========================================================== -** -** -** Auto configuration: attach and init a host adapter. -** -** -**========================================================== -*/ - - -static int -ncr_attach (device_t dev) -{ - ncb_p np = (struct ncb*) device_get_softc(dev); - u_char rev = 0; - u_long period; - int i, rid; - u_int8_t usrsync; - u_int8_t usrwide; - struct cam_devq *devq; - - /* - ** allocate and initialize structures. - */ - - np->dev = dev; - mtx_init(&np->lock, "ncr", NULL, MTX_DEF); - callout_init_mtx(&np->timer, &np->lock, 0); - - /* - ** Try to map the controller chip to - ** virtual and physical memory. - */ - - np->reg_rid = PCIR_BAR(1); - np->reg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &np->reg_rid, RF_ACTIVE); - if (!np->reg_res) { - device_printf(dev, "could not map memory\n"); - return ENXIO; - } - - /* - ** Now the INB INW INL OUTB OUTW OUTL macros - ** can be used safely. - */ - -#ifdef NCR_IOMAPPED - /* - ** Try to map the controller chip into iospace. - */ - - if (!pci_map_port (config_id, 0x10, &np->port)) - return; -#endif - - - /* - ** Save some controller register default values - */ - - np->rv_scntl3 = INB(nc_scntl3) & 0x77; - np->rv_dmode = INB(nc_dmode) & 0xce; - np->rv_dcntl = INB(nc_dcntl) & 0xa9; - np->rv_ctest3 = INB(nc_ctest3) & 0x01; - np->rv_ctest4 = INB(nc_ctest4) & 0x88; - np->rv_ctest5 = INB(nc_ctest5) & 0x24; - np->rv_gpcntl = INB(nc_gpcntl); - np->rv_stest2 = INB(nc_stest2) & 0x20; - - if (bootverbose >= 2) { - printf ("\tBIOS values: SCNTL3:%02x DMODE:%02x DCNTL:%02x\n", - np->rv_scntl3, np->rv_dmode, np->rv_dcntl); - printf ("\t CTEST3:%02x CTEST4:%02x CTEST5:%02x\n", - np->rv_ctest3, np->rv_ctest4, np->rv_ctest5); - } - - np->rv_dcntl |= NOCOM; - - /* - ** Do chip dependent initialization. - */ - - rev = pci_get_revid(dev); - - /* - ** Get chip features from chips table. - */ - i = ncr_chip_lookup(pci_get_devid(dev), rev); - - if (i >= 0) { - np->maxburst = ncr_chip_table[i].maxburst; - np->maxoffs = ncr_chip_table[i].maxoffs; - np->clock_divn = ncr_chip_table[i].clock_divn; - np->features = ncr_chip_table[i].features; - } else { /* Should'nt happen if probe() is ok */ - np->maxburst = 4; - np->maxoffs = 8; - np->clock_divn = 4; - np->features = FE_ERL; - } - - np->maxwide = np->features & FE_WIDE ? 1 : 0; - np->clock_khz = np->features & FE_CLK80 ? 80000 : 40000; - if (np->features & FE_QUAD) np->multiplier = 4; - else if (np->features & FE_DBLR) np->multiplier = 2; - else np->multiplier = 1; - - /* - ** Get the frequency of the chip's clock. - ** Find the right value for scntl3. - */ - if (np->features & (FE_ULTRA|FE_ULTRA2)) - ncr_getclock(np, np->multiplier); - -#ifdef NCR_TEKRAM_EEPROM - if (bootverbose) { - device_printf(dev, "Tekram EEPROM read %s\n", - read_tekram_eeprom (np, NULL) ? - "succeeded" : "failed"); - } -#endif /* NCR_TEKRAM_EEPROM */ - - /* - * If scntl3 != 0, we assume BIOS is present. - */ - if (np->rv_scntl3) - np->features |= FE_BIOS; - - /* - * Divisor to be used for async (timer pre-scaler). - */ - i = np->clock_divn - 1; - while (i >= 0) { - --i; - if (10ul * SCSI_NCR_MIN_ASYNC * np->clock_khz > div_10M[i]) { - ++i; - break; - } - } - np->rv_scntl3 = i+1; - - /* - * Minimum synchronous period factor supported by the chip. - * Btw, 'period' is in tenths of nanoseconds. - */ - - period = howmany(4 * div_10M[0], np->clock_khz); - if (period <= 250) np->minsync = 10; - else if (period <= 303) np->minsync = 11; - else if (period <= 500) np->minsync = 12; - else np->minsync = howmany(period, 40); - - /* - * Check against chip SCSI standard support (SCSI-2,ULTRA,ULTRA2). - */ - - if (np->minsync < 25 && !(np->features & (FE_ULTRA|FE_ULTRA2))) - np->minsync = 25; - else if (np->minsync < 12 && !(np->features & FE_ULTRA2)) - np->minsync = 12; - - /* - * Maximum synchronous period factor supported by the chip. - */ - - period = (11 * div_10M[np->clock_divn - 1]) / (4 * np->clock_khz); - np->maxsync = period > 2540 ? 254 : period / 10; - - /* - * Now, some features available with Symbios compatible boards. - * LED support through GPIO0 and DIFF support. - */ - -#ifdef SCSI_NCR_SYMBIOS_COMPAT - if (!(np->rv_gpcntl & 0x01)) - np->features |= FE_LED0; -#if 0 /* Not safe enough without NVRAM support or user settable option */ - if (!(INB(nc_gpreg) & 0x08)) - np->features |= FE_DIFF; -#endif -#endif /* SCSI_NCR_SYMBIOS_COMPAT */ - - /* - * Prepare initial IO registers settings. - * Trust BIOS only if we believe we have one and if we want to. - */ -#ifdef SCSI_NCR_TRUST_BIOS - if (!(np->features & FE_BIOS)) { -#else - if (1) { -#endif - np->rv_dmode = 0; - np->rv_dcntl = NOCOM; - np->rv_ctest3 = 0; - np->rv_ctest4 = MPEE; - np->rv_ctest5 = 0; - np->rv_stest2 = 0; - - if (np->features & FE_ERL) - np->rv_dmode |= ERL; /* Enable Read Line */ - if (np->features & FE_BOF) - np->rv_dmode |= BOF; /* Burst Opcode Fetch */ - if (np->features & FE_ERMP) - np->rv_dmode |= ERMP; /* Enable Read Multiple */ - if (np->features & FE_CLSE) - np->rv_dcntl |= CLSE; /* Cache Line Size Enable */ - if (np->features & FE_WRIE) - np->rv_ctest3 |= WRIE; /* Write and Invalidate */ - if (np->features & FE_PFEN) - np->rv_dcntl |= PFEN; /* Prefetch Enable */ - if (np->features & FE_DFS) - np->rv_ctest5 |= DFS; /* Dma Fifo Size */ - if (np->features & FE_DIFF) - np->rv_stest2 |= 0x20; /* Differential mode */ - ncr_init_burst(np, np->maxburst); /* Max dwords burst length */ - } else { - np->maxburst = - burst_code(np->rv_dmode, np->rv_ctest4, np->rv_ctest5); - } - - /* - ** Get on-chip SRAM address, if supported - */ - if ((np->features & FE_RAM) && sizeof(struct script) <= 4096) { - np->sram_rid = PCIR_BAR(2); - np->sram_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &np->sram_rid, - RF_ACTIVE); - } - - /* - ** Allocate structure for script relocation. - */ - if (np->sram_res != NULL) { - np->script = NULL; - np->p_script = rman_get_start(np->sram_res); - } else if (sizeof (struct script) > PAGE_SIZE) { - np->script = (struct script*) contigmalloc - (round_page(sizeof (struct script)), M_DEVBUF, M_WAITOK, - 0, 0xffffffff, PAGE_SIZE, 0); - } else { - np->script = (struct script *) - malloc (sizeof (struct script), M_DEVBUF, M_WAITOK); - } - - if (sizeof (struct scripth) > PAGE_SIZE) { - np->scripth = (struct scripth*) contigmalloc - (round_page(sizeof (struct scripth)), M_DEVBUF, M_WAITOK, - 0, 0xffffffff, PAGE_SIZE, 0); - } else - { - np->scripth = (struct scripth *) - malloc (sizeof (struct scripth), M_DEVBUF, M_WAITOK); - } - -#ifdef SCSI_NCR_PCI_CONFIG_FIXUP - /* - ** If cache line size is enabled, check PCI config space and - ** try to fix it up if necessary. - */ -#ifdef PCIR_CACHELNSZ /* To be sure that new PCI stuff is present */ - { - u_char cachelnsz = pci_read_config(dev, PCIR_CACHELNSZ, 1); - u_short command = pci_read_config(dev, PCIR_COMMAND, 2); - - if (!cachelnsz) { - cachelnsz = 8; - device_printf(dev, - "setting PCI cache line size register to %d.\n", - (int)cachelnsz); - pci_write_config(dev, PCIR_CACHELNSZ, cachelnsz, 1); - } - - if (!(command & PCIM_CMD_MWRICEN)) { - command |= PCIM_CMD_MWRICEN; - device_printf(dev, - "setting PCI command write and invalidate.\n"); - pci_write_config(dev, PCIR_COMMAND, command, 2); - } - } -#endif /* PCIR_CACHELNSZ */ - -#endif /* SCSI_NCR_PCI_CONFIG_FIXUP */ - - /* Initialize per-target user settings */ - usrsync = 0; - if (SCSI_NCR_DFLT_SYNC) { - usrsync = SCSI_NCR_DFLT_SYNC; - if (usrsync > np->maxsync) - usrsync = np->maxsync; - if (usrsync < np->minsync) - usrsync = np->minsync; - } - - usrwide = (SCSI_NCR_MAX_WIDE); - if (usrwide > np->maxwide) usrwide=np->maxwide; - - for (i=0;itarget[i]; - - tp->tinfo.user.period = usrsync; - tp->tinfo.user.offset = usrsync != 0 ? np->maxoffs : 0; - tp->tinfo.user.width = usrwide; - tp->tinfo.disc_tag = NCR_CUR_DISCENB - | NCR_CUR_TAGENB - | NCR_USR_DISCENB - | NCR_USR_TAGENB; - } - - /* - ** Bells and whistles ;-) - */ - if (bootverbose) - device_printf(dev, - "minsync=%d, maxsync=%d, maxoffs=%d, %d dwords burst, %s dma fifo\n", - np->minsync, np->maxsync, np->maxoffs, - burst_length(np->maxburst), - (np->rv_ctest5 & DFS) ? "large" : "normal"); - - /* - ** Print some complementary information that can be helpful. - */ - if (bootverbose) - device_printf(dev, "%s, %s IRQ driver%s\n", - np->rv_stest2 & 0x20 ? "differential" : "single-ended", - np->rv_dcntl & IRQM ? "totem pole" : "open drain", - np->sram_res ? ", using on-chip SRAM" : ""); - - /* - ** Patch scripts to physical addresses - */ - ncr_script_fill (&script0, &scripth0); - - if (np->script) - np->p_script = vtophys(np->script); - np->p_scripth = vtophys(np->scripth); - - ncr_script_copy_and_bind (np, (ncrcmd *) &script0, - (ncrcmd *) np->script, sizeof(struct script)); - - ncr_script_copy_and_bind (np, (ncrcmd *) &scripth0, - (ncrcmd *) np->scripth, sizeof(struct scripth)); - - /* - ** Patch the script for LED support. - */ - - if (np->features & FE_LED0) { - WRITESCRIPT(reselect[0], SCR_REG_REG(gpreg, SCR_OR, 0x01)); - WRITESCRIPT(reselect1[0], SCR_REG_REG(gpreg, SCR_AND, 0xfe)); - WRITESCRIPT(reselect2[0], SCR_REG_REG(gpreg, SCR_AND, 0xfe)); - } - - /* - ** init data structure - */ - - np->jump_tcb.l_cmd = SCR_JUMP; - np->jump_tcb.l_paddr = NCB_SCRIPTH_PHYS (np, abort); - - /* - ** Get SCSI addr of host adapter (set by bios?). - */ - - np->myaddr = INB(nc_scid) & 0x07; - if (!np->myaddr) np->myaddr = SCSI_NCR_MYADDR; - -#ifdef NCR_DUMP_REG - /* - ** Log the initial register contents - */ - { - int reg; - 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. - */ - - OUTB (nc_istat, SRST); - DELAY (1000); - OUTB (nc_istat, 0 ); - - - /* - ** Now check the cache handling of the pci chipset. - */ - - if (ncr_snooptest (np)) { - printf ("CACHE INCORRECTLY CONFIGURED.\n"); - return EINVAL; - } - - /* - ** Install the interrupt handler. - */ - - rid = 0; - np->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (np->irq_res == NULL) { - device_printf(dev, - "interruptless mode: reduced performance.\n"); - } else { - bus_setup_intr(dev, np->irq_res, INTR_TYPE_CAM | INTR_ENTROPY | - INTR_MPSAFE, NULL, ncr_intr, np, &np->irq_handle); - } - - /* - ** Create the device queue. We only allow MAX_START-1 concurrent - ** transactions so we can be sure to have one element free in our - ** start queue to reset to the idle loop. - */ - devq = cam_simq_alloc(MAX_START - 1); - if (devq == NULL) - return ENOMEM; - - /* - ** Now tell the generic SCSI layer - ** about our bus. - */ - np->sim = cam_sim_alloc(ncr_action, ncr_poll, "ncr", np, - device_get_unit(dev), &np->lock, 1, MAX_TAGS, devq); - if (np->sim == NULL) { - cam_simq_free(devq); - return ENOMEM; - } - - mtx_lock(&np->lock); - if (xpt_bus_register(np->sim, dev, 0) != CAM_SUCCESS) { - cam_sim_free(np->sim, /*free_devq*/ TRUE); - mtx_unlock(&np->lock); - return ENOMEM; - } - - if (xpt_create_path(&np->path, /*periph*/NULL, - cam_sim_path(np->sim), CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD) != CAM_REQ_CMP) { - xpt_bus_deregister(cam_sim_path(np->sim)); - cam_sim_free(np->sim, /*free_devq*/TRUE); - mtx_unlock(&np->lock); - return ENOMEM; - } - - /* - ** start the timeout daemon - */ - ncr_timeout (np); - np->lasttime=0; - mtx_unlock(&np->lock); - gone_in_dev(dev, 12, "ncr(4) driver, use sym(4) instead"); - - return 0; -} - -/*========================================================== -** -** -** Process pending device interrupts. -** -** -**========================================================== -*/ - -static void -ncr_intr(vnp) - void *vnp; -{ - ncb_p np = vnp; - - mtx_lock(&np->lock); - ncr_intr_locked(np); - mtx_unlock(&np->lock); -} - -static void -ncr_intr_locked(ncb_p np) -{ - - if (DEBUG_FLAGS & DEBUG_TINY) printf ("["); - - if (INB(nc_istat) & (INTF|SIP|DIP)) { - /* - ** Repeat until no outstanding ints - */ - do { - ncr_exception (np); - } while (INB(nc_istat) & (INTF|SIP|DIP)); - - np->ticks = 100; - } - - if (DEBUG_FLAGS & DEBUG_TINY) printf ("]\n"); -} - -/*========================================================== -** -** -** Start execution of a SCSI command. -** This is called from the generic SCSI driver. -** -** -**========================================================== -*/ - -static void -ncr_action (struct cam_sim *sim, union ccb *ccb) -{ - ncb_p np; - - np = (ncb_p) cam_sim_softc(sim); - mtx_assert(&np->lock, MA_OWNED); - - switch (ccb->ccb_h.func_code) { - /* Common cases first */ - case XPT_SCSI_IO: /* Execute the requested I/O operation */ - { - nccb_p cp; - lcb_p lp; - tcb_p tp; - struct ccb_scsiio *csio; - u_int8_t *msgptr; - u_int msglen; - u_int msglen2; - int segments; - u_int8_t nego; - u_int8_t idmsg; - int qidx; - - tp = &np->target[ccb->ccb_h.target_id]; - csio = &ccb->csio; - - /* - * Make sure we support this request. We can't do - * PHYS pointers. - */ - if (ccb->ccb_h.flags & CAM_CDB_PHYS) { - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - return; - } - - /* - * Last time we need to check if this CCB needs to - * be aborted. - */ - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { - xpt_done(ccb); - return; - } - ccb->ccb_h.status |= CAM_SIM_QUEUED; - - /*--------------------------------------------------- - ** - ** Assign an nccb / bind ccb - ** - **---------------------------------------------------- - */ - cp = ncr_get_nccb (np, ccb->ccb_h.target_id, - ccb->ccb_h.target_lun); - if (cp == NULL) { - /* XXX JGibbs - Freeze SIMQ */ - ccb->ccb_h.status = CAM_RESRC_UNAVAIL; - xpt_done(ccb); - return; - } - - cp->ccb = ccb; - - /*--------------------------------------------------- - ** - ** timestamp - ** - **---------------------------------------------------- - */ - /* - ** XXX JGibbs - Isn't this expensive - ** enough to be conditionalized?? - */ - - bzero (&cp->phys.header.stamp, sizeof (struct tstamp)); - cp->phys.header.stamp.start = ticks; - - nego = 0; - if (tp->nego_cp == NULL) { - - if (tp->tinfo.current.width - != tp->tinfo.goal.width) { - tp->nego_cp = cp; - nego = NS_WIDE; - } else if ((tp->tinfo.current.period - != tp->tinfo.goal.period) - || (tp->tinfo.current.offset - != tp->tinfo.goal.offset)) { - tp->nego_cp = cp; - nego = NS_SYNC; - } - } - - /*--------------------------------------------------- - ** - ** choose a new tag ... - ** - **---------------------------------------------------- - */ - lp = tp->lp[ccb->ccb_h.target_lun]; - - if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0 - && (ccb->csio.tag_action != CAM_TAG_ACTION_NONE) - && (nego == 0)) { - /* - ** assign a tag to this nccb - */ - while (!cp->tag) { - nccb_p cp2 = lp->next_nccb; - lp->lasttag = lp->lasttag % 255 + 1; - while (cp2 && cp2->tag != lp->lasttag) - cp2 = cp2->next_nccb; - if (cp2) continue; - cp->tag=lp->lasttag; - if (DEBUG_FLAGS & DEBUG_TAGS) { - PRINT_ADDR(ccb); - printf ("using tag #%d.\n", cp->tag); - } - } - } else { - cp->tag=0; - } - - /*---------------------------------------------------- - ** - ** Build the identify / tag / sdtr message - ** - **---------------------------------------------------- - */ - idmsg = MSG_IDENTIFYFLAG | ccb->ccb_h.target_lun; - if (tp->tinfo.disc_tag & NCR_CUR_DISCENB) - idmsg |= MSG_IDENTIFY_DISCFLAG; - - msgptr = cp->scsi_smsg; - msglen = 0; - msgptr[msglen++] = idmsg; - - if (cp->tag) { - msgptr[msglen++] = ccb->csio.tag_action; - msgptr[msglen++] = cp->tag; - } - - switch (nego) { - case NS_SYNC: - msgptr[msglen++] = MSG_EXTENDED; - msgptr[msglen++] = MSG_EXT_SDTR_LEN; - msgptr[msglen++] = MSG_EXT_SDTR; - msgptr[msglen++] = tp->tinfo.goal.period; - msgptr[msglen++] = tp->tinfo.goal.offset; - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(ccb); - printf ("sync msgout: "); - ncr_show_msg (&cp->scsi_smsg [msglen-5]); - printf (".\n"); - }; - break; - case NS_WIDE: - msgptr[msglen++] = MSG_EXTENDED; - msgptr[msglen++] = MSG_EXT_WDTR_LEN; - msgptr[msglen++] = MSG_EXT_WDTR; - msgptr[msglen++] = tp->tinfo.goal.width; - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(ccb); - printf ("wide msgout: "); - ncr_show_msg (&cp->scsi_smsg [msglen-4]); - printf (".\n"); - }; - break; - } - - /*---------------------------------------------------- - ** - ** Build the identify message for getcc. - ** - **---------------------------------------------------- - */ - - cp->scsi_smsg2 [0] = idmsg; - msglen2 = 1; - - /*---------------------------------------------------- - ** - ** Build the data descriptors - ** - **---------------------------------------------------- - */ - - /* XXX JGibbs - Handle other types of I/O */ - if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - segments = ncr_scatter(&cp->phys, - (vm_offset_t)csio->data_ptr, - (vm_size_t)csio->dxfer_len); - - if (segments < 0) { - ccb->ccb_h.status = CAM_REQ_TOO_BIG; - ncr_free_nccb(np, cp); - xpt_done(ccb); - return; - } - if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { - cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_in); - cp->phys.header.goalp = cp->phys.header.savep +20 +segments*16; - } else { /* CAM_DIR_OUT */ - cp->phys.header.savep = NCB_SCRIPT_PHYS (np, data_out); - cp->phys.header.goalp = cp->phys.header.savep +20 +segments*16; - } - } else { - cp->phys.header.savep = NCB_SCRIPT_PHYS (np, no_data); - cp->phys.header.goalp = cp->phys.header.savep; - } - - cp->phys.header.lastp = cp->phys.header.savep; - - - /*---------------------------------------------------- - ** - ** fill in nccb - ** - **---------------------------------------------------- - ** - ** - ** physical -> virtual backlink - ** Generic SCSI command - */ - cp->phys.header.cp = cp; - /* - ** Startqueue - */ - cp->phys.header.launch.l_paddr = NCB_SCRIPT_PHYS (np, select); - cp->phys.header.launch.l_cmd = SCR_JUMP; - /* - ** select - */ - cp->phys.select.sel_id = ccb->ccb_h.target_id; - cp->phys.select.sel_scntl3 = tp->tinfo.wval; - cp->phys.select.sel_sxfer = tp->tinfo.sval; - /* - ** message - */ - cp->phys.smsg.addr = CCB_PHYS (cp, scsi_smsg); - cp->phys.smsg.size = msglen; - - cp->phys.smsg2.addr = CCB_PHYS (cp, scsi_smsg2); - cp->phys.smsg2.size = msglen2; - /* - ** command - */ - cp->phys.cmd.addr = vtophys (scsiio_cdb_ptr(csio)); - cp->phys.cmd.size = csio->cdb_len; - /* - ** sense command - */ - cp->phys.scmd.addr = CCB_PHYS (cp, sensecmd); - cp->phys.scmd.size = 6; - /* - ** patch requested size into sense command - */ - cp->sensecmd[0] = 0x03; - cp->sensecmd[1] = ccb->ccb_h.target_lun << 5; - cp->sensecmd[4] = csio->sense_len; - /* - ** sense data - */ - cp->phys.sense.addr = vtophys (&csio->sense_data); - cp->phys.sense.size = csio->sense_len; - /* - ** status - */ - cp->actualquirks = QUIRK_NOMSG; - cp->host_status = nego ? HS_NEGOTIATE : HS_BUSY; - cp->s_status = SCSI_STATUS_ILLEGAL; - cp->parity_status = 0; - - cp->xerr_status = XE_OK; - cp->sync_status = tp->tinfo.sval; - cp->nego_status = nego; - cp->wide_status = tp->tinfo.wval; - - /*---------------------------------------------------- - ** - ** Critical region: start this job. - ** - **---------------------------------------------------- - */ - - /* - ** reselect pattern and activate this job. - */ - - cp->jump_nccb.l_cmd = (SCR_JUMP ^ IFFALSE (DATA (cp->tag))); - cp->tlimit = time_second - + ccb->ccb_h.timeout / 1000 + 2; - cp->magic = CCB_MAGIC; - - /* - ** insert into start queue. - */ - - 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 = qidx; - - if(DEBUG_FLAGS & DEBUG_QUEUE) - device_printf(np->dev, "queuepos=%d tryoffset=%d.\n", - np->squeueput, - (unsigned)(READSCRIPT(startpos[0]) - - (NCB_SCRIPTH_PHYS (np, tryloop)))); - - /* - ** Script processor may be waiting for reselect. - ** Wake it up. - */ - OUTB (nc_istat, SIGP); - break; - } - case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ - case XPT_ABORT: /* Abort the specified CCB */ - /* XXX Implement */ - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - case XPT_SET_TRAN_SETTINGS: - { - struct ccb_trans_settings *cts = &ccb->cts; - tcb_p tp; - u_int update_type; - struct ccb_trans_settings_scsi *scsi = - &cts->proto_specific.scsi; - struct ccb_trans_settings_spi *spi = - &cts->xport_specific.spi; - - update_type = 0; - if (cts->type == CTS_TYPE_CURRENT_SETTINGS) - update_type |= NCR_TRANS_GOAL; - if (cts->type == CTS_TYPE_USER_SETTINGS) - update_type |= NCR_TRANS_USER; - - tp = &np->target[ccb->ccb_h.target_id]; - /* Tag and disc enables */ - if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { - if (update_type & NCR_TRANS_GOAL) { - if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) - tp->tinfo.disc_tag |= NCR_CUR_DISCENB; - else - tp->tinfo.disc_tag &= ~NCR_CUR_DISCENB; - } - - if (update_type & NCR_TRANS_USER) { - if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) - tp->tinfo.disc_tag |= NCR_USR_DISCENB; - else - tp->tinfo.disc_tag &= ~NCR_USR_DISCENB; - } - - } - - if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { - if (update_type & NCR_TRANS_GOAL) { - if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) - tp->tinfo.disc_tag |= NCR_CUR_TAGENB; - else - tp->tinfo.disc_tag &= ~NCR_CUR_TAGENB; - } - - if (update_type & NCR_TRANS_USER) { - if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) - tp->tinfo.disc_tag |= NCR_USR_TAGENB; - else - tp->tinfo.disc_tag &= ~NCR_USR_TAGENB; - } - } - - /* Filter bus width and sync negotiation settings */ - if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { - if (spi->bus_width > np->maxwide) - spi->bus_width = np->maxwide; - } - - if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) - || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) { - if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) { - if (spi->sync_period != 0 - && (spi->sync_period < np->minsync)) - spi->sync_period = np->minsync; - } - if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) { - if (spi->sync_offset == 0) - spi->sync_period = 0; - if (spi->sync_offset > np->maxoffs) - spi->sync_offset = np->maxoffs; - } - } - if ((update_type & NCR_TRANS_USER) != 0) { - if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) - tp->tinfo.user.period = spi->sync_period; - if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) - tp->tinfo.user.offset = spi->sync_offset; - if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) - tp->tinfo.user.width = spi->bus_width; - } - if ((update_type & NCR_TRANS_GOAL) != 0) { - if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) - tp->tinfo.goal.period = spi->sync_period; - - if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) - tp->tinfo.goal.offset = spi->sync_offset; - - if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) - tp->tinfo.goal.width = spi->bus_width; - } - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - case XPT_GET_TRAN_SETTINGS: - /* Get default/user set transfer settings for the target */ - { - struct ccb_trans_settings *cts = &ccb->cts; - struct ncr_transinfo *tinfo; - tcb_p tp = &np->target[ccb->ccb_h.target_id]; - struct ccb_trans_settings_scsi *scsi = - &cts->proto_specific.scsi; - struct ccb_trans_settings_spi *spi = - &cts->xport_specific.spi; - - cts->protocol = PROTO_SCSI; - cts->protocol_version = SCSI_REV_2; - cts->transport = XPORT_SPI; - cts->transport_version = 2; - - if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { - tinfo = &tp->tinfo.current; - if (tp->tinfo.disc_tag & NCR_CUR_DISCENB) - spi->flags |= CTS_SPI_FLAGS_DISC_ENB; - else - spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; - - if (tp->tinfo.disc_tag & NCR_CUR_TAGENB) - scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; - else - scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; - } else { - tinfo = &tp->tinfo.user; - if (tp->tinfo.disc_tag & NCR_USR_DISCENB) - spi->flags |= CTS_SPI_FLAGS_DISC_ENB; - else - spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; - - if (tp->tinfo.disc_tag & NCR_USR_TAGENB) - scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; - else - scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; - } - - spi->sync_period = tinfo->period; - spi->sync_offset = tinfo->offset; - spi->bus_width = tinfo->width; - - spi->valid = CTS_SPI_VALID_SYNC_RATE - | CTS_SPI_VALID_SYNC_OFFSET - | CTS_SPI_VALID_BUS_WIDTH - | CTS_SPI_VALID_DISC; - scsi->valid = CTS_SCSI_VALID_TQ; - - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - case XPT_CALC_GEOMETRY: - { - /* XXX JGibbs - I'm sure the NCR uses a different strategy, - * but it should be able to deal with Adaptec - * geometry too. - */ - cam_calc_geometry(&ccb->ccg, /*extended*/1); - xpt_done(ccb); - break; - } - case XPT_RESET_BUS: /* Reset the specified SCSI bus */ - { - OUTB (nc_scntl1, CRST); - ccb->ccb_h.status = CAM_REQ_CMP; - DELAY(10000); /* Wait until our interrupt handler sees it */ - xpt_done(ccb); - break; - } - case XPT_TERM_IO: /* Terminate the I/O process */ - /* XXX Implement */ - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - case XPT_PATH_INQ: /* Path routing inquiry */ - { - struct ccb_pathinq *cpi = &ccb->cpi; - - cpi->version_num = 1; /* XXX??? */ - cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE; - if ((np->features & FE_WIDE) != 0) - cpi->hba_inquiry |= PI_WIDE_16; - cpi->target_sprt = 0; - cpi->hba_misc = 0; - cpi->hba_eng_cnt = 0; - cpi->max_target = (np->features & FE_WIDE) ? 15 : 7; - cpi->max_lun = MAX_LUN - 1; - cpi->initiator_id = np->myaddr; - cpi->bus_id = cam_sim_bus(sim); - cpi->base_transfer_speed = 3300; - strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strlcpy(cpi->hba_vid, "Symbios", HBA_IDLEN); - strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); - cpi->unit_number = cam_sim_unit(sim); - cpi->transport = XPORT_SPI; - cpi->transport_version = 2; - cpi->protocol = PROTO_SCSI; - cpi->protocol_version = SCSI_REV_2; - cpi->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - default: - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; - } -} - -/*========================================================== -** -** -** Complete execution of a SCSI command. -** Signal completion to the generic SCSI driver. -** -** -**========================================================== -*/ - -static void -ncr_complete (ncb_p np, nccb_p cp) -{ - union ccb *ccb; - tcb_p tp; - - /* - ** Sanity check - */ - - if (!cp || (cp->magic!=CCB_MAGIC) || !cp->ccb) return; - cp->magic = 1; - cp->tlimit= 0; - - /* - ** No Reselect anymore. - */ - cp->jump_nccb.l_cmd = (SCR_JUMP); - - /* - ** No starting. - */ - cp->phys.header.launch.l_paddr= NCB_SCRIPT_PHYS (np, idle); - - /* - ** timestamp - */ - ncb_profile (np, cp); - - if (DEBUG_FLAGS & DEBUG_TINY) - printf ("CCB=%x STAT=%x/%x\n", (int)(intptr_t)cp & 0xfff, - cp->host_status,cp->s_status); - - ccb = cp->ccb; - cp->ccb = NULL; - tp = &np->target[ccb->ccb_h.target_id]; - - /* - ** We do not queue more than 1 nccb per target - ** with negotiation at any time. If this nccb was - ** used for negotiation, clear this info in the tcb. - */ - - if (cp == tp->nego_cp) - tp->nego_cp = NULL; - - /* - ** Check for parity errors. - */ - /* XXX JGibbs - What about reporting them??? */ - - if (cp->parity_status) { - PRINT_ADDR(ccb); - printf ("%d parity error(s), fallback.\n", cp->parity_status); - /* - ** fallback to asynch transfer. - */ - tp->tinfo.goal.period = 0; - tp->tinfo.goal.offset = 0; - } - - /* - ** Check for extended errors. - */ - - if (cp->xerr_status != XE_OK) { - PRINT_ADDR(ccb); - switch (cp->xerr_status) { - case XE_EXTRA_DATA: - printf ("extraneous data discarded.\n"); - break; - case XE_BAD_PHASE: - printf ("illegal scsi phase (4/5).\n"); - break; - default: - printf ("extended error %d.\n", cp->xerr_status); - break; - } - if (cp->host_status==HS_COMPLETE) - cp->host_status = HS_FAIL; - } - - /* - ** Check the status. - */ - if (cp->host_status == HS_COMPLETE) { - - if (cp->s_status == SCSI_STATUS_OK) { - - /* - ** All went well. - */ - /* XXX JGibbs - Properly calculate residual */ - - tp->bytes += ccb->csio.dxfer_len; - tp->transfers ++; - - ccb->ccb_h.status = CAM_REQ_CMP; - } else if ((cp->s_status & SCSI_STATUS_SENSE) != 0) { - - /* - * XXX Could be TERMIO too. Should record - * original status. - */ - ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; - cp->s_status &= ~SCSI_STATUS_SENSE; - if (cp->s_status == SCSI_STATUS_OK) { - ccb->ccb_h.status = - CAM_AUTOSNS_VALID|CAM_SCSI_STATUS_ERROR; - } else { - ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; - } - } else { - ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; - ccb->csio.scsi_status = cp->s_status; - } - - - } else if (cp->host_status == HS_SEL_TIMEOUT) { - - /* - ** Device failed selection - */ - ccb->ccb_h.status = CAM_SEL_TIMEOUT; - - } else if (cp->host_status == HS_TIMEOUT) { - - /* - ** No response - */ - ccb->ccb_h.status = CAM_CMD_TIMEOUT; - } else if (cp->host_status == HS_STALL) { - ccb->ccb_h.status = CAM_REQUEUE_REQ; - } else { - - /* - ** Other protocol messes - */ - PRINT_ADDR(ccb); - printf ("COMMAND FAILED (%x %x) @%p.\n", - cp->host_status, cp->s_status, cp); - - ccb->ccb_h.status = CAM_CMD_TIMEOUT; - } - - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { - xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); - ccb->ccb_h.status |= CAM_DEV_QFRZN; - } - - /* - ** Free this nccb - */ - ncr_free_nccb (np, cp); - - /* - ** signal completion to generic driver. - */ - xpt_done (ccb); -} - -/*========================================================== -** -** -** Signal all (or one) control block done. -** -** -**========================================================== -*/ - -static void -ncr_wakeup (ncb_p np, u_long code) -{ - /* - ** Starting at the default nccb and following - ** the links, complete all jobs with a - ** host_status greater than "disconnect". - ** - ** If the "code" parameter is not zero, - ** complete all jobs that are not IDLE. - */ - - nccb_p cp = np->link_nccb; - while (cp) { - switch (cp->host_status) { - - case HS_IDLE: - break; - - case HS_DISCONNECT: - if(DEBUG_FLAGS & DEBUG_TINY) printf ("D"); - /* FALLTHROUGH */ - - case HS_BUSY: - case HS_NEGOTIATE: - if (!code) break; - cp->host_status = code; - - /* FALLTHROUGH */ - - default: - ncr_complete (np, cp); - break; - } - cp = cp -> link_nccb; - } -} - -static void -ncr_freeze_devq (ncb_p np, struct cam_path *path) -{ - nccb_p cp; - int i; - int count; - int firstskip; - /* - ** Starting at the first nccb and following - ** the links, complete all jobs that match - ** the passed in path and are in the start queue. - */ - - cp = np->link_nccb; - count = 0; - firstskip = 0; - while (cp) { - switch (cp->host_status) { - - case HS_BUSY: - case HS_NEGOTIATE: - if ((cp->phys.header.launch.l_paddr - == NCB_SCRIPT_PHYS (np, select)) - && (xpt_path_comp(path, cp->ccb->ccb_h.path) >= 0)) { - - /* Mark for removal from the start queue */ - for (i = 1; i < MAX_START; i++) { - int idx; - - idx = np->squeueput - i; - - if (idx < 0) - idx = MAX_START + idx; - if (np->squeue[idx] - == CCB_PHYS(cp, phys)) { - np->squeue[idx] = - NCB_SCRIPT_PHYS (np, skip); - if (i > firstskip) - firstskip = i; - break; - } - } - cp->host_status=HS_STALL; - ncr_complete (np, cp); - count++; - } - break; - default: - break; - } - cp = cp->link_nccb; - } - - if (count > 0) { - int j; - int bidx; - - /* Compress the start queue */ - j = 0; - bidx = np->squeueput; - i = np->squeueput - firstskip; - if (i < 0) - i = MAX_START + i; - for (;;) { - - bidx = i - j; - if (bidx < 0) - bidx = MAX_START + bidx; - - if (np->squeue[i] == NCB_SCRIPT_PHYS (np, skip)) { - j++; - } else if (j != 0) { - np->squeue[bidx] = np->squeue[i]; - if (np->squeue[bidx] - == NCB_SCRIPT_PHYS(np, idle)) - break; - } - i = (i + 1) % MAX_START; - } - np->squeueput = bidx; - } -} - -/*========================================================== -** -** -** Start NCR chip. -** -** -**========================================================== -*/ - -static void -ncr_init(ncb_p np, char * msg, u_long code) -{ - int i; - - /* - ** Reset chip. - */ - - OUTB (nc_istat, SRST); - DELAY (1000); - OUTB (nc_istat, 0); - - /* - ** Message. - */ - - if (msg) - device_printf(np->dev, "restart (%s).\n", msg); - - /* - ** Clear Start Queue - */ - - for (i=0;i squeue [i] = NCB_SCRIPT_PHYS (np, idle); - - /* - ** Start at first entry. - */ - - np->squeueput = 0; - WRITESCRIPT(startpos[0], NCB_SCRIPTH_PHYS (np, tryloop)); - WRITESCRIPT(start0 [0], SCR_INT ^ IFFALSE (0)); - - /* - ** Wakeup all pending jobs. - */ - - ncr_wakeup (np, code); - - /* - ** Init chip. - */ - - 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!! */ - ncr_selectclock(np, np->rv_scntl3); /* Select SCSI clock */ - OUTB (nc_scid , RRE|np->myaddr);/* host adapter SCSI address */ - OUTW (nc_respid, 1ul<myaddr);/* id to respond to */ - OUTB (nc_istat , SIGP ); /* Signal Process */ - 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, np->rv_ctest4);/* enable master parity checking */ - OUTB (nc_stest2, np->rv_stest2|EXT); /* Extended Sreq/Sack filtering */ - OUTB (nc_stest3, TE ); /* TolerANT enable */ - OUTB (nc_stime0, 0x0b ); /* HTH = disabled, STO = 0.1 sec. */ - - if (bootverbose >= 2) { - printf ("\tACTUAL values:SCNTL3:%02x DMODE:%02x DCNTL:%02x\n", - np->rv_scntl3, np->rv_dmode, np->rv_dcntl); - printf ("\t CTEST3:%02x CTEST4:%02x CTEST5:%02x\n", - np->rv_ctest3, np->rv_ctest4, np->rv_ctest5); - } - - /* - ** Enable GPIO0 pin for writing if LED support. - */ - - if (np->features & FE_LED0) { - OUTOFFB (nc_gpcntl, 0x01); - } - - /* - ** Fill in target structure. - */ - for (i=0;itarget[i]; - - tp->tinfo.sval = 0; - tp->tinfo.wval = np->rv_scntl3; - - tp->tinfo.current.period = 0; - tp->tinfo.current.offset = 0; - tp->tinfo.current.width = MSG_EXT_WDTR_BUS_8_BIT; - } - - /* - ** enable ints - */ - - OUTW (nc_sien , STO|HTH|MA|SGE|UDC|RST); - OUTB (nc_dien , MDPE|BF|ABRT|SSI|SIR|IID); - - /* - ** Start script processor. - */ - - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start)); - - /* - * Notify the XPT of the event - */ - if (code == HS_RESET) - xpt_async(AC_BUS_RESET, np->path, NULL); -} - -static void -ncr_poll(struct cam_sim *sim) -{ - ncr_intr_locked(cam_sim_softc(sim)); -} - - -/*========================================================== -** -** Get clock factor and sync divisor for a given -** synchronous factor period. -** Returns the clock factor (in sxfer) and scntl3 -** synchronous divisor field. -** -**========================================================== -*/ - -static void ncr_getsync(ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p) -{ - u_long clk = np->clock_khz; /* SCSI clock frequency in kHz */ - int div = np->clock_divn; /* Number of divisors supported */ - u_long fak; /* Sync factor in sxfer */ - u_long per; /* Period in tenths of ns */ - u_long kpc; /* (per * clk) */ - - /* - ** Compute the synchronous period in tenths of nano-seconds - */ - if (sfac <= 10) per = 250; - else if (sfac == 11) per = 303; - else if (sfac == 12) per = 500; - else per = 40 * sfac; - - /* - ** Look for the greatest clock divisor that allows an - ** input speed faster than the period. - */ - kpc = per * clk; - while (--div >= 0) - if (kpc >= (div_10M[div] * 4)) break; - - /* - ** Calculate the lowest clock factor that allows an output - ** speed not faster than the period. - */ - fak = (kpc - 1) / div_10M[div] + 1; - -#if 0 /* You can #if 1 if you think this optimization is useful */ - - per = (fak * div_10M[div]) / clk; - - /* - ** Why not to try the immediate lower divisor and to choose - ** the one that allows the fastest output speed ? - ** We dont want input speed too much greater than output speed. - */ - if (div >= 1 && fak < 6) { - u_long fak2, per2; - fak2 = (kpc - 1) / div_10M[div-1] + 1; - per2 = (fak2 * div_10M[div-1]) / clk; - if (per2 < per && fak2 <= 6) { - fak = fak2; - per = per2; - --div; - } - } -#endif - - if (fak < 4) fak = 4; /* Should never happen, too bad ... */ - - /* - ** Compute and return sync parameters for the ncr - */ - *fakp = fak - 4; - *scntl3p = ((div+1) << 4) + (sfac < 25 ? 0x80 : 0); -} - -/*========================================================== -** -** Switch sync mode for current job and its target -** -**========================================================== -*/ - -static void -ncr_setsync(ncb_p np, nccb_p cp, u_char scntl3, u_char sxfer, u_char period) -{ - union ccb *ccb; - struct ccb_trans_settings neg; - tcb_p tp; - int div; - u_int target = INB (nc_sdid) & 0x0f; - u_int period_10ns; - - assert (cp); - if (!cp) return; - - ccb = cp->ccb; - assert (ccb); - if (!ccb) return; - assert (target == ccb->ccb_h.target_id); - - tp = &np->target[target]; - - if (!scntl3 || !(sxfer & 0x1f)) - scntl3 = np->rv_scntl3; - scntl3 = (scntl3 & 0xf0) | (tp->tinfo.wval & EWS) - | (np->rv_scntl3 & 0x07); - - /* - ** Deduce the value of controller sync period from scntl3. - ** period is in tenths of nano-seconds. - */ - - div = ((scntl3 >> 4) & 0x7); - if ((sxfer & 0x1f) && div) - period_10ns = - (((sxfer>>5)+4)*div_10M[div-1])/np->clock_khz; - else - period_10ns = 0; - - tp->tinfo.goal.period = period; - tp->tinfo.goal.offset = sxfer & 0x1f; - tp->tinfo.current.period = period; - tp->tinfo.current.offset = sxfer & 0x1f; - - /* - ** Stop there if sync parameters are unchanged - */ - if (tp->tinfo.sval == sxfer && tp->tinfo.wval == scntl3) return; - tp->tinfo.sval = sxfer; - tp->tinfo.wval = scntl3; - - if (sxfer & 0x1f) { - /* - ** Disable extended Sreq/Sack filtering - */ - if (period_10ns <= 2000) OUTOFFB (nc_stest2, EXT); - } - - /* - ** Tell the SCSI layer about the - ** new transfer parameters. - */ - memset(&neg, 0, sizeof (neg)); - neg.protocol = PROTO_SCSI; - neg.protocol_version = SCSI_REV_2; - neg.transport = XPORT_SPI; - neg.transport_version = 2; - neg.xport_specific.spi.sync_period = period; - neg.xport_specific.spi.sync_offset = sxfer & 0x1f; - neg.xport_specific.spi.valid = CTS_SPI_VALID_SYNC_RATE - | CTS_SPI_VALID_SYNC_OFFSET; - xpt_setup_ccb(&neg.ccb_h, ccb->ccb_h.path, - /*priority*/1); - xpt_async(AC_TRANSFER_NEG, ccb->ccb_h.path, &neg); - - /* - ** set actual value and sync_status - */ - OUTB (nc_sxfer, sxfer); - np->sync_st = sxfer; - OUTB (nc_scntl3, scntl3); - np->wide_st = scntl3; - - /* - ** patch ALL nccbs of this target. - */ - for (cp = np->link_nccb; cp; cp = cp->link_nccb) { - if (!cp->ccb) continue; - if (cp->ccb->ccb_h.target_id != target) continue; - cp->sync_status = sxfer; - cp->wide_status = scntl3; - } -} - -/*========================================================== -** -** Switch wide mode for current job and its target -** SCSI specs say: a SCSI device that accepts a WDTR -** message shall reset the synchronous agreement to -** asynchronous mode. -** -**========================================================== -*/ - -static void ncr_setwide (ncb_p np, nccb_p cp, u_char wide, u_char ack) -{ - union ccb *ccb; - struct ccb_trans_settings neg; - u_int target = INB (nc_sdid) & 0x0f; - tcb_p tp; - u_char scntl3; - u_char sxfer; - - assert (cp); - if (!cp) return; - - ccb = cp->ccb; - assert (ccb); - if (!ccb) return; - assert (target == ccb->ccb_h.target_id); - - tp = &np->target[target]; - tp->tinfo.current.width = wide; - tp->tinfo.goal.width = wide; - tp->tinfo.current.period = 0; - tp->tinfo.current.offset = 0; - - scntl3 = (tp->tinfo.wval & (~EWS)) | (wide ? EWS : 0); - - sxfer = ack ? 0 : tp->tinfo.sval; - - /* - ** Stop there if sync/wide parameters are unchanged - */ - if (tp->tinfo.sval == sxfer && tp->tinfo.wval == scntl3) return; - tp->tinfo.sval = sxfer; - tp->tinfo.wval = scntl3; - - /* Tell the SCSI layer about the new transfer params */ - memset(&neg, 0, sizeof (neg)); - neg.protocol = PROTO_SCSI; - neg.protocol_version = SCSI_REV_2; - neg.transport = XPORT_SPI; - neg.transport_version = 2; - neg.xport_specific.spi.bus_width = (scntl3 & EWS) ? - MSG_EXT_WDTR_BUS_16_BIT : MSG_EXT_WDTR_BUS_8_BIT; - neg.xport_specific.spi.sync_period = 0; - neg.xport_specific.spi.sync_offset = 0; - neg.xport_specific.spi.valid = CTS_SPI_VALID_SYNC_RATE - | CTS_SPI_VALID_SYNC_OFFSET - | CTS_SPI_VALID_BUS_WIDTH; - xpt_setup_ccb(&neg.ccb_h, ccb->ccb_h.path, /*priority*/1); - xpt_async(AC_TRANSFER_NEG, ccb->ccb_h.path, &neg); - - /* - ** set actual value and sync_status - */ - OUTB (nc_sxfer, sxfer); - np->sync_st = sxfer; - OUTB (nc_scntl3, scntl3); - np->wide_st = scntl3; - - /* - ** patch ALL nccbs of this target. - */ - for (cp = np->link_nccb; cp; cp = cp->link_nccb) { - if (!cp->ccb) continue; - if (cp->ccb->ccb_h.target_id != target) continue; - cp->sync_status = sxfer; - cp->wide_status = scntl3; - } -} - -/*========================================================== -** -** -** ncr timeout handler. -** -** -**========================================================== -** -** Misused to keep the driver running when -** interrupts are not configured correctly. -** -**---------------------------------------------------------- -*/ - -static void -ncr_timeout (void *arg) -{ - ncb_p np = arg; - time_t thistime = time_second; - ticks_t step = np->ticks; - u_long count = 0; - long signed t; - nccb_p cp; - - mtx_assert(&np->lock, MA_OWNED); - if (np->lasttime != thistime) { - np->lasttime = thistime; - - /*---------------------------------------------------- - ** - ** handle ncr chip timeouts - ** - ** Assumption: - ** We have a chance to arbitrate for the - ** SCSI bus at least every 10 seconds. - ** - **---------------------------------------------------- - */ - - t = thistime - np->heartbeat; - - if (t<2) np->latetime=0; else np->latetime++; - - if (np->latetime>2) { - /* - ** If there are no requests, the script - ** processor will sleep on SEL_WAIT_RESEL. - ** But we have to check whether it died. - ** Let's try to wake it up. - */ - OUTB (nc_istat, SIGP); - } - - /*---------------------------------------------------- - ** - ** handle nccb timeouts - ** - **---------------------------------------------------- - */ - - for (cp=np->link_nccb; cp; cp=cp->link_nccb) { - /* - ** look for timed out nccbs. - */ - if (!cp->host_status) continue; - count++; - if (cp->tlimit > thistime) continue; - - /* - ** Disable reselect. - ** Remove it from startqueue. - */ - cp->jump_nccb.l_cmd = (SCR_JUMP); - if (cp->phys.header.launch.l_paddr == - NCB_SCRIPT_PHYS (np, select)) { - device_printf(np->dev, - "timeout nccb=%p (skip)\n", cp); - cp->phys.header.launch.l_paddr - = NCB_SCRIPT_PHYS (np, skip); - } - - switch (cp->host_status) { - - case HS_BUSY: - case HS_NEGOTIATE: - /* FALLTHROUGH */ - case HS_DISCONNECT: - cp->host_status=HS_TIMEOUT; - } - cp->tag = 0; - - /* - ** wakeup this nccb. - */ - ncr_complete (np, cp); - } - } - - callout_reset(&np->timer, step ? step : 1, ncr_timeout, np); - - if (INB(nc_istat) & (INTF|SIP|DIP)) { - - /* - ** Process pending interrupts. - */ - - if (DEBUG_FLAGS & DEBUG_TINY) printf ("{"); - ncr_exception (np); - if (DEBUG_FLAGS & DEBUG_TINY) printf ("}"); - } -} - -/*========================================================== -** -** log message for real hard errors -** -** "ncr0 targ 0?: ERROR (ds:si) (so-si-sd) (sxfer/scntl3) @ name (dsp:dbc)." -** " reg: r0 r1 r2 r3 r4 r5 r6 ..... rf." -** -** exception register: -** ds: dstat -** si: sist -** -** SCSI bus lines: -** so: control lines as driver by NCR. -** si: control lines as seen by NCR. -** sd: scsi data lines as seen by NCR. -** -** wide/fastmode: -** sxfer: (see the manual) -** scntl3: (see the manual) -** -** current script command: -** dsp: script address (relative to start of script). -** dbc: first word of script command. -** -** First 16 register of the chip: -** r0..rf -** -**========================================================== -*/ - -static void ncr_log_hard_error(ncb_p np, u_short sist, u_char dstat) -{ - u_int32_t dsp; - int script_ofs; - int script_size; - char *script_name; - u_char *script_base; - int i; - - dsp = INL (nc_dsp); - - if (np->p_script < dsp && - dsp <= np->p_script + sizeof(struct script)) { - script_ofs = dsp - np->p_script; - script_size = sizeof(struct script); - script_base = (u_char *) np->script; - script_name = "script"; - } - else if (np->p_scripth < dsp && - dsp <= np->p_scripth + sizeof(struct scripth)) { - script_ofs = dsp - np->p_scripth; - script_size = sizeof(struct scripth); - script_base = (u_char *) np->scripth; - script_name = "scripth"; - } else { - script_ofs = dsp; - script_size = 0; - script_base = NULL; - script_name = "mem"; - } - - device_printf(np->dev, - "%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%s %x:%08x).\n", - (unsigned)INB (nc_sdid)&0x0f, dstat, sist, - (unsigned)INB (nc_socl), (unsigned)INB (nc_sbcl), (unsigned)INB (nc_sbdl), - (unsigned)INB (nc_sxfer),(unsigned)INB (nc_scntl3), script_name, script_ofs, - (unsigned)INL (nc_dbc)); - - if (((script_ofs & 3) == 0) && - (unsigned)script_ofs < script_size) { - device_printf(np->dev, "script cmd = %08x\n", - (int)READSCRIPT_OFF(script_base, script_ofs)); - } - - device_printf(np->dev, "regdump:"); - for (i=0; i<16;i++) - printf (" %02x", (unsigned)INB_OFF(i)); - printf (".\n"); -} - -/*========================================================== -** -** -** ncr chip exception handler. -** -** -**========================================================== -*/ - -static void ncr_exception (ncb_p np) -{ - u_char istat, dstat; - u_short sist; - - /* - ** interrupt on the fly ? - */ - while ((istat = INB (nc_istat)) & INTF) { - if (DEBUG_FLAGS & DEBUG_TINY) printf ("F "); - OUTB (nc_istat, INTF); - np->profile.num_fly++; - ncr_wakeup (np, 0); - } - if (!(istat & (SIP|DIP))) { - return; - } - - /* - ** Steinbach's Guideline for Systems Programming: - ** 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; - np->profile.num_int++; - - if (DEBUG_FLAGS & DEBUG_TINY) - printf ("<%d|%x:%x|%x:%x>", - INB(nc_scr0), - dstat,sist, - (unsigned)INL(nc_dsp), - (unsigned)INL(nc_dbc)); - if ((dstat==DFE) && (sist==PAR)) return; - -/*========================================================== -** -** First the normal cases. -** -**========================================================== -*/ - /*------------------------------------------- - ** SCSI reset - **------------------------------------------- - */ - - if (sist & RST) { - ncr_init (np, bootverbose ? "scsi reset" : NULL, HS_RESET); - return; - } - - /*------------------------------------------- - ** selection timeout - ** - ** IID excluded from dstat mask! - ** (chip bug) - **------------------------------------------- - */ - - if ((sist & STO) && - !(sist & (GEN|HTH|MA|SGE|UDC|RST|PAR)) && - !(dstat & (MDPE|BF|ABRT|SIR))) { - ncr_int_sto (np); - return; - } - - /*------------------------------------------- - ** Phase mismatch. - **------------------------------------------- - */ - - if ((sist & MA) && - !(sist & (STO|GEN|HTH|SGE|UDC|RST|PAR)) && - !(dstat & (MDPE|BF|ABRT|SIR|IID))) { - ncr_int_ma (np, dstat); - return; - } - - /*---------------------------------------- - ** move command with length 0 - **---------------------------------------- - */ - - if ((dstat & IID) && - !(sist & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) && - !(dstat & (MDPE|BF|ABRT|SIR)) && - ((INL(nc_dbc) & 0xf8000000) == SCR_MOVE_TBL)) { - /* - ** Target wants more data than available. - ** The "no_data" script will do it. - */ - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, no_data)); - return; - } - - /*------------------------------------------- - ** Programmed interrupt - **------------------------------------------- - */ - - if ((dstat & SIR) && - !(sist & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) && - !(dstat & (MDPE|BF|ABRT|IID)) && - (INB(nc_dsps) <= SIR_MAX)) { - ncr_int_sir (np); - return; - } - - /*======================================== - ** log message for real hard errors - **======================================== - */ - - ncr_log_hard_error(np, sist, dstat); - - /*======================================== - ** do the register dump - **======================================== - */ - - if (time_second - np->regtime > 10) { - int i; - np->regtime = time_second; - for (i=0; iregdump); i++) - ((volatile char*)&np->regdump)[i] = INB_OFF(i); - np->regdump.nc_dstat = dstat; - np->regdump.nc_sist = sist; - } - - - /*---------------------------------------- - ** clean up the dma fifo - **---------------------------------------- - */ - - if ( (INB(nc_sstat0) & (ILF|ORF|OLF) ) || - (INB(nc_sstat1) & (FF3210) ) || - (INB(nc_sstat2) & (ILF1|ORF1|OLF1)) || /* wide .. */ - !(dstat & DFE)) { - device_printf(np->dev, "have to clear fifos.\n"); - OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */ - OUTB (nc_ctest3, np->rv_ctest3 | CLF); - /* clear dma fifo */ - } - - /*---------------------------------------- - ** handshake timeout - **---------------------------------------- - */ - - if (sist & HTH) { - device_printf(np->dev, "handshake timeout\n"); - OUTB (nc_scntl1, CRST); - DELAY (1000); - OUTB (nc_scntl1, 0x00); - OUTB (nc_scr0, HS_FAIL); - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, cleanup)); - return; - } - - /*---------------------------------------- - ** unexpected disconnect - **---------------------------------------- - */ - - if ((sist & UDC) && - !(sist & (STO|GEN|HTH|MA|SGE|RST|PAR)) && - !(dstat & (MDPE|BF|ABRT|SIR|IID))) { - OUTB (nc_scr0, HS_UNEXPECTED); - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, cleanup)); - return; - } - - /*---------------------------------------- - ** cannot disconnect - **---------------------------------------- - */ - - if ((dstat & IID) && - !(sist & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) && - !(dstat & (MDPE|BF|ABRT|SIR)) && - ((INL(nc_dbc) & 0xf8000000) == SCR_WAIT_DISC)) { - /* - ** Unexpected data cycle while waiting for disconnect. - */ - if (INB(nc_sstat2) & LDSC) { - /* - ** It's an early reconnect. - ** Let's continue ... - */ - OUTB (nc_dcntl, np->rv_dcntl | STD); - /* - ** info message - */ - device_printf(np->dev, "INFO: LDSC while IID.\n"); - return; - } - device_printf(np->dev, "target %d doesn't release the bus.\n", - INB (nc_sdid)&0x0f); - /* - ** return without restarting the NCR. - ** timeout will do the real work. - */ - return; - } - - /*---------------------------------------- - ** single step - **---------------------------------------- - */ - - if ((dstat & SSI) && - !(sist & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) && - !(dstat & (MDPE|BF|ABRT|SIR|IID))) { - OUTB (nc_dcntl, np->rv_dcntl | STD); - return; - } - -/* -** @RECOVER@ HTH, SGE, ABRT. -** -** We should try to recover from these interrupts. -** They may occur if there are problems with synch transfers, or -** if targets are switched on or off while the driver is running. -*/ - - if (sist & SGE) { - /* clear scsi offsets */ - OUTB (nc_ctest3, np->rv_ctest3 | CLF); - } - - /* - ** Freeze controller to be able to read the messages. - */ - - if (DEBUG_FLAGS & DEBUG_FREEZE) { - int i; - unsigned char val; - for (i=0; i<0x60; i++) { - switch (i%16) { - - case 0: - device_printf(np->dev, "reg[%d0]: ", i / 16); - break; - case 4: - case 8: - case 12: - printf (" "); - break; - } - val = bus_read_1(np->reg_res, i); - printf (" %x%x", val/16, val%16); - if (i%16==15) printf (".\n"); - } - - callout_stop(&np->timer); - - device_printf(np->dev, "halted!\n"); - /* - ** don't restart controller ... - */ - OUTB (nc_istat, SRST); - return; - } - -#ifdef NCR_FREEZE - /* - ** Freeze system to be able to read the messages. - */ - printf ("ncr: fatal error: system halted - press reset to reboot ..."); - for (;;); -#endif - - /* - ** sorry, have to kill ALL jobs ... - */ - - ncr_init (np, "fatal error", HS_FAIL); -} - -/*========================================================== -** -** ncr chip exception handler for selection timeout -** -**========================================================== -** -** There seems to be a bug in the 53c810. -** Although a STO-Interrupt is pending, -** it continues executing script commands. -** But it will fail and interrupt (IID) on -** the next instruction where it's looking -** for a valid phase. -** -**---------------------------------------------------------- -*/ - -static void ncr_int_sto (ncb_p np) -{ - u_long dsa, scratcha, diff; - nccb_p cp; - if (DEBUG_FLAGS & DEBUG_TINY) printf ("T"); - - /* - ** look for nccb and set the status. - */ - - dsa = INL (nc_dsa); - cp = np->link_nccb; - while (cp && (CCB_PHYS (cp, phys) != dsa)) - cp = cp->link_nccb; - - if (cp) { - cp-> host_status = HS_SEL_TIMEOUT; - ncr_complete (np, cp); - } - - /* - ** repair start queue - */ - - scratcha = INL (nc_scratcha); - diff = scratcha - NCB_SCRIPTH_PHYS (np, tryloop); - -/* assert ((diff <= MAX_START * 20) && !(diff % 20));*/ - - if ((diff <= MAX_START * 20) && !(diff % 20)) { - WRITESCRIPT(startpos[0], scratcha); - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, start)); - return; - } - ncr_init (np, "selection timeout", HS_FAIL); -} - -/*========================================================== -** -** -** ncr chip exception handler for phase errors. -** -** -**========================================================== -** -** We have to construct a new transfer descriptor, -** to transfer the rest of the current block. -** -**---------------------------------------------------------- -*/ - -static void ncr_int_ma (ncb_p np, u_char dstat) -{ - u_int32_t dbc; - u_int32_t rest; - u_int32_t dsa; - u_int32_t dsp; - u_int32_t nxtdsp; - volatile void *vdsp_base; - size_t vdsp_off; - u_int32_t oadr, olen; - u_int32_t *tblp, *newcmd; - u_char cmd, sbcl, ss0, ss2, ctest5; - u_short delta; - nccb_p cp; - - dsp = INL (nc_dsp); - dsa = INL (nc_dsa); - dbc = INL (nc_dbc); - ss0 = INB (nc_sstat0); - ss2 = INB (nc_sstat2); - sbcl= INB (nc_sbcl); - - cmd = dbc >> 24; - rest= dbc & 0xffffff; - - ctest5 = (np->rv_ctest5 & DFS) ? INB (nc_ctest5) : 0; - if (ctest5 & DFS) - delta=(((ctest5<<8) | (INB (nc_dfifo) & 0xff)) - rest) & 0x3ff; - else - delta=(INB (nc_dfifo) - rest) & 0x7f; - - - /* - ** The data in the dma fifo has not been transferred to - ** the target -> add the amount to the rest - ** and clear the data. - ** Check the sstat2 register in case of wide transfer. - */ - - if (!(dstat & DFE)) rest += delta; - if (ss0 & OLF) rest++; - if (ss0 & ORF) rest++; - if (INB(nc_scntl3) & EWS) { - if (ss2 & OLF1) rest++; - if (ss2 & ORF1) rest++; - } - OUTB (nc_ctest3, np->rv_ctest3 | CLF); /* clear dma fifo */ - OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */ - - /* - ** locate matching cp - */ - cp = np->link_nccb; - while (cp && (CCB_PHYS (cp, phys) != dsa)) - cp = cp->link_nccb; - - if (!cp) { - device_printf(np->dev, - "SCSI phase error fixup: CCB already dequeued (%p)\n", - (void *)np->header.cp); - return; - } - if (cp != np->header.cp) { - device_printf(np->dev, - "SCSI phase error fixup: CCB address mismatch " - "(%p != %p) np->nccb = %p\n", - (void *)cp, (void *)np->header.cp, - (void *)np->link_nccb); -/* return;*/ - } - - /* - ** find the interrupted script command, - ** and the address at which to continue. - */ - - if (dsp == vtophys (&cp->patch[2])) { - vdsp_base = cp; - vdsp_off = offsetof(struct nccb, patch[0]); - nxtdsp = READSCRIPT_OFF(vdsp_base, vdsp_off + 3*4); - } else if (dsp == vtophys (&cp->patch[6])) { - vdsp_base = cp; - vdsp_off = offsetof(struct nccb, patch[4]); - nxtdsp = READSCRIPT_OFF(vdsp_base, vdsp_off + 3*4); - } else if (dsp > np->p_script && - dsp <= np->p_script + sizeof(struct script)) { - vdsp_base = np->script; - vdsp_off = dsp - np->p_script - 8; - nxtdsp = dsp; - } else { - vdsp_base = np->scripth; - vdsp_off = dsp - np->p_scripth - 8; - nxtdsp = dsp; - } - - /* - ** log the information - */ - if (DEBUG_FLAGS & (DEBUG_TINY|DEBUG_PHASE)) { - printf ("P%x%x ",cmd&7, sbcl&7); - printf ("RL=%d D=%d SS0=%x ", - (unsigned) rest, (unsigned) delta, ss0); - } - if (DEBUG_FLAGS & DEBUG_PHASE) { - printf ("\nCP=%p CP2=%p DSP=%x NXT=%x VDSP=%p CMD=%x ", - cp, np->header.cp, - dsp, - nxtdsp, (volatile char*)vdsp_base+vdsp_off, cmd); - } - - /* - ** get old startaddress and old length. - */ - - oadr = READSCRIPT_OFF(vdsp_base, vdsp_off + 1*4); - - if (cmd & 0x10) { /* Table indirect */ - tblp = (u_int32_t *) ((char*) &cp->phys + oadr); - olen = tblp[0]; - oadr = tblp[1]; - } else { - tblp = (u_int32_t *) 0; - olen = READSCRIPT_OFF(vdsp_base, vdsp_off) & 0xffffff; - } - - if (DEBUG_FLAGS & DEBUG_PHASE) { - printf ("OCMD=%x\nTBLP=%p OLEN=%lx OADR=%lx\n", - (unsigned) (READSCRIPT_OFF(vdsp_base, vdsp_off) >> 24), - (void *) tblp, - (u_long) olen, - (u_long) oadr); - } - - /* - ** if old phase not dataphase, leave here. - */ - - if (cmd != (READSCRIPT_OFF(vdsp_base, vdsp_off) >> 24)) { - PRINT_ADDR(cp->ccb); - printf ("internal error: cmd=%02x != %02x=(vdsp[0] >> 24)\n", - (unsigned)cmd, - (unsigned)READSCRIPT_OFF(vdsp_base, vdsp_off) >> 24); - - return; - } - if (cmd & 0x06) { - PRINT_ADDR(cp->ccb); - printf ("phase change %x-%x %d@%08x resid=%d.\n", - cmd&7, sbcl&7, (unsigned)olen, - (unsigned)oadr, (unsigned)rest); - - OUTB (nc_dcntl, np->rv_dcntl | STD); - return; - } - - /* - ** choose the correct patch area. - ** if savep points to one, choose the other. - */ - - newcmd = cp->patch; - if (cp->phys.header.savep == vtophys (newcmd)) newcmd+=4; - - /* - ** fillin the commands - */ - - newcmd[0] = ((cmd & 0x0f) << 24) | rest; - newcmd[1] = oadr + olen - rest; - newcmd[2] = SCR_JUMP; - newcmd[3] = nxtdsp; - - if (DEBUG_FLAGS & DEBUG_PHASE) { - PRINT_ADDR(cp->ccb); - printf ("newcmd[%d] %x %x %x %x.\n", - (int)(newcmd - cp->patch), - (unsigned)newcmd[0], - (unsigned)newcmd[1], - (unsigned)newcmd[2], - (unsigned)newcmd[3]); - } - /* - ** fake the return address (to the patch). - ** and restart script processor at dispatcher. - */ - np->profile.num_break++; - OUTL (nc_temp, vtophys (newcmd)); - if ((cmd & 7) == 0) - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch)); - else - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, checkatn)); -} - -/*========================================================== -** -** -** ncr chip exception handler for programmed interrupts. -** -** -**========================================================== -*/ - -static int ncr_show_msg (u_char * msg) -{ - u_char i; - printf ("%x",*msg); - if (*msg==MSG_EXTENDED) { - for (i=1;i<8;i++) { - if (i-1>msg[1]) break; - printf ("-%x",msg[i]); - } - return (i+1); - } else if ((*msg & 0xf0) == 0x20) { - printf ("-%x",msg[1]); - return (2); - } - return (1); -} - -static void ncr_int_sir (ncb_p np) -{ - u_char scntl3; - u_char chg, ofs, per, fak, wide; - u_char num = INB (nc_dsps); - nccb_p cp = NULL; - u_long dsa; - u_int target = INB (nc_sdid) & 0x0f; - tcb_p tp = &np->target[target]; - int i; - if (DEBUG_FLAGS & DEBUG_TINY) printf ("I#%d", num); - - switch (num) { - case SIR_SENSE_RESTART: - case SIR_STALL_RESTART: - break; - - default: - /* - ** lookup the nccb - */ - dsa = INL (nc_dsa); - cp = np->link_nccb; - while (cp && (CCB_PHYS (cp, phys) != dsa)) - cp = cp->link_nccb; - - assert (cp); - if (!cp) - goto out; - assert (cp == np->header.cp); - if (cp != np->header.cp) - goto out; - } - - switch (num) { - -/*-------------------------------------------------------------------- -** -** Processing of interrupted getcc selects -** -**-------------------------------------------------------------------- -*/ - - case SIR_SENSE_RESTART: - /*------------------------------------------ - ** Script processor is idle. - ** Look for interrupted "check cond" - **------------------------------------------ - */ - - if (DEBUG_FLAGS & DEBUG_RESTART) - device_printf(np->dev, "int#%d", num); - cp = (nccb_p) 0; - for (i=0; itarget[i]; - if (DEBUG_FLAGS & DEBUG_RESTART) printf ("+"); - cp = tp->hold_cp; - if (!cp) continue; - if (DEBUG_FLAGS & DEBUG_RESTART) printf ("+"); - if ((cp->host_status==HS_BUSY) && - (cp->s_status==SCSI_STATUS_CHECK_COND)) - break; - if (DEBUG_FLAGS & DEBUG_RESTART) printf ("- (remove)"); - tp->hold_cp = cp = (nccb_p) 0; - } - - if (cp) { - if (DEBUG_FLAGS & DEBUG_RESTART) - printf ("+ restart job ..\n"); - OUTL (nc_dsa, CCB_PHYS (cp, phys)); - OUTL (nc_dsp, NCB_SCRIPTH_PHYS (np, getcc)); - return; - } - - /* - ** no job, resume normal processing - */ - if (DEBUG_FLAGS & DEBUG_RESTART) printf (" -- remove trap\n"); - WRITESCRIPT(start0[0], SCR_INT ^ IFFALSE (0)); - break; - - case SIR_SENSE_FAILED: - /*------------------------------------------- - ** While trying to select for - ** getting the condition code, - ** a target reselected us. - **------------------------------------------- - */ - if (DEBUG_FLAGS & DEBUG_RESTART) { - PRINT_ADDR(cp->ccb); - printf ("in getcc reselect by t%d.\n", - INB(nc_ssid) & 0x0f); - } - - /* - ** Mark this job - */ - cp->host_status = HS_BUSY; - cp->s_status = SCSI_STATUS_CHECK_COND; - np->target[cp->ccb->ccb_h.target_id].hold_cp = cp; - - /* - ** And patch code to restart it. - */ - WRITESCRIPT(start0[0], SCR_INT); - break; - -/*----------------------------------------------------------------------------- -** -** Was Sie schon immer ueber transfermode negotiation wissen wollten ... -** -** We try to negotiate sync and wide transfer only after -** a successful inquire command. We look at byte 7 of the -** inquire data to determine the capabilities if the target. -** -** When we try to negotiate, we append the negotiation message -** to the identify and (maybe) simple tag message. -** The host status field is set to HS_NEGOTIATE to mark this -** situation. -** -** If the target doesn't answer this message immediately -** (as required by the standard), the SIR_NEGO_FAIL interrupt -** will be raised eventually. -** The handler removes the HS_NEGOTIATE status, and sets the -** negotiated value to the default (async / nowide). -** -** If we receive a matching answer immediately, we check it -** for validity, and set the values. -** -** If we receive a Reject message immediately, we assume the -** negotiation has failed, and fall back to standard values. -** -** If we receive a negotiation message while not in HS_NEGOTIATE -** state, it's a target initiated negotiation. We prepare a -** (hopefully) valid answer, set our parameters, and send back -** this answer to the target. -** -** If the target doesn't fetch the answer (no message out phase), -** we assume the negotiation has failed, and fall back to default -** settings. -** -** When we set the values, we adjust them in all nccbs belonging -** to this target, in the controller's register, and in the "phys" -** field of the controller's struct ncb. -** -** Possible cases: hs sir msg_in value send goto -** We try try to negotiate: -** -> target doesnt't msgin NEG FAIL noop defa. - dispatch -** -> target rejected our msg NEG FAIL reject defa. - dispatch -** -> target answered (ok) NEG SYNC sdtr set - clrack -** -> target answered (!ok) NEG SYNC sdtr defa. REJ--->msg_bad -** -> target answered (ok) NEG WIDE wdtr set - clrack -** -> target answered (!ok) NEG WIDE wdtr defa. REJ--->msg_bad -** -> any other msgin NEG FAIL noop defa. - dispatch -** -** Target tries to negotiate: -** -> incoming message --- SYNC sdtr set SDTR - -** -> incoming message --- WIDE wdtr set WDTR - -** We sent our answer: -** -> target doesn't msgout --- PROTO ? defa. - dispatch -** -**----------------------------------------------------------------------------- -*/ - - case SIR_NEGO_FAILED: - /*------------------------------------------------------- - ** - ** Negotiation failed. - ** Target doesn't send an answer message, - ** or target rejected our message. - ** - ** Remove negotiation request. - ** - **------------------------------------------------------- - */ - OUTB (HS_PRT, HS_BUSY); - - /* FALLTHROUGH */ - - case SIR_NEGO_PROTO: - /*------------------------------------------------------- - ** - ** Negotiation failed. - ** Target doesn't fetch the answer message. - ** - **------------------------------------------------------- - */ - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->ccb); - printf ("negotiation failed sir=%x status=%x.\n", - num, cp->nego_status); - } - - /* - ** any error in negotiation: - ** fall back to default mode. - */ - switch (cp->nego_status) { - - case NS_SYNC: - ncr_setsync (np, cp, 0, 0xe0, 0); - break; - - case NS_WIDE: - ncr_setwide (np, cp, 0, 0); - break; - - } - np->msgin [0] = MSG_NOOP; - np->msgout[0] = MSG_NOOP; - cp->nego_status = 0; - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch)); - break; - - case SIR_NEGO_SYNC: - /* - ** Synchronous request message received. - */ - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->ccb); - printf ("sync msgin: "); - (void) ncr_show_msg (np->msgin); - printf (".\n"); - } - - /* - ** get requested values. - */ - - chg = 0; - per = np->msgin[3]; - ofs = np->msgin[4]; - if (ofs==0) per=255; - - /* - ** check values against driver limits. - */ - if (per < np->minsync) - {chg = 1; per = np->minsync;} - if (per < tp->tinfo.user.period) - {chg = 1; per = tp->tinfo.user.period;} - if (ofs > tp->tinfo.user.offset) - {chg = 1; ofs = tp->tinfo.user.offset;} - - /* - ** Check against controller limits. - */ - - fak = 7; - scntl3 = 0; - if (ofs != 0) { - ncr_getsync(np, per, &fak, &scntl3); - if (fak > 7) { - chg = 1; - ofs = 0; - } - } - if (ofs == 0) { - fak = 7; - per = 0; - scntl3 = 0; - } - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->ccb); - printf ("sync: per=%d scntl3=0x%x ofs=%d fak=%d chg=%d.\n", - per, scntl3, ofs, fak, chg); - } - - if (INB (HS_PRT) == HS_NEGOTIATE) { - OUTB (HS_PRT, HS_BUSY); - switch (cp->nego_status) { - - case NS_SYNC: - /* - ** This was an answer message - */ - if (chg) { - /* - ** Answer wasn't acceptable. - */ - ncr_setsync (np, cp, 0, 0xe0, 0); - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad)); - } else { - /* - ** Answer is ok. - */ - ncr_setsync (np,cp,scntl3,(fak<<5)|ofs, per); - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack)); - } - return; - - case NS_WIDE: - ncr_setwide (np, cp, 0, 0); - break; - } - } - - /* - ** It was a request. Set value and - ** prepare an answer message - */ - - ncr_setsync (np, cp, scntl3, (fak<<5)|ofs, per); - - np->msgout[0] = MSG_EXTENDED; - np->msgout[1] = 3; - np->msgout[2] = MSG_EXT_SDTR; - np->msgout[3] = per; - np->msgout[4] = ofs; - - cp->nego_status = NS_SYNC; - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->ccb); - printf ("sync msgout: "); - (void) ncr_show_msg (np->msgout); - printf (".\n"); - } - - if (!ofs) { - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad)); - return; - } - np->msgin [0] = MSG_NOOP; - - break; - - case SIR_NEGO_WIDE: - /* - ** Wide request message received. - */ - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->ccb); - printf ("wide msgin: "); - (void) ncr_show_msg (np->msgin); - printf (".\n"); - } - - /* - ** get requested values. - */ - - chg = 0; - wide = np->msgin[3]; - - /* - ** check values against driver limits. - */ - - if (wide > tp->tinfo.user.width) - {chg = 1; wide = tp->tinfo.user.width;} - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->ccb); - printf ("wide: wide=%d chg=%d.\n", wide, chg); - } - - if (INB (HS_PRT) == HS_NEGOTIATE) { - OUTB (HS_PRT, HS_BUSY); - switch (cp->nego_status) { - - case NS_WIDE: - /* - ** This was an answer message - */ - if (chg) { - /* - ** Answer wasn't acceptable. - */ - ncr_setwide (np, cp, 0, 1); - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad)); - } else { - /* - ** Answer is ok. - */ - ncr_setwide (np, cp, wide, 1); - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, clrack)); - } - return; - - case NS_SYNC: - ncr_setsync (np, cp, 0, 0xe0, 0); - break; - } - } - - /* - ** It was a request, set value and - ** prepare an answer message - */ - - ncr_setwide (np, cp, wide, 1); - - np->msgout[0] = MSG_EXTENDED; - np->msgout[1] = 2; - np->msgout[2] = MSG_EXT_WDTR; - np->msgout[3] = wide; - - np->msgin [0] = MSG_NOOP; - - cp->nego_status = NS_WIDE; - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->ccb); - printf ("wide msgout: "); - (void) ncr_show_msg (np->msgout); - printf (".\n"); - } - break; - -/*-------------------------------------------------------------------- -** -** Processing of special messages -** -**-------------------------------------------------------------------- -*/ - - case SIR_REJECT_RECEIVED: - /*----------------------------------------------- - ** - ** We received a MSG_MESSAGE_REJECT message. - ** - **----------------------------------------------- - */ - - PRINT_ADDR(cp->ccb); - printf ("MSG_MESSAGE_REJECT received (%x:%x).\n", - (unsigned)np->lastmsg, np->msgout[0]); - break; - - case SIR_REJECT_SENT: - /*----------------------------------------------- - ** - ** We received an unknown message - ** - **----------------------------------------------- - */ - - PRINT_ADDR(cp->ccb); - printf ("MSG_MESSAGE_REJECT sent for "); - (void) ncr_show_msg (np->msgin); - printf (".\n"); - break; - -/*-------------------------------------------------------------------- -** -** Processing of special messages -** -**-------------------------------------------------------------------- -*/ - - case SIR_IGN_RESIDUE: - /*----------------------------------------------- - ** - ** We received an IGNORE RESIDUE message, - ** which couldn't be handled by the script. - ** - **----------------------------------------------- - */ - - PRINT_ADDR(cp->ccb); - printf ("MSG_IGN_WIDE_RESIDUE received, but not yet implemented.\n"); - break; - - case SIR_MISSING_SAVE: - /*----------------------------------------------- - ** - ** We received an DISCONNECT message, - ** but the datapointer wasn't saved before. - ** - **----------------------------------------------- - */ - - PRINT_ADDR(cp->ccb); - printf ("MSG_DISCONNECT received, but datapointer not saved:\n" - "\tdata=%x save=%x goal=%x.\n", - (unsigned) INL (nc_temp), - (unsigned) np->header.savep, - (unsigned) np->header.goalp); - break; - -/*-------------------------------------------------------------------- -** -** Processing of a "SCSI_STATUS_QUEUE_FULL" status. -** -** XXX JGibbs - We should do the same thing for BUSY status. -** -** The current command has been rejected, -** because there are too many in the command queue. -** We have started too many commands for that target. -** -**-------------------------------------------------------------------- -*/ - case SIR_STALL_QUEUE: - cp->xerr_status = XE_OK; - cp->host_status = HS_COMPLETE; - cp->s_status = SCSI_STATUS_QUEUE_FULL; - ncr_freeze_devq(np, cp->ccb->ccb_h.path); - ncr_complete(np, cp); - - /* FALLTHROUGH */ - - case SIR_STALL_RESTART: - /*----------------------------------------------- - ** - ** Enable selecting again, - ** if NO disconnected jobs. - ** - **----------------------------------------------- - */ - /* - ** Look for a disconnected job. - */ - cp = np->link_nccb; - while (cp && cp->host_status != HS_DISCONNECT) - cp = cp->link_nccb; - - /* - ** if there is one, ... - */ - if (cp) { - /* - ** wait for reselection - */ - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, reselect)); - return; - } - - /* - ** else remove the interrupt. - */ - - device_printf(np->dev, "queue empty.\n"); - WRITESCRIPT(start1[0], SCR_INT ^ IFFALSE (0)); - break; - } - -out: - OUTB (nc_dcntl, np->rv_dcntl | STD); -} - -/*========================================================== -** -** -** Acquire a control block -** -** -**========================================================== -*/ - -static nccb_p ncr_get_nccb - (ncb_p np, u_long target, u_long lun) -{ - lcb_p lp; - nccb_p cp = NULL; - - /* - ** Lun structure available ? - */ - - lp = np->target[target].lp[lun]; - if (lp) { - cp = lp->next_nccb; - - /* - ** Look for free CCB - */ - - while (cp && cp->magic) { - cp = cp->next_nccb; - } - } - - /* - ** if nothing available, create one. - */ - - if (cp == NULL) - cp = ncr_alloc_nccb(np, target, lun); - - if (cp != NULL) { - if (cp->magic) { - device_printf(np->dev, "Bogus free cp found\n"); - return (NULL); - } - cp->magic = 1; - } - return (cp); -} - -/*========================================================== -** -** -** Release one control block -** -** -**========================================================== -*/ - -static void ncr_free_nccb (ncb_p np, nccb_p cp) -{ - /* - ** sanity - */ - - assert (cp != NULL); - - cp -> host_status = HS_IDLE; - cp -> magic = 0; -} - -/*========================================================== -** -** -** Allocation of resources for Targets/Luns/Tags. -** -** -**========================================================== -*/ - -static nccb_p -ncr_alloc_nccb (ncb_p np, u_long target, u_long lun) -{ - tcb_p tp; - lcb_p lp; - nccb_p cp; - - assert (np != NULL); - - if (target>=MAX_TARGET) return(NULL); - if (lun >=MAX_LUN ) return(NULL); - - tp=&np->target[target]; - - if (!tp->jump_tcb.l_cmd) { - - /* - ** initialize it. - */ - tp->jump_tcb.l_cmd = (SCR_JUMP^IFFALSE (DATA (0x80 + target))); - tp->jump_tcb.l_paddr = np->jump_tcb.l_paddr; - - tp->getscr[0] = - (np->features & FE_PFEN)? SCR_COPY(1) : SCR_COPY_F(1); - tp->getscr[1] = vtophys (&tp->tinfo.sval); - tp->getscr[2] = rman_get_start(np->reg_res) + offsetof (struct ncr_reg, nc_sxfer); - tp->getscr[3] = - (np->features & FE_PFEN)? SCR_COPY(1) : SCR_COPY_F(1); - tp->getscr[4] = vtophys (&tp->tinfo.wval); - tp->getscr[5] = rman_get_start(np->reg_res) + offsetof (struct ncr_reg, nc_scntl3); - - assert (((offsetof(struct ncr_reg, nc_sxfer) ^ - (offsetof(struct tcb ,tinfo) - + offsetof(struct ncr_target_tinfo, sval))) & 3) == 0); - assert (((offsetof(struct ncr_reg, nc_scntl3) ^ - (offsetof(struct tcb, tinfo) - + offsetof(struct ncr_target_tinfo, wval))) &3) == 0); - - tp->call_lun.l_cmd = (SCR_CALL); - tp->call_lun.l_paddr = NCB_SCRIPT_PHYS (np, resel_lun); - - tp->jump_lcb.l_cmd = (SCR_JUMP); - tp->jump_lcb.l_paddr = NCB_SCRIPTH_PHYS (np, abort); - np->jump_tcb.l_paddr = vtophys (&tp->jump_tcb); - } - - /* - ** Logic unit control block - */ - lp = tp->lp[lun]; - if (!lp) { - /* - ** Allocate a lcb - */ - lp = (lcb_p) malloc (sizeof (struct lcb), M_DEVBUF, - M_NOWAIT | M_ZERO); - if (!lp) return(NULL); - - /* - ** Initialize it - */ - lp->jump_lcb.l_cmd = (SCR_JUMP ^ IFFALSE (DATA (lun))); - lp->jump_lcb.l_paddr = tp->jump_lcb.l_paddr; - - lp->call_tag.l_cmd = (SCR_CALL); - lp->call_tag.l_paddr = NCB_SCRIPT_PHYS (np, resel_tag); - - lp->jump_nccb.l_cmd = (SCR_JUMP); - lp->jump_nccb.l_paddr = NCB_SCRIPTH_PHYS (np, aborttag); - - lp->actlink = 1; - - /* - ** Chain into LUN list - */ - tp->jump_lcb.l_paddr = vtophys (&lp->jump_lcb); - tp->lp[lun] = lp; - - } - - /* - ** Allocate a nccb - */ - cp = (nccb_p) malloc (sizeof (struct nccb), M_DEVBUF, M_NOWAIT|M_ZERO); - - if (!cp) - return (NULL); - - if (DEBUG_FLAGS & DEBUG_ALLOC) { - printf ("new nccb @%p.\n", cp); - } - - /* - ** Fill in physical addresses - */ - - cp->p_nccb = vtophys (cp); - - /* - ** Chain into reselect list - */ - cp->jump_nccb.l_cmd = SCR_JUMP; - cp->jump_nccb.l_paddr = lp->jump_nccb.l_paddr; - lp->jump_nccb.l_paddr = CCB_PHYS (cp, jump_nccb); - cp->call_tmp.l_cmd = SCR_CALL; - cp->call_tmp.l_paddr = NCB_SCRIPT_PHYS (np, resel_tmp); - - /* - ** Chain into wakeup list - */ - cp->link_nccb = np->link_nccb; - np->link_nccb = cp; - - /* - ** Chain into CCB list - */ - cp->next_nccb = lp->next_nccb; - lp->next_nccb = cp; - - return (cp); -} - -/*========================================================== -** -** -** Build Scatter Gather Block -** -** -**========================================================== -** -** The transfer area may be scattered among -** several non adjacent physical pages. -** -** We may use MAX_SCATTER blocks. -** -**---------------------------------------------------------- -*/ - -static int ncr_scatter - (struct dsb* phys, vm_offset_t vaddr, vm_size_t datalen) -{ - u_long paddr, pnext; - - u_short segment = 0; - u_long segsize, segaddr; - u_long size, csize = 0; - u_long chunk = MAX_SIZE; - int free; - - bzero (&phys->data, sizeof (phys->data)); - if (!datalen) return (0); - - paddr = vtophys (vaddr); - - /* - ** insert extra break points at a distance of chunk. - ** We try to reduce the number of interrupts caused - ** by unexpected phase changes due to disconnects. - ** A typical harddisk may disconnect before ANY block. - ** If we wanted to avoid unexpected phase changes at all - ** we had to use a break point every 512 bytes. - ** Of course the number of scatter/gather blocks is - ** limited. - */ - - free = MAX_SCATTER - 1; - - if (vaddr & PAGE_MASK) free -= datalen / PAGE_SIZE; - - if (free>1) - while ((chunk * free >= 2 * datalen) && (chunk>=1024)) - chunk /= 2; - - if(DEBUG_FLAGS & DEBUG_SCATTER) - printf("ncr?:\tscattering virtual=%p size=%d chunk=%d.\n", - (void *) vaddr, (unsigned) datalen, (unsigned) chunk); - - /* - ** Build data descriptors. - */ - while (datalen && (segment < MAX_SCATTER)) { - - /* - ** this segment is empty - */ - segsize = 0; - segaddr = paddr; - pnext = paddr; - - if (!csize) csize = chunk; - - while ((datalen) && (paddr == pnext) && (csize)) { - - /* - ** continue this segment - */ - pnext = (paddr & (~PAGE_MASK)) + PAGE_SIZE; - - /* - ** Compute max size - */ - - size = pnext - paddr; /* page size */ - if (size > datalen) size = datalen; /* data size */ - if (size > csize ) size = csize ; /* chunksize */ - - segsize += size; - vaddr += size; - csize -= size; - datalen -= size; - paddr = vtophys (vaddr); - } - - if(DEBUG_FLAGS & DEBUG_SCATTER) - printf ("\tseg #%d addr=%x size=%d (rest=%d).\n", - segment, - (unsigned) segaddr, - (unsigned) segsize, - (unsigned) datalen); - - phys->data[segment].addr = segaddr; - phys->data[segment].size = segsize; - segment++; - } - - if (datalen) { - printf("ncr?: scatter/gather failed (residue=%d).\n", - (unsigned) datalen); - return (-1); - } - - return (segment); -} - -/*========================================================== -** -** -** Test the pci bus snoop logic :-( -** -** Has to be called with interrupts disabled. -** -** -**========================================================== -*/ - -#ifndef NCR_IOMAPPED -static int ncr_regtest (struct ncb* np) -{ - register volatile u_int32_t data; - /* - ** ncr registers may NOT be cached. - ** write 0xffffffff to a read only register area, - ** and try to read it back. - */ - data = 0xffffffff; - OUTL_OFF(offsetof(struct ncr_reg, nc_dstat), data); - data = INL_OFF(offsetof(struct ncr_reg, nc_dstat)); -#if 1 - if (data == 0xffffffff) { -#else - if ((data & 0xe2f0fffd) != 0x02000080) { -#endif - printf ("CACHE TEST FAILED: reg dstat-sstat2 readback %x.\n", - (unsigned) data); - return (0x10); - } - return (0); -} -#endif - -static int ncr_snooptest (struct ncb* np) -{ - u_int32_t ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc; - int i, err=0; -#ifndef NCR_IOMAPPED - err |= ncr_regtest (np); - if (err) return (err); -#endif - /* - ** init - */ - pc = NCB_SCRIPTH_PHYS (np, snooptest); - host_wr = 1; - ncr_wr = 2; - /* - ** Set memory and register. - */ - ncr_cache = host_wr; - OUTL (nc_temp, ncr_wr); - /* - ** Start script (exchange values) - */ - OUTL (nc_dsp, pc); - /* - ** Wait 'til done (with timeout) - */ - for (i=0; i=NCR_SNOOP_TIMEOUT) { - printf ("CACHE TEST FAILED: timeout.\n"); - return (0x20); - } - /* - ** Check termination position. - */ - if (pc != NCB_SCRIPTH_PHYS (np, snoopend)+8) { - printf ("CACHE TEST FAILED: script execution failed.\n"); - printf ("start=%08lx, pc=%08lx, end=%08lx\n", - (u_long) NCB_SCRIPTH_PHYS (np, snooptest), (u_long) pc, - (u_long) NCB_SCRIPTH_PHYS (np, snoopend) +8); - return (0x40); - } - /* - ** Show results. - */ - if (host_wr != ncr_rd) { - printf ("CACHE TEST FAILED: host wrote %d, ncr read %d.\n", - (int) host_wr, (int) ncr_rd); - err |= 1; - } - if (host_rd != ncr_wr) { - printf ("CACHE TEST FAILED: ncr wrote %d, host read %d.\n", - (int) ncr_wr, (int) host_rd); - err |= 2; - } - if (ncr_bk != ncr_wr) { - printf ("CACHE TEST FAILED: ncr wrote %d, read back %d.\n", - (int) ncr_wr, (int) ncr_bk); - err |= 4; - } - return (err); -} - -/*========================================================== -** -** -** Profiling the drivers and targets performance. -** -** -**========================================================== -*/ - -/* -** Compute the difference in milliseconds. -**/ - -static int ncr_delta (int *from, int *to) -{ - if (!from) return (-1); - if (!to) return (-2); - return ((to - from) * 1000 / hz); -} - -#define PROFILE cp->phys.header.stamp -static void ncb_profile (ncb_p np, nccb_p cp) -{ - int co, da, st, en, di, se, post,work,disc; - u_long diff; - - PROFILE.end = ticks; - - st = ncr_delta (&PROFILE.start,&PROFILE.status); - if (st<0) return; /* status not reached */ - - da = ncr_delta (&PROFILE.start,&PROFILE.data); - if (da<0) return; /* No data transfer phase */ - - co = ncr_delta (&PROFILE.start,&PROFILE.command); - if (co<0) return; /* command not executed */ - - en = ncr_delta (&PROFILE.start,&PROFILE.end), - di = ncr_delta (&PROFILE.start,&PROFILE.disconnect), - se = ncr_delta (&PROFILE.start,&PROFILE.select); - post = en - st; - - /* - ** @PROFILE@ Disconnect time invalid if multiple disconnects - */ - - if (di>=0) disc = se-di; else disc = 0; - - work = (st - co) - disc; - - diff = (np->disc_phys - np->disc_ref) & 0xff; - np->disc_ref += diff; - - np->profile.num_trans += 1; - if (cp->ccb) - np->profile.num_bytes += cp->ccb->csio.dxfer_len; - np->profile.num_disc += diff; - np->profile.ms_setup += co; - np->profile.ms_data += work; - np->profile.ms_disc += disc; - np->profile.ms_post += post; -} -#undef PROFILE - -/*========================================================== -** -** Determine the ncr's clock frequency. -** This is essential for the negotiation -** of the synchronous transfer rate. -** -**========================================================== -** -** Note: we have to return the correct value. -** THERE IS NO SAVE DEFAULT VALUE. -** -** Most NCR/SYMBIOS boards are delivered with a 40 Mhz clock. -** 53C860 and 53C875 rev. 1 support fast20 transfers but -** do not have a clock doubler and so are provided with a -** 80 MHz clock. All other fast20 boards incorporate a doubler -** and so should be delivered with a 40 MHz clock. -** The future fast40 chips (895/895) use a 40 Mhz base clock -** and provide a clock quadrupler (160 Mhz). The code below -** tries to deal as cleverly as possible with all this stuff. -** -**---------------------------------------------------------- -*/ - -/* - * Select NCR SCSI clock frequency - */ -static void ncr_selectclock(ncb_p np, u_char scntl3) -{ - if (np->multiplier < 2) { - OUTB(nc_scntl3, scntl3); - return; - } - - if (bootverbose >= 2) - device_printf(np->dev, "enabling clock multiplier\n"); - - OUTB(nc_stest1, DBLEN); /* Enable clock multiplier */ - if (np->multiplier > 2) { /* Poll bit 5 of stest4 for quadrupler */ - int i = 20; - while (!(INB(nc_stest4) & LCKFRQ) && --i > 0) - DELAY(20); - if (!i) - device_printf(np->dev, - "the chip cannot lock the frequency\n"); - } else /* Wait 20 micro-seconds for doubler */ - DELAY(20); - OUTB(nc_stest3, HSC); /* Halt the scsi clock */ - OUTB(nc_scntl3, scntl3); - OUTB(nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */ - OUTB(nc_stest3, 0x00); /* Restart scsi clock */ -} - -/* - * 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<= 2) - 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, u_char multiplier) -{ - unsigned char scntl3; - unsigned char stest1; - scntl3 = INB(nc_scntl3); - stest1 = INB(nc_stest1); - - np->multiplier = 1; - - if (multiplier > 1) { - np->multiplier = multiplier; - np->clock_khz = 40000 * multiplier; - } 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 >= 2) - 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 */ - } - } - else if ((scntl3 & 7) == 5) - np->clock_khz = 80000; /* Probably a 875 rev. 1 ? */ - } -} - -/*=========================================================================*/ - -#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 */ - -static device_method_t ncr_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ncr_probe), - DEVMETHOD(device_attach, ncr_attach), - - { 0, 0 } -}; - -static driver_t ncr_driver = { - "ncr", - ncr_methods, - sizeof(struct ncb), -}; - -static devclass_t ncr_devclass; - -DRIVER_MODULE(ncr, pci, ncr_driver, ncr_devclass, 0, 0); -MODULE_PNP_INFO("W32:vendor/device;U16:#;D:#", pci, ncr, ncr_chip_table, - nitems(ncr_chip_table)); -MODULE_DEPEND(ncr, cam, 1, 1, 1); -MODULE_DEPEND(ncr, pci, 1, 1, 1); - -/*=========================================================================*/ -#endif /* _KERNEL */ diff --git a/sys/dev/ncr/ncrreg.h b/sys/dev/ncr/ncrreg.h deleted file mode 100644 index 34f1618f8d49..000000000000 --- a/sys/dev/ncr/ncrreg.h +++ /dev/null @@ -1,574 +0,0 @@ -/************************************************************************** -** -** $FreeBSD$ -** -** Device driver for the NCR 53C810 PCI-SCSI-Controller. -** -** 386bsd / FreeBSD / NetBSD -** -**------------------------------------------------------------------------- -** -** Written for 386bsd and FreeBSD by -** wolf@cologne.de Wolfgang Stanglmeier -** se@mi.Uni-Koeln.de Stefan Esser -** -** Ported to NetBSD by -** mycroft@gnu.ai.mit.edu -** -**------------------------------------------------------------------------- -*/ -/*- -** Copyright (c) 1994 Wolfgang Stanglmeier. All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -** -*************************************************************************** -*/ - -#ifndef __NCR_REG_H__ -#define __NCR_REG_H__ - -/*----------------------------------------------------------------- -** -** The ncr 53c810 register structure. -** -**----------------------------------------------------------------- -*/ - -struct ncr_reg { -/*00*/ u_char nc_scntl0; /* full arb., ena parity, par->ATN */ - -/*01*/ u_char nc_scntl1; /* no reset */ - #define ISCON 0x10 /* connected to scsi */ - #define CRST 0x08 /* force reset */ - -/*02*/ u_char nc_scntl2; /* no disconnect expected */ - #define SDU 0x80 /* cmd: disconnect will raise error */ - #define CHM 0x40 /* sta: chained mode */ - #define WSS 0x08 /* sta: wide scsi send [W]*/ - #define WSR 0x01 /* sta: wide scsi received [W]*/ - -/*03*/ u_char nc_scntl3; /* cnf system clock dependent */ - #define EWS 0x08 /* cmd: enable wide scsi [W]*/ - -/*04*/ u_char nc_scid; /* cnf host adapter scsi address */ - #define RRE 0x40 /* r/w:e enable response to resel. */ - #define SRE 0x20 /* r/w:e enable response to select */ - -/*05*/ u_char nc_sxfer; /* ### Sync speed and count */ - -/*06*/ u_char nc_sdid; /* ### Destination-ID */ - -/*07*/ u_char nc_gpreg; /* ??? IO-Pins */ - -/*08*/ u_char nc_sfbr; /* ### First byte in phase */ - -/*09*/ u_char nc_socl; - #define CREQ 0x80 /* r/w: SCSI-REQ */ - #define CACK 0x40 /* r/w: SCSI-ACK */ - #define CBSY 0x20 /* r/w: SCSI-BSY */ - #define CSEL 0x10 /* r/w: SCSI-SEL */ - #define CATN 0x08 /* r/w: SCSI-ATN */ - #define CMSG 0x04 /* r/w: SCSI-MSG */ - #define CC_D 0x02 /* r/w: SCSI-C_D */ - #define CI_O 0x01 /* r/w: SCSI-I_O */ - -/*0a*/ u_char nc_ssid; - -/*0b*/ u_char nc_sbcl; - -/*0c*/ u_char nc_dstat; - #define DFE 0x80 /* sta: dma fifo empty */ - #define MDPE 0x40 /* int: master data parity error */ - #define BF 0x20 /* int: script: bus fault */ - #define ABRT 0x10 /* int: script: command aborted */ - #define SSI 0x08 /* int: script: single step */ - #define SIR 0x04 /* int: script: interrupt instruct. */ - #define IID 0x01 /* int: script: illegal instruct. */ - -/*0d*/ u_char nc_sstat0; - #define ILF 0x80 /* sta: data in SIDL register lsb */ - #define ORF 0x40 /* sta: data in SODR register lsb */ - #define OLF 0x20 /* sta: data in SODL register lsb */ - #define AIP 0x10 /* sta: arbitration in progress */ - #define LOA 0x08 /* sta: arbitration lost */ - #define WOA 0x04 /* sta: arbitration won */ - #define IRST 0x02 /* sta: scsi reset signal */ - #define SDP 0x01 /* sta: scsi parity signal */ - -/*0e*/ u_char nc_sstat1; - #define FF3210 0xf0 /* sta: bytes in the scsi fifo */ - -/*0f*/ u_char nc_sstat2; - #define ILF1 0x80 /* sta: data in SIDL register msb[W]*/ - #define ORF1 0x40 /* sta: data in SODR register msb[W]*/ - #define OLF1 0x20 /* sta: data in SODL register msb[W]*/ - #define LDSC 0x02 /* sta: disconnect & reconnect */ - -/*10*/ u_int32_t nc_dsa; /* --> Base page */ - -/*14*/ u_char nc_istat; /* --> Main Command and status */ - #define CABRT 0x80 /* cmd: abort current operation */ - #define SRST 0x40 /* mod: reset chip */ - #define SIGP 0x20 /* r/w: message from host to ncr */ - #define SEM 0x10 /* r/w: message between host + ncr */ - #define CON 0x08 /* sta: connected to scsi */ - #define INTF 0x04 /* sta: int on the fly (reset by wr)*/ - #define SIP 0x02 /* sta: scsi-interrupt */ - #define DIP 0x01 /* sta: host/script interrupt */ - -/*15*/ u_char nc_15_; -/*16*/ u_char nc_16_; -/*17*/ u_char nc_17_; - -/*18*/ u_char nc_ctest0; -/*19*/ u_char nc_ctest1; - -/*1a*/ u_char nc_ctest2; - #define CSIGP 0x40 - -/*1b*/ u_char nc_ctest3; - #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_int32_t 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; - #define DFS 0x20 /* mod: dma fifo size */ -/*23*/ u_char nc_ctest6; - -/*24*/ u_int32_t nc_dbc; /* ### Byte count and command */ -/*28*/ u_int32_t nc_dnad; /* ### Next command register */ -/*2c*/ u_int32_t nc_dsp; /* --> Script Pointer */ -/*30*/ u_int32_t nc_dsps; /* --> Script pointer save/opcode#2 */ -/*34*/ u_int32_t 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_int32_t nc_adder; - -/*40*/ u_short nc_sien; /* -->: interrupt enable */ -/*42*/ u_short nc_sist; /* <--: interrupt status */ - #define STO 0x0400/* sta: timeout (select) */ - #define GEN 0x0200/* sta: timeout (general) */ - #define HTH 0x0100/* sta: timeout (handshake) */ - #define MA 0x80 /* sta: phase mismatch */ - #define CMP 0x40 /* sta: arbitration complete */ - #define SEL 0x20 /* sta: selected by another device */ - #define RSL 0x10 /* sta: reselected by another device*/ - #define SGE 0x08 /* sta: gross error (over/underflow)*/ - #define UDC 0x04 /* sta: unexpected disconnect */ - #define RST 0x02 /* sta: scsi bus reset detected */ - #define PAR 0x01 /* sta: scsi parity error */ - -/*44*/ u_char nc_slpar; -/*45*/ u_char nc_swide; -/*46*/ u_char nc_macntl; -/*47*/ u_char nc_gpcntl; -/*48*/ u_char nc_stime0; /* cmd: timeout for select&handshake*/ -/*49*/ u_char nc_stime1; /* cmd: timeout user defined */ -/*4a*/ u_short nc_respid; /* sta: Reselect-IDs */ - -/*4c*/ u_char nc_stest0; - -/*4d*/ u_char nc_stest1; - #define DBLEN 0x08 /* clock doubler running */ - #define DBLSEL 0x04 /* clock doubler selected */ - -/*4e*/ u_char nc_stest2; - #define ROF 0x40 /* reset scsi offset (after gross error!) */ - #define EXT 0x02 /* extended filtering */ - -/*4f*/ u_char nc_stest3; - #define TE 0x80 /* c: tolerAnt enable */ - #define HSC 0x20 /* c: Halt SCSI Clock */ - #define CSF 0x02 /* c: clear scsi fifo */ - -/*50*/ u_short nc_sidl; /* Lowlevel: latched from scsi data */ -/*52*/ u_char nc_stest4; - #define SMODE 0xc0 /* SCSI bus mode (895/6 only) */ - #define SMODE_HVD 0x40 /* High Voltage Differential */ - #define SMODE_SE 0x80 /* Single Ended */ - #define SMODE_LVD 0xc0 /* Low Voltage Differential */ - #define LCKFRQ 0x20 /* Frequency Lock (895/6 only) */ - -/*53*/ u_char nc_53_; -/*54*/ u_short nc_sodl; /* Lowlevel: data out to scsi data */ -/*56*/ u_short nc_56_; -/*58*/ u_short nc_sbdl; /* Lowlevel: data from scsi data */ -/*5a*/ u_short nc_5a_; -/*5c*/ u_char nc_scr0; /* Working register B */ -/*5d*/ u_char nc_scr1; /* */ -/*5e*/ u_char nc_scr2; /* */ -/*5f*/ u_char nc_scr3; /* */ -/*60*/ -}; - -/*----------------------------------------------------------- -** -** Utility macros for the script. -** -**----------------------------------------------------------- -*/ - -#define REGJ(p,r) (offsetof(struct ncr_reg, p ## r)) -#define REG(r) REGJ (nc_, r) - -#ifndef TARGET_MODE -#define TARGET_MODE 0 -#endif - -typedef u_int32_t ncrcmd; - -/*----------------------------------------------------------- -** -** SCSI phases -** -**----------------------------------------------------------- -*/ - -#define SCR_DATA_OUT 0x00000000 -#define SCR_DATA_IN 0x01000000 -#define SCR_COMMAND 0x02000000 -#define SCR_STATUS 0x03000000 -#define SCR_ILG_OUT 0x04000000 -#define SCR_ILG_IN 0x05000000 -#define SCR_MSG_OUT 0x06000000 -#define SCR_MSG_IN 0x07000000 - -/*----------------------------------------------------------- -** -** Data transfer via SCSI. -** -**----------------------------------------------------------- -** -** MOVE_ABS (LEN) -** <> -** -** MOVE_IND (LEN) -** <> -** -** MOVE_TBL -** <> -** -**----------------------------------------------------------- -*/ - -#define SCR_MOVE_ABS(l) ((0x08000000 ^ (TARGET_MODE << 1ul)) | (l)) -#define SCR_MOVE_IND(l) ((0x28000000 ^ (TARGET_MODE << 1ul)) | (l)) -#define SCR_MOVE_TBL (0x18000000 ^ (TARGET_MODE << 1ul)) - -struct scr_tblmove { - u_int32_t size; - u_int32_t addr; -}; - -/*----------------------------------------------------------- -** -** Selection -** -**----------------------------------------------------------- -** -** SEL_ABS | SCR_ID (0..7) [ | REL_JMP] -** <> -** -** SEL_TBL | << dnad_offset>> [ | REL_JMP] -** <> -** -**----------------------------------------------------------- -*/ - -#define SCR_SEL_ABS 0x40000000 -#define SCR_SEL_ABS_ATN 0x41000000 -#define SCR_SEL_TBL 0x42000000 -#define SCR_SEL_TBL_ATN 0x43000000 - -struct scr_tblsel { - u_char sel_0; - u_char sel_sxfer; - u_char sel_id; - u_char sel_scntl3; -}; - -#define SCR_JMP_REL 0x04000000 -#define SCR_ID(id) (((u_int32_t)(id)) << 16) - -/*----------------------------------------------------------- -** -** Waiting for Disconnect or Reselect -** -**----------------------------------------------------------- -** -** WAIT_DISC -** dummy: <> -** -** WAIT_RESEL -** <> -** -**----------------------------------------------------------- -*/ - -#define SCR_WAIT_DISC 0x48000000 -#define SCR_WAIT_RESEL 0x50000000 - -/*----------------------------------------------------------- -** -** Bit Set / Reset -** -**----------------------------------------------------------- -** -** SET (flags {|.. }) -** -** CLR (flags {|.. }) -** -**----------------------------------------------------------- -*/ - -#define SCR_SET(f) (0x58000000 | (f)) -#define SCR_CLR(f) (0x60000000 | (f)) - -#define SCR_CARRY 0x00000400 -#define SCR_TRG 0x00000200 -#define SCR_ACK 0x00000040 -#define SCR_ATN 0x00000008 - - -/*----------------------------------------------------------- -** -** Memory to memory move -** -**----------------------------------------------------------- -** -** COPY (bytecount) -** << source_address >> -** << destination_address >> -** -** SCR_COPY sets the NO FLUSH option by default. -** SCR_COPY_F does not set this option. -** -** For chips which do not support this option, -** ncr_copy_and_bind() will remove this bit. -**----------------------------------------------------------- -*/ - -#define SCR_NO_FLUSH 0x01000000 - -#define SCR_COPY(n) (0xc0000000 | SCR_NO_FLUSH | (n)) -#define SCR_COPY_F(n) (0xc0000000 | (n)) - - -/*----------------------------------------------------------- -** -** Register move and binary operations -** -**----------------------------------------------------------- -** -** SFBR_REG (reg, op, data) reg = SFBR op data -** << 0 >> -** -** REG_SFBR (reg, op, data) SFBR = reg op data -** << 0 >> -** -** REG_REG (reg, op, data) reg = reg op data -** << 0 >> -** -**----------------------------------------------------------- -*/ - -#define SCR_REG_OFS(ofs) ((ofs) << 16ul) - -#define SCR_SFBR_REG(reg,op,data) \ - (0x68000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul)) - -#define SCR_REG_SFBR(reg,op,data) \ - (0x70000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul)) - -#define SCR_REG_REG(reg,op,data) \ - (0x78000000 | (SCR_REG_OFS(REG(reg))) | (op) | ((data)<<8ul)) - - -#define SCR_LOAD 0x00000000 -#define SCR_SHL 0x01000000 -#define SCR_OR 0x02000000 -#define SCR_XOR 0x03000000 -#define SCR_AND 0x04000000 -#define SCR_SHR 0x05000000 -#define SCR_ADD 0x06000000 -#define SCR_ADDC 0x07000000 - -/*----------------------------------------------------------- -** -** FROM_REG (reg) reg = SFBR -** << 0 >> -** -** TO_REG (reg) SFBR = reg -** << 0 >> -** -** LOAD_REG (reg, data) reg = -** << 0 >> -** -** LOAD_SFBR(data) SFBR = -** << 0 >> -** -**----------------------------------------------------------- -*/ - -#define SCR_FROM_REG(reg) \ - SCR_REG_SFBR(reg,SCR_OR,0) - -#define SCR_TO_REG(reg) \ - SCR_SFBR_REG(reg,SCR_OR,0) - -#define SCR_LOAD_REG(reg,data) \ - SCR_REG_REG(reg,SCR_LOAD,data) - -#define SCR_LOAD_SFBR(data) \ - (SCR_REG_SFBR (gpreg, SCR_LOAD, data)) - -/*----------------------------------------------------------- -** -** Waiting for Disconnect or Reselect -** -**----------------------------------------------------------- -** -** JUMP [ | IFTRUE/IFFALSE ( ... ) ] -** <
> -** -** JUMPR [ | IFTRUE/IFFALSE ( ... ) ] -** <> -** -** CALL [ | IFTRUE/IFFALSE ( ... ) ] -** <
> -** -** CALLR [ | IFTRUE/IFFALSE ( ... ) ] -** <> -** -** RETURN [ | IFTRUE/IFFALSE ( ... ) ] -** <> -** -** INT [ | IFTRUE/IFFALSE ( ... ) ] -** <> -** -** INT_FLY [ | IFTRUE/IFFALSE ( ... ) ] -** <> -** -** Conditions: -** WHEN (phase) -** IF (phase) -** CARRY -** DATA (data, mask) -** -**----------------------------------------------------------- -*/ - -#define SCR_NO_OP 0x80000000 -#define SCR_JUMP 0x80080000 -#define SCR_JUMPR 0x80880000 -#define SCR_CALL 0x88080000 -#define SCR_CALLR 0x88880000 -#define SCR_RETURN 0x90080000 -#define SCR_INT 0x98080000 -#define SCR_INT_FLY 0x98180000 - -#define IFFALSE(arg) (0x00080000 | (arg)) -#define IFTRUE(arg) (0x00000000 | (arg)) - -#define WHEN(phase) (0x00030000 | (phase)) -#define IF(phase) (0x00020000 | (phase)) - -#define DATA(D) (0x00040000 | ((D) & 0xff)) -#define MASK(D,M) (0x00040000 | (((M ^ 0xff) & 0xff) << 8ul)|((D) & 0xff)) - -#define CARRYSET (0x00200000) - -/*----------------------------------------------------------- -** -** SCSI constants. -** -**----------------------------------------------------------- -*/ - -/* -** Messages -*/ -#define M_X_MODIFY_DP (0x00) - -/* -** Status -*/ -#define SCSI_STATUS_ILLEGAL (0xff) -#define SCSI_STATUS_SENSE (0x80) - -/* -** Bits defining chip features. -** For now only some of them are used, since we explicitely -** deal with PCI device id and revision id. -*/ -#define FE_LED0 (1<<0) -#define FE_WIDE (1<<1) -#define FE_ULTRA (1<<2) -#define FE_ULTRA2 (1<<3) -#define FE_DBLR (1<<4) -#define FE_QUAD (1<<5) -#define FE_ERL (1<<6) -#define FE_CLSE (1<<7) -#define FE_WRIE (1<<8) -#define FE_ERMP (1<<9) -#define FE_BOF (1<<10) -#define FE_DFS (1<<11) -#define FE_PFEN (1<<12) -#define FE_LDSTR (1<<13) -#define FE_RAM (1<<14) -#define FE_CLK80 (1<<15) -#define FE_DIFF (1<<16) -#define FE_BIOS (1<<17) -#define FE_CACHE_SET (FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP) -#define FE_SCSI_SET (FE_WIDE|FE_ULTRA|FE_ULTRA2|FE_DBLR|FE_QUAD|F_CLK80) -#define FE_SPECIAL_SET (FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM) - -#endif /*__NCR_REG_H__*/ diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index 1e8172ad5b8a..dd0abcf9adaf 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -132,8 +132,7 @@ device isp # Qlogic family device mpt # LSI-Logic MPT-Fusion device mps # LSI-Logic MPT-Fusion 2 device mpr # LSI-Logic MPT-Fusion 3 -#device ncr # NCR/Symbios Logic -device sym # NCR/Symbios Logic (newer chipsets + those of `ncr') +device sym # NCR/Symbios Logic device trm # Tekram DC395U/UW/F DC315U adapters device isci # Intel C600 SAS controller diff --git a/sys/i386/conf/PAE b/sys/i386/conf/PAE index 72543c4f6e29..07dfec58fd8e 100644 --- a/sys/i386/conf/PAE +++ b/sys/i386/conf/PAE @@ -17,6 +17,5 @@ nodevice hptmv nodevice ida # The following drivers don't work with PAE enabled. -makeoptions WITHOUT_MODULES+="ncr pst" -nodevice ncr +makeoptions WITHOUT_MODULES+="pst" nodevice pst diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 617b9b7c9e10..e31dc1bd5e51 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -266,7 +266,6 @@ SUBDIR= \ my \ ${_nandfs} \ ${_nandsim} \ - ${_ncr} \ ${_nctgpio} \ ${_ndis} \ ${_netgraph} \ @@ -751,7 +750,6 @@ _cp= cp _glxiic= glxiic _glxsb= glxsb #_ibcs2= ibcs2 -_ncr= ncr _pcfclock= pcfclock _pst= pst _sbni= sbni diff --git a/sys/modules/ncr/Makefile b/sys/modules/ncr/Makefile deleted file mode 100644 index a2060bf5c502..000000000000 --- a/sys/modules/ncr/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/ncr - -KMOD= ncr -SRCS= ncr.c -SRCS+= device_if.h bus_if.h pci_if.h opt_ncr.h opt_cam.h - -.include