diff options
author | Martin Reindl <martin@cvs.openbsd.org> | 2005-05-27 02:13:53 +0000 |
---|---|---|
committer | Martin Reindl <martin@cvs.openbsd.org> | 2005-05-27 02:13:53 +0000 |
commit | d7ac4e083fc8f819d24fc539bae884cda86c1f07 (patch) | |
tree | 8d3a9fb3a12be5a4e7596ed10f8e16ce493e075a /sys | |
parent | 068a09343f95deca53ce8a92e8b6a8669666f581 (diff) |
byebye ncr(4) and some vtophys
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/files.pci | 7 | ||||
-rw-r--r-- | sys/dev/pci/ncr.c | 8060 | ||||
-rw-r--r-- | sys/dev/pci/ncrreg.h | 665 | ||||
-rw-r--r-- | sys/dev/pci/ncrstat.c | 1629 |
4 files changed, 1 insertions, 10360 deletions
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index 38816fe419b..2441a6248e6 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $OpenBSD: files.pci,v 1.177 2005/05/24 05:57:36 ho Exp $ +# $OpenBSD: files.pci,v 1.178 2005/05/27 02:13:51 martin Exp $ # $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $ # # Config file and device description for machine-independent PCI code. @@ -198,11 +198,6 @@ file dev/pci/if_fpa.c fpa attach le at pci with le_pci file dev/pci/if_le_pci.c le_pci -# NCR 53c8xx SCSI chips -device ncr: scsi -attach ncr at pci -file dev/pci/ncr.c ncr - # common code for siop/esiop pci front end define siop_pci_common file dev/pci/siop_pci_common.c siop_pci_common diff --git a/sys/dev/pci/ncr.c b/sys/dev/pci/ncr.c deleted file mode 100644 index 589434d6b60..00000000000 --- a/sys/dev/pci/ncr.c +++ /dev/null @@ -1,8060 +0,0 @@ -/* $OpenBSD: ncr.c,v 1.72 2005/05/23 23:26:56 tedu Exp $ */ -/* $NetBSD: ncr.c,v 1.63 1997/09/23 02:39:15 perry Exp $ */ - -/************************************************************************** -** -** Id: ncr.c,v 1.112 1997/11/07 09:20:56 phk Exp -** -** Device driver for the NCR 53C8xx PCI-SCSI-Controller. -** -** FreeBSD / NetBSD / OpenBSD -** -**------------------------------------------------------------------------- -** -** Written for 386bsd and FreeBSD by -** Wolfgang Stanglmeier <wolf@cologne.de> -** Stefan Esser <se@mi.Uni-Koeln.de> -** -** Ported to NetBSD by -** Charles M. Hannum <mycroft@gnu.ai.mit.edu> -** -** Modified for big endian systems by -** Per Fogelstrom for RTMX Inc, North Carolina. <pefo@opsycon.se> -** -**------------------------------------------------------------------------- -** -** 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. -** -*************************************************************************** -*/ - -#define NCR_DATE "pl24 96/12/14" - -#define NCR_VERSION (2) -#define MAX_UNITS (16) - -#define NCR_GETCC_WITHMSG - -#if defined (__FreeBSD__) && defined(KERNEL) -#include "opt_ncr.h" -#endif /* defined (__FreeBSD__) && defined(KERNEL) */ - -#ifdef FAILSAFE -#ifndef SCSI_NCR_DFLT_TAGS -#define SCSI_NCR_DFLT_TAGS (0) -#endif /* SCSI_NCR_DFLT_TAGS */ -#define NCR_CDROM_ASYNC -#endif /* FAILSAFE */ - -/*========================================================== -** -** Configuration and Debugging -** -** May be overwritten in <arch/conf/xxxx> -** -**========================================================== -*/ - -/* -** 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 (10) -#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 */ - -/* -** The maximum number of tags per logic unit. -** Used only for disk devices that support tags. -*/ - -#ifndef SCSI_NCR_DFLT_TAGS -#define SCSI_NCR_DFLT_TAGS (4) -#endif /* SCSI_NCR_DFLT_TAGS */ - -/*========================================================== -** -** Configuration and Debugging -** -**========================================================== -*/ - -/* -** Number of targets supported by the driver. -** n permits target numbers 0..n-1. -** Default is 16, meaning targets #0..#15. -** #7 is the host adapter. -*/ - -#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. -*/ - -#ifndef MAX_START -#define MAX_START (256) -#endif - -/* -** 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. -*/ - -#ifdef __OpenBSD__ -#define MAX_SIZE ((MAX_SCATTER-1) * (long) NBPG) -#else -#define MAX_SIZE ((MAX_SCATTER-1) * (long) PAGE_SIZE) -#endif - -/* -** other -*/ - -#define NCR_SNOOP_TIMEOUT (1000000) - -/*========================================================== -** -** Include files -** -**========================================================== -*/ - -#ifdef __OpenBSD__ -#ifdef _KERNEL -#define KERNEL -#endif -#else -#include <stddef.h> -#endif - -#include <sys/param.h> -#include <sys/time.h> - -#ifdef KERNEL -#include <sys/systm.h> -#include <sys/malloc.h> -#include <sys/buf.h> -#include <sys/kernel.h> -#ifndef __OpenBSD__ -#include <sys/sysctl.h> -#include <machine/clock.h> -#else -#include <sys/timeout.h> -#endif -#include <uvm/uvm_extern.h> -#endif /* KERNEL */ - - -#ifndef __OpenBSD__ -#include <pci/pcivar.h> -#include <pci/pcireg.h> -#include <pci/ncrreg.h> -#else -#include <sys/device.h> -#include <machine/bus.h> -#include <machine/intr.h> -#include <dev/pci/ncrreg.h> -#include <dev/pci/pcireg.h> -#include <dev/pci/pcivar.h> -#if !defined(__alpha__) && !defined(__mips__) && !defined(__powerpc__) -#define DELAY(x) delay(x) -#endif -#include <scsi/scsi_all.h> -#endif /* __OpenBSD__ */ - -#include <scsi/scsiconf.h> - -#ifdef __OpenBSD__ -#define __BROKEN_INDIRECT_CONFIG -#ifdef NCR_VERBOSE -#define bootverbose NCR_VERBOSE -#else -#define bootverbose 0 -#endif -#endif - -#if !defined(NCR_KVATOPHYS) -#define NCR_KVATOPHYS(sc, va) vtophys(va) -#endif - -#if defined(__OpenBSD__) && defined(__alpha__) -/* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */ -#undef vtophys -#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)(va)) -#endif - -/*========================================================== -** -** 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 -** -**---------------------------------------------------------- -*/ - -#undef assert -#define assert(expression) { \ - if (!(expression)) { \ - (void)printf(\ - "assertion \"%s\" failed: file \"%s\", line %d\n", \ - #expression, \ - __FILE__, __LINE__); \ - } \ -} - -/*========================================================== -** -** Access to the controller chip. -** -**========================================================== -*/ - -#ifdef __OpenBSD__ - -#define INB(r) \ - INB_OFF(offsetof(struct ncr_reg, r)) -#define INB_OFF(o) \ - bus_space_read_1 (np->sc_st, np->sc_sh, (o)) -#define INW(r) \ - bus_space_read_2 (np->sc_st, np->sc_sh, offsetof(struct ncr_reg, r)) -#define INL(r) \ - INL_OFF(offsetof(struct ncr_reg, r)) -#define INL_OFF(o) \ - bus_space_read_4 (np->sc_st, np->sc_sh, (o)) - -#define OUTB(r, val) \ - bus_space_write_1 (np->sc_st, np->sc_sh, offsetof(struct ncr_reg, r), (val)) -#define OUTW(r, val) \ - bus_space_write_2 (np->sc_st, np->sc_sh, offsetof(struct ncr_reg, r), (val)) -#define OUTL(r, val) \ - OUTL_OFF(offsetof(struct ncr_reg, r), (val)) -#define OUTL_OFF(o, val) \ - bus_space_write_4 (np->sc_st, np->sc_sh, (o), (val)) - -#define READSCRIPT_OFF(base, off) \ - SCR_BO(base ? *((int32_t *)((char *)base + (off))) : \ - bus_space_read_4 (np->ram_tag, np->ram_handle, off)) - -#define WRITESCRIPT_OFF(base, off, val) \ - do { \ - if (base) \ - *((int32_t *)((char *)base + (off))) = (SCR_BO(val)); \ - else \ - bus_space_write_4 (np->ram_tag, np->ram_handle, off, SCR_BO(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) - -#else /* !__OpenBSD__ */ - -#ifdef NCR_IOMAPPED - -#define INB(r) inb (np->port + offsetof(struct ncr_reg, r)) -#define INB_OFF(o) inb (np->port + (o)) -#define INW(r) inw (np->port + offsetof(struct ncr_reg, r)) -#define INL(r) inl (np->port + offsetof(struct ncr_reg, r)) -#define INL_OFF(o) inl (np->port + (o)) - -#define OUTB(r, val) outb (np->port+offsetof(struct ncr_reg,r),(val)) -#define OUTW(r, val) outw (np->port+offsetof(struct ncr_reg,r),(val)) -#define OUTL(r, val) outl (np->port+offsetof(struct ncr_reg,r),(val)) -#define OUTL_OFF(o, val) outl (np->port+(o),(val)) - -#else - -#define INB(r) (np->reg->r) -#define INB_OFF(o) (*((volatile int8_t *)((char *)np->reg + (o)))) -#define INW(r) (np->reg->r) -#define INL(r) (np->reg->r) -#define INL_OFF(o) (*((volatile int32_t *)((char *)np->reg + (o)))) - -#define OUTB(r, val) np->reg->r = (val) -#define OUTW(r, val) np->reg->r = (val) -#define OUTL(r, val) np->reg->r = (val) -#define OUTL_OFF(o, val) *((volatile int32_t *)((char *)np->reg + (o))) = val - -#endif - -#define READSCRIPT_OFF(base, off) (*((int32_t *)((char *)base + (off)))) -#define READSCRIPT(r) (np->script->r) -#define WRITESCRIPT(r, val) np->script->r = (val) - -#endif /* __OpenBSD__ */ - -/* -** 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_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 ccb. -** -**========================================================== -*/ - -#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 ccb. -** -**========================================================== -*/ - -#define NS_SYNC (1) -#define NS_WIDE (2) - -/*========================================================== -** -** "Special features" of targets. -** quirks field of struct tcb. -** actualquirks field of struct ccb. -** -**========================================================== -*/ - -#define QUIRK_AUTOSAVE (0x01) -#define QUIRK_NOMSG (0x02) -#define QUIRK_NOSYNC (0x10) -#define QUIRK_NOWIDE16 (0x20) -#define QUIRK_NOTAGS (0x40) -#define QUIRK_UPDATE (0x80) - -/*========================================================== -** -** Capability bits in Inquire response byte 7. -** -**========================================================== -*/ - -#define INQ7_QUEUE (0x02) -#define INQ7_SYNC (0x10) -#define INQ7_WIDE16 (0x20) - -/*========================================================== -** -** Misc. -** -**========================================================== -*/ - -#define CCB_MAGIC (0xf2691ad2) -#define MAX_TAGS (16) /* hard limit */ - -/*========================================================== -** -** OS dependencies. -** -** Note that various types are defined in ncrreg.h. -** -**========================================================== -*/ - -#define PRINT_ADDR(xp) sc_print_addr(xp->sc_link) - -/*========================================================== -** -** Declaration of structs. -** -**========================================================== -*/ - -struct tcb; -struct lcb; -struct ccb; -struct ncb; -struct script; - -typedef struct ncb * ncb_p; -typedef struct tcb * tcb_p; -typedef struct lcb * lcb_p; -typedef struct ccb * ccb_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 -** -**--------------------------------------- -*/ - -struct tstamp { - struct timeval start; - struct timeval end; - struct timeval select; - struct timeval command; - struct timeval data; - struct timeval status; - struct timeval disconnect; - struct timeval reselect; -}; - -/* -** 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 -** -**========================================================== -*/ - -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 - ** <RESEL_LUN> - */ - - struct link call_lun; - - /* - ** now look for the right lun. - ** - ** JUMP - ** @(first ccb of this lun) - */ - - struct link jump_lcb; - - /* - ** pointer to interrupted getcc ccb - */ - - ccb_p hold_cp; - - /* - ** pointer to ccb used for negotiating. - ** Avoid to start a nego for all queued commands - ** when tagged command queuing is enabled. - */ - - ccb_p nego_cp; - - /* - ** statistical data - */ - - u_long transfers; - u_long bytes; - - /* - ** user settable limits for sync transfer - ** and tagged commands. - */ - - u_char usrsync; - u_char usrtags; - u_char usrwide; - u_char usrflag; - - /* - ** negotiation of wide and synch transfer. - ** device quirks. - */ - -/*0*/ u_char minsync; -/*1*/ u_char sval; -/*2*/ u_short period; -/*0*/ u_char maxoffs; - -/*1*/ u_char quirks; - -/*2*/ u_char widedone; -/*3*/ u_char wval; - /* - ** inquire data - */ -#define MAX_INQUIRE 36 - u_char inqdata[MAX_INQUIRE]; - - /* - ** 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 - ** <RESEL_TAG> - */ - - struct link call_tag; - - /* - ** now look for the right ccb. - ** - ** JUMP - ** @(first ccb of this lun) - */ - - struct link jump_ccb; - - /* - ** start of the ccb chain - */ - - ccb_p next_ccb; - - /* - ** Control of tagged queueing - */ - - u_char reqccbs; - u_char actccbs; - u_char reqlink; - u_char actlink; - u_char usetags; - u_char lasttag; -}; - -/*========================================================== -** -** Declaration of structs: COMMAND control block -** -**========================================================== -** -** This substructure is copied from the ccb 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 ccb 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 ccb - ** containing this header. - */ - - ccb_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 ncrreg.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 choosen 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 scsi_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 ccb by the script processor, -** the DSA (data structure address) register points -** to this substructure of the ccb. -** 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 ccb by the script processor, -** the DSA (data structure address) register points -** to this substructure of the ccb. -** This substructure contains the header with -** the script-processor-changable data and then -** data blocks for the indirect move commands. -** -**---------------------------------------------------------- -*/ - - -struct ccb { - /* - ** 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 ccb. - ** - ** JUMP IF (SFBR != #TAG#) - ** @(next ccb of this lun) - */ - - struct link jump_ccb; - - /* - ** 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 - ** <RESEL_TMP> - */ - - 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. - */ - - struct scsi_xfer *xfer; - - /* - ** 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]; -#if defined(__mips__) - u_char local_sense[sizeof(struct scsi_sense_data)]; -#endif - - /* - ** Lock this ccb. - ** Flag is used while looking for a free ccb. - */ - - u_long magic; - - /* - ** Physical address of this instance of ccb - */ - - u_long p_ccb; - - /* - ** Completion time out for this job. - ** It's set to time of start + allowed number of seconds. - */ - - u_long tlimit; - - /* - ** All ccbs of one hostadapter are chained. - */ - - ccb_p link_ccb; - - /* - ** All ccbs of one target/lun are chained. - */ - - ccb_p next_ccb; - - /* - ** Sense command - */ - - u_char sensecmd[6]; - - /* - ** Tag for this transfer. - ** It's patched into jump_ccb. - ** If it's not zero, a SIMPLE_TAG - ** message is included in smsg. - */ - - u_char tag; -}; - -#define CCB_PHYS(cp,lbl) (cp->p_ccb + offsetof(struct ccb, lbl)) - -/*========================================================== -** -** Declaration of structs: NCR device descriptor -** -**========================================================== -*/ - -struct ncb { -#ifndef __OpenBSD__ - /* - ** The global header. - ** Accessible to both the host and the - ** script-processor. - ** We assume it is cache line size aligned. - */ - struct head header; -#endif - -#ifdef __OpenBSD__ - struct device sc_dev; - pci_chipset_tag_t sc_pc; - void *sc_ih; - bus_space_tag_t sc_st; - bus_space_handle_t sc_sh; - int sc_iomapped; -#else /* !__OpenBSD__ */ - int unit; -#endif /* __OpenBSD__ */ - - /*----------------------------------------------- - ** 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. - */ -#ifdef __OpenBSD__ - bus_addr_t paddr; - - bus_space_tag_t ram_tag; - bus_space_handle_t ram_handle; - bus_addr_t paddr2; - int scriptmapped; -#else - vm_offset_t vaddr; - vm_offset_t paddr; - - vm_offset_t vaddr2; - vm_offset_t paddr2; - - /* - ** pointer to the chip's registers. - */ - volatile - struct ncr_reg* reg; -#endif - - /* - ** 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; - - /*----------------------------------------------- - ** Link to the generic SCSI driver - **----------------------------------------------- - */ - - struct scsi_link sc_link; - - /*----------------------------------------------- - ** Job control - **----------------------------------------------- - ** - ** Commands from user - */ - struct usrcmd user; - u_char order; - - /* - ** Target data - */ - struct tcb target[MAX_TARGET]; - - /* - ** Start queue. - */ - u_int32_t squeue [MAX_START]; - u_short squeueput; - u_short actccbs; - - /* - ** Timeout handler - */ - u_long heartbeat; - u_short ticks; - u_short latetime; - u_long lasttime; -#ifdef __FreeBSD__ - struct callout_handle timeout_ch; -#elif defined (__OpenBSD__) - struct timeout sc_timeout; -#endif - - /*----------------------------------------------- - ** Debug and profiling - **----------------------------------------------- - ** - ** register dump - */ - struct ncr_reg regdump; - struct timeval regtime; - - /* - ** Profiling data - */ - struct profile profile; - u_long disc_phys; - u_long disc_ref; - -#ifdef __OpenBSD__ - /* - ** The global header. - ** Accessible to both the host and the - ** script-processor. - ** We assume it is cache line size aligned. - */ - struct head header; -#endif - - /* - ** The global control block. - ** It's used only during the configuration phase. - ** A target control block will be created - ** after the first successful transfer. - ** It is allocated separately in order to ensure - ** cache line size alignment. - */ - struct ccb *ccb; - - /* - ** 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; - - /* - ** option for M_IDENTIFY message: enables disconnecting - */ - u_char disc; - -#if defined(NCR_IOMAPPED) && !defined(__OpenBSD__) - /* - ** address of the ncr control registers in io space - */ - u_short 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 void ncr_alloc_ccb (ncb_p np, u_long target, u_long lun); -static void ncr_complete (ncb_p np, ccb_p cp); -static int ncr_delta (struct timeval * from, struct timeval * to); -static void ncr_exception (ncb_p np); -static void ncr_free_ccb (ncb_p np, ccb_p cp, int flags); -static void ncr_selectclock (ncb_p np, u_char scntl3); -static void ncr_getclock (ncb_p np, u_char multiplier); -static ccb_p ncr_get_ccb (ncb_p np, u_long flags, u_long t,u_long l); -static void ncr_init (ncb_p np, char * msg, u_long code); -#ifdef __OpenBSD__ -static int ncr_intr (void *vnp); -#else -static void ncr_intr (void *vnp); -static u_int32_t ncr_info (int unit); -#endif /* !__OpenBSD__ */ -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); -#ifdef __OpenBSD__ -static u_long ncr_lookup (char *id); -#endif -static void ncr_min_phys (struct buf *bp); -static void ncr_negotiate (struct ncb* np, struct tcb* tp); -static void ncr_opennings (ncb_p np, lcb_p lp, struct scsi_xfer * xp); -static void ncb_profile (ncb_p np, ccb_p cp); -static void ncr_script_copy_and_bind - (ncb_p np, ncrcmd *src, ncrcmd *dst, int len); -static void ncr_script_fill (struct script * scr, struct scripth *scrh); -static int ncr_scatter (ncb_p np, struct dsb* phys, vm_offset_t vaddr, - vm_size_t datalen); -static void ncr_setmaxtags (tcb_p tp, u_long usrtags); -static void ncr_getsync (ncb_p np, u_char sfac, u_char *fakp, - u_char *scntl3p); -static void ncr_setsync (ncb_p np, ccb_p cp,u_char scntl3,u_char sxfer); -static void ncr_settags (tcb_p tp, lcb_p lp, u_long usrtags); -static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack); -static int ncr_show_msg (u_char * msg); -static int ncr_snooptest (ncb_p np); -static int32_t ncr_start (struct scsi_xfer *xp); -static void ncr_timeout (void *arg); -static void ncr_usercmd (ncb_p np); -static void ncr_wakeup (ncb_p np, u_long code); - -#ifdef __OpenBSD__ -#ifdef __BROKEN_INDIRECT_CONFIG -static int ncr_probe (struct device *, void *, void *); -#else -static int ncr_probe (struct device *, struct cfdata *, void *); -#endif -static void ncr_attach (struct device *, struct device *, void *); -#else /* !__OpenBSD__ */ -static char *ncr_probe (pcici_t tag, pcidi_t type); -static void ncr_attach (pcici_t tag, int unit); -#endif /* __OpenBSD__ */ - -#endif /* KERNEL */ - -/*========================================================== -** -** -** Global static data. -** -** -**========================================================== -*/ - - -#if 0 -static char ident[] = - "\n$OpenBSD: ncr.c,v 1.72 2005/05/23 23:26:56 tedu Exp $\n"; -#endif - -static const u_long ncr_version = NCR_VERSION * 11 - + (u_long) sizeof (struct ncb) * 7 - + (u_long) sizeof (struct ccb) * 5 - + (u_long) sizeof (struct lcb) * 3 - + (u_long) sizeof (struct tcb) * 2; - -#ifdef KERNEL - -#ifndef __OpenBSD__ -static const int nncr=MAX_UNITS; /* XXX to be replaced by SYSCTL */ -ncb_p ncrp [MAX_UNITS]; /* XXX to be replaced by SYSCTL */ -#endif /* !__OpenBSD__ */ - -static int ncr_debug = SCSI_NCR_DEBUG; -#ifndef __OpenBSD__ -SYSCTL_INT(_debug, OID_AUTO, ncr_debug, CTLFLAG_RW, &ncr_debug, 0, ""); -#endif /* !__OpenBSD__ */ - -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_895A_ID (0x00121000ul) -#define NCR_896_ID (0x000b1000ul) -#define NCR_1510_ID (0x00101000ul) -#define NCR_1510D_ID (0x000a1000ul) - -#ifdef __OpenBSD__ - -struct cfattach ncr_ca = { - sizeof(struct ncb), ncr_probe, ncr_attach -}; - -struct cfdriver ncr_cd = { - NULL, "ncr", DV_DULL -}; - -#else /* !__OpenBSD__ */ - -static u_long ncr_count; - -static struct pci_device ncr_device = { - "ncr", - ncr_probe, - ncr_attach, - &ncr_count, - NULL -}; - -DATA_SET (pcidevice_set, ncr_device); - -#endif /* !__OpenBSD__ */ - -static struct scsi_adapter ncr_switch = -{ - ncr_start, - ncr_min_phys, - 0, - 0, -#ifndef __OpenBSD__ - ncr_info, - "ncr", -#endif /* !__OpenBSD__ */ -}; - -static struct scsi_device ncr_dev = -{ - NULL, /* Use default error handler */ - NULL, /* have a queue, served by this */ - NULL, /* have no async handler */ - NULL, /* Use default 'done' routine */ -#ifndef __OpenBSD__ - "ncr", -#endif /* !__OpenBSD__ */ -}; - -#ifdef __OpenBSD__ - -#define ncr_name(np) (np->sc_dev.dv_xname) - -#else /* !__OpenBSD__ */ - -static char *ncr_name (ncb_p np) -{ - static char name[10]; - snprintf(name, sizeof name, "ncr%d", np->unit); - return (name); -} -#endif - -/*========================================================== -** -** -** 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_TIME_TV_SEC (0) -#define KVAR_TIME (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. - */ -#ifdef __OpenBSD__ -/* - * XXX - set up a timer that will update a local copy of microuptime once - * every tick. - */ -static unsigned long script_kvars[] = { - (unsigned long)&mono_time.tv_sec, - (unsigned long)&mono_time, - (unsigned long)&ncr_cache, -}; -#else -static void *script_kvars[] = - { &time.tv_sec, &time, &ncr_cache }; -#endif - -static struct script script0 = { -/*--------------------------< START >-----------------------*/ { - /* - ** Claim to be still alive ... - */ - SCR_COPY (sizeof (((struct ncb *)0)->heartbeat)), - KVAR (KVAR_TIME_TV_SEC), - 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 ccb. - ** 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 M_X_SYNC_REQ 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 ccb as not scheduled. - */ - SCR_COPY (8), - PADDR (idle), - NADDR (header.launch), - /* - ** Set a time stamp for this selection - */ - SCR_COPY (sizeof (struct timeval)), - KVAR (KVAR_TIME), - 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, M_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 (M_EXTENDED)), - PADDR (msg_in), - SCR_JUMP ^ IFTRUE (DATA (M_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 tranfer 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 M_ID_ERROR message - ** (initiator detected error). - ** The target should retry the transfer. - */ - SCR_LOAD_REG (scratcha, M_ID_ERROR), - 0, - SCR_JUMP, - PADDR (setmsg), - -}/*-------------------------< COMMAND >--------------------*/,{ - /* - ** If this is not a GETCC transfer ... - */ - SCR_FROM_REG (SS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFTRUE (DATA (S_CHECK_COND)), - 28, - /* - ** ... set a timestamp ... - */ - SCR_COPY (sizeof (struct timeval)), - KVAR (KVAR_TIME), - 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 (struct timeval)), - KVAR (KVAR_TIME), - NADDR (header.stamp.status), - /* - ** If this is a GETCC transfer, - */ - SCR_FROM_REG (SS_REG), - 0, -/*<<<*/ SCR_JUMPR ^ IFFALSE (DATA (S_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, S_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 (S_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 (M_COMPLETE)), - PADDR (complete), - SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)), - PADDR (save_dp), - SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)), - PADDR (restore_dp), - SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)), - PADDR (disconnect), - SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)), - PADDRH (msg_extended), - SCR_JUMP ^ IFTRUE (DATA (M_NOOP)), - PADDR (clrack), - SCR_JUMP ^ IFTRUE (DATA (M_REJECT)), - PADDRH (msg_reject), - SCR_JUMP ^ IFTRUE (DATA (M_IGN_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, M_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 (S_SENSE, S_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 ccb - ** or xxxxxxFF (no ccb) - ** - ** 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 ccb. - */ - 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 (S_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 (S_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 an "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 (struct timeval)), - KVAR (KVAR_TIME), - 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 (M_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, M_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 ccb - ** 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 (M_IDENTIFY, 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 (M_SIMPLE_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 (struct timeval)), -** KVAR (KVAR_TIME), -** NADDR (header.stamp.data), -** SCR_MOVE_TBL ^ SCR_DATA_IN, -** offsetof (struct dsb, data[ 0]), -** -** ##===========< i=1; i<MAX_SCATTER >========= -** || 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 (struct timeval)), -** KVAR (KVAR_TIME), -** NADDR (header.stamp.data), -** SCR_MOVE_TBL ^ SCR_DATA_OUT, -** offsetof (struct dsb, data[ 0]), -** -** ##===========< i=1; i<MAX_SCATTER >========= -** || 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), -** -**--------------------------------------------------------- -*/ -#ifdef __OpenBSD__ -0 -#else -(u_long)&ident -#endif - -}/*--------------------------------------------------------*/ -}; - - -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<MAX_START >=========== -** || 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, M_PARITY), - 0, - SCR_JUMP, - PADDR (setmsg), -}/*-------------------------< MSG_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 (M_X_WIDE_REQ)), - 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 M_X_WIDE_REQ - */ - 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 (M_X_SYNC_REQ)), - 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 M_X_SYNC_REQ - */ - 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, M_ABORT_TAG), - 0, - SCR_JUMPR ^ IFFALSE (CARRYSET), - 8, -}/*-------------------------< ABORT >----------------------*/,{ - SCR_LOAD_REG (scratcha, M_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 -** -** -**========================================================== -*/ - -void ncr_script_fill (struct script * scr, struct scripth * scrh) -{ - int i; - ncrcmd *p; - - p = scrh->tryloop; - for (i=0; i<MAX_START; i++) { - *p++ =SCR_COPY (4); - *p++ =NADDR (squeue[i]); - *p++ =RADDR (dsa); - *p++ =SCR_CALL; - *p++ =PADDR (trysel); - }; - *p++ =SCR_JUMP; - *p++ =PADDRH(tryloop); - - assert ((u_long)p == (u_long)&scrh->tryloop + sizeof (scrh->tryloop)); - - p = scr->data_in; - - *p++ =SCR_JUMP ^ IFFALSE (WHEN (SCR_DATA_IN)); - *p++ =PADDR (no_data); - *p++ =SCR_COPY (sizeof (struct timeval)); - *p++ =(ncrcmd) KVAR (KVAR_TIME); - *p++ =NADDR (header.stamp.data); - *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN; - *p++ =offsetof (struct dsb, data[ 0]); - - for (i=1; i<MAX_SCATTER; i++) { - *p++ =SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_IN)); - *p++ =PADDR (checkatn); - *p++ =SCR_MOVE_TBL ^ SCR_DATA_IN; - *p++ =offsetof (struct dsb, data[i]); - }; - - *p++ =SCR_CALL; - *p++ =PADDR (checkatn); - *p++ =SCR_JUMP; - *p++ =PADDR (no_data); - - assert ((u_long)p == (u_long)&scr->data_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 (struct timeval)); - *p++ =(ncrcmd) KVAR (KVAR_TIME); - *p++ =NADDR (header.stamp.data); - *p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT; - *p++ =offsetof (struct dsb, data[ 0]); - - for (i=1; i<MAX_SCATTER; i++) { - *p++ =SCR_CALL ^ IFFALSE (WHEN (SCR_DATA_OUT)); - *p++ =PADDR (dispatch); - *p++ =SCR_MOVE_TBL ^ SCR_DATA_OUT; - *p++ =offsetof (struct dsb, data[i]); - }; - - *p++ =SCR_CALL; - *p++ =PADDR (dispatch); - *p++ =SCR_JUMP; - *p++ =PADDR (no_data); - - assert ((u_long)p == (u_long)&scr->data_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) { - printf ("%s: ERROR0 IN SCRIPT at %ld.\n", - ncr_name(np), (long)(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) { - printf ("%s: ERROR1 IN SCRIPT at %ld.\n", - ncr_name(np), (long)(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) + np->paddr; - 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) + NCR_KVATOPHYS(np, 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 = NCR_KVATOPHYS(np, (void *)script_kvars[old & - ~RELOC_MASK]); - break; - case 0: - /* Don't relocate a 0 address. */ - if (old == 0) { - new = old; - break; - } - /* fall through */ - default: - panic("ncr_script_copy_and_bind: weird relocation %x @ %ld", old, (long)(src - start)); - break; - } - - WRITESCRIPT_OFF(dst, offset, new); - offset += 4; - } - } else { - WRITESCRIPT_OFF(dst, offset, *src); - offset += 4; - src++; - } - - }; -} - -/*========================================================== -** -** -** Auto configuration. -** -** -**========================================================== -*/ - -/*---------------------------------------------------------- -** -** 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 -** <FreeBSD-bugs@freefall.cdrom.com>. -** It should be fixed in the current release. -** -**---------------------------------------------------------- -*/ - -#ifndef __OpenBSD__ -void ncr_min_phys (struct buf *bp) -{ - if ((unsigned long)bp->b_bcount > MAX_SIZE) bp->b_bcount = MAX_SIZE; -} -#else -void ncr_min_phys (struct buf *bp) -{ - if (bp->b_bcount > MAX_SIZE) - bp->b_bcount = MAX_SIZE; - minphys(bp); -} -#endif - -/*---------------------------------------------------------- -** -** Maximal number of outstanding requests per target. -** -**---------------------------------------------------------- -*/ - -#ifndef __OpenBSD__ -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 { - unsigned long device_id; - unsigned short minrevid; - 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, 4, 8, 4, - FE_ERL} - , - {NCR_810_ID, 0x10, 4, 8, 4, - FE_ERL|FE_LDSTR|FE_PFEN|FE_BOF} - , - {NCR_815_ID, 0x00, 4, 8, 4, - FE_ERL|FE_BOF} - , - {NCR_820_ID, 0x00, 4, 8, 4, - FE_WIDE|FE_ERL} - , - {NCR_825_ID, 0x00, 4, 8, 4, - FE_WIDE|FE_ERL|FE_BOF} - , - {NCR_825_ID, 0x10, 7, 8, 4, - FE_WIDE|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_860_ID, 0x00, 4, 8, 5, - FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_LDSTR|FE_PFEN} - , - {NCR_875_ID, 0x00, 7, 16, 5, - FE_WIDE|FE_ULTRA|FE_CLK80|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_875_ID, 0x02, 7, 16, 5, - FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , -#ifdef NCR_NARROW_875J - {NCR_875_ID2, 0x00, 4, 8, 5, - FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} -#else - {NCR_875_ID2, 0x00, 7, 16, 5, - FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} -#endif - , - {NCR_885_ID, 0x00, 7, 16, 5, - FE_WIDE|FE_ULTRA|FE_DBLR|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_895_ID, 0x00, 7, 31, 7, - FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_895A_ID, 0x00, 7, 31, 7, - FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_896_ID, 0x00, 7, 31, 7, - FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_1510_ID, 0x00, 7, 31, 7, - FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM} - , - {NCR_1510D_ID, 0x00, 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(u_long device_id, u_char revision_id) -{ - int i, found; - - found = -1; - for (i = 0; i < sizeof(ncr_chip_table)/sizeof(ncr_chip_table[0]); 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. -** -**---------------------------------------------------------- -*/ - -#ifdef __OpenBSD__ - -int -ncr_probe(parent, match, aux) - struct device *parent; -#ifdef __BROKEN_INDIRECT_CONFIG - void *match; -#else - struct cfdata *match; -#endif - void *aux; -{ - struct pci_attach_args * const pa = aux; - u_char rev = PCI_REVISION(pa->pa_class); -#if 0 - struct cfdata *cf = match; - - if (!pci_targmatch(cf, pa)) - return 0; -#endif - if (ncr_chip_lookup(pa->pa_id, rev) < 0) - return 0; - - return 1; -} - -#else /* !__OpenBSD__ */ - - -static char *ncr_probe (pcici_t tag, pcidi_t type) -{ - u_char rev = PCI_REVISION(pa->pa_class); - int i; - - i = ncr_chip_lookup(type, rev); - if (i >= 0) - return ncr_chip_table[i].name; - - return (NULL); -} - -#endif /* !__OpenBSD__ */ - - -/*========================================================== -** -** 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. -** -** -**========================================================== -*/ - -#ifdef __OpenBSD__ -void -ncr_attach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct pci_attach_args *pa = aux; - pci_chipset_tag_t pc = pa->pa_pc; - int retval; - pci_intr_handle_t intrhandle; - const char *intrstr; - ncb_p np = (void *)self; - u_long period; - int i; - u_char rev = PCI_REVISION(pa->pa_class); - bus_space_tag_t iot, memt; - bus_space_handle_t ioh, memh; - bus_addr_t ioaddr, memaddr; - int ioh_valid, memh_valid; - char *type; - -#if defined(__mips__) - pci_sync_cache(pc, (vm_offset_t)np, sizeof (struct ncb)); - np = (struct ncb *)PHYS_TO_UNCACHED(NCR_KVATOPHYS(np, np)); -#endif /*__mips__*/ - - np->sc_pc = pc; - np->ccb = (ccb_p) malloc (sizeof (struct ccb), M_DEVBUF, M_NOWAIT); - if (np->ccb == NULL) - return; -#if defined(__mips__) - pci_sync_cache(pc, (vm_offset_t)np->ccb, sizeof (struct ccb)); - np->ccb = (struct ccb *)PHYS_TO_UNCACHED(NCR_KVATOPHYS(np, np->ccb)); -#endif /* __mips__ */ - bzero (np->ccb, sizeof (*np->ccb)); - - /* - ** Try to map the controller chip to - ** virtual and physical memory. - */ - - ioh_valid = (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_IO, 0, - &iot, &ioh, &ioaddr, NULL, 0) == 0); - memh_valid = (pci_mapreg_map(pa, 0x14, - PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, - &memt, &memh, &memaddr, NULL, 0) == 0); - -#if defined(NCR_IOMAPPED) - if (ioh_valid) { - np->sc_st = iot; - np->sc_sh = ioh; - np->paddr = ioaddr; - np->sc_iomapped = 1; - } else if (memh_valid) { - np->sc_st = memt; - np->sc_sh = memh; - np->paddr = memaddr; - np->sc_iomapped = 0; - } -#else /* defined(NCR_IOMAPPED) */ - if (memh_valid) { - np->sc_st = memt; - np->sc_sh = memh; - np->paddr = memaddr; - np->sc_iomapped = 0; - } else if (ioh_valid) { - np->sc_st = iot; - np->sc_sh = ioh; - np->paddr = ioaddr; - np->sc_iomapped = 1; - } -#endif /* defined(NCR_IOMAPPED) */ - else { - printf(": unable to map device registers\n"); - return; - } - - /* - ** Set up the controller chip's interrupt. - */ - retval = pci_intr_map(pa, &intrhandle); - if (retval) { - printf(": couldn't map interrupt\n"); - return; - } - intrstr = pci_intr_string(pc, intrhandle); - np->sc_ih = pci_intr_establish(pc, intrhandle, IPL_BIO, - ncr_intr, np, self->dv_xname); - if (np->sc_ih == NULL) { - printf(": couldn't establish interrupt"); - if (intrstr != NULL) - printf(" at %s", intrstr); - printf("\n"); - return; - } - - i = ncr_chip_lookup(pa->pa_id, rev); - if (ncr_chip_table[i].features & FE_ULTRA2) - type = "ultra2"; - else if (ncr_chip_table[i].features & FE_ULTRA) - type = "ultra"; - else - type = "fast"; - if (intrstr != NULL) - printf(": %s%s scsi, %s\n", type, - (ncr_chip_table[i].features & FE_WIDE) ? " wide" : "", - intrstr); - else - printf(": %s%s scsi\n", type, - (ncr_chip_table[i].features & FE_WIDE) ? " wide" : ""); - -#else /* !__OpenBSD__ */ - -static void ncr_attach (pcici_t config_id, int unit) -{ - ncb_p np = (struct ncb*) 0; -#if ! (__FreeBSD__ >= 2) - extern unsigned bio_imask; -#endif - -#if (__FreeBSD__ >= 2) - struct scsibus_data *scbus; -#endif - u_char rev = 0; - u_long period; - int i; - - /* - ** allocate and initialize structures. - */ - - if (!np) { - np = (ncb_p) malloc (sizeof (struct ncb), M_DEVBUF, M_WAITOK); - ncrp[unit]=np; - } - bzero (np, sizeof (*np)); - - np->ccb = (ccb_p) malloc (sizeof (struct ccb), M_DEVBUF, M_WAITOK); -#if defined(__mips__) - pci_sync_cache(pc, (vm_offset_t)np->ccb, sizeof (struct ccb)); - np->ccb = (struct ccb *)PHYS_TO_UNCACHED(NCR_KVATOPHYS(np, np->ccb)); -#endif /* __mips__ */ - bzero (np->ccb, sizeof (*np->ccb)); - - np->unit = unit; - - /* - ** Try to map the controller chip to - ** virtual and physical memory. - */ - - if (!pci_map_mem (config_id, 0x14, &np->vaddr, &np->paddr)) - return; - - /* - ** Make the controller's registers available. - ** Now the INB INW INL OUTB OUTW OUTL macros - ** can be used safely. - */ - - np->reg = (struct ncr_reg*) np->vaddr; - -#ifdef NCR_IOMAPPED - /* - ** Try to map the controller chip into iospace. - */ - - if (!pci_map_port (config_id, 0x10, &np->port)) - return; -#endif - -#endif /* !__OpenBSD__ */ - - /* - ** 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. - */ - -#ifndef __OpenBSD__ - rev = pci_conf_read (config_id, PCI_CLASS_REG) & 0xff; -#endif /* !__OpenBSD__ */ - - /* - ** Get chip features from chips table. - */ -#ifndef __OpenBSD__ - i = ncr_chip_lookup(pci_conf_read(config_id, PCI_ID_REG), rev); -#endif /* !__OpenBSD__ */ - - 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; -#ifdef NEED_PCI_SCSI_CLOCK_FUNC - { - int b, d, f; - pci_decompose_tag(pc, pa->pa_tag, &b, &d, &f); \ - if((np->clock_khz = pci_scsi_clock(pc, b, d)) == 0) - np->clock_khz = np->features & FE_CLK80 ? 80000 : 40000; - } -#else - np->clock_khz = np->features & FE_CLK80 ? 80000 : 40000; -#endif - 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) { - printf ("%s: Tekram EEPROM read %s\n", - ncr_name(np), - 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 = (4 * div_10M[0] + np->clock_khz - 1) / 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 = (period + 40 - 1) / 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); - } - -#ifndef NCR_IOMAPPED - /* - ** Get on-chip SRAM address, if supported - */ -#ifdef __OpenBSD__ - if ((np->features & FE_RAM) && sizeof(struct script) <= 4096) { - if (pci_mapreg_map(pa, 0x18, - PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, - &memt, &memh, &memaddr, NULL, 0) == 0) { - np->ram_tag = memt; - np->ram_handle = memh; - np->paddr2 = memaddr; - np->scriptmapped = 1; - } else { - np->scriptmapped = 0; - } - } -#else /* !__OpenBSD__ */ - if ((np->features & FE_RAM) && sizeof(struct script) <= 4096) - (void)(!pci_map_mem (config_id,0x18, &np->vaddr2, &np->paddr2)); -#endif /* __OpenBSD__ */ -#endif /* !NCR_IOMAPPED */ - - /* - ** Allocate structure for script relocation. - */ -#ifdef __FreeBSD__ - if (np->vaddr2 != NULL) { - np->script = (struct script *) np->vaddr2; - np->p_script = np->paddr2; - } else if (sizeof (struct script) > PAGE_SIZE) { - np->script = (struct script*) vm_page_alloc_contig - (round_page(sizeof (struct script)), - 0x100000, 0xffffffff, PAGE_SIZE); -#else - if (ISSCRIPTRAMMAPPED(np)) { - /* - * A NULL value means that the script is in the chip's - * on-board RAM and has no virtual address. - */ - np->script = NULL; - np->p_script = np->paddr2; -#endif /* __FreeBSD__ */ - } else { - np->script = (struct script *) - malloc (sizeof (struct script), M_DEVBUF, M_WAITOK); -#if defined(__mips__) - pci_sync_cache(pc, (vm_offset_t)np->script, sizeof (struct script)); - np->script = (struct script *)PHYS_TO_UNCACHED(NCR_KVATOPHYS(np, np->script)); -#endif /*__mips__*/ - } - -#ifdef __FreeBSD__ - if (sizeof (struct scripth) > PAGE_SIZE) { - np->scripth = (struct scripth*) vm_page_alloc_contig - (round_page(sizeof (struct scripth)), - 0x100000, 0xffffffff, PAGE_SIZE); - } else -#endif /* __FreeBSD__ */ - { - np->scripth = (struct scripth *) - malloc (sizeof (struct scripth), M_DEVBUF, M_WAITOK); -#if defined(__mips__) - pci_sync_cache(pc, (vm_offset_t)np->scripth, sizeof (struct scripth)); - np->scripth = (struct scripth *)PHYS_TO_UNCACHED(NCR_KVATOPHYS(np, np->scripth)); -#endif /*__mips__*/ - } - -#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_cfgread(config_id, PCIR_CACHELNSZ, 1); - u_short command = pci_cfgread(config_id, PCIR_COMMAND, 2); - - if (!cachelnsz) { - cachelnsz = 8; - printf("%s: setting PCI cache line size register to %d.\n", - ncr_name(np), (int)cachelnsz); - pci_cfgwrite(config_id, PCIR_CACHELNSZ, cachelnsz, 1); - } - - if (!(command & (1<<4))) { - command |= (1<<4); - printf("%s: setting PCI command write and invalidate.\n", - ncr_name(np)); - pci_cfgwrite(config_id, PCIR_COMMAND, command, 2); - } - } -#endif /* PCIR_CACHELNSZ */ - -#endif /* SCSI_NCR_PCI_CONFIG_FIXUP */ - - /* - ** Bells and whistles ;-) - */ - if (bootverbose) - printf("%s: minsync=%d, maxsync=%d, maxoffs=%d, %d dwords burst, %s dma fifo\n", - ncr_name(np), np->minsync, np->maxsync, np->maxoffs, - burst_length(np->maxburst), - (np->rv_ctest5 & DFS) ? "large" : "normal"); - - /* - ** Print some complementary information that can be helpfull. - */ - if (bootverbose) - printf("%s: %s, %s IRQ driver%s\n", - ncr_name(np), - np->rv_stest2 & 0x20 ? "differential" : "single-ended", - np->rv_dcntl & IRQM ? "totem pole" : "open drain", - ISSCRIPTRAMMAPPED(np) ? ", using on-chip SRAM" : ""); - - /* - ** Patch scripts to physical addresses - */ - ncr_script_fill (&script0, &scripth0); - - if (np->script) - np->p_script = NCR_KVATOPHYS(np, np->script); - np->p_scripth = NCR_KVATOPHYS(np, 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)); - - np->ccb->p_ccb = NCR_KVATOPHYS (np, np->ccb); - - /* - ** 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_BO(SCR_JUMP); - np->jump_tcb.l_paddr = SCR_BO(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; -#ifdef __OpenBSD__ - u_long config_id = pa->pa_tag; -#endif /* __OpenBSD__ */ - for (reg=0; reg<256; reg+=4) { - if (reg%16==0) printf ("reg[%2x]", reg); - printf (" %08x", (int)pci_conf_read (config_id, reg)); - if (reg%16==12) printf ("\n"); - } - } -#endif /* NCR_DUMP_REG */ - - /* - ** Reset chip. - */ - - 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; - }; - -#ifndef __OpenBSD__ - /* - ** Install the interrupt handler. - */ - - if (!pci_map_int (config_id, ncr_intr, np, &bio_imask)) - printf ("\tinterruptless mode: reduced performance.\n"); -#endif /* !__OpenBSD__ */ - - /* - ** After SCSI devices have been opened, we cannot - ** reset the bus safely, so we do it here. - ** Interrupt handler does the real work. - */ - - OUTB (nc_scntl1, CRST); - DELAY (1000); - - /* - ** Process the reset exception, - ** if interrupts are not enabled yet. - ** Then enable disconnects. - */ - ncr_exception (np); - np->disc = 1; - - /* - ** Now let the generic SCSI driver - ** look for the SCSI devices on the bus .. - */ - -#ifdef __OpenBSD__ - np->sc_link.adapter_softc = np; - np->sc_link.adapter_target = np->myaddr; - np->sc_link.openings = 1; - if (np->maxwide) - np->sc_link.adapter_buswidth = MAX_TARGET; -#else /* !__OpenBSD__ */ - np->sc_link.adapter_unit = unit; - np->sc_link.adapter_softc = np; - np->sc_link.adapter_targ = np->myaddr; - np->sc_link.fordriver = 0; -#endif /* !__OpenBSD__ */ - np->sc_link.adapter = &ncr_switch; - np->sc_link.device = &ncr_dev; - np->sc_link.flags = 0; - -#ifdef __OpenBSD__ - config_found(self, &np->sc_link, scsiprint); -#else /* !__OpenBSD__ */ -#if (__FreeBSD__ >= 2) - scbus = scsi_alloc_bus(); - if(!scbus) - return; - scbus->adapter_link = &np->sc_link; - - if(np->maxwide) - scbus->maxtarg = 15; - - if (bootverbose) { - unsigned t_from = 0; - unsigned t_to = scbus->maxtarg; - unsigned myaddr = np->myaddr; - - char *txt_and = ""; - printf ("%s scanning for targets ", ncr_name (np)); - if (t_from < myaddr) { - printf ("%d..%d ", t_from, myaddr -1); - txt_and = "and "; - } - if (myaddr < t_to) - printf ("%s%d..%d ", txt_and, myaddr +1, t_to); - printf ("(V%d " NCR_DATE ")\n", NCR_VERSION); - } - - scsi_attachdevs (scbus); - scbus = NULL; /* Upper-level SCSI code owns this now */ -#else - scsi_attachdevs (&np->sc_link); -#endif /* !__FreeBSD__ >= 2 */ -#endif /* !__OpenBSD__ */ - - /* - ** start the timeout daemon - */ - timeout_set(&np->sc_timeout, ncr_timeout, np); - ncr_timeout (np); - np->lasttime=0; - - /* - ** use SIMPLE TAG messages by default - */ - - np->order = M_SIMPLE_TAG; - - /* - ** Done. - */ - - return; -} - -/*========================================================== -** -** -** Process pending device interrupts. -** -** -**========================================================== -*/ - -#ifdef __OpenBSD__ -static int -#else /* !__OpenBSD__ */ -static void -#endif /* __OpenBSD__ */ -ncr_intr(vnp) - void *vnp; -{ -#ifdef __OpenBSD__ - int n = 0; -#endif - ncb_p np = vnp; - int oldspl = splbio(); - - 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)); - -#ifdef __OpenBSD__ - n=1; -#endif - np->ticks = 100; - }; - - if (DEBUG_FLAGS & DEBUG_TINY) printf ("]\n"); - - splx (oldspl); -#ifdef __OpenBSD__ - return (n); -#endif -} - -/*========================================================== -** -** -** Start execution of a SCSI command. -** This is called from the generic SCSI driver. -** -** -**========================================================== -*/ - -static int32_t ncr_start (struct scsi_xfer * xp) -{ - ncb_p np = (ncb_p) xp->sc_link->adapter_softc; - - struct scsi_generic * cmd = (struct scsi_generic *)xp->cmd; - ccb_p cp; - lcb_p lp; - tcb_p tp = &np->target[xp->sc_link->target]; - - int i, oldspl, segments, flags = xp->flags, pollmode; - u_char qidx, nego, idmsg, *msgptr; - u_long msglen, msglen2; - - /*--------------------------------------------- - ** - ** Reset SCSI bus - ** - ** Interrupt handler does the real work. - ** - **--------------------------------------------- - */ - - if (flags & SCSI_RESET) { - OUTB (nc_scntl1, CRST); - DELAY (1000); - return(COMPLETE); - }; - - /*--------------------------------------------- - ** - ** Some shortcuts ... - ** - **--------------------------------------------- - */ - - if ((xp->sc_link->target == np->myaddr ) || - (xp->sc_link->target >= MAX_TARGET) || - (xp->sc_link->lun >= MAX_LUN ) || - (flags & SCSI_DATA_UIO)) { - xp->error = XS_DRIVER_STUFFUP; - return(COMPLETE); - }; - - /*--------------------------------------------- - ** - ** Diskaccess to partial blocks? - ** - **--------------------------------------------- - */ - - if ((xp->datalen & 0x1ff) && !(tp->inqdata[0] & 0x1f)) { - switch (cmd->opcode) { - case 0x28: /* READ_BIG (10) */ - case 0xa8: /* READ_HUGE (12) */ - case 0x2a: /* WRITE_BIG (10) */ - case 0xaa: /* WRITE_HUGE(12) */ - PRINT_ADDR(xp); - printf ("access to partial disk block refused.\n"); - xp->error = XS_DRIVER_STUFFUP; - return(COMPLETE); - }; - }; - - if ((unsigned)xp->datalen > 128*1024*1024) { - PRINT_ADDR(xp); - printf ("trying to transfer %8x bytes, mem addr = %p\n", - xp->datalen, xp->data); - { - int j; - PRINT_ADDR(xp); - printf ("command: %2x (", cmd->opcode); - for (j = 0; j<11; j++) - printf (" %2x", cmd->bytes[j]); - printf (")\n"); - } - } - - if (DEBUG_FLAGS & DEBUG_TINY) { - PRINT_ADDR(xp); - printf ("CMD=%x F=%x A=%p L=%x ", - cmd->opcode, (unsigned)xp->flags, xp->data, - (unsigned)xp->datalen); - } - - /*-------------------------------------------- - ** - ** Sanity checks ... - ** copied from Elischer's Adaptec driver. - ** - **-------------------------------------------- - */ - - flags = xp->flags; - if(flags & ITSDONE) { - printf("%s: ?ITSDONE?\n", ncr_name (np)); - xp->flags &= ~ITSDONE; - }; - - if (xp->bp) - flags |= (SCSI_NOSLEEP); /* just to be sure */ - - /*--------------------------------------------------- - ** - ** Assign a ccb / bind xp - ** - **---------------------------------------------------- - */ - -#if defined(__mips__) - if (xp->data && xp->datalen) { - pci_sync_cache(np->sc_pc, (vm_offset_t)xp->data, xp->datalen); - } - pci_sync_cache(np->sc_pc, (vm_offset_t)xp->cmd, xp->cmdlen); - pci_sync_cache(np->sc_pc, (vm_offset_t)&xp->sense, sizeof(struct scsi_sense_data)); -#endif /* __mips__ */ - - oldspl = splbio(); - - if (!(cp=ncr_get_ccb (np, flags, xp->sc_link->target, - xp->sc_link->lun))) { - printf ("%s: no ccb.\n", ncr_name (np)); - xp->error = XS_DRIVER_STUFFUP; - splx(oldspl); - return(TRY_AGAIN_LATER); - }; - cp->xfer = xp; - - /*--------------------------------------------------- - ** - ** timestamp - ** - **---------------------------------------------------- - */ - - bzero (&cp->phys.header.stamp, sizeof (struct tstamp)); -#ifdef __OpenBSD__ - microuptime(&cp->phys.header.stamp.start); -#else - gettime(&cp->phys.header.stamp.start); -#endif - - /*---------------------------------------------------- - ** - ** Get device quirks from a speciality table. - ** - ** @GENSCSI@ - ** This should be a part of the device table - ** in "scsi_conf.c". - ** - **---------------------------------------------------- - */ - - if (tp->quirks & QUIRK_UPDATE) { -#ifdef __OpenBSD__ - tp->quirks = ncr_lookup ((char *) &tp->inqdata[0]); -#else - int q = xp->sc_link->quirks; - tp->quirks = QUIRK_NOMSG; - if (q & SD_Q_NO_TAGS) - tp->quirks |= QUIRK_NOTAGS; - if (q & SD_Q_NO_SYNC) - tp->quirks |= QUIRK_NOSYNC; - if (q & SD_Q_NO_WIDE) - tp->quirks |= QUIRK_NOWIDE16; -#endif - if (bootverbose && (tp->quirks & ~QUIRK_NOMSG)) { - PRINT_ADDR(xp); - printf ("NCR quirks=0x%x\n", tp->quirks); - }; - /* - ** set number of tags - */ - ncr_setmaxtags (tp, tp->usrtags); - }; - - /*--------------------------------------------------- - ** - ** negotiation required? - ** - **---------------------------------------------------- - */ - - nego = 0; - - if (!tp->nego_cp && tp->inqdata[7]) { - /* - ** negotiate wide transfers ? - */ - - if (!tp->widedone) { - if (tp->inqdata[7] & INQ7_WIDE16) { - nego = NS_WIDE; - } else - tp->widedone=1; - }; - - /* - ** negotiate synchronous transfers? - */ - - if (!nego && !tp->period) { - if (SCSI_NCR_DFLT_SYNC -#ifdef NCR_CDROM_ASYNC - && ((tp->inqdata[0] & 0x1f) != 5) -#endif /* NCR_CDROM_ASYNC */ - && (tp->inqdata[7] & INQ7_SYNC)) { - nego = NS_SYNC; - } else { - tp->period =0xffff; - tp->sval = 0xe0; - PRINT_ADDR(xp); - printf ("asynchronous.\n"); - }; - }; - - /* - ** remember nego is pending for the target. - ** Avoid to start a nego for all queued commands - ** when tagged command queuing is enabled. - */ - - if (nego) - tp->nego_cp = cp; - }; - - /*--------------------------------------------------- - ** - ** choose a new tag ... - ** - **---------------------------------------------------- - */ - - if ((lp = tp->lp[xp->sc_link->lun]) && (lp->usetags)) { - /* - ** assign a tag to this ccb! - */ - while (!cp->tag) { - ccb_p cp2 = lp->next_ccb; - lp->lasttag = lp->lasttag % 255 + 1; - while (cp2 && cp2->tag != lp->lasttag) - cp2 = cp2->next_ccb; - if (cp2) continue; - cp->tag=lp->lasttag; - if (DEBUG_FLAGS & DEBUG_TAGS) { - PRINT_ADDR(xp); - printf ("using tag #%d.\n", cp->tag); - }; - }; - } else { - cp->tag=0; - }; - - /*---------------------------------------------------- - ** - ** Build the identify / tag / sdtr message - ** - **---------------------------------------------------- - */ - - idmsg = M_IDENTIFY | xp->sc_link->lun; - if ((cp!=np->ccb) && (np->disc)) - idmsg |= 0x40; - - msgptr = cp->scsi_smsg; - msglen = 0; - msgptr[msglen++] = idmsg; - - if (cp->tag) { - char tag; - - tag = np->order; - if (tag == 0) { - /* - ** Ordered write ops, unordered read ops. - */ - switch (cmd->opcode) { - case 0x08: /* READ_SMALL (6) */ - case 0x28: /* READ_BIG (10) */ - case 0xa8: /* READ_HUGE (12) */ - tag = M_SIMPLE_TAG; - break; - default: - tag = M_ORDERED_TAG; - } - } - msgptr[msglen++] = tag; - msgptr[msglen++] = cp -> tag; - } - - switch (nego) { - case NS_SYNC: - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 3; - msgptr[msglen++] = M_X_SYNC_REQ; - msgptr[msglen++] = tp->minsync; - msgptr[msglen++] = tp->maxoffs; - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - printf ("sync msgout: "); - ncr_show_msg (&cp->scsi_smsg [msglen-5]); - printf (".\n"); - }; - break; - case NS_WIDE: - msgptr[msglen++] = M_EXTENDED; - msgptr[msglen++] = 2; - msgptr[msglen++] = M_X_WIDE_REQ; - msgptr[msglen++] = tp->usrwide; - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - 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 - ** - **---------------------------------------------------- - */ - - segments = ncr_scatter (np, &cp->phys, (vm_offset_t) xp->data, - (vm_size_t) xp->datalen); - - if (segments < 0) { - xp->error = XS_DRIVER_STUFFUP; - ncr_free_ccb(np, cp, flags); - splx(oldspl); - return(COMPLETE); - }; - - /*---------------------------------------------------- - ** - ** Set the SAVED_POINTER. - ** - **---------------------------------------------------- - */ - - if (flags & SCSI_DATA_IN) { - u_long sp; - sp = NCB_SCRIPT_PHYS (np, data_in); - cp->phys.header.savep = SCR_BO(sp); - cp->phys.header.goalp = SCR_BO(sp + 20 + segments * 16); - } else if (flags & SCSI_DATA_OUT) { - u_long sp; - sp = NCB_SCRIPT_PHYS (np, data_out); - cp->phys.header.savep = SCR_BO(sp); - cp->phys.header.goalp = SCR_BO(sp + 20 + segments * 16); - } else { - cp->phys.header.savep = SCR_BO(NCB_SCRIPT_PHYS (np, no_data)); - cp->phys.header.goalp = cp->phys.header.savep; - }; - cp->phys.header.lastp = cp->phys.header.savep; - - - /*---------------------------------------------------- - ** - ** fill in ccb - ** - **---------------------------------------------------- - ** - ** - ** physical -> virtual backlink - ** Generic SCSI command - */ - cp->phys.header.cp = cp; - /* - ** Startqueue - */ - cp->phys.header.launch.l_paddr = SCR_BO(NCB_SCRIPT_PHYS (np, select)); - cp->phys.header.launch.l_cmd = SCR_BO(SCR_JUMP); - /* - ** select - */ - cp->phys.select.sel_id = xp->sc_link->target; - cp->phys.select.sel_scntl3 = tp->wval; - cp->phys.select.sel_sxfer = tp->sval; - /* - ** message - */ - cp->phys.smsg.addr = SCR_BO(CCB_PHYS (cp, scsi_smsg)); - cp->phys.smsg.size = SCR_BO(msglen); - - cp->phys.smsg2.addr = SCR_BO(CCB_PHYS (cp, scsi_smsg2)); - cp->phys.smsg2.size = SCR_BO(msglen2); - /* - ** command - */ - cp->phys.cmd.addr = SCR_BO(NCR_KVATOPHYS (np, cmd)); - cp->phys.cmd.size = SCR_BO(xp->cmdlen); - /* - ** sense command - */ - cp->phys.scmd.addr = SCR_BO(CCB_PHYS (cp, sensecmd)); - cp->phys.scmd.size = SCR_BO(6); - /* - ** patch requested size into sense command - */ - cp->sensecmd[0] = 0x03; - cp->sensecmd[1] = xp->sc_link->lun << 5; - cp->sensecmd[4] = sizeof(struct scsi_sense_data); - if (xp->req_sense_length) - cp->sensecmd[4] = xp->req_sense_length; - /* - ** sense data - */ -#if defined(__mips__) - cp->phys.sense.addr = SCR_BO(NCR_KVATOPHYS (np, &cp->local_sense)); -#else - cp->phys.sense.addr = SCR_BO(NCR_KVATOPHYS (np, &cp->xfer->sense)); -#endif - cp->phys.sense.size = SCR_BO(sizeof(struct scsi_sense_data)); - /* - ** status - */ - cp->actualquirks = tp->quirks; - cp->host_status = nego ? HS_NEGOTIATE : HS_BUSY; - cp->scsi_status = S_ILLEGAL; - cp->parity_status = 0; - - cp->xerr_status = XE_OK; - cp->sync_status = tp->sval; - cp->nego_status = nego; - cp->wide_status = tp->wval; - - /*---------------------------------------------------- - ** - ** Critical region: start this job. - ** - **---------------------------------------------------- - */ - - /* - ** reselect pattern and activate this job. - */ - - cp->jump_ccb.l_cmd = SCR_BO((SCR_JUMP ^ IFFALSE (DATA (cp->tag)))); -#ifdef __OpenBSD__ - cp->tlimit = time_uptime + xp->timeout / 1000 + 2; -#else - cp->tlimit = time.tv_sec + xp->timeout / 1000 + 2; -#endif - cp->magic = CCB_MAGIC; - - /* - ** insert into start queue. - */ - - qidx = np->squeueput + 1; - if (qidx >= MAX_START) qidx=0; - np->squeue [qidx ] = SCR_BO(NCB_SCRIPT_PHYS (np, idle)); - np->squeue [np->squeueput] = SCR_BO(CCB_PHYS (cp, phys)); - np->squeueput = qidx; - - if(DEBUG_FLAGS & DEBUG_QUEUE) - printf ("%s: queuepos=%d tryoffset=%d.\n", ncr_name (np), - 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); - - /* - ** and reenable interrupts - */ -#ifdef __OpenBSD__ - pollmode = flags & SCSI_POLL; -#else - pollmode = flags & SCSI_NOMASK; -#endif - splx (oldspl); - - /* - ** If interrupts are enabled, return now. - ** Command is successfully queued. - */ - - if (!pollmode) { - if(DEBUG_FLAGS & DEBUG_TINY) printf ("Q"); - return(SUCCESSFULLY_QUEUED); - }; - - /*---------------------------------------------------- - ** - ** Interrupts not yet enabled - have to poll. - ** - **---------------------------------------------------- - */ - - if (DEBUG_FLAGS & DEBUG_POLL) printf("P"); - - for (i=xp->timeout; i && !(xp->flags & ITSDONE);i--) { - if ((DEBUG_FLAGS & DEBUG_POLL) && (cp->host_status)) - printf ("%c", (cp->host_status & 0xf) + '0'); - DELAY (1000); - ncr_exception (np); - }; - - /* - ** Abort if command not done. - */ - if (!(xp->flags & ITSDONE)) { - printf ("%s: aborting job ...\n", ncr_name (np)); - OUTB (nc_istat, CABRT); - DELAY (100000); - OUTB (nc_istat, SIGP); - ncr_exception (np); - }; - - if (!(xp->flags & ITSDONE)) { - printf ("%s: abortion failed at %x.\n", - ncr_name (np), (unsigned) INL(nc_dsp)); - ncr_init (np, "timeout", HS_TIMEOUT); - }; - - if (!(xp->flags & ITSDONE)) { - cp-> host_status = HS_SEL_TIMEOUT; - ncr_complete (np, cp); - }; - - if (DEBUG_FLAGS & DEBUG_RESULT) { - printf ("%s: result: %x %x.\n", - ncr_name (np), cp->host_status, cp->scsi_status); - }; - switch (xp->error) { - case 0 : return (COMPLETE); - case XS_BUSY: return (TRY_AGAIN_LATER); - }; - return (COMPLETE); -} - -/*========================================================== -** -** -** Complete execution of a SCSI command. -** Signal completion to the generic SCSI driver. -** -** -**========================================================== -*/ - -void ncr_complete (ncb_p np, ccb_p cp) -{ - struct scsi_xfer * xp; - tcb_p tp; - lcb_p lp; - - /* - ** Sanity check - */ - - if (!cp || (cp->magic!=CCB_MAGIC) || !cp->xfer) return; - cp->magic = 1; - cp->tlimit= 0; - - /* - ** No Reselect anymore. - */ - cp->jump_ccb.l_cmd = SCR_BO((SCR_JUMP)); - - /* - ** No starting. - */ - cp->phys.header.launch.l_paddr= SCR_BO(NCB_SCRIPT_PHYS (np, idle)); - - /* - ** timestamp - */ - ncb_profile (np, cp); - - if (DEBUG_FLAGS & DEBUG_TINY) - printf ("CCB=%lx STAT=%x/%x\n", (unsigned long)cp & 0xfff, - cp->host_status,cp->scsi_status); - - xp = cp->xfer; - cp->xfer = NULL; - tp = &np->target[xp->sc_link->target]; - lp = tp->lp[xp->sc_link->lun]; - -#if defined(__mips__) - /* - ** Move sense data back to request struct. - */ - { - int i; - u_char *p = (u_char *)&xp->sense; - for(i = 0; i < sizeof(struct scsi_sense_data); i++) { - *p++ = cp->local_sense[i]; - } - } -#endif - /* - ** We do not queue more than 1 ccb per target - ** with negotiation at any time. If this ccb was - ** used for negotiation, clear this info in the tcb. - */ - - if (cp == tp->nego_cp) - tp->nego_cp = 0; - - /* - ** Check for parity errors. - */ - - if (cp->parity_status) { - PRINT_ADDR(xp); - printf ("%d parity error(s), fallback.\n", cp->parity_status); - /* - ** fallback to asynch transfer. - */ - tp->usrsync=255; - tp->period = 0; - }; - - /* - ** Check for extended errors. - */ - - if (cp->xerr_status != XE_OK) { - PRINT_ADDR(xp); - 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. - */ -#ifdef __OpenBSD__ - if (xp->error != XS_NOERROR) { - - /* - ** Don't override the error value. - */ - } else -#endif /* __OpenBSD__ */ - if ( (cp->host_status == HS_COMPLETE) - && (cp->scsi_status == S_GOOD)) { - - /* - ** All went well. - */ - - xp->resid = 0; - - /* - ** if (cp->phys.header.lastp != cp->phys.header.goalp)... - ** - ** @RESID@ - ** Could dig out the correct value for resid, - ** but it would be quite complicated. - ** - ** The ah1542.c driver sets it to 0 too ... - */ - - /* - ** Try to assign a ccb to this nexus - */ - ncr_alloc_ccb (np, xp->sc_link->target, xp->sc_link->lun); - - /* - ** On inquire cmd (0x12) save some data. - */ - if (xp->cmd->opcode == 0x12 && xp->sc_link->lun == 0) { - bcopy ( xp->data, - &tp->inqdata, - sizeof (tp->inqdata)); - /* - ** prepare negotiation of synch and wide. - */ - ncr_negotiate (np, tp); - - /* - ** force quirks update before next command start - */ - tp->quirks |= QUIRK_UPDATE; - }; - - /* - ** Announce changes to the generic driver - */ - if (lp) { - if (lp->reqlink != lp->actlink) - ncr_opennings (np, lp, xp); - }; - - tp->bytes += xp->datalen; - tp->transfers ++; -#ifndef __OpenBSD__ - } else if (xp->flags & SCSI_ERR_OK) { - - /* - ** Not correct, but errors expected. - */ - xp->resid = 0; -#endif /* !__OpenBSD__ */ - } else if ((cp->host_status == HS_COMPLETE) - && (cp->scsi_status == (S_SENSE|S_GOOD))) { - - /* - ** Check condition code - */ - xp->error = XS_SENSE; - - if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) { - u_char * p = (u_char *) & xp->sense; - int i; - printf ("\n%s: sense data:", ncr_name (np)); - for (i=0; i<14; i++) printf (" %x", *p++); - printf (".\n"); - }; - - } else if ((cp->host_status == HS_COMPLETE) - && ((cp->scsi_status == S_BUSY) - || (cp->scsi_status == S_CONFLICT))) { - - /* - ** Target is busy, or reservation conflict - */ - xp->error = XS_BUSY; - - } else if (cp->host_status == HS_SEL_TIMEOUT) { - - /* - ** Device failed selection - */ - xp->error = XS_SELTIMEOUT; - - } else if(cp->host_status == HS_TIMEOUT) { - - /* - ** No response - */ - xp->error = XS_TIMEOUT; - - } else { - - /* - ** Other protocol messes - */ - PRINT_ADDR(xp); - printf ("COMMAND FAILED (%x %x) @%p.\n", - cp->host_status, cp->scsi_status, cp); - - xp->error = XS_TIMEOUT; - } - - xp->flags |= ITSDONE; - - /* - ** trace output - */ - - if (tp->usrflag & UF_TRACE) { - u_char * p; - int i; - PRINT_ADDR(xp); - printf (" CMD:"); - p = (u_char *) &xp->cmd->opcode; - for (i=0; i<xp->cmdlen; i++) printf (" %x", *p++); - - if (cp->host_status==HS_COMPLETE) { - switch (cp->scsi_status) { - case S_GOOD: - printf (" GOOD"); - break; - case S_CHECK_COND: - printf (" SENSE:"); - p = (u_char *) &xp->sense; - for (i=0; i<xp->req_sense_length; i++) - printf (" %x", *p++); - break; - default: - printf (" STAT: %x\n", cp->scsi_status); - break; - }; - } else printf (" HOSTERROR: %x", cp->host_status); - printf ("\n"); - }; - - /* - ** Free this ccb - */ - ncr_free_ccb (np, cp, xp->flags); - - /* - ** signal completion to generic driver. - */ - scsi_done (xp); -} - -/*========================================================== -** -** -** Signal all (or one) control block done. -** -** -**========================================================== -*/ - -void ncr_wakeup (ncb_p np, u_long code) -{ - /* - ** Starting at the default ccb 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. - */ - - ccb_p cp = np->ccb; - while (cp) { - switch (cp->host_status) { - - case HS_IDLE: - break; - - case HS_DISCONNECT: - if(DEBUG_FLAGS & DEBUG_TINY) printf ("D"); - /* fall through */ - - case HS_BUSY: - case HS_NEGOTIATE: - if (!code) break; - cp->host_status = code; - - /* fall through */ - - default: - ncr_complete (np, cp); - break; - }; - cp = cp -> link_ccb; - }; -} - -/*========================================================== -** -** -** Start NCR chip. -** -** -**========================================================== -*/ - -void ncr_init (ncb_p np, char * msg, u_long code) -{ - int i; - u_long usrsync; - u_char usrwide; - - /* - ** Reset chip. - */ - - OUTB (nc_istat, SRST); - DELAY (1000); - OUTB (nc_istat, 0); - - /* - ** Message. - */ - - if (msg) printf ("%s: restart (%s).\n", ncr_name (np), msg); - - /* - ** Clear Start Queue - */ - - for (i=0;i<MAX_START;i++) - np -> squeue [i] = SCR_BO(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<<np->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); - } - - /* - ** Reinitialize usrsync. - ** Have to renegotiate synch mode. - */ - - usrsync = 255; - if (SCSI_NCR_DFLT_SYNC) { - usrsync = SCSI_NCR_DFLT_SYNC; - if (usrsync > np->maxsync) - usrsync = np->maxsync; - if (usrsync < np->minsync) - usrsync = np->minsync; - }; - - /* - ** Reinitialize usrwide. - ** Have to renegotiate wide mode. - */ - - usrwide = (SCSI_NCR_MAX_WIDE); - if (usrwide > np->maxwide) usrwide=np->maxwide; - - /* - ** Disable disconnects. - */ - - np->disc = 0; - - /* - ** Fill in target structure. - */ - - for (i=0;i<MAX_TARGET;i++) { - tcb_p tp = &np->target[i]; - - tp->sval = 0; - tp->wval = np->rv_scntl3; - - tp->usrsync = usrsync; - tp->usrwide = usrwide; - - ncr_negotiate (np, tp); - } - - /* - ** 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)); -} - -/*========================================================== -** -** Prepare the negotiation values for wide and -** synchronous transfers. -** -**========================================================== -*/ - -static void ncr_negotiate (struct ncb* np, struct tcb* tp) -{ - /* - ** minsync unit is 4ns ! - */ - - u_long minsync = tp->usrsync; - - /* - ** if not scsi 2 - ** don't believe FAST! - */ - - if ((minsync < 50) && (tp->inqdata[2] & 0x0f) < 2) - minsync=50; - - /* - ** our limit .. - */ - - if (minsync < np->minsync) - minsync = np->minsync; - - /* - ** divider limit - */ - - if (minsync > np->maxsync) - minsync = 255; - - tp->minsync = minsync; - tp->maxoffs = (minsync<255 ? np->maxoffs : 0); - - /* - ** period=0: has to negotiate sync transfer - */ - - tp->period=0; - - /* - ** widedone=0: has to negotiate wide transfer - */ - tp->widedone=0; -} - -/*========================================================== -** -** 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 usefull */ - - 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 it's target -** -**========================================================== -*/ - -static void ncr_setsync (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer) -{ - struct scsi_xfer *xp; - tcb_p tp; - int div; - u_char target = INB (nc_sdid) & 0x0f; - - assert (cp); - if (!cp) return; - - xp = cp->xfer; - assert (xp); - if (!xp) return; - assert (target == (xp->sc_link->target & 0x0f)); - - tp = &np->target[target]; - - if (!scntl3 || !(sxfer & 0x1f)) - scntl3 = np->rv_scntl3; - scntl3 = (scntl3 & 0xf0) | (tp->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) - tp->period = (((sxfer>>5)+4)*div_10M[div-1])/np->clock_khz; - else - tp->period = 0xffff; - - /* - ** Stop there if sync parameters are unchanged - */ - - if (tp->sval == sxfer && tp->wval == scntl3) return; - tp->sval = sxfer; - tp->wval = scntl3; - - /* - ** Bells and whistles ;-) - */ - PRINT_ADDR(xp); - if (sxfer & 0x1f) { - unsigned f10 = 100000 << (tp->widedone ? tp->widedone -1 : 0); - unsigned mb10 = (f10 + tp->period/2) / tp->period; - /* - ** Disable extended Sreq/Sack filtering - */ - if (tp->period <= 2000) OUTOFFB (nc_stest2, EXT); - printf ("%d.%d MB/s (%d ns, offset %d)\n", - mb10 / 10, mb10 % 10, tp->period / 10, sxfer & 0x1f); - } else printf ("asynchronous.\n"); - - /* - ** set actual value and sync_status - */ - OUTB (nc_sxfer, sxfer); - np->sync_st = sxfer; - OUTB (nc_scntl3, scntl3); - np->wide_st = scntl3; - - /* - ** patch ALL ccbs of this target. - */ - for (cp = np->ccb; cp; cp = cp->link_ccb) { - if (!cp->xfer) continue; - if (cp->xfer->sc_link->target != target) continue; - cp->sync_status = sxfer; - cp->wide_status = scntl3; - }; -} - -/*========================================================== -** -** Switch wide mode for current job and it's 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, ccb_p cp, u_char wide, u_char ack) -{ - struct scsi_xfer *xp; - u_short target = INB (nc_sdid) & 0x0f; - tcb_p tp; - u_char scntl3; - u_char sxfer; - - assert (cp); - if (!cp) return; - - xp = cp->xfer; - assert (xp); - if (!xp) return; - assert (target == (xp->sc_link->target & 0x0f)); - - tp = &np->target[target]; - tp->widedone = wide+1; - scntl3 = (tp->wval & (~EWS)) | (wide ? EWS : 0); - - sxfer = ack ? 0 : tp->sval; - - /* - ** Stop there if sync/wide parameters are unchanged - */ - if (tp->sval == sxfer && tp->wval == scntl3) return; - tp->sval = sxfer; - tp->wval = scntl3; - - /* - ** Bells and whistles ;-) - */ - PRINT_ADDR(xp); - if (scntl3 & EWS) - printf ("WIDE SCSI (16 bit) enabled\n"); - else - printf ("WIDE SCSI disabled\n"); - - /* - ** set actual value and sync_status - */ - OUTB (nc_sxfer, sxfer); - np->sync_st = sxfer; - OUTB (nc_scntl3, scntl3); - np->wide_st = scntl3; - - /* - ** patch ALL ccbs of this target. - */ - for (cp = np->ccb; cp; cp = cp->link_ccb) { - if (!cp->xfer) continue; - if (cp->xfer->sc_link->target != target) continue; - cp->sync_status = sxfer; - cp->wide_status = scntl3; - }; -} - -/*========================================================== -** -** Switch tagged mode for a target. -** -**========================================================== -*/ - -static void ncr_setmaxtags (tcb_p tp, u_long usrtags) -{ - int l; - for (l=0; l<MAX_LUN; l++) { - lcb_p lp; - if (!tp) break; - lp=tp->lp[l]; - if (!lp) continue; - ncr_settags (tp, lp, usrtags); - }; -} - -static void ncr_settags (tcb_p tp, lcb_p lp, u_long usrtags) -{ - u_char reqtags, tmp; - - if ((!tp) || (!lp)) return; - - /* - ** only devices capable of tagges commands - ** only disk devices - ** only if enabled by user .. - */ - if ((tp->inqdata[0] & 0x1f) != 0x00 - || (tp->inqdata[7] & INQ7_QUEUE) == 0 - || (tp->quirks & QUIRK_NOTAGS) != 0) { - usrtags=0; - } - if (usrtags) { - reqtags = usrtags; - if (lp->actlink <= 1) - lp->usetags=reqtags; - } else { - reqtags = 1; - if (lp->actlink <= 1) - lp->usetags=0; - }; - - /* - ** don't announce more than available. - */ - tmp = lp->actccbs; - if (tmp > reqtags) tmp = reqtags; - lp->reqlink = tmp; - - /* - ** don't discard if announced. - */ - tmp = lp->actlink; - if (tmp < reqtags) tmp = reqtags; - lp->reqccbs = tmp; - if (lp->reqlink < lp->reqccbs) - lp->reqlink = lp->reqccbs; -} - -/*---------------------------------------------------- -** -** handle user commands -** -**---------------------------------------------------- -*/ - -static void ncr_usercmd (ncb_p np) -{ - u_char t; - tcb_p tp; - - switch (np->user.cmd) { - - case 0: return; - - case UC_SETSYNC: - for (t=0; t<MAX_TARGET; t++) { - if (!((np->user.target>>t)&1)) continue; - tp = &np->target[t]; - tp->usrsync = np->user.data; - ncr_negotiate (np, tp); - }; - break; - - case UC_SETTAGS: - if (np->user.data > MAX_TAGS) - break; - for (t=0; t<MAX_TARGET; t++) { - if (!((np->user.target>>t)&1)) continue; - tp = &np->target[t]; - tp->usrtags = np->user.data; - ncr_setmaxtags (tp, tp->usrtags); - }; - break; - - case UC_SETDEBUG: - ncr_debug = np->user.data; - break; - - case UC_SETORDER: - np->order = np->user.data; - break; - - case UC_SETWIDE: - for (t=0; t<MAX_TARGET; t++) { - u_long size; - if (!((np->user.target>>t)&1)) continue; - tp = &np->target[t]; - size = np->user.data; - if (size > np->maxwide) size=np->maxwide; - tp->usrwide = size; - ncr_negotiate (np, tp); - }; - break; - - case UC_SETFLAG: - for (t=0; t<MAX_TARGET; t++) { - if (!((np->user.target>>t)&1)) continue; - tp = &np->target[t]; - tp->usrflag = np->user.data; - }; - break; - } - np->user.cmd=0; -} - - - - -/*========================================================== -** -** -** 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; -#ifdef __OpenBSD__ - u_long thistime = time_uptime; -#else - u_long thistime = time.tv_sec; -#endif - u_long step = np->ticks; - u_long count = 0; - long signed t; - ccb_p cp; - - if (np->lasttime != thistime) { - /* - ** block ncr interrupts - */ - int oldspl = splbio(); - np->lasttime = thistime; - - ncr_usercmd (np); - - /*---------------------------------------------------- - ** - ** 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 ccb timeouts - ** - **---------------------------------------------------- - */ - - for (cp=np->ccb; cp; cp=cp->link_ccb) { - /* - ** look for timed out ccbs. - */ - if (!cp->host_status) continue; - count++; - if (cp->tlimit > thistime) continue; - - /* - ** Disable reselect. - ** Remove it from startqueue. - */ - cp->jump_ccb.l_cmd = SCR_BO((SCR_JUMP)); - if (cp->phys.header.launch.l_paddr == - SCR_BO(NCB_SCRIPT_PHYS (np, select))) { - printf ("%s: timeout ccb=%p (skip)\n", - ncr_name (np), cp); - cp->phys.header.launch.l_paddr - = SCR_BO(NCB_SCRIPT_PHYS (np, skip)); - }; - - switch (cp->host_status) { - - case HS_BUSY: - case HS_NEGOTIATE: - /* - ** still in start queue ? - */ - if (cp->phys.header.launch.l_paddr == - SCR_BO(NCB_SCRIPT_PHYS (np, skip))) - continue; - - /* fall through */ - case HS_DISCONNECT: - cp->host_status=HS_TIMEOUT; - }; - cp->tag = 0; - - /* - ** wakeup this ccb. - */ - ncr_complete (np, cp); - }; - splx (oldspl); - } - -#ifdef __FreeBSD__ - np->timeout_ch = timeout (ncr_timeout, (caddr_t) np, step ? step : 1); -#else - timeout_add(&np->sc_timeout, step ? step : 1); -#endif - - if (INB(nc_istat) & (INTF|SIP|DIP)) { - - /* - ** Process pending interrupts. - */ - - int oldspl = splbio (); - if (DEBUG_FLAGS & DEBUG_TINY) printf ("{"); - ncr_exception (np); - if (DEBUG_FLAGS & DEBUG_TINY) printf ("}"); - splx (oldspl); - }; -} - -/*========================================================== -** -** 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 driven 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 = 0; - script_name = "mem"; - } - - printf ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%s %x:%08x).\n", - ncr_name (np), (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) { - printf ("%s: script cmd = %08x\n", ncr_name(np), - (int)READSCRIPT_OFF(script_base, script_ofs)); - } - - printf ("%s: regdump:", ncr_name(np)); - for (i=0; i<16;i++) - printf (" %02x", (unsigned)INB_OFF(i)); - printf (".\n"); -} - -/*========================================================== -** -** -** ncr chip exception handler. -** -** -**========================================================== -*/ - -void ncr_exception (ncb_p np) -{ - u_int8_t istat, dstat; - u_int16_t 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 - **======================================== - */ - -#ifdef __OpenBSD__ - if (time_uptime - np->regtime.tv_sec>10) { - int i; - microuptime(&np->regtime); -#else - if (time.tv_sec - np->regtime.tv_sec>10) { - int i; - gettime(&np->regtime); -#endif - for (i=0; i<sizeof(np->regdump); i++) - ((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)) { - printf ("%s: have to clear fifos.\n", ncr_name (np)); - OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */ - OUTB (nc_ctest3, np->rv_ctest3 | CLF); - /* clear dma fifo */ - } - - /*---------------------------------------- - ** handshake timeout - **---------------------------------------- - */ - - if (sist & HTH) { - printf ("%s: handshake timeout\n", ncr_name(np)); - OUTB (nc_scntl1, CRST); - DELAY (1000); - OUTB (nc_scntl1, 0x00); - OUTB (nc_scr0, HS_FAIL); - OUTL (nc_dsp, 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 - */ - printf ("%s: INFO: LDSC while IID.\n", - ncr_name (np)); - return; - }; - printf ("%s: target %d doesn't release the bus.\n", - ncr_name (np), 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: - printf ("%s: reg[%d0]: ", - ncr_name(np),i/16); - break; - case 4: - case 8: - case 12: - printf (" "); - break; - }; - val = INB_OFF(i); - printf (" %x%x", val/16, val%16); - if (i%16==15) printf (".\n"); - }; - -#ifdef __FreeBSD__ - untimeout (ncr_timeout, (caddr_t) np, np->timeout_ch); -#else - timeout_del(&np->sc_timeout); -#endif - - printf ("%s: halted!\n", ncr_name(np)); - /* - ** 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 ..."); - (void) splhigh(); - 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. -** -**---------------------------------------------------------- -*/ - -void ncr_int_sto (ncb_p np) -{ - u_long dsa, scratcha, diff; - ccb_p cp; - if (DEBUG_FLAGS & DEBUG_TINY) printf ("T"); - - /* - ** look for ccb and set the status. - */ - - dsa = INL (nc_dsa); - cp = np->ccb; - while (cp && (CCB_PHYS (cp, phys) != dsa)) - cp = cp->link_ccb; - - 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; - void *vdsp_base; - size_t vdsp_off; - u_int32_t oadr, olen; - u_int32_t *tblp; - ncrcmd *newcmd; - u_int32_t cmd, sbcl, delta, ss0, ss2, ctest5; - ccb_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 - */ - dsa = INL (nc_dsa); - cp = np->ccb; - while (cp && (CCB_PHYS (cp, phys) != dsa)) - cp = cp->link_ccb; - - if (!cp) { - printf ("%s: SCSI phase error fixup: CCB already dequeued (%p)\n", - ncr_name (np), np->header.cp); - return; - } - if (cp != np->header.cp) { - printf ("%s: SCSI phase error fixup: CCB address mismatch (0x%08lx != 0x%08lx) np->ccb = %p\n", - ncr_name (np), (u_long) cp, (u_long) np->header.cp, np->ccb); -/* return;*/ - } - - /* - ** find the interrupted script command, - ** and the address at which to continue. - */ - - if (dsp == NCR_KVATOPHYS (np, &cp->patch[2])) { - vdsp_base = cp; - vdsp_off = offsetof(struct ccb, patch[0]); - nxtdsp = READSCRIPT_OFF(vdsp_base, vdsp_off + 3*4); - } else if (dsp == NCR_KVATOPHYS (np, &cp->patch[6])) { - vdsp_base = cp; - vdsp_off = offsetof(struct ccb, 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_BASE=%p VDSP_OFF=0x%x CMD=%x ", - cp, np->header.cp, (unsigned)dsp, - (unsigned)nxtdsp, vdsp_base, (unsigned)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 = SCR_BO(tblp[0]); - oadr = SCR_BO(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=%x OADR=%x\n", - (unsigned) (READSCRIPT_OFF(vdsp_base, vdsp_off) >> 24), - tblp, - (unsigned) olen, - (unsigned) oadr); - }; - - /* - ** if old phase not dataphase, leave here. - */ - - if (cmd != (READSCRIPT_OFF(vdsp_base, vdsp_off) >> 24)) { - PRINT_ADDR(cp->xfer); - 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->xfer); - 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 == SCR_BO(NCR_KVATOPHYS (np, newcmd))) newcmd+=4; - - /* - ** fillin the commands - */ - - newcmd[0] = SCR_BO(((cmd & 0x0f) << 24) | rest); - newcmd[1] = SCR_BO(oadr + olen - rest); - newcmd[2] = SCR_BO(SCR_JUMP); - newcmd[3] = SCR_BO(nxtdsp); - - if (DEBUG_FLAGS & DEBUG_PHASE) { - PRINT_ADDR(cp->xfer); - printf ("newcmd[%ld] %x %x %x %x.\n", - (long)(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, NCR_KVATOPHYS (np, 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==M_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); -} - -void ncr_int_sir (ncb_p np) -{ - u_char scntl3; - u_char chg, ofs, per, fak, wide; - u_char num = INB (nc_dsps); - ccb_p cp=0; - u_long dsa; - u_char 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 ccb - */ - dsa = INL (nc_dsa); - cp = np->ccb; - while (cp && (CCB_PHYS (cp, phys) != dsa)) - cp = cp->link_ccb; - - 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) - printf ("%s: int#%d",ncr_name (np),num); - cp = (ccb_p) 0; - for (i=0; i<MAX_TARGET; i++) { - if (DEBUG_FLAGS & DEBUG_RESTART) printf (" t%d", i); - tp = &np->target[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->scsi_status==S_CHECK_COND)) - break; - if (DEBUG_FLAGS & DEBUG_RESTART) printf ("- (remove)"); - tp->hold_cp = cp = (ccb_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->xfer); - printf ("in getcc reselect by t%d.\n", - INB(nc_ssid) & 0x0f); - } - - /* - ** Mark this job - */ - cp->host_status = HS_BUSY; - cp->scsi_status = S_CHECK_COND; - np->target[cp->xfer->sc_link->target].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 immidiately -** (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 ccbs 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); - - /* fall through */ - - case SIR_NEGO_PROTO: - /*------------------------------------------------------- - ** - ** Negotiation failed. - ** Target doesn't fetch the answer message. - ** - **------------------------------------------------------- - */ - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - 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); - break; - - case NS_WIDE: - ncr_setwide (np, cp, 0, 0); - break; - - }; - np->msgin [0] = M_NOOP; - np->msgout[0] = M_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->xfer); - 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; - - /* - ** if target sends SDTR message, - ** it CAN transfer synch. - */ - - if (ofs) - tp->inqdata[7] |= INQ7_SYNC; - - /* - ** check values against driver limits. - */ - - if (per < np->minsync) - {chg = 1; per = np->minsync;} - if (per < tp->minsync) - {chg = 1; per = tp->minsync;} - if (ofs > tp->maxoffs) - {chg = 1; ofs = tp->maxoffs;} - - /* - ** 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; - tp->minsync = 0; - } - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - 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); - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, msg_bad)); - } else { - /* - ** Answer is ok. - */ - ncr_setsync (np,cp,scntl3,(fak<<5)|ofs); - 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); - - np->msgout[0] = M_EXTENDED; - np->msgout[1] = 3; - np->msgout[2] = M_X_SYNC_REQ; - np->msgout[3] = per; - np->msgout[4] = ofs; - - cp->nego_status = NS_SYNC; - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - 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] = M_NOOP; - - break; - - case SIR_NEGO_WIDE: - /* - ** Wide request message received. - */ - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - printf ("wide msgin: "); - (void) ncr_show_msg (np->msgin); - printf (".\n"); - }; - - /* - ** get requested values. - */ - - chg = 0; - wide = np->msgin[3]; - - /* - ** if target sends WDTR message, - ** it CAN transfer wide. - */ - - if (wide) - tp->inqdata[7] |= INQ7_WIDE16; - - /* - ** check values against driver limits. - */ - - if (wide > tp->usrwide) - {chg = 1; wide = tp->usrwide;} - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - 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); - break; - }; - }; - - /* - ** It was a request, set value and - ** prepare an answer message - */ - - ncr_setwide (np, cp, wide, 1); - - np->msgout[0] = M_EXTENDED; - np->msgout[1] = 2; - np->msgout[2] = M_X_WIDE_REQ; - np->msgout[3] = wide; - - np->msgin [0] = M_NOOP; - - cp->nego_status = NS_WIDE; - - if (DEBUG_FLAGS & DEBUG_NEGO) { - PRINT_ADDR(cp->xfer); - printf ("wide msgout: "); - (void) ncr_show_msg (np->msgout); - printf (".\n"); - } - break; - -/*-------------------------------------------------------------------- -** -** Processing of special messages -** -**-------------------------------------------------------------------- -*/ - - case SIR_REJECT_RECEIVED: - /*----------------------------------------------- - ** - ** We received a M_REJECT message. - ** - **----------------------------------------------- - */ - - PRINT_ADDR(cp->xfer); - printf ("M_REJECT received (%x:%x).\n", - (unsigned)np->lastmsg, np->msgout[0]); - break; - - case SIR_REJECT_SENT: - /*----------------------------------------------- - ** - ** We received an unknown message - ** - **----------------------------------------------- - */ - - PRINT_ADDR(cp->xfer); - printf ("M_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->xfer); - printf ("M_IGN_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->xfer); - printf ("M_DISCONNECT received, but datapointer not saved:\n" - "\tdata=%x save=%x goal=%x.\n", - (unsigned) INL (nc_temp), - SCR_BO((unsigned) np->header.savep), - SCR_BO((unsigned) np->header.goalp)); - break; - -/*-------------------------------------------------------------------- -** -** Processing of a "S_QUEUE_FULL" 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. -** -** If possible, reinsert at head of queue. -** Stall queue until there are no disconnected jobs -** (ncr is REALLY idle). Then restart processing. -** -** We should restart the current job after the controller -** has become idle. But this is not yet implemented. -** -**-------------------------------------------------------------------- -*/ - case SIR_STALL_QUEUE: - /*----------------------------------------------- - ** - ** Stall the start queue. - ** - **----------------------------------------------- - */ - PRINT_ADDR(cp->xfer); - printf ("queue full.\n"); - - WRITESCRIPT(start1[0], SCR_INT); - - /* - ** Try to disable tagged transfers. - */ - ncr_setmaxtags (&np->target[target], 0); - - /* - ** @QUEUE@ - ** - ** Should update the launch field of the - ** current job to be able to restart it. - ** Then prepend it to the start queue. - */ - - /* fall through */ - - case SIR_STALL_RESTART: - /*----------------------------------------------- - ** - ** Enable selecting again, - ** if NO disconnected jobs. - ** - **----------------------------------------------- - */ - /* - ** Look for a disconnected job. - */ - cp = np->ccb; - while (cp && cp->host_status != HS_DISCONNECT) - cp = cp->link_ccb; - - /* - ** if there is one, ... - */ - if (cp) { - /* - ** wait for reselection - */ - OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, reselect)); - return; - }; - - /* - ** else remove the interrupt. - */ - - printf ("%s: queue empty.\n", ncr_name (np)); - WRITESCRIPT(start1[0], SCR_INT ^ IFFALSE (0)); - break; - }; - -out: - OUTB (nc_dcntl, np->rv_dcntl | STD); -} - -/*========================================================== -** -** -** Acquire a control block -** -** -**========================================================== -*/ - -static ccb_p ncr_get_ccb - (ncb_p np, u_long flags, u_long target, u_long lun) -{ - lcb_p lp; - ccb_p cp = (ccb_p) 0; - int oldspl; - - oldspl = splbio(); - /* - ** Lun structure available ? - */ - - lp = np->target[target].lp[lun]; - if (lp) { - cp = lp->next_ccb; - - /* - ** Look for free CCB - */ - - while (cp && cp->magic) { - cp = cp->next_ccb; - } - } - - /* - ** if nothing available, take the default. - */ - - if (!cp) cp = np->ccb; - - /* - ** Wait until available. - */ - - while (cp->magic) { - if (flags & SCSI_NOSLEEP) break; - if (tsleep ((caddr_t)cp, PRIBIO|PCATCH, "ncr", 0)) - break; - }; - - if (cp->magic) { - splx(oldspl); - return ((ccb_p) 0); - } - - cp->magic = 1; - splx(oldspl); - return (cp); -} - -/*========================================================== -** -** -** Release one control block -** -** -**========================================================== -*/ - -void ncr_free_ccb (ncb_p np, ccb_p cp, int flags) -{ - /* - ** sanity - */ - - assert (cp != NULL); - - cp -> host_status = HS_IDLE; - cp -> magic = 0; - if (cp == np->ccb) - wakeup ((caddr_t) cp); -} - -/*========================================================== -** -** -** Allocation of resources for Targets/Luns/Tags. -** -** -**========================================================== -*/ - -static void ncr_alloc_ccb (ncb_p np, u_long target, u_long lun) -{ - tcb_p tp; - lcb_p lp; - ccb_p cp; - - assert (np != NULL); - - if (target>=MAX_TARGET) return; - if (lun >=MAX_LUN ) return; - - tp=&np->target[target]; - - if (!tp->jump_tcb.l_cmd) { - - /* - ** initialize it. - */ - tp->jump_tcb.l_cmd = SCR_BO((SCR_JUMP^IFFALSE (DATA (0x80 + target)))); - tp->jump_tcb.l_paddr = np->jump_tcb.l_paddr; - - tp->getscr[0] = - (np->features & FE_PFEN)? SCR_BO(SCR_COPY(1)) : SCR_BO(SCR_COPY_F(1)); - tp->getscr[1] = SCR_BO(NCR_KVATOPHYS (np, &tp->sval)); - tp->getscr[2] = SCR_BO(np->paddr + offsetof (struct ncr_reg, nc_sxfer)); - tp->getscr[3] = tp->getscr[0]; - tp->getscr[4] = SCR_BO(NCR_KVATOPHYS (np, &tp->wval)); - tp->getscr[5] = SCR_BO(np->paddr + offsetof (struct ncr_reg, nc_scntl3)); - - assert (( (offsetof(struct ncr_reg, nc_sxfer) ^ - offsetof(struct tcb , sval )) &3) == 0); - assert (( (offsetof(struct ncr_reg, nc_scntl3) ^ - offsetof(struct tcb , wval )) &3) == 0); - - tp->call_lun.l_cmd = SCR_BO((SCR_CALL)); - tp->call_lun.l_paddr = SCR_BO(NCB_SCRIPT_PHYS (np, resel_lun)); - - tp->jump_lcb.l_cmd = SCR_BO((SCR_JUMP)); - tp->jump_lcb.l_paddr = SCR_BO(NCB_SCRIPTH_PHYS (np, abort)); - np->jump_tcb.l_paddr = SCR_BO(NCR_KVATOPHYS (np, &tp->jump_tcb)); - - tp->usrtags = SCSI_NCR_DFLT_TAGS; - ncr_setmaxtags (tp, tp->usrtags); - } - - /* - ** Logic unit control block - */ - lp = tp->lp[lun]; - if (!lp) { - /* - ** Allocate a lcb - */ - lp = (lcb_p) malloc (sizeof (struct lcb), M_DEVBUF, M_NOWAIT); - if (!lp) return; - -#if defined(__mips__) - pci_sync_cache(np->sc_pc, (vm_offset_t)lp, sizeof (struct lcb)); - lp = (struct lcb *)PHYS_TO_UNCACHED(NCR_KVATOPHYS(np, lp)); -#endif /* __mips__ */ - - /* - ** Initialize it - */ - bzero (lp, sizeof (*lp)); - lp->jump_lcb.l_cmd = SCR_BO((SCR_JUMP ^ IFFALSE (DATA (lun)))); - lp->jump_lcb.l_paddr = tp->jump_lcb.l_paddr; - - lp->call_tag.l_cmd = SCR_BO((SCR_CALL)); - lp->call_tag.l_paddr = SCR_BO(NCB_SCRIPT_PHYS (np, resel_tag)); - - lp->jump_ccb.l_cmd = SCR_BO((SCR_JUMP)); - lp->jump_ccb.l_paddr = SCR_BO(NCB_SCRIPTH_PHYS (np, aborttag)); - - lp->actlink = 1; - - /* - ** Chain into LUN list - */ - tp->jump_lcb.l_paddr = SCR_BO(NCR_KVATOPHYS (np, &lp->jump_lcb)); - tp->lp[lun] = lp; - - } - - /* - ** Limit possible number of ccbs. - ** - ** If tagged command queueing is enabled, - ** can use more than one ccb. - */ - - if (np->actccbs >= MAX_START-2) - return; - if (lp->actccbs && (lp->actccbs >= lp->reqccbs)) - return; - - /* - ** Allocate a ccb - */ - cp = (ccb_p) malloc (sizeof (struct ccb), M_DEVBUF, M_NOWAIT); - - if (!cp) - return; - -#if defined(__mips__) - pci_sync_cache(np->sc_pc, (vm_offset_t)cp, sizeof (struct ccb)); - cp = (struct ccb *)PHYS_TO_UNCACHED(NCR_KVATOPHYS(np, cp)); -#endif /* __mips__ */ - - if (DEBUG_FLAGS & DEBUG_ALLOC) { - printf ("new ccb @%p.\n", cp); - } - - /* - ** Count it - */ - lp->actccbs++; - np->actccbs++; - - /* - ** Initialize it - */ - bzero (cp, sizeof (*cp)); - - /* - ** Fill in physical addresses - */ - - cp->p_ccb = NCR_KVATOPHYS (np, cp); - - /* - ** Chain into reselect list - */ - cp->jump_ccb.l_cmd = SCR_BO(SCR_JUMP); - cp->jump_ccb.l_paddr = lp->jump_ccb.l_paddr; - lp->jump_ccb.l_paddr = SCR_BO(CCB_PHYS (cp, jump_ccb)); - cp->call_tmp.l_cmd = SCR_BO(SCR_CALL); - cp->call_tmp.l_paddr = SCR_BO(NCB_SCRIPT_PHYS (np, resel_tmp)); - - /* - ** Chain into wakeup list - */ - cp->link_ccb = np->ccb->link_ccb; - np->ccb->link_ccb = cp; - - /* - ** Chain into CCB list - */ - cp->next_ccb = lp->next_ccb; - lp->next_ccb = cp; -} - -/*========================================================== -** -** -** Announce the number of ccbs/tags to the scsi driver. -** -** -**========================================================== -*/ - -static void ncr_opennings (ncb_p np, lcb_p lp, struct scsi_xfer * xp) -{ - /* - ** want to reduce the number ... - */ - if (lp->actlink > lp->reqlink) { - - /* - ** Try to reduce the count. - ** We assume to run at splbio .. - */ - u_char diff = lp->actlink - lp->reqlink; - - if (!diff) return; - -#ifdef __OpenBSD__ - if (diff > xp->sc_link->openings) - diff = xp->sc_link->openings; - - xp->sc_link->openings -= diff; -#else - if (diff > xp->sc_link->opennings) - diff = xp->sc_link->opennings; - - xp->sc_link->opennings -= diff; -#endif - lp->actlink -= diff; - if (DEBUG_FLAGS & DEBUG_TAGS) - printf ("%s: actlink: diff=%d, new=%d, req=%d\n", - ncr_name(np), diff, lp->actlink, lp->reqlink); - return; - }; - - /* - ** want to increase the number ? - */ - if (lp->reqlink > lp->actlink) { - u_char diff = lp->reqlink - lp->actlink; - - xp->sc_link->openings += diff; - lp->actlink += diff; - wakeup ((caddr_t) xp->sc_link); - if (DEBUG_FLAGS & DEBUG_TAGS) - printf ("%s: actlink: diff=%d, new=%d, req=%d\n", - ncr_name(np), diff, lp->actlink, lp->reqlink); - }; -} - -/*========================================================== -** -** -** 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 - (ncb_p np, 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 = NCR_KVATOPHYS (np, (void *)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; - -#ifdef __OpenBSD__ - if (vaddr & (NBPG-1)) free -= datalen / NBPG; -#else - if (vaddr & PAGE_MASK) free -= datalen / PAGE_SIZE; -#endif - - if (free>1) - while ((chunk * free >= 2 * datalen) && (chunk>=1024)) - chunk /= 2; - - if(DEBUG_FLAGS & DEBUG_SCATTER) - printf("ncr?:\tscattering virtual=0x%x size=%d chunk=%d.\n", - (unsigned) 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 - */ -#ifdef __OpenBSD__ - pnext = (paddr & (~(NBPG - 1))) + NBPG; -#else - pnext = (paddr & (~PAGE_MASK)) + PAGE_SIZE; -#endif - - /* - ** 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 = NCR_KVATOPHYS (np, (void *)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 = SCR_BO(segaddr); - phys->data[segment].size = SCR_BO(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. -** -** -**========================================================== -*/ - -#if !defined(NCR_IOMAPPED) || defined(__OpenBSD__) -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) -{ - volatile u_int32_t ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc; - int i, err=0; - -#if !defined(NCR_IOMAPPED) || defined(__OpenBSD__) -#ifdef __OpenBSD__ - if (!np->sc_iomapped) -#endif - { - 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; -#if defined(__mips__) - pci_sync_cache(np->sc_pc, (vm_offset_t)&ncr_cache, sizeof (ncr_cache)); -#endif /* __mips__ */ - OUTL (nc_temp, SCR_BO(ncr_wr)); - /* - ** Start script (exchange values) - */ - OUTL (nc_dsp, pc); - /* - ** Wait 'til done (with timeout) - */ - for (i=0; i<NCR_SNOOP_TIMEOUT; i++) - if (INB(nc_istat) & (INTF|SIP|DIP)) - break; - /* - ** Save termination position. - */ - pc = INL (nc_dsp); - /* - ** Read memory and register. - */ - host_rd = ncr_cache; - ncr_rd = SCR_BO(INL (nc_scratcha)); - ncr_bk = SCR_BO(INL (nc_temp)); - /* - ** Reset ncr chip - */ - OUTB (nc_istat, SRST); - DELAY (1000); - OUTB (nc_istat, 0 ); - /* - ** check for timeout - */ - if (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 (struct timeval * from, struct timeval * to) -{ - if (!from->tv_sec) return (-1); - if (!to ->tv_sec) return (-2); - return ( (to->tv_sec - from->tv_sec - 2)*1000+ - +(to->tv_usec - from->tv_usec + 2000000)/1000); -} - -#define PROFILE cp->phys.header.stamp -static void ncb_profile (ncb_p np, ccb_p cp) -{ - int co, da, st, en, di, se, post,work,disc; - u_long diff; - -#ifdef __OpenBSD__ - getmicrouptime(&PROFILE.end); -#else - gettime(&PROFILE.end); -#endif - - 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->xfer) - np->profile.num_bytes += cp->xfer->datalen; - 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 - -#ifdef __OpenBSD__ -/*========================================================== -** -** -** Device lookup. -** -** @GENSCSI@ should be integrated to scsiconf.c -** -** -**========================================================== -*/ - -struct table_entry { - char * manufacturer; - char * model; - char * version; - u_long info; -}; - -static struct table_entry device_tab[] = -{ -#ifdef NCR_GETCC_WITHMSG - {"HP ", "C372", "", QUIRK_NOTAGS|QUIRK_NOMSG}, - {"", "", "", QUIRK_NOMSG}, - {"SONY", "SDT-5000", "3.17", QUIRK_NOMSG}, - {"WangDAT", "Model 2600", "01.7", QUIRK_NOMSG}, - {"WangDAT", "Model 3200", "02.2", QUIRK_NOMSG}, - {"WangDAT", "Model 1300", "02.4", QUIRK_NOMSG}, -#endif - {"", "", "", 0} /* catch all: must be last entry. */ -}; - -static u_long ncr_lookup(char * id) -{ - struct table_entry * p = device_tab; - char *d, *r, c; - - for (;;p++) { - - d = id+8; - r = p->manufacturer; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - d = id+16; - r = p->model; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - d = id+32; - r = p->version; - while ((c=*r++)) if (c!=*d++) break; - if (c) continue; - - return (p->info); - } -} -#endif /* __OpenBSD__ */ - -/*========================================================== -** -** 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) - printf ("%s: enabling clock multiplier\n", ncr_name(np)); - - 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) - printf("%s: the chip cannot lock the frequency\n", ncr_name(np)); - } 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<<gen) * 125us */ - while (!(INW(nc_sist) & GEN) && ms++ < 1000) - DELAY(1000); /* count ms */ - OUTB (nc_stime1, 0); /* disable general purpose timer */ - OUTB (nc_scntl3, 0); - /* - * Set prescaler to divide by whatever "0" means. - * "0" ought to choose divide by 2, but appears - * to set divide by 3.5 mode in my 53c810 ... - */ - OUTB (nc_scntl3, 0); - - if (bootverbose >= 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; - /* always false, except for 875 with clock doubler selected */ - if ((stest1 & (DBLEN+DBLSEL)) == DBLEN+DBLSEL) { - 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 */ - -/*=========================================================================*/ -#endif /* KERNEL */ diff --git a/sys/dev/pci/ncrreg.h b/sys/dev/pci/ncrreg.h deleted file mode 100644 index ce47a3d9380..00000000000 --- a/sys/dev/pci/ncrreg.h +++ /dev/null @@ -1,665 +0,0 @@ -/* $OpenBSD: ncrreg.h,v 1.2 2001/11/18 20:55:42 deraadt Exp $ */ -/* $NetBSD: ncrreg.h,v 1.14 1997/09/23 02:27:46 perry Exp $ */ - -/************************************************************************** -** -** Id: ncrreg.h,v 1.11 1997/08/31 19:42:31 se Exp -** -** Device driver for the NCR 53C810 PCI-SCSI-Controller. -** -** FreeBSD / NetBSD / OpenBSD -** -**------------------------------------------------------------------------- -** -** 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__ - -/*========================================================== -** -** OS dependencies. -** -**========================================================== -*/ - -#ifdef __OpenBSD__ -#define ISSCRIPTRAMMAPPED(np) (np->scriptmapped) -#else /*__OpenBSD__*/ -#define ISSCRIPTRAMMAPPED(np) (np->vaddr2) -#endif /*__OpenBSD__*/ - -/*----------------------------------------------------------------- -** -** The ncr 53c810 register structure. -** -**----------------------------------------------------------------- -*/ - -struct ncr_reg { -/*00*/ u_int8_t nc_scntl0; /* full arb., ena parity, par->ATN */ - -/*01*/ u_int8_t nc_scntl1; /* no reset */ - #define ISCON 0x10 /* connected to scsi */ - #define CRST 0x08 /* force reset */ - -/*02*/ u_int8_t 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_int8_t nc_scntl3; /* cnf system clock dependent */ - #define EWS 0x08 /* cmd: enable wide scsi [W]*/ - -/*04*/ u_int8_t 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_int8_t nc_sxfer; /* ### Sync speed and count */ - -/*06*/ u_int8_t nc_sdid; /* ### Destination-ID */ - -/*07*/ u_int8_t nc_gpreg; /* ??? IO-Pins */ - -/*08*/ u_int8_t nc_sfbr; /* ### First byte in phase */ - -/*09*/ u_int8_t 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_int8_t nc_ssid; - -/*0b*/ u_int8_t nc_sbcl; - -/*0c*/ u_int8_t 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_int8_t 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_int8_t nc_sstat1; - #define FF3210 0xf0 /* sta: bytes in the scsi fifo */ - -/*0f*/ u_int8_t 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_int8_t 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_int8_t nc_15_; -/*16*/ u_int8_t nc_16_; -/*17*/ u_int8_t nc_17_; - -/*18*/ u_int8_t nc_ctest0; -/*19*/ u_int8_t nc_ctest1; - -/*1a*/ u_int8_t nc_ctest2; - #define CSIGP 0x40 - -/*1b*/ u_int8_t 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_int8_t nc_dfifo; -/*21*/ u_int8_t nc_ctest4; - #define BDIS 0x80 /* mod: burst disable */ - #define MPEE 0x08 /* mod: master parity error enable */ - -/*22*/ u_int8_t nc_ctest5; - #define DFS 0x20 /* mod: dma fifo size */ -/*23*/ u_int8_t 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_int8_t 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_int8_t nc_dien; -/*3a*/ u_int8_t nc_dwt; - -/*3b*/ u_int8_t 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_int16_t nc_sien; /* -->: interrupt enable */ -/*42*/ u_int16_t 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_int8_t nc_slpar; -/*45*/ u_int8_t nc_swide; -/*46*/ u_int8_t nc_macntl; -/*47*/ u_int8_t nc_gpcntl; -/*48*/ u_int8_t nc_stime0; /* cmd: timeout for select&handshake*/ -/*49*/ u_int8_t nc_stime1; /* cmd: timeout user defined */ -/*4a*/ u_int16_t nc_respid; /* sta: Reselect-IDs */ - -/*4c*/ u_int8_t nc_stest0; - -/*4d*/ u_int8_t nc_stest1; - #define DBLEN 0x08 /* clock doubler running */ - #define DBLSEL 0x04 /* clock doubler selected */ - -/*4e*/ u_int8_t nc_stest2; - #define ROF 0x40 /* reset scsi offset (after gross error!) */ - #define EXT 0x02 /* extended filtering */ - -/*4f*/ u_int8_t nc_stest3; - #define TE 0x80 /* c: tolerAnt enable */ - #define HSC 0x20 /* c: Halt SCSI Clock */ - #define CSF 0x02 /* c: clear scsi fifo */ - -/*50*/ u_int16_t nc_sidl; /* Lowlevel: latched from scsi data */ -/*52*/ u_int8_t 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_int8_t nc_53_; -/*54*/ u_int16_t nc_sodl; /* Lowlevel: data out to scsi data */ -/*56*/ u_int16_t nc_56_; -/*58*/ u_int16_t nc_sbdl; /* Lowlevel: data from scsi data */ -/*5a*/ u_int16_t nc_5a_; -/*5c*/ u_int8_t nc_scr0; /* Working register B */ -/*5d*/ u_int8_t nc_scr1; /* */ -/*5e*/ u_int8_t nc_scr2; /* */ -/*5f*/ u_int8_t 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; - -#if BYTE_ORDER == BIG_ENDIAN -#define SCR_BO(x) (((x) >> 24) | (((x) >> 8) & 0xff00) | \ - ((x) << 24) | (((x) & 0xff00) << 8)) -#else -#define SCR_BO(x) (x) -#endif - -/*----------------------------------------------------------- -** -** 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) -** <<start address>> -** -** MOVE_IND (LEN) -** <<dnad_offset>> -** -** MOVE_TBL -** <<dnad_offset>> -** -**----------------------------------------------------------- -*/ - -#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] -** <<alternate_address>> -** -** SEL_TBL | << dnad_offset>> [ | REL_JMP] -** <<alternate_address>> -** -**----------------------------------------------------------- -*/ - -#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_int8_t sel_0; - u_int8_t sel_sxfer; - u_int8_t sel_id; - u_int8_t sel_scntl3; -}; - -#define SCR_JMP_REL 0x04000000 -#define SCR_ID(id) (((u_int32_t)(id)) << 16) - -/*----------------------------------------------------------- -** -** Waiting for Disconnect or Reselect -** -**----------------------------------------------------------- -** -** WAIT_DISC -** dummy: <<alternate_address>> -** -** WAIT_RESEL -** <<alternate_address>> -** -**----------------------------------------------------------- -*/ - -#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 = <data> -** << 0 >> -** -** LOAD_SFBR(data) SFBR = <data> -** << 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 ( ... ) ] -** <<address>> -** -** JUMPR [ | IFTRUE/IFFALSE ( ... ) ] -** <<distance>> -** -** CALL [ | IFTRUE/IFFALSE ( ... ) ] -** <<address>> -** -** CALLR [ | IFTRUE/IFFALSE ( ... ) ] -** <<distance>> -** -** RETURN [ | IFTRUE/IFFALSE ( ... ) ] -** <<dummy>> -** -** INT [ | IFTRUE/IFFALSE ( ... ) ] -** <<ident>> -** -** INT_FLY [ | IFTRUE/IFFALSE ( ... ) ] -** <<ident>> -** -** 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 -*/ -#ifdef __OpenBSD__ -#include <scsi/scsi_message.h> - -#define M_COMPLETE MSG_CMDCOMPLETE -#define M_EXTENDED MSG_EXTENDED -#define M_SAVE_DP MSG_SAVEDATAPOINTER -#define M_RESTORE_DP MSG_RESTOREPOINTERS -#define M_DISCONNECT MSG_DISCONNECT -#define M_ID_ERROR MSG_INITIATOR_DET_ERR -#define M_ABORT MSG_ABORT -#define M_REJECT MSG_MESSAGE_REJECT -#define M_NOOP MSG_NOOP -#define M_PARITY MSG_PARITY_ERROR -#define M_LCOMPLETE MSG_LINK_CMD_COMPLETE -#define M_FCOMPLETE MSG_LINK_CMD_COMPLETEF -#define M_RESET MSG_BUS_DEV_RESET -#define M_ABORT_TAG MSG_ABORT_TAG -#define M_CLEAR_QUEUE MSG_CLEAR_QUEUE -#define M_INIT_REC MSG_INIT_RECOVERY -#define M_REL_REC MSG_REL_RECOVERY -#define M_TERMINATE MSG_TERM_IO_PROC -#define M_SIMPLE_TAG MSG_SIMPLE_Q_TAG -#define M_HEAD_TAG MSG_HEAD_OF_Q_TAG -#define M_ORDERED_TAG MSG_ORDERED_Q_TAG -#define M_IGN_RESIDUE MSG_IGN_WIDE_RESIDUE -#define M_IDENTIFY MSG_IDENTIFY(0, 0) - -/* #define M_X_MODIFY_DP (0x00) */ /* XXX what is this? */ -#define M_X_SYNC_REQ MSG_EXT_SDTR -#define M_X_WIDE_REQ MSG_EXT_WDTR -#else -#define M_COMPLETE (0x00) -#define M_EXTENDED (0x01) -#define M_SAVE_DP (0x02) -#define M_RESTORE_DP (0x03) -#define M_DISCONNECT (0x04) -#define M_ID_ERROR (0x05) -#define M_ABORT (0x06) -#define M_REJECT (0x07) -#define M_NOOP (0x08) -#define M_PARITY (0x09) -#define M_LCOMPLETE (0x0a) -#define M_FCOMPLETE (0x0b) -#define M_RESET (0x0c) -#define M_ABORT_TAG (0x0d) -#define M_CLEAR_QUEUE (0x0e) -#define M_INIT_REC (0x0f) -#define M_REL_REC (0x10) -#define M_TERMINATE (0x11) -#define M_SIMPLE_TAG (0x20) -#define M_HEAD_TAG (0x21) -#define M_ORDERED_TAG (0x22) -#define M_IGN_RESIDUE (0x23) -#define M_IDENTIFY (0x80) - -#define M_X_MODIFY_DP (0x00) -#define M_X_SYNC_REQ (0x01) -#define M_X_WIDE_REQ (0x03) -#endif - - -/* -** Status -*/ - -#define S_GOOD (0x00) -#define S_CHECK_COND (0x02) -#define S_COND_MET (0x04) -#define S_BUSY (0x08) -#define S_INT (0x10) -#define S_INT_COND_MET (0x14) -#define S_CONFLICT (0x18) -#define S_TERMINATED (0x20) -#define S_QUEUE_FULL (0x28) -#define S_ILLEGAL (0xff) -#define S_SENSE (0x80) - -/* -** Bits defining chip features. -** For now only some of them are used, since we explicitly -** 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/dev/pci/ncrstat.c b/sys/dev/pci/ncrstat.c deleted file mode 100644 index 9ddd305b338..00000000000 --- a/sys/dev/pci/ncrstat.c +++ /dev/null @@ -1,1629 +0,0 @@ -/* $OpenBSD: ncrstat.c,v 1.5 2003/04/27 11:22:53 ho Exp $ */ -/* $NetBSD: ncrstat.c,v 1.7 1996/03/17 00:55:36 thorpej Exp $ */ - -/************************************************************************** -** -** Utility for NCR 53C810 device driver. -** -** FreeBSD / NetBSD / OpenBSD -** -**------------------------------------------------------------------------- -** -** Written for 386bsd and FreeBSD by -** wolf@dentaro.gun.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. -** -** -**------------------------------------------------------------------------- -*/ - -#include <sys/file.h> -#include <sys/types.h> -#if defined(__NetBSD__) || defined(__OpenBSD__) -#include <sys/device.h> -#endif -#include <nlist.h> -#include <stdio.h> -#include <errno.h> -#include <paths.h> -#include <limits.h> -#include <kvm.h> -#include <dev/pci/ncr.c> - -/* -** used external functions -*/ - -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD__ >= 2) -kvm_t *kvm; -#define KVM_NLIST(n) (kvm_nlist(kvm, (n)) >= 0) -#define KVM_READ(o, p, l) (kvm_read(kvm, (o), (void *)(p), (l)) == (l)) -#else -#define KVM_NLIST(n) (kvm_nlist((n)) >= 0) -#define KVM_READ(o, p, l) (kvm_read((void *)(o), (p), (l)) == (l)) -#endif - - -/*=========================================================== -** -** Global variables. -** -**=========================================================== -*/ - -char *prog; -u_long verbose; -u_long wizard; - - - -struct nlist nl[] = { -#define N_NCR_VERSION 0 - { "_ncr_version" }, -#if defined(__NetBSD__) || defined(__OpenBSD__) -#define N_NCRCD 1 - { "_ncr_cd" }, -#else -#define N_NCRP 1 - { "_ncrp" }, -#define N_NNCR 2 - { "_nncr" }, -#endif - { 0 } -}; - - -char *vmunix = _PATH_UNIX; -char *kmemf = NULL; - -int kvm_isopen; - -u_long ncr_base; -u_long lcb_base; -u_long ccb_base; - -u_long ncr_unit; -#if defined(__NetBSD__) || defined(__OpenBSD__) -struct cfdriver ncr_cd; -#else -u_long ncr_units; -#endif - -struct ncb ncr; -struct lcb lcb; -struct ccb ccb; - -u_long target_mask; -u_long global_lun_mask; -u_long lun_mask; -u_long interval; - -/*=========================================================== -** -** Accessing kernel memory via kvm library. -** -**=========================================================== -*/ - -read_ccb(u_long base) -{ - ccb_base = base; - if (!KVM_READ ( - base, - &ccb, - sizeof (struct ccb))) { - fprintf (stderr, "%s: bad kvm read at %x.\n", prog, base); - exit (1); - }; -} - -read_lcb(u_long base) -{ - lcb_base = base; - if (!KVM_READ ( - base, - &lcb, - sizeof (struct lcb))) { - fprintf (stderr, "%s: bad kvm read at %x.\n", prog, base); - exit (1); - }; -} - -read_ncr() -{ - if (!KVM_READ ( - ncr_base, - &ncr, - sizeof (ncr))) { - fprintf (stderr, "%s: bad kvm read at %x.\n", prog, ncr_base); - exit (1); - }; -} - -void open_kvm(int flags) -{ - int i; - u_long kernel_version; -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD__ >= 2) - char errbuf[_POSIX2_LINE_MAX]; -#endif - - if (kvm_isopen) return; - -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD__ >= 2) - kvm = kvm_openfiles(vmunix, kmemf, NULL, flags, errbuf); - if (kvm == NULL) { - fprintf(stderr, "%s: kvm_openfiles: %s\n", prog, errbuf); - exit(1); - } -#else - if (kvm_openfiles(vmunix, kmemf, NULL) == -1) { - fprintf(stderr, "%s: kvm_openfiles: %s\n", prog, kvm_geterr()); - exit(1); - } -#endif - - if (!KVM_NLIST(nl)) { - fprintf(stderr, "%s: no symbols in \"%s\".\n", - prog, vmunix); - exit (2); - }; - - for (i=0; nl[i].n_name; i++) - if (nl[i].n_type == 0) { - fprintf(stderr, "%s: no symbol \"%s\" in \"%s\".\n", - prog, nl[i].n_name, vmunix); - exit(1); - } - - if (!KVM_READ ( - nl[N_NCR_VERSION].n_value, - &kernel_version, - sizeof (kernel_version))) { - fprintf (stderr, "%s: bad kvm read.\n", prog); - exit (1); - }; - - if (kernel_version != ncr_version){ - fprintf (stderr, "%s: incompatible with kernel. Rebuild!\n", - prog); - exit (1); - }; - -#if defined(__NetBSD__) || defined(__OpenBSD__) - - if (!KVM_READ ( - nl[N_NCRCD].n_value, - &ncr_cd, - sizeof (ncr_cd))) { - fprintf (stderr, "%s: bad kvm read.\n", prog); - exit (1); - }; - - if (ncr_unit >= ncr_cd.cd_ndevs){ - fprintf (stderr, "%s: bad unit number (valid range: 0-%d).\n", - prog, ncr_cd.cd_ndevs-1); - exit (1); - }; - - if (!KVM_READ ( - ncr_cd.cd_devs+4*ncr_unit, - &ncr_base, - sizeof (ncr_base))) { - fprintf (stderr, "%s: bad kvm read.\n", prog); - exit (1); - }; - - if (!ncr_base) { - fprintf (stderr, - "%s: control structure not allocated (not found in autoconfig?)\n", prog); - exit (1); - }; - -#else /* !(__NetBSD__ || __OpenBSD__) */ - - if (!KVM_READ ( - nl[N_NNCR].n_value, - &ncr_units, - sizeof (ncr_units))) { - fprintf (stderr, "%s: bad kvm read.\n", prog); - exit (1); - }; - - if (ncr_unit >= ncr_units){ - fprintf (stderr, "%s: bad unit number (valid range: 0-%d).\n", - prog, ncr_units-1); - exit (1); - }; - - if (!KVM_READ ( - nl[N_NCRP].n_value+4*ncr_unit, - &ncr_base, - sizeof (ncr_base))) { - fprintf (stderr, "%s: bad kvm read.\n", prog); - exit (1); - }; - - if (!ncr_base) { - fprintf (stderr, - "%s: control structure not allocated (not found in autoconfig?)\n", prog); - exit (1); - }; - -#endif /* !(__NetBSD__ || __OpenBSD__) */ - - read_ncr(); - - if (!ncr.vaddr) { - fprintf (stderr, - "%s: 53c810 not mapped (not found in autoconfig?)\n", prog); - exit (1); - }; - - kvm_isopen = 1; -} - - - - -void set_target_mask(void) -{ - int t; - if (target_mask) return; - for (t=0; t<MAX_TARGET; t++) - if (ncr.target[t].jump_tcb.l_cmd) target_mask |= (1<<t); -} - -void set_lun_mask(struct tcb * tp) -{ - int l; - lun_mask = global_lun_mask; - if (lun_mask) return; - for (l=0; l<MAX_LUN; l++) - if (tp->lp[l]) lun_mask |= (1<<l); -} - -void printc (u_char *p, int l) -{ - for (;l>0;l--) { - char c=*p++; - printf ("%c", c?c:'_'); - } -} - -/*================================================================ -** -** -** system info -** -** -**================================================================ -*/ - -do_info(void) -{ - int t,l,i,d,f,fl; - struct tcb * tip; - open_kvm(O_RDONLY); - - if (verbose>=3) - printf ("ncr unit=%d data@%x register@%x (pci@%x)\n\n", - ncr_unit, ncr_base, ncr.vaddr, ncr.paddr); - - set_target_mask(); - - printf ("T:L Vendor Device Rev Speed Max Wide Tags\n"); - for (t=0; t<MAX_TARGET;t++) { - if (!((target_mask>>t)&1)) continue; - tip = &ncr.target[t]; - - set_lun_mask(tip); - if (!lun_mask) lun_mask=1; - fl=1; - - for (l=0; l<MAX_LUN; l++) { - if (!((lun_mask>>l)&1)) continue; - - printf ("%d:%d ", t, l); - - if (!tip->jump_tcb.l_cmd) break; - - if (fl) { - fl=0; - printc (&tip->inqdata[ 8], 8);printf(" "); - printc (&tip->inqdata[16],16);printf(" "); - printc (&tip->inqdata[32], 4);printf(" "); - - if (tip->period==0xffff) { - printf ("asyn"); - } else if (tip->period) { - printf ("%4.1f", 1000.0 / tip->period); - } else { - printf (" ?"); - } - - printf (" "); - - if (tip->minsync==255) { - printf ("asyn"); - } else if (tip->minsync) { - printf ("%4.1f", 250.0 / tip->minsync); - } else { - printf (" ?"); - } - } else printf (" "); - - if (!tip->lp[l]) { - printf (" no\n"); - continue; - }; - read_lcb ((u_long) tip->lp[l]); - - switch (tip->widedone) { - case 1: - printf (" 8"); - break; - case 2: - printf (" 16"); - break; - case 3: - printf (" 32"); - break; - default: - printf (" ?"); - }; - - if (lcb.usetags) - printf ("%5d", lcb.actlink); - else - printf (" -"); - - printf ("\n"); - - }; - - if (!tip->jump_tcb.l_cmd) { - printf (" --- no target.\n"); - continue; - }; - - if (verbose<1) continue; - - for (i=0; i<8; i++) { - char *(class[10])={ - "disk","tape","printer","processor", - "worm", "cdrom", "scanner", "optical disk", - "media changer", "communication device"}; - d = tip->inqdata[i]; - printf ("[%02x]: ",d); - - switch (i) { - - case 0: - f = d & 0x1f; - if (f<10) printf (class[f]); - else printf ("unknown (%x)", f); - break; - case 1: - f = (d>>7) & 1; - if (f) printf ("removable media"); - else printf ("fixed media"); - break; - - case 2: - f = d & 7; - switch (f) { - case 0: printf ("SCSI-1"); - break; - case 1: printf ("SCSI-1 with CCS"); - break; - case 2: printf ("SCSI-2"); - break; - default: - printf ("unknown ansi version (%d)", - f); - } - break; - - case 3: - if (d&0xc0) printf ("capabilities:"); - if (d&0x80) printf (" AEN"); - if (d&0x40) printf (" TERMINATE-I/O"); - break; - - case 7: - if (d&0xfb) printf ("capabilities:"); - if (d&0x80) printf (" relative"); - if (d&0x40) printf (" wide32"); - if (d&0x20) printf (" wide"); - if (d&0x10) printf (" synch"); - if (d&0x08) printf (" link"); - if (d&0x02) printf (" tags"); - if (d&0x01) printf (" soft-reset"); - }; - printf ("\n"); - }; - printf ("\n"); - }; - printf ("\n"); -#if !defined(__NetBSD__) && !defined(__OpenBSD__) - if (ncr.imask) { - int v; - printf ("Interrupt vector is"); - if (ncr.imask & (ncr.imask-1)) - printf (" one of the following:"); - for (v=15;v>0;v--) - if ((ncr.imask>>v)&1) - printf (" %d",v); - printf (".\n\n"); - }; -#endif -} - -/*================================================================ -** -** -** profiling -** -** -**================================================================ -*/ - -do_profile(void) -{ -#define old backup.profile -#define new ncr.profile - - struct ncb backup; - struct profile diff; - int tra,line,t; - - open_kvm(O_RDONLY); - - set_target_mask(); - - if (interval<1) interval=1; - for (;;) { - /* - ** Header Line 1 - */ - printf (" total "); - - for (t=0; t<MAX_TARGET; t++) { - if (!((target_mask>>t)&1)) continue; - printf (" "); - printc (&ncr.target[t].inqdata[16],8); - }; - - printf (" transf. disconn interru"); - - if (verbose>=1) printf (" ---- ms/transfer ----"); - - printf ("\n"); - - /* - ** Header Line 2 - */ - - printf ("t/s kb/s "); - - for (t=0; t<MAX_TARGET; t++) { - if (!((target_mask>>t)&1)) continue; - printf (" t/s kb/s"); - }; - - printf (" length exp une fly brk"); - - if (verbose>=1) printf (" total pre post disc"); - - printf ("\n"); - - /* - ** Data - */ - - for(line=0;line<20;line++) { - backup = ncr; - read_ncr(); - diff.num_trans = new.num_trans - old.num_trans; - diff.num_bytes = new.num_bytes - old.num_bytes; - diff.num_fly = new.num_fly - old.num_fly ; - diff.num_int = new.num_int - old.num_int ; - diff.ms_setup = new.ms_setup - old.ms_setup; - diff.ms_data = new.ms_data - old.ms_data; - diff.ms_disc = new.ms_disc - old.ms_disc; - diff.ms_post = new.ms_post - old.ms_post; - diff.num_disc = new.num_disc - old.num_disc; - diff.num_break = new.num_break - old.num_break; - - tra = diff.num_trans; - if (!tra) tra=1; - - printf ("%3.0f %4.0f ", - (1.0 * diff.num_trans) / interval, - (1.0 * diff.num_bytes) / (1024*interval)); - - - for (t=0; t<MAX_TARGET; t++) { - if (!((target_mask>>t)&1)) continue; - printf (" %3.0f %4.0f", - ((ncr.target[t].transfers- - backup.target[t].transfers)*1.0) - /interval, - ((ncr.target[t].bytes- - backup.target[t].bytes)*1.0) - /(1024*interval)); - }; - - printf ("%7.0f ", (diff.num_bytes*1.0) / tra); - - printf (" %4.0f", (1.0*(diff.num_disc-diff.num_break)) - /interval); - - printf ("%4.0f", (1.0*diff.num_break)/interval); - - printf ("%4.0f", (1.0*diff.num_fly) / interval); - - printf ("%4.0f", (1.0*diff.num_int) / interval); - - if (verbose >= 1) { - printf ("%7.1f", - (diff.ms_disc+diff.ms_data+diff.ms_setup+diff.ms_post) - * 1.0 / tra); - - printf ("%5.1f%5.1f%6.1f", - 1.0 * diff.ms_setup / tra, - 1.0 * diff.ms_post / tra, - 1.0 * diff.ms_disc / tra); - }; - - printf ("\n"); - fflush (stdout); - sleep (interval); - }; - }; -} - -/*================================================================ -** -** -** Port access -** -** -**================================================================ -*/ - -static int kernelwritefile; -static char *kernelwritefilename = _PATH_KMEM; - -void openkernelwritefile(void) -{ - if (kernelwritefile) return; - - kernelwritefile = open (kernelwritefilename, O_WRONLY); - if (kernelwritefile<3) { - fprintf (stderr, "%s: %s: %s\n", - prog, kernelwritefilename, strerror(errno)); - exit (1); - }; -} - -void out (u_char reg, u_char val) -{ - u_long addr = ncr.vaddr + reg; - openkernelwritefile(); - if (lseek (kernelwritefile, addr, 0) != addr) { - fprintf (stderr, "%s: %s: %s\n", - prog, kernelwritefilename, strerror(errno)); - exit (1); - } - if (write (kernelwritefile, &val, 1) < 0) { - fprintf (stderr, "%s: %s: %s\n", - prog, kernelwritefilename, strerror(errno)); - exit (1); - }; -} - -u_char in (u_char reg) -{ - u_char res; - if (!KVM_READ ( - (ncr.vaddr + reg), - &res, - 1)) { - fprintf (stderr, "%s: bad kvm read.\n", prog); - exit (1); - } - return (res); -} - -/*================================================================ -** -** -** Setting of driver parameters -** -** -**================================================================ -*/ - -void do_set (char * arg) -{ - struct usrcmd user; - u_long addr; - int i; - - open_kvm(O_RDWR); - addr = ncr_base + offsetof (struct ncb, user); - - for (i=3; i; i--) { - if (!KVM_READ ( - (addr), - &user, - sizeof (user))) { - fprintf (stderr, "%s: bad kvm read.\n", prog); - exit (1); - } - if (!user.cmd) break; - sleep (1); - } - if (user.cmd) { - fprintf (stderr, "%s: ncb.user busy.\n", prog); - exit (1); - }; - - user.target = target_mask; - user.lun = lun_mask; - user.data = 0; - user.cmd = 0; - - if (!strcmp(arg, "?")) { printf ( -"async: disable synchronous transfers.\n" -"sync=value: set the maximal synchronous transfer rate (MHz).\n" -"fast: set FAST SCSI-2.\n" -"\n" -"wide=value: set the bus width (0=8bit 1=16bit).\n" -"\n" -"tags=value: use this number of tags.\n" -"orderedtag: use ordered tags only.\n" -"simpletag: use simple tags only.\n" -"orderedwrite: use simple tags for read, else ordered tags.\n" -"\n" -"debug=value: set debug mode.\n" -"\n"); - return; - }; - - if (!strcmp(arg, "async")) { - user.data = 255; - user.cmd = UC_SETSYNC; - }; - - if (!strcmp(arg, "fast")) { - user.data = 25; - user.cmd = UC_SETSYNC; - }; - - if (!strncmp(arg, "sync=", 5)) { - float f = strtod (arg+5, NULL); - if (f>=4.0 && f<=10.0) { - user.data = 250.0 / f; - user.cmd = UC_SETSYNC; - }; - }; - - if (!strncmp(arg, "wide=", 5)) { - u_char t = strtoul (arg+5, (char **)0, 0); - if (t<=1) { - user.data = t; - user.cmd = UC_SETWIDE; - }; - }; - - if (!strncmp(arg, "tags=", 5)) { - u_char t = strtoul (arg+5, (char **)0, 0); - if (t<=SCSI_NCR_MAX_TAGS) { - user.data = t; - user.cmd = UC_SETTAGS; - }; - }; - - if (!strncmp(arg, "flags=", 6)) { - u_char t = strtoul (arg+6, (char **)0, 0); - if (t<=0xff) { - user.data = t; - user.cmd = UC_SETFLAG; - }; - }; - - if (!strncmp(arg, "debug=", 6)) { - user.data = strtoul (arg+6, (char **)0, 0); - user.cmd = UC_SETDEBUG; - }; - - if (!strcmp(arg, "orderedtag")) { - user.data = M_ORDERED_TAG; - user.cmd = UC_SETORDER; - }; - - if (!strcmp(arg, "simpletag")) { - user.data = M_SIMPLE_TAG; - user.cmd = UC_SETORDER; - }; - - if (!strcmp(arg, "orderedwrite")) { - user.data = 0; - user.cmd = UC_SETORDER; - }; - - if (user.cmd) { - openkernelwritefile(); - - if (lseek (kernelwritefile, addr, 0) != addr) { - fprintf (stderr, "%s: %s: %s\n", - prog, kernelwritefilename, strerror(errno)); - exit (1); - } - if (write (kernelwritefile, &user, sizeof (user)) < 0) { - fprintf (stderr, "%s: %s: %s\n", - prog, kernelwritefilename, strerror(errno)); - exit (1); - } - - return; - }; - - fprintf (stderr, "%s: do_set \"%s\" not (yet) implemented.\n", - prog, arg); -} - -/*================================================================ -** -** -** D O _ K I L L -** -** -**================================================================ -*/ - -do_kill(char * arg) -{ - open_kvm(O_RDWR); - - if (!strcmp(arg, "?")) { printf ( -"scsireset: force SCSI bus reset.\n" -"scriptabort: send an abort cmd to the script processor.\n" -"scriptstart: start script processind (set SIGP bit).\n" -"evenparity: force even parity.\n" -"oddparity: force odd parity.\n" -"noreselect: disable reselect (force timeouts).\n" -"doreselect: enable reselect.\n" -"\n"); - return; - }; - - if (!wizard) { - fprintf (stderr, "%s: You are NOT a wizard!\n", prog); - exit (2); - }; - - if (!strcmp(arg, "scsireset")) { - out (0x01, 0x08); - out (0x01, 0x00); - return; - }; - if (!strcmp(arg, "scriptabort")) { - out (0x14, 0x80); - out (0x14, 0x20); - return; - }; - if (!strcmp(arg, "scriptstart")) { - out (0x14, 0x20); - return; - }; - if (!strcmp(arg, "evenparity")) { - out (0x01, 0x04); - return; - }; - if (!strcmp(arg, "oddparity")) { - out (0x01, 0x00); - return; - }; - if (!strcmp(arg, "noreselect")) { - out (0x04, in (0x04) & ~RRE); - return; - }; - if (!strcmp(arg, "doreselect")) { - out (0x04, in (0x04) | RRE); - return; - }; - fprintf (stderr, "%s: do_kill \"%s\" not (yet) implemented.\n", - prog, arg); -} - -/*================================================================ -** -** -** Write debug info: utilities: write symbolname. -** -** -**================================================================ -*/ - -static const char * sn (u_long a) -{ - static char buffer[100]; - - const char * s=""; - u_long d,m; - - a -= ncr.p_script; - m = sizeof (struct script); - - if ((d=a-offsetof(struct script, start))<m) m=d, s="<start>"; - if ((d=a-offsetof(struct script, start1))<m) m=d, s="<start1>"; - if ((d=a-offsetof(struct script, startpos))<m) m=d, s="<startpos>"; - if ((d=a-offsetof(struct script, tryloop))<m) m=d, s="<tryloop>"; - if ((d=a-offsetof(struct script, trysel))<m) m=d, s="<trysel>"; - if ((d=a-offsetof(struct script, skip))<m) m=d, s="<skip>"; - if ((d=a-offsetof(struct script, skip2))<m) m=d, s="<skip2>"; - if ((d=a-offsetof(struct script, idle))<m) m=d, s="<idle>"; - if ((d=a-offsetof(struct script, select))<m) m=d, s="<select>"; - if ((d=a-offsetof(struct script, prepare))<m) m=d, s="<prepare>"; - if ((d=a-offsetof(struct script, loadpos))<m) m=d, s="<loadpos>"; - if ((d=a-offsetof(struct script, prepare2))<m) m=d, s="<prepare2>"; - if ((d=a-offsetof(struct script, setmsg))<m) m=d, s="<setmsg>"; - if ((d=a-offsetof(struct script, clrack))<m) m=d, s="<clrack>"; - if ((d=a-offsetof(struct script, dispatch))<m) m=d, s="<dispatch>"; - if ((d=a-offsetof(struct script, checkatn))<m) m=d, s="<checkatn>"; - if ((d=a-offsetof(struct script, command))<m) m=d, s="<command>"; - if ((d=a-offsetof(struct script, status))<m) m=d, s="<status>"; - if ((d=a-offsetof(struct script, msg_in))<m) m=d, s="<msg_in>"; - if ((d=a-offsetof(struct script, msg_bad))<m) m=d, s="<msg_bad>"; - if ((d=a-offsetof(struct script, msg_parity))<m) m=d, s="<msg_parity>"; - if ((d=a-offsetof(struct script, msg_reject))<m) m=d, s="<msg_reject>"; - if ((d=a-offsetof(struct script, msg_extended))<m) m=d, s="<msg_extended>"; - if ((d=a-offsetof(struct script, msg_sdtr))<m) m=d, s="<msg_sdtr>"; - if ((d=a-offsetof(struct script, complete))<m) m=d, s="<complete>"; - if ((d=a-offsetof(struct script, cleanup))<m) m=d, s="<cleanup>"; - if ((d=a-offsetof(struct script, cleanup0))<m) m=d, s="<cleanup>"; - if ((d=a-offsetof(struct script, signal))<m) m=d, s="<signal>"; - if ((d=a-offsetof(struct script, save_dp))<m) m=d, s="<save_dp>"; - if ((d=a-offsetof(struct script, restore_dp))<m) m=d, s="<restore_dp>"; - if ((d=a-offsetof(struct script, disconnect))<m) m=d, s="<disconnect>"; - if ((d=a-offsetof(struct script, msg_out))<m) m=d, s="<msg_out>"; - if ((d=a-offsetof(struct script, msg_out_done))<m) m=d, s="<msg_out_done>"; - if ((d=a-offsetof(struct script, msg_out_abort))<m) m=d, s="<msg_out_abort>"; - if ((d=a-offsetof(struct script, getcc))<m) m=d, s="<getcc>"; - if ((d=a-offsetof(struct script, getcc1))<m) m=d, s="<getcc1>"; - if ((d=a-offsetof(struct script, getcc2))<m) m=d, s="<getcc2>"; - if ((d=a-offsetof(struct script, badgetcc))<m) m=d, s="<badgetcc>"; - if ((d=a-offsetof(struct script, reselect))<m) m=d, s="<reselect>"; - if ((d=a-offsetof(struct script, reselect2))<m) m=d, s="<reselect2>"; - if ((d=a-offsetof(struct script, resel_tmp))<m) m=d, s="<resel_tmp>"; - if ((d=a-offsetof(struct script, resel_lun))<m) m=d, s="<resel_lun>"; - if ((d=a-offsetof(struct script, resel_tag))<m) m=d, s="<resel_tag>"; - if ((d=a-offsetof(struct script, data_in))<m) m=d, s="<data_in>"; - if ((d=a-offsetof(struct script, data_out))<m) m=d, s="<data_out>"; - if ((d=a-offsetof(struct script, no_data))<m) m=d, s="<no_data>"; - if ((d=a-offsetof(struct script, aborttag))<m) m=d, s="<aborttag>"; - if ((d=a-offsetof(struct script, abort))<m) m=d, s="<abort>"; - - if (!*s) return s; - - snprintf (buffer, sizeof buffer, "%s:%d%c", s, m/4, 0); - return (buffer); -} - -/*================================================================ -** -** -** Write debug info: utilities: write misc. fields. -** -** -**================================================================ -*/ - -static void printm (u_char * msg, int len) -{ - u_char l; - do { - if (*msg==M_EXTENDED) - l=msg[1]+2; - else if ((*msg & 0xf0)==0x20) - l=2; - else l=1; - len-=l; - - printf (" %x",*msg++); - while (--l>0) printf ("-%x",*msg++); - } while (len>0); -} - -void dump_table (const char * str, struct scr_tblmove * p, int l) -{ - int i; - for (i=0;l>0;i++,p++,l--) if (p->size) { - printf (" %s[%d]: %5d @ 0x%08x\n", - str, i, p->size, p->addr); - }; -} - -void dump_link (const char *name, struct link * link) -{ - printf ("%s: cmd=%08x pa=%08x %s\n", - name, link->l_cmd, link->l_paddr, sn(link->l_paddr)); -} - -/*================================================================ -** -** -** Write debug info: utilities: write time fields. -** -** -**================================================================ -*/ - -void dump_tstamp (const char *name, struct tstamp * p) -#define P(id,fld)\ - if (p->fld.tv_sec) \ - printf ("%s: "id" at %s.%06d",\ - name,ctime(&p->fld.tv_sec),p->fld.tv_usec); -{ - P ("started ", start); - P ("ended ", end ); - P ("selected ", select); - P ("command ", command); - P ("data ", data); - P ("status ", status); - P ("disconnected", disconnect); - P ("reselected ", reselect); - printf ("\n"); -} - - - - -void dump_profile (const char *name, struct profile * p) -{ - printf ("%s: %10d transfers.\n" ,name,p->num_trans); - printf ("%s: %10d bytes transferred.\n",name,p->num_bytes); - printf ("%s: %10d disconnects.\n" ,name,p->num_disc); - printf ("%s: %10d short transfers.\n" ,name,p->num_break); - printf ("%s: %10d interrupts.\n" ,name,p->num_int); - printf ("%s: %10d on the fly ints.\n" ,name,p->num_fly); - printf ("%s: %10d ms setup time.\n" ,name,p->ms_setup); - printf ("%s: %10d ms data transfer.\n" ,name,p->ms_data); - printf ("%s: %10d ms disconnected.\n" ,name,p->ms_disc); - printf ("%s: %10d ms postprocessing.\n",name,p->ms_post); - printf ("\n"); -} - -/*================================================================ -** -** -** Write debug info: utilities: write script registers. -** -** -**================================================================ -*/ - -static void dump_reg(struct ncr_reg * rp) -{ - u_char *reg = (u_char *) rp; -#define l(i) (reg[i]+(reg[i+1]<<8ul)+(reg[i+2]<<16ul)+(reg[i+3]<<24ul)) - int ad; - - char *(phasename[8])={"DATA-OUT","DATA-IN","COMMAND","STATUS", - "ILG-OUT","ILG-IN","MESSAGE-OUT","MESSAGE-IN"}; - for (ad=0x00;ad<0x80;ad++) { - switch (ad % 16) { - - case 0: - printf (" %02x:\t",ad); - break; - case 8: - printf (" : "); - break; - default: - printf (" "); - }; - printf ("%02x", reg[ad]); - if (ad % 16 == 15) printf ("\n"); - }; - printf ("\n"); - printf (" DSP %08x %-20s CMD %08x DSPS %08x %s\n", - l(0x2c),sn(l(0x2c)),l(0x24),l(0x30), sn(l(0x30))); - printf (" TEMP %08x %-20s DSA %08x\n", - l(0x1c),sn(l(0x1c)),l(0x10)); - printf ("\n"); - printf (" Busstatus: "); - if ((reg[0x0b]>>7)&1) printf (" Req"); - if ((reg[0x0b]>>6)&1) printf (" Ack"); - if ((reg[0x0b]>>5)&1) printf (" Bsy"); - if ((reg[0x0b]>>4)&1) printf (" Sel"); - if ((reg[0x0b]>>3)&1) printf (" Atn"); - printf (" %s\n", phasename[reg[0x0b]&7]); - - printf (" Dmastatus: "); - if ((reg[0x0c]>>7)&1) printf (" FifoEmpty"); - if ((reg[0x0c]>>6)&1) printf (" MasterParityError"); - if ((reg[0x0c]>>5)&1) printf (" BusFault"); - if ((reg[0x0c]>>4)&1) printf (" Aborted"); - if ((reg[0x0c]>>3)&1) printf (" SingleStep"); - if ((reg[0x0c]>>2)&1) printf (" Interrupt"); - if ((reg[0x0c]>>0)&1) printf (" IllegalInstruction"); - printf ("\n"); - printf (" Intstatus: "); - if ((reg[0x14]>>7)&1) printf (" Abort"); - if ((reg[0x14]>>6)&1) printf (" SoftwareReset"); - if ((reg[0x14]>>5)&1) printf (" SignalProcess"); - if ((reg[0x14]>>4)&1) printf (" Semaphore"); - if ((reg[0x14]>>3)&1) printf (" Connected"); - if ((reg[0x14]>>2)&1) printf (" IntOnTheFly"); - if ((reg[0x14]>>1)&1) printf (" SCSI-Interrupt"); - if ((reg[0x14]>>0)&1) printf (" DMA-Interrupt"); - printf ("\n"); - printf (" ScsiIstat: "); - if ((reg[0x42]>>7)&1) printf (" PhaseMismatch"); - if ((reg[0x42]>>6)&1) printf (" Complete"); - if ((reg[0x42]>>5)&1) printf (" Selected"); - if ((reg[0x42]>>4)&1) printf (" Reselected"); - if ((reg[0x42]>>3)&1) printf (" GrossError"); - if ((reg[0x42]>>2)&1) printf (" UnexpectedDisconnect"); - if ((reg[0x42]>>1)&1) printf (" ScsiReset"); - if ((reg[0x42]>>0)&1) printf (" ParityError"); - if ((reg[0x43]>>2)&1) printf (" SelectionTimeout"); - if ((reg[0x43]>>1)&1) printf (" TimerExpired"); - if ((reg[0x43]>>0)&1) printf (" HandshakeTimeout"); - printf ("\n"); - printf (" ID=%d DEST-ID=%d RESEL-ID=%d\n", reg[4]&7, reg[6]&7, reg[0xa]&7); - printf ("\n"); -} - -/*================================================================ -** -** -** Write debug info: utilities: write header. -** -** -**================================================================ -*/ - -char * debug_opt; - -dump_head (struct head * hp) -{ - dump_link (" launch", & hp->launch); - printf (" savep: %08x %s\n", - hp->savep, sn((u_long) hp->savep)); - printf (" cp: %08x %s\n", - hp->cp, sn((u_long)hp->cp)); - if (strchr (debug_opt, 'y')) { - printf ("\n"); - dump_tstamp (" timestamp", &hp->stamp); - }; - - printf (" status: %x %x %x %x %x %x %x %x\n", - hp->status[0], hp->status[1], hp->status[2], hp->status[3], - hp->status[4], hp->status[5], hp->status[6], hp->status[7]); - - printf ("\n"); -} - -/*================================================================ -** -** -** Write debug info: utilities: write ccb. -** -** -**================================================================ -*/ - -void dump_ccb (struct ccb * cp, u_long base) -{ - printf ("----------------------\n"); - printf ("struct ccb @ %08x:\n", base); - printf ("----------------------\n"); - - dump_link (" next", &cp->jump_ccb); - dump_link (" call", &cp->call_tmp); - - dump_head (&cp->phys.header); - - if (strchr (debug_opt, 's')) { - dump_table(" smsg", &cp->phys.smsg, 1); - dump_table("smsg2", &cp->phys.smsg2, 1); - dump_table(" cmd", &cp->phys.cmd, 1); - dump_table(" data", &cp->phys.data[0],MAX_SCATTER); - dump_table("sense", &cp->phys.sense, 1); - }; - - if (strchr (debug_opt, 'a')) { - int i; - for (i=0; i<8; i++) - printf (" patch[%d]: %08x\n", i, cp->patch[i]); - }; - - if (strchr (debug_opt, 'x')) { - printf (" xfer: -- dump not yet implemented.\n"); - }; - - if (strchr (debug_opt, 'm')) { - printf (" smsg:"); - printm (cp->scsi_smsg, cp->phys.smsg.size); - printf ("\n"); - printf (" smsg2:"); - printm (cp->scsi_smsg2, cp->phys.smsg2.size); - printf ("\n"); - }; - - printf (" magic: %x\n", cp->magic); - if (cp->tlimit) - printf (" timeout at: %s", ctime((time_t*)&cp->tlimit)); - printf (" link_ccb: %08x\n", (u_long) cp->link_ccb); - printf (" next_ccb: %08x\n", (u_long) cp->next_ccb); - printf (" tag: %d\n", cp->tag); - printf ("\n"); -} - -/*================================================================ -** -** -** Write debug info: struct lcb -** -** -**================================================================ -*/ - -static void dump_lcb (u_long base) -{ - struct lcb l; - struct ccb c; - u_long cp,cn; - - printf ("----------------------\n"); - printf ("struct lcb @ %08x:\n", base); - printf ("----------------------\n"); - - if (!KVM_READ ( - base, - &l, - sizeof (struct lcb))) { - fprintf (stderr, "%s: bad kvm read.\n", prog); - exit (1); - }; - printf (" reqccbs: %d\n", l.reqccbs); - printf (" actccbs: %d\n", l.actccbs); - printf (" reqlink: %d\n", l.reqlink); - printf (" actlink: %d\n", l.actlink); - printf (" usetags: %d\n", l.usetags); - dump_link (" jump_lcb", &l.jump_lcb); - dump_link (" call_tag", &l.call_tag); - dump_link (" jump_ccb", &l.jump_ccb); - printf ("\n"); - cp = (u_long) l.next_ccb; - cn = 0; - while (cp) { - cn++; - printf ("ccb #%d:\n", cn); - if (!KVM_READ ( - cp, - &c, - sizeof (struct ccb))) { - fprintf (stderr, "%s: bad kvm read.\n", prog); - exit (1); - }; - dump_ccb (&c, cp); - cp= (u_long) c.next_ccb; - }; -} - -/*================================================================ -** -** -** Write debug info: struct tcb -** -** -**================================================================ -*/ - -static void dump_tip (struct tcb * tip) -{ - int i; - u_long lp; - - printf ("----------------------\n"); - printf ("struct tcb:\n"); - printf ("----------------------\n"); - - printf (" transfers:%10d.\n", tip->transfers); - printf (" bytes:%10d.\n", tip->bytes ); - printf (" user limits: usrsync=%d usrwide=%d usrtags=%d.\n", - tip->usrsync, tip->usrwide, tip->usrtags); - printf (" sync: minsync=%d, maxoffs=%d, period=%d ns, sval=%x.\n", - tip->minsync, tip->maxoffs, tip->period, tip->sval); - printf (" wide: widedone=%d, wval=%x.\n", - tip->widedone, tip->wval); - - printf (" hold_cp: %x\n", tip->hold_cp); - dump_link (" jump_tcb", &tip->jump_tcb); - dump_link (" call_lun", &tip->call_lun); - dump_link (" jump_lcb", &tip->jump_lcb); - if (tip->hold_cp) printf (" hold_cp: @ %x\n", tip->hold_cp); - printf ("\n"); - - if (strchr (debug_opt, 'l')) { - for (i=0;i<MAX_LUN;i++) { - lp= (u_long) tip->lp[i]; - printf ("logic unit #%d:\n", i); - if (lp) dump_lcb (lp); - }; - } -} - -/*================================================================ -** -** -** Write debug info: struct ncb -** -** -**================================================================ -*/ - - -static void dump_ncr (void) -{ - u_long tp; - int i; - - printf ("----------------------\n"); - printf ("struct ncb @ %x:\n", ncr_base); - printf ("----------------------\n"); - - dump_link (" jump_tcb", &ncr.jump_tcb); - printf (" register: @ %x (p=%x)\n", ncr.vaddr, ncr.paddr); - - if (strchr (debug_opt, 'r')) { - struct ncr_reg reg; - - if (!KVM_READ ( - ncr.vaddr, - ®, - sizeof (reg))) { - fprintf (stderr, "%s: bad kvm read.\n", prog); - exit (1); - }; - - printf ("\n"); - dump_reg (®); - }; - - printf (" script: @ %x (p=%x)\n", ncr.script, ncr.p_script); - - printf ("hostscsiaddr: %d\n", ncr.myaddr); - printf (" ns_async: %d ns\n", ncr.ns_async); - printf (" ns_sync : %d ns\n", ncr.ns_sync); - printf (" scntl3: 0x%02x\n", ncr.rv_scntl3); - printf ("\n"); - - /* sc_link not dumped */ - - if (strchr (debug_opt, 'u')) { - printf (" usercmd: cmd=%x data=%x target=%x lun=%x\n", - ncr.user.cmd, - ncr.user.data, - ncr.user.target, - ncr.user.lun); - }; - - printf (" actccbs: %d\n", ncr.actccbs); - - if (strchr (debug_opt, 'q')) { - - u_long startpos; - - if (!KVM_READ ( - ((u_long)ncr.script - +offsetof(struct script, startpos)), - &startpos, - sizeof (startpos))) { - fprintf (stderr, "%s: bad kvm read.\n", prog); - exit (1); - }; - - printf (" startpos: %x\n", startpos); - printf (" slot: %d\n", (startpos- - (ncr.p_script+offsetof(struct script, tryloop)))/20); - printf (" squeuput: %d\n", ncr.squeueput); - for (i=0; i<MAX_START; i++) - printf ("%12d: %08x %s\n", i, - ncr.squeue[i], sn(ncr.squeue[i])); - - printf ("\n"); - }; - - printf (" ticks: %d ms\n", ncr.ticks * 10); - printf (" heartbeat: %s", ctime ((time_t*)&ncr.heartbeat)); - printf (" lasttime: %s", ctime ((time_t*)&ncr.lasttime)); -#if !defined(__NetBSD__) && !defined(__OpenBSD__) - printf ("imask/mcount: %x / %d\n", ncr.imask, ncr.mcount); -#endif - printf ("\n"); - - if (strchr (debug_opt, 'd') && ncr.regtime.tv_sec) { - printf (" regdump: %s", ctime (&ncr.regtime.tv_sec)); - dump_reg (&ncr.regdump); - }; - - if (strchr (debug_opt, 'p')) { - printf ("\n"); - dump_profile (" profile", &ncr.profile); - }; - - if (strchr (debug_opt, 'h')) { - printf ("\n"); - dump_head ( &ncr.header); - }; - - if (strchr (debug_opt, 'c')) { - dump_ccb (&ncr.ccb, ncr_base + offsetof (struct ncb, ccb)); - }; - - if (strchr (debug_opt, 'm')) { - printf (" msgout:"); printm (ncr.msgout,0); printf ("\n"); - printf (" msg in:"); printm (ncr.msgin,0); printf ("\n"); - printf ("\n"); - }; - - if (strchr (debug_opt, 't')) { - struct tcb * tip; - for (i=0;i<MAX_TARGET;i++) { - tip = &ncr.target[i]; - if (!tip->jump_tcb.l_cmd) continue; - printf ("target #%d:\n", i); - dump_tip (tip); - } - } -} - -/*================================================================ -** -** -** D O _ D E B U G -** -** -**================================================================ -*/ - - -do_debug(char * arg) -{ - open_kvm(O_RDONLY); - debug_opt = arg; - if (strchr (debug_opt, '?')) printf ( -"'?': list debug options [sic].\n" -"'a': show patchfields in ccbs (requires c).\n" -"'c': show ccbs.\n" -"'d': show register dump.\n" -"'h': show header information.\n" -"'m': show message buffers.\n" -"'n': show ncr main control block.\n" -"'p': show profiling information.\n" -"'q': show start queue.\n" -"'r': show registers (*DANGEROUS*).\n" -"'s': show scatter/gather info.\n" -"'t': show target control blocks.\n" -"'u': show user cmd field.\n" -"'x': show generic xfer structure.\n" -"'y': show timestamps.\n" -"\n" - ); - - if (strchr (debug_opt, 'n')) dump_ncr (); - if (strchr (debug_opt, 'r')) { - struct ncr_reg reg; - if (!KVM_READ ( - ncr.vaddr, - ®, - sizeof (reg))) { - fprintf (stderr, "%s: bad kvm read.\n", prog); - exit (1); - }; - dump_reg (®); - }; -} - - -/*================================================================ -** -** -** Main function -** -** -**================================================================ -*/ - -void main(argc, argv) - int argc; - char **argv; -{ - extern char *optarg; - extern int optind; - int usage=0; - char * charp; - int ch, getopt(),atoi(); - int i,step; - - prog = *argv; - while ((ch = getopt(argc, argv, "M:N:u:f:t:l:p:s:k:d:vwhin:?")) != -1) - switch((char)ch) { - case 'M': - if (kvm_isopen) { - fprintf (stderr, - "%s: -M: kernel file already open.\n", - prog); - exit (1); - }; - kmemf = optarg; - break; - case 'N': - if (kvm_isopen) { - fprintf (stderr, - "%s: -N: symbol table already open.\n", - prog); - exit (1); - }; - vmunix = optarg; - break; - case 'f': - fprintf (stderr, - "%s: -f: option not yet implemented.\n", - prog); - exit (1); - - case 'u': - i = strtoul (optarg, &charp, 0); - if (!*optarg || *charp || (i<0)) { - fprintf (stderr, - "%s: bad unit number \"%s\".\n", - prog, optarg); - exit (1); - } - ncr_unit = i; - break; - case 't': - i = strtoul (optarg, &charp, 0); - if (!*optarg || *charp || (i<0) || (i>=MAX_TARGET)) { - fprintf (stderr, - "%s: bad target number \"%s\" (valid range: 0-%d).\n", - prog, optarg, MAX_TARGET-1); - exit (1); - } - target_mask |= 1ul << i; - break; - case 'n': - open_kvm(O_RDONLY); - i = strtoul (optarg, &charp, 0); - printf ("addr %d (0x%x) has label %s.\n", - i,i,sn(i)); - break; - case 'l': - i = strtoul (optarg, &charp, 0); - if (!*optarg || *charp || (i<0) || (i>=MAX_LUN)) { - fprintf (stderr, - "%s: bad logic unit number \"%s\" (valid range: 0-%d).\n", - prog, optarg, MAX_LUN); - exit (1); - } - global_lun_mask |= 1ul << i; - break; - case 'p': - i = strtoul (optarg, &charp, 0); - if (!*optarg || *charp || (i<1) || (i>60)) { - fprintf (stderr, - "%s: bad interval \"%s\".\n", - prog, optarg); - exit (1); - } - interval = i; - do_profile(); - break; - - case 'w': - wizard=1; - break; - case 'v': - verbose++; - break; - case 'i': - do_info(); - break; - - case 's': - do_set(optarg); - break; - case 'd': - do_debug(optarg); - break; - case 'k': - do_kill(optarg); - break; - case 'h': - case '?': - usage++; - break; - default:(void)fprintf(stderr, - "%s: illegal option \"%c\".\n", prog, ch); - usage++; - } - - argv += optind; - argc -= optind; - - if (argc) printf ("%s: rest of line starting with \"%s\" ignored.\n", - prog, *argv); - - if (verbose&&!kvm_isopen) usage++; - if (usage) { - fprintf (stderr, - "Usage:\n" - "\n" - "%s [-M$] [-N$] {-f$} {-t#} {-l#} [-hivw?] [-d$] [-s$] [-k] [[-p] <time>]\n" - "\n" - "-t <#> select target number\n" - "-l <#> select lun number\n" - "-i get info\n" - "-v verbose\n" - "-p <seconds> performance data\n" - "\n" - "Wizards only (proceed on your own risk):\n" - "-n <#> get the name for address #\n" - "-w wizard mode\n" - "-d <options> debug info\n" - "-d? list debug options\n" - "-s <param=value> set parameter\n" - "-s? list parameters\n" - "-k <torture> torture driver by simulating errors\n" - "-k? list tortures\n" - "-M <kernelimage> (default: %s)\n" - "-N <symboltable> (default: %s)\n" - , prog, _PATH_KMEM, _PATH_UNIX); - if (verbose) fprintf (stderr, ident); - exit (1); - } - - if (!kvm_isopen) { - do_info(); - do_profile(); - }; - exit (0); -} |