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